The Inspection Platform
Building software that inspectors actually wanted to use
When we finished the mission planner and the processing pipeline, we finally had an end-to-end system.
The drone could execute repeatable missions.
Thousands of images could be uploaded and processed automatically.
Every image could be correlated to the correct inspection asset.
From a systems perspective, we had something we were proud of.
The next challenge wasn't making the platform more capable.
It was making it more useful.
Our goal was never to build an image viewer.
It was to build a tool that inspectors would actually want to use.
Every inspection followed the same flow.
Pilots collected the data in the field.
The media was uploaded automatically.
Our backend processed everything.
A new inspection appeared in the platform, ready for review.
The inspector opened the inspection, reviewed the images, annotated anomalies, and generated a report.
The workflow itself was simple.
Designing an experience that supported it wasn't.
As inspectors started using the platform, one limitation became obvious.
Our correlation pipeline correctly identified which asset every image belonged to, but that alone wasn't enough to review an inspection efficiently.
An electrical transformer isn't a single object.
It's made up of dozens of connectors, insulators, terminals, and other components, often photographed from different angles.
Knowing the asset without understanding the camera's perspective still left room for uncertainty.
Inspectors needed context.
Fortunately, we already had most of the information required.
The drone's position.
The camera orientation.
The orthophoto.
The correlated asset.
By combining those pieces, we could recreate the camera's position inside the map and show exactly where the drone had been looking when the image was captured.
It wasn't the most technically impressive feature we built.
It ended up being one of the features inspectors appreciated the most.
Sometimes helping users understand their data is more important than giving them another tool.

After we started building features like the virtual camera preview, something else became clear.
Many of the features we wanted to build weren't limited by frontend or backend development.
They were limited by how well we understood the drone itself.
Every new capability raised questions about what information was actually available.
What metadata did each image contain?
How accurate was the GPS position?
What exactly did DJI expose through the SDK?
What assumptions could we safely make?
As a full-stack team, those questions affected everyone.
Frontend engineers needed to know what data they could rely on to build meaningful experiences.
Backend engineers needed to understand what could be extracted during processing and what required talking directly to DJI's SDK.
Many product discussions ended up becoming technical discussions about the capture pipeline itself.
Somewhere along the way, I naturally became the person people came to with those questions.
I had spent enough time reading DJI's documentation, experimenting with the SDK, inspecting metadata, and trying to understand how the drone actually produced its data that I could usually explain where the platform's capabilities ended and its limitations began.
That became especially important once we started working with thermal imagery.
Thermal images introduced a completely different set of constraints.
We were using the DJI Mavic 3T, which stores thermal captures as Radiometric JPEGs (RJPEGs).
Unlike a normal image, an RJPEG doesn't just contain colors. It also contains the thermal measurements needed to calculate temperatures for every pixel.
The catch was that DJI only exposed those calculations through their native SDK.
There was no documented file format we could fully decode ourselves.
If we wanted accurate temperatures—or even thermal corrections—we had to use their native libraries.
We explored a few alternatives.
One idea was to extract everything during backend processing and persist the thermal information alongside the image. That worked for part of the data, but not all of it. Some corrections depended on information the SDK calculated internally, which meant we couldn't faithfully reproduce the same results ourselves.

At that point, the discussion shifted from "How do we avoid the SDK?" to "How do we build a good system around it?"
The solution we settled on was far from ideal.
The frontend requested thermal data from our backend, the backend invoked the DJI SDK, applied the required corrections, and returned the resulting thermal matrix.
Every request involved executing native code, waiting a few seconds, and transferring several megabytes of floating-point data back to the browser.
It worked.
It just wasn't the architecture we would have designed if we controlled the file format.
This became a team effort. We spent a lot of time discussing where the SDK should live, what could be cached, and which parts of the processing could realistically be moved out of the request path.
Around that time, Vitor Lopes had recently joined the team as a junior engineer. Despite being early in his career, he ended up taking ownership of one of the most difficult integrations in the platform.
In hindsight, I probably underestimated how challenging that problem really was. It wasn't simply about exposing an API—it was about designing a reliable system around a proprietary SDK that behaved like a black box and left us very little room to optimize.
We worked through the design together, discussing the SDK's limitations and the trade-offs we had available. From there, Vitor led the implementation, building a reliable integration and introducing a caching strategy that significantly reduced repeated processing, making the experience much smoother for inspectors.
Something else became increasingly clear throughout the project.
Building multidisciplinary software isn't just about writing code.
Pilots understand how inspections happen in the field.
Inspectors understand what information they need to make decisions.
Software engineers translate those requirements into software.
And sometimes someone needs to bridge the gap between hardware capabilities and software expectations.
I found myself doing that more and more as the project evolved.
Not because I knew everything about drones, but because I had spent enough time exploring the edges of the platform to understand where its capabilities ended and its limitations began.
Helping the rest of the team navigate those constraints became just as important as implementing new features.
By the time we finished the platform, I had stopped thinking about it as a frontend application.
It was simply the last stage of the inspection pipeline.
Every feature existed because of a decision that had been made much earlier—during mission planning, media processing, image correlation, or thermal handling.
Looking at the project as a whole, that's probably what I appreciate most.
None of the individual pieces were particularly valuable on their own.
The value came from how they fit together.