Skip to content
Anderson Rocha

work / 02BairesDev

Tree Navigation with Optimistic Sync

Role
Senior Frontend Engineer
Company
BairesDev
Period
2025–2026
Stack
React · TypeScript · Next.js · React Query · Jest · Stripe · GraphQL
Impact
~34% improvement in perceived responsiveness; frontend unit test coverage raised to ~80%.

Context

Through BairesDev, I worked as Senior Frontend Engineer on an AI-driven SaaS platform — a product that analyzes web pages and documents and generates structured insights from them. This study covers the architecture and the reasoning, not the product.

The central frontend problem was organization at scale. Users accumulate large collections of analyzed documents, and the product needed a real hierarchy: nested folders and files, drag-and-drop, and recursive operations — move a folder and everything beneath it moves with it; delete one and the subtree goes too. Every one of those operations had to feel immediate while the actual work happened over the network. The same codebase also carried the platform's monetization: subscription and billing flows that had to be correct before they were fast. I led the frontend architecture for this work.

Decisions

Treat the tree as server state, not UI state. The hierarchy lives in the React Query cache as the single source of truth, and every component renders from it. The alternative — mirroring the tree into local component state — is simpler on day one and drifts out of sync the first time a recursive operation touches nodes in two places at once. Centralizing in the cache made invalidation and background synchronization mechanical instead of ad hoc.

Optimistic first, reconcile after. Drag a folder and the UI commits the move instantly; React Query synchronizes with the server in the background and rolls the tree back if the mutation fails. The trade-off is real: rollback for a recursive operation is harder to get right than a loading spinner, because a failed move has to restore an entire subtree, not one row. We accepted that complexity because the alternative — blocking every drag on a network round trip — made the product feel broken even when it was working. Perceived interaction responsiveness improved by ~34% after the optimistic UI work.

Hybrid SSR/CSR rather than picking a side. Next.js renders the public, SEO-relevant surfaces on the server; the authenticated workspace runs as client-rendered application code, lazy-loaded and code-split so the initial payload stays small. Two rendering modes in one codebase demand discipline about where data loads, but the split improved initial load performance and search visibility without dragging the interactive tree through server round trips.

Buy the insurance before it is needed. Recursive operations plus optimistic rollback produce a wide surface of edge cases, so I pushed frontend unit test coverage to ~80% with Jest and TDD. TDD costs velocity in the week you adopt it and pays it back every week after.

optimistic tree — live demo

Simulated network

sidebar nav

  1. ready — drag a file or folder, or use its move menu

Impact

The numbers that can be stated: perceived interaction responsiveness improved by ~34% after the optimistic UI work, and unit test coverage reached ~80%, with a corresponding drop in regression bugs reaching production. Qualitatively, the hybrid rendering architecture improved initial load performance and SEO, and the Stripe subscription and billing flows — built end to end, APIs and webhooks — gave the platform recurring revenue on top of secure payment processing. Alongside the feature work, I mentored frontend engineers and delivered structured training for the internal internship program.

Stack notes

React and TypeScript form the tree system itself; the component API leans on the type system to keep recursive structures honest. React Query handles caching, invalidation, and background sync — it is the reason optimistic updates stay tractable rather than becoming hand-rolled state machines. Next.js provides the hybrid SSR/CSR split, with lazy loading and code-splitting doing the initial-load work. Jest carries the unit suite. Stripe APIs and webhooks drive subscriptions and billing. API contracts with the backend were defined across GraphQL and REST, which improved data consistency between the UI and the services behind it.