Project Overview
ECAM.ai is an app built for security monitoring at Gardaworld. It provides video event monitoring, AI-powered vehicle detection, and additional functionalities through a network of IoT devices and cameras deployed across North America, delivering real-time updates to client applications.
My Role on the Project
When I joined, the project was in its early development stages with a small team. Initially hired as a Full-Stack Developer, my primary focus was on building and maintaining the website and its API. Over time, I transitioned into a more frontend-focused role while continuing to contribute as a Full-Stack Developer, leveraging my strong frontend expertise within a predominantly backend-oriented team.
In this capacity, I spearheaded the development of a new mobile application using React Native from the ground up, led the "UI v2" website redesign initiative, and engineered complex components to support key product features.
My Challenges & Solutions
Defining a standard and UI components for "UI v2"
Choosing a standard is hard. You have to balance the pros & cons and have to make sure your team is onboard with your plan.
The first bases of that plan was "how should we structure our code from this point forward?" and "what technologies should we keep or add?". At this point, we've all had some pain points about the codebase, but knew we didn't want to rewrite everything and we also didn't have the time or resource for a whole new project. So we kept our original codebase and added the new stuff prefixed with a lot of "new" to differenciate new components from old ones.
For state management, we initially relied solely on React Query. However, during the rewrite, we transitioned to tRPC & Reat Query, which provided significantly faster development and unparalleled type safety. This was crucial for our team, enabling us to build and deploy new features more efficiently.
For component development, I leveraged Radix UI, which enhances accessibility and provides a seamless user experience for Accessible Rich Internet Applications (ARIA). One of its most valuable features is the Slot component, which allows for flexible composition without replacing the underlying element.
This was particularly useful for our common Button component. Depending on the context, the button could be rendered as a <button>
, an <a>
, or, in the case of Next.js, a <Link>
. With Radix Slots, we could dynamically override the button node with any clickable (or non-clickable) component, ensuring greater flexibility and maintainability across the application.
Hacking React to bypass it's slow render function
React is an excellent choice for building websites, offering fast performance, seamless user interactions, and an efficient component-based architecture that enhances both quality and productivity. However, React struggles with rendering large amounts of content and handling frequent updates efficiently.
In two key features I developed, I had to implement workarounds to optimize performance and ensure a smooth user experience across all devices. These solutions involved strategically "hacking" React to overcome its limitations in high-update and heavy-rendering scenarios.
Leaving React and simply using the browser APIs
The most challenging feature was the infinitely scrollable timeline, which was implemented as an SVG and animated in JavaScript based on the current time. Every time marker, text element, and other visual component had to be continuously updated to animate smoothly across the timeline. Additionally, elements needed to be dynamically removed when they went out of view and added when they came into view—either due to the passage of time or user interactions such as dragging the timeline horizontally.
This required handling hundreds to thousands of updates per second, a workload that would have quickly overwhelmed React’s rendering capabilities. To maintain performance and ensure a smooth experience, I had to develop an optimized approach that bypassed React’s virtual DOM for critical updates, reducing unnecessary re-renders while keeping the UI responsive.
Leveraging powerful, but not commonly known React tools
For the scheduling feature, I implemented a highly efficient schedule picker using useSyncExternalStore
, a React hook designed for subscribing to external state outside React’s lifecycle. Typically, React triggers re-renders when state updates immutably, which, while maintaining predictability, also increases memory usage due to duplication.
In this case, the schedule picker required managing 336 individual input states (48 slots per day across a full week). Using traditional state management like useState
would cause excessive re-renders, significantly impacting performance.
To optimize this, I leveraged useSyncExternalStore
with a mutable state array, avoiding unnecessary memory duplication. Instead of triggering a full component re-render on every state change, each component subscribes only to its relevant index and updates when necessary. This approach minimized re-renders, reduced memory overhead, and resulted in a much smoother user experience.
Performant data aggregation via processing caching
To effectively monitor device uptimes and track outages, I developed a solution to extract and analyze downtime from ping logs. Since querying and processing thousands of logs per device in real time would be highly inefficient, I implemented a caching mechanism to optimize performance.
Inspired by GitHub’s repository insights model, I designed a three-part API:
Sync Check
Determines whether the cached data is up to date.
Processing Endpoint
If the sync is out of date, this process runs from the last recorded state, appending new data to the existing cache instead of reprocessing everything.
Data Retrieval
Queries are made directly from the cache, significantly reducing computation time.
This approach ensures that data remains fresh while minimizing redundant processing. The system periodically reprocesses logs when the cache becomes stale, maintaining an efficient and scalable solution for tracking device uptime.