- How I used a MyRouteApp gpx with my Beeline moto II + I built a sandbox to test integration platforms. +
+September 5, 2025
+ +diff --git a/.gitignore b/.gitignore index 844b1cc..0ac3294 100644 --- a/.gitignore +++ b/.gitignore @@ -87,4 +87,6 @@ lerna-debug.log # System Files .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db + +*.obsidian* \ No newline at end of file diff --git a/_site/approach/index.html b/_site/approach/index.html index 5a9e16d..f6328d2 100644 --- a/_site/approach/index.html +++ b/_site/approach/index.html @@ -1,5 +1,5 @@ - +
@@ -8,7 +8,13 @@ - + + + +September 5, 2025
+ +May 28, 2025
diff --git a/_site/bundle.css b/_site/bundle.css index 1c63c07..74f4532 100644 --- a/_site/bundle.css +++ b/_site/bundle.css @@ -140,6 +140,15 @@ h1 { text-align: center; } +pre.mermaid { + text-align: center; + background: transparent !important; + background-color: transparent !important; + border: none !important; + padding: 1rem; /* adjust as needed */ + font-family: inherit; /* removes monospace font if you don't want it */ +} + @charset "UTF-8";/*! * Pico CSS ✨ v2.1.1 (https://picocss.com) * Copyright 2019-2025 - Licensed under MIT diff --git a/_site/contact/index.html b/_site/contact/index.html index 6c45927..e59d160 100644 --- a/_site/contact/index.html +++ b/_site/contact/index.html @@ -1,5 +1,5 @@ - + @@ -8,7 +8,13 @@ - + + + +September 5, 2025
+ +Say you're in the market for a new integration solution and you want to try a few out before committing. Nearly every platform offers demos or trials. But what then? How are you going to decide whether to fully invest (time, money, training) based on a limited trial experience that may not reflect real-world usage?
+In my experience working with clients, demos are polished to look good, but nothing beats hands-on experience. For trials to succeed you need something meaningful to test. Setting up proper test environments often requires at least VPN access, permissions for other environments or cloud services and IT approvals. This can be challenging and time consuming. So it's tempting to fall back on 'foo', 'bar' examples or the Pokemon API. But will this paint a clear enough picture?
+This challenge has led me to build an integration sandbox. The sandbox provides the mock endpoints to test against, so I can test integration flows immediately. My goal was to evaluate how platforms handle common integration patterns:
+By testing these features I expect to gain insight into a platform's general usability:
+Note: This leaves out performance and scalability. Any serious performance testing would require enterprise-scale infrastructure and realistic data volumes beyond this evaluation's scope.
+To test these features in a real world (but somewhat simplified) example, I thought of a use case in Transport and Logistics. Specifically the integration between a Shipper and a Broker.
+Imagine you are a Shipper with a TMS that needs to send orders to a Carrier. The Carrier requires all communication to go through their preferred Broker (visibility platform). +The integration platform sits in the middle, translating the TMS data to the Broker and vice versa.
++ sequenceDiagram + participant TMS as TMS / Shipper + participant IP as Integration platform + participant VP as Broker / Visibility platform + + box transparent Sandbox + participant TMS + end + box transparent Sandbox + participant VP + end + + TMS->>IP: New shipment + IP->>VP: Create order + VP->>IP: New event + IP->>TMS: Create event ++
The sandbox mocks both the TMS and Broker ends of the integration use case and has REST API endpoints to authenticate, seed, trigger, get and create either TMS shipments or Broker events. It's the job of the integrator to make both mock systems work together. Here's an example of a process flow that you can integrate:
+
+flowchart TD
+A@{ shape: circle, label: "start" } --> B
+B@{ shape: rect, label: "get new shipments" } --> C
+subgraph for each shipment
+ C@{shape: lean-r, label: "transform to order"} --> D
+ D@{shape: rect, label: "post order"} --> E
+ E@{shape: rect, label: "log result"}
+end
+E --> F@{shape: diam, label: "success?"}
+ F --> |Yes| G@{shape: framed-circle, label: "End"}
+ F --> |No| H@{shape: rect, label: "Handle errors"}
+
+
+I designed the sandbox with simplicity in mind. It should also be easy to maintain and test for a single developer. I wanted to run it in a container and have the possibility to deploy and use it anywhere. At this stage I'm not really concerned about high performance.
+The mock APIs are built with Python and FastAPI. I chose FastAPI because it goes hand in hand with Pydantic dataclasses and has a complete set of features like security, easy serialisation and deserialisation of json and the automatic generation of swagger docs. The TMS and Broker endpoints both use different JSON payloads that are generated using the Faker library. The generated data is saved in a SQLite database so that I can later validate the incoming transformations against a set of business rules. Users will get a corresponding HTTP response code with the result of their requests. If something fails users get detailed error messages.
+Want to try it yourself? The sandbox is available as a Docker image:
+docker run -d -p 8000:8000 atetz/integration-sandbox:latest
Once running, you can access the API documentation at http://localhost:8000/docs and start building your integration flows immediately. The mapping specifications can be found in the repo!
+I also have it running in AWS Lightsail with minimal effort.
In the next weeks I'm going to put it to the test with Fluxygen, Azure Logic Apps and n8n.
+What do you think? I'd love to hear your thoughts, experiences, or even just a quick hello!
+ +May 28, 2025
Testing out my new Beeline Moto II motorbike navigation, I ran into some compatibility issues with my routes created with the MyRouteApp. Upon inspecting both files I noticed a difference in the gpx file structure. Since a gpx is defined in XML I created small tool using JavaScript and XSLT to convert the MyRouteApp file to a Beeline compatible file. You can find the tool here
+While testing out my new Beeline Moto II motorbike navigation, I ran into some compatibility issues with my routes created with MyRouteApp. Namely, losing the turn-by-turn navigation while going off track. My short roadside frustration turned into a deep dive into GPX files and how to integrate the MyRouteApp format with my Beeline. Upon inspecting both files, I noticed a difference in the GPX file structure. Since a GPX is defined in XML, I decided to make a tool in vanilla JavaScript and XSL that will transform the file for me. And since there are other users with the same issue, I thought it would be nice to share my solution and make it available to anyone that can benefit from it. You can find the tool here

But, I wanted a more minimalistic device in my cockpit and I liked the idea of having my phone in my pocket instead of on my bike in case of an emergency. So after some "very deep research" on YouTube and Google, I naturally found (or was influenced towards...) the Beeline Moto II.
-Fast forward to unboxing and using the Beeline. I was super hyped. I exported my gpx file from MyRouteApp and hit the road. And all went surprisingly well.
+Fast forward to unboxing and using the Beeline. I was super hyped. I exported my GPX file from MyRouteApp and hit the road. And all went surprisingly well.

What on earth? Why is my newest piece of navigation technology not navigating? So I stopped, grabbed my phone and opened the Beeline app. Skipping a waypoint wasn't an option because I only had 1 waypoint. Hmm... I opened my maps app and after memorizing some villages I got back on track and my turn by turn navigation was restored. Sweet!
On my way home my inner problem solver was already working. Did I export my file wrong? Did I forget to check a box on importing?
-Soon I learned that other users had similar issues combining MyRouteApp and Beeline, and that their forum topics hit a dead end. They noted that their route seemed to be converted to a track, and only had a start- and end-point. I also learned that it was impossible to import a Beeline gpx in the MyRouteApp. I tried a couple of things on the MyRouteApp end without success. Then on the Beeline support page I found an article on importing and exporting a gpx with this note:
+Soon I learned that other users had similar issues combining MyRouteApp and Beeline, and that their forum topics hit a dead end. They noted that their route seemed to be converted to a track, and only had a start- and end-point. I also learned that it was impossible to import a Beeline GPX in the MyRouteApp. I tried a couple of things on the MyRouteApp end without success. Then on the Beeline support page I found an article on importing and exporting a GPX with this note:
Please note: you can only edit GPX-imported routes within the Beeline app if you are using the "Waypoints only" import mode. You can learn more about that mode in the article listed above.-
Waypoints only import mode? I didn't see that option at all! But surely my gpx had waypoints? During the creation of my route I added 30 or so...
+Waypoints only import mode? I didn't see that option at all! But surely my GPX had waypoints? During the creation of my route I added 30 or so...
You might be thinking: Why aren't you using the Beeline app anyway? While the Beeline app comes with a route creation functionality, I find the feature set of MyRouteApp superior. I want to skip dirt roads, maximize twisty roads, maximize elevation, toggle different points of interest along the way like petrol stations etc.
-Carrying on with my problem, I created a small test route in the Beeline app and exported a gpx file. Since the gpx file is actually a xml file, I shouldn't have any trouble figuring out what the differences are.
-This is a snippet of the Beeline gpx export without the xml declaration and namespaces:
+Carrying on with my problem, I created a small test route in the Beeline app and exported a GPX file. Since the GPX file is actually a XML file, I shouldn't have any trouble figuring out what the differences are.
+This is a snippet of the Beeline GPX export without the XML declaration and namespaces:
.....
<!-- The route waypoints -->
<wpt lat="47.765573749816014" lon="4.5727777081385605"/>
@@ -93,7 +99,7 @@ Problem
<rtept lat="47.76614" lon="4.57222"/>
.....
-Alright, now let's have a look at the MyRouteApp gpx that I'm importing:
+Alright, now let's have a look at the MyRouteApp GPX that I'm importing:
.....
<rte>
<name>test</name>
@@ -117,10 +123,10 @@ Problem
A few things are going on here:
<wpt> nodes while the MyRouteApp has not.<rte>.<trk>.<rte> segment suspiciously looks a lot like the MyRouteApp <trkseg> because the coordinates are very close to each-other.<wpt> nodes while the MyRouteApp has not.<rte>.<trk>.<rte> segment suspiciously looks a lot like the MyRouteApp <trkseg> because the coordinates are very close to each-other.Both seem to have a different interpretation of the GPX 1.1 Schema Documentation. Looking at the definitions I note 3 things:
Given the definitions and examples above. I find that the Beeline app should be using the rteType instead of individual waypoints for a route. Because that is what it's designed for. Also, the trkType is meant for tracks and it seems Beeline is using rteType for that.
As a good user, I obviously raised a ticket with Beeline, providing as much details as possible. I was then gracefully thanked for my suggestions and informed that my feedback was forwarded up the chain. Great! But knowing that technical feedback like this often gets dismissed as subjective interpretation rather than standards compliance, I knew I had to work on a solution in the meantime.
Knowing the differences between the formats, the workaround was relatively straightforward: I only had to transform the MyRouteApp gpx to a Beeline gpx. To make my MyRouteApp gpx compatible with the Beeline app I decided to:
+Knowing the differences between the formats, the workaround was relatively straightforward: I only had to transform the MyRouteApp GPX to a Beeline GPX. To make my MyRouteApp GPX compatible with the Beeline app I decided to:
<rtept> nodes to <wpt> nodes.<trkseg> to a <rte>.My first test file was hacked together using some good old copy, paste search and replaces.
-Et voila! Upon importing my newly created gpx I was greeted by another option: "Points de cheminement uniquem...". +
Et voila! Upon importing my newly created GPX I was greeted by another option: "Points de cheminement uniquem...".
Which translates to the "Waypoints only import mode" mentioned by Beeline above.

This methods imports the waypoints added in the MyRouteApp but will re-calculate the route in between them. If you want the Beeline to calculate the same or near similar route, I advise you to take an extra 15 min to add waypoints on every main road change. My approach looked like this:

Obviously I wasn't planning on manually editing gpx files every time I wanted to use one of my routes. +
Obviously I wasn't planning on manually editing GPX files every time I wanted to use one of my routes. So I decided to make a tool that will transform the file for me. And since there are other users with the same issue, I thought it would be nice to share my solution and make it available to anyone that can benefit from it. The solution is simple:
You can find the result here
+You can find the result here
My short road side frustration turned into a deep dive into gpx files and how to integrate the MyRouteApp format with my Beeline. While I hope that Beeline will eventually improve their compatibility, in the meantime my tool will provide a practical solution. If you're facing similar issues, give the tool a try and let me know how it works for your routes. Happy riding!
+My short road side frustration turned into a deep dive into GPX files and how to integrate the MyRouteApp format with my Beeline. While I hope that Beeline will eventually improve their compatibility, in the meantime my tool will provide a practical solution. If you're facing similar issues, give the tool a try and let me know how it works for your routes. Happy riding!
May 26, 2025
My goal was to make a simple page that would enable me to write something about myself and what I do. And it should also be a spot where I could share my ideas. I heard about Github pages before and I wanted to give it a go. Naturally I found loads of resources naming jekyll.
-I spun up a repo and tried it out with a simple theme. Soon I noticed that once I wanted to make some changes to the theme, it required some effort to understand and override what the prevous designer intended. Should I just have picked something and call it a day? Maybe.
+I spun up a repo and tried it out with a simple theme. Soon I noticed that once I wanted to make some changes to the theme, it required some effort to understand and override what the previous designer intended. Should I just have picked something and call it a day? Maybe.
But there was also a feeling lingering. I wanted something more minimalistic....
-When I was a teen my "hobby" used to be designing websites. Designing a template in a graphic program, slicing it up in 1px images and using HTML + CSS2.
+When I was a teenager my "hobby" used to be making websites. Designing a template in a graphic program, slicing it up in 1px images and using HTML + CSS2.
Nowadays we have HTML5 and CSS3. I heard great stories about grid and flexbox. Which meant the days of fighting <div> are long gone..
So I decided I'd roll my own. With the help of some usefull libraries/tools:
+So I decided I'd roll my own. With the help of some useful libraries/tools:
- This methods imports the waypoints added in the MyRouteApp but _will
- re-calculate_ the route in between them. If you want the Beeline to
- calculate the same or near similar route, I advise you to take an extra 15
- min to add waypoints on every main road change. My approach looked like
+ This methods imports the waypoints added in the MyRouteApp but
+ will re-calculate the route in between them. If you want the Beeline
+ to calculate the same or near similar route, I advise you to take an extra
+ 15 min to add waypoints on every main road change. My approach looked like
this:

+ sequenceDiagram + participant TMS as TMS / Shipper + participant IP as Integration platform + participant VP as Broker / Visibility platform + + box transparent Sandbox + participant TMS + end + box transparent Sandbox + participant VP + end + + TMS->>IP: New shipment + IP->>VP: Create order + VP->>IP: New event + IP->>TMS: Create event ++ +The sandbox mocks both the TMS and Broker ends of the integration use case and has REST API endpoints to authenticate, seed, trigger, get and create either TMS shipments or Broker events. It's the job of the integrator to make both mock systems work together. Here's an example of a process flow that you can integrate: + +
+flowchart TD
+A@{ shape: circle, label: "start" } --> B
+B@{ shape: rect, label: "get new shipments" } --> C
+subgraph for each shipment
+ C@{shape: lean-r, label: "transform to order"} --> D
+ D@{shape: rect, label: "post order"} --> E
+ E@{shape: rect, label: "log result"}
+end
+E --> F@{shape: diam, label: "success?"}
+ F --> |Yes| G@{shape: framed-circle, label: "End"}
+ F --> |No| H@{shape: rect, label: "Handle errors"}
+
+
+
+1. Scheduler starts the process
+2. Get new shipments from the /tms/shipments endpoint
+3. Split shipments payload into a sequence of single shipments (for each)
+ 1. Perform a data mapping to the broker format
+ 2. Create the order with the /broker/order endpoint
+ 3. Log the result
+4. Check the aggregated results for errors and handle if necessary.
+
+### Technical
+I designed the sandbox with simplicity in mind. It should also be easy to maintain and test for a single developer. I wanted to run it in a container and have the possibility to deploy and use it anywhere. At this stage I'm not really concerned about high performance.
+
+The mock APIs are built with Python and [FastAPI](https://fastapi.tiangolo.com/). I chose FastAPI because it goes hand in hand with Pydantic dataclasses and has a complete set of features like security, easy serialisation and deserialisation of json and the automatic generation of swagger docs. The TMS and Broker endpoints both use different JSON payloads that are generated using the [Faker](https://faker.readthedocs.io/en/master/) library. The generated data is saved in a SQLite database so that I can later validate the incoming transformations against a set of business rules. Users will get a corresponding HTTP response code with the result of their requests. If something fails users get detailed error messages.
+
+### Get started
+Want to try it yourself? The sandbox is available as a Docker image:
+`docker run -d -p 8000:8000 atetz/integration-sandbox:latest`
+
+Once running, you can access the API documentation at `http://localhost:8000/docs` and start building your integration flows immediately. The mapping specifications can be found in the [repo](https://github.com/atetz/integration-sandbox/tree/main/docs/integrations)!
+I also have it running in AWS Lightsail with minimal effort.
+
+### What's next?
+In the next weeks I'm going to put it to the test with [Fluxygen](https://fluxygen.com/), [Azure Logic Apps](https://azure.microsoft.com/en-us/products/logic-apps/) and [n8n](https://n8n.io/).
+
+What do you think? I'd love to [hear your thoughts](https://data-integration.dev/contact/), experiences, or even just a quick hello!
\ No newline at end of file
diff --git a/todo.md b/todo.md
index 614fdd5..cd8f29f 100644
--- a/todo.md
+++ b/todo.md
@@ -25,4 +25,8 @@
- My role & tools used (e.g. “Designed a serverless ETL pipeline using AWS Lambda and Step Functions”)
- Impact or outcome (e.g. “Reduced data latency by 80%”)
- Blog
+ - Intro to integration-sandbox
+ - Solve problem with Fluxygen
+ - Solve problem with Azure Logic Apps
+ - Solve problem with n8n
~~- Contact~~
\ No newline at end of file