Building a chart is easy when the data is simple. This wasn’t simple data.
The application needed to present thousands of data points representing mission activity in a way that operators could explore without being overwhelmed by everything happening underneath. The challenge wasn’t simply choosing a chart library and putting points on a screen. It meant deciding what information should be visible, how users should interact with it, how the backend should structure it, and how the application could remain responsive as the amount of information increased.
My role crossed several of those boundaries. I helped shape the visualization itself, worked on the structure of the data feeding it, improved the surrounding interface, and solved some less obvious problems that surfaced once we tried to run everything consistently inside our development environment.
Designing for the Information, Not the Data
One of the first problems was scale.
There could be thousands of individual points available for a plot and it looked messy to render all of them at once, I recommended that individual points remain hidden until the user zoomed into the chart far enough for them to become useful. The client accepted the approach, and I implemented it so the points appeared as the user moved deeper into the data.
I also increased the size of individual points as the user zoomed in. Besides making them easier to select and inspect, the effect created a subtle sense of depth as the visualization changed scale.
Just because the application can show everything at once doesn’t mean the user should have to understand everything at once.
That became an important principle for the work. The goal wasn’t to expose as much data as possible. It was to expose the right amount of information at the right moment.
Making the Data Easier to Consume
I helped structure the response coming from the backend API so the frontend didn’t have to repeatedly reshape the same information for different charts. Rather than allowing each visualization to invent its own interpretation of the response, we established a predictable structure that could be consumed consistently across the application.
That meant a single frontend component could handle the same general data shape while adapting to different chart configurations.
It also reduced the amount of transformation happening in the browser. The frontend became simpler because the contract between the backend and frontend became clearer.
That work reinforced something I’ve found repeatedly in application development: sometimes the best way to simplify the frontend isn’t to write cleverer frontend code. It’s to improve the boundary between the systems.
Solving a Problem That Wasn’t Supposed to Be Mine
One of the more interesting problems had almost nothing to do with chart design.
The application was developed and deployed using Docker, and we encountered a significant issue: the charts simply wouldn’t render correctly inside the container.
The team had already spent considerable time investigating it. At one point, we were close to abandoning the work and moving to a different charting solution.
I kept digging.
Eventually, I traced the problem to differences in how the required NPM dependencies were being resolved inside Docker compared with our local development environments. The charting library depended on a particular module configuration, and the container wasn’t reproducing the environment we thought it was.
I found that the actual problem didn’t respect the boundary between “frontend” and “infrastructure.” Solving it required following the evidence until I understood what was actually happening. So, instead of replacing weeks of work, I changed the Docker configuration so the container used its own appropriate NPM installation rather than depending on assumptions inherited from the local environment.
The charts worked.
Simplifying a Complicated Interface
The application also contained a hierarchical configuration manager with parent and child selections spread across a tree. The original implementation repeatedly traversed portions of that structure, which made the code harder to reason about and created unnecessary processing.
I refactored that logic so the hierarchy could be processed in a single pass which reduced repeated looping, simplified the implementation, and made the configuration manager easier to maintain. Because the application already knew where changes needed to occur, it no longer had to continually rediscover the same relationships.
I also developed a flexible filtering experience that could work across multiple branches of the tree. Together, those changes made a complicated configuration interface feel considerably more immediate from the user’s perspective.
Building for an Operational System
This wasn’t a visualization living on a marketing dashboard. The system supported mission operations, which changed how I thought about the work.
Reliability had to be designed from the start.
Failures needed to be understandable. Logging, monitoring, recovery, and performance under concurrent scheduling activity all mattered.
I worked with stakeholders to translate those operational needs into clear service contracts, while improving the observability needed to understand when something went wrong.
What I Took Away From It
By the end of the project, my contribution went well beyond implementing portions of a Chart.js interface. I had helped shape how information was presented, how data moved between systems, how complex configuration was managed, and how the application behaved in the environment where it actually had to run.
A few lessons from that work have stayed with me:
- Design for clarity first. More information isn’t necessarily more useful information.
- Good API design is also frontend design. A predictable data contract eliminates complexity everywhere downstream.
- Performance problems are often structural. Removing unnecessary work is usually better than making unnecessary work faster.
- Follow problems across boundaries. A frontend failure can originate in a container, dependency tree, API contract, or somewhere else entirely.
- Observability belongs in the design. Reliable systems need to explain what they’re doing when things don’t go according to plan.
- Stakeholder communication is engineering work. Understanding what someone actually needs is every bit as important as implementing it correctly.
The project reinforced something I value about software development: the most satisfying solutions aren’t necessarily the ones with the most sophisticated code. They’re the ones where a complicated system becomes easier for someone else to understand and use.
And in this case, that was the entire point.
More Case Studies
Different problems. Different constraints. The same goal: make the complicated parts simpler.
Have a Complicated Problem of Your Own?
If you’re working with an application that’s difficult to understand, data that’s difficult to present, or a system that’s accumulated more complexity than anyone intended, I’d be happy to hear about it. You don’t need to have the solution figured out—that’s part of what I enjoy about the work. Send me a message below or reach me directly at mitchell@betavc.com