Back to all posts
36 curated articles

The Architecture Playbook

Frontend spent a long time being treated as the part of the codebase that didn’t need real architecture — FSD exists because that stopped being true. This is a reading path through every architecture-focused piece on this site, pulled out of the React Playbook and the rest of the blog and regrouped around the decisions themselves: boundaries, state, rendering, and what happens when a real product puts them under load.

Why Architecture at All

5 articles

Frontend spent years being treated as "not real architecture." This is the case that it is.

  1. 8 min read

    The Smeared Component: When Architecture Scatters What Should Stay Together

    FSD is one of the best frontend methodologies out there. Used without thinking, it turns a complex component into a scavenger hunt across eight folders. Here's what I learned.

  2. 12 min read

    Code Structure in React: The FSD Version I Actually Use

    Flat folders are fine until every feature starts touching routes, queries, forms, permissions, and UI state. Here's the React structure I use when a TanStack app grows past the simple stage without turning FSD into folder theater.

  3. 11 min read

    The shared/ Folder Is Not a Place, It's a Promise

    Every codebase grows a shared/ folder, and given enough time every shared/ folder becomes a junk drawer. Not because the team got lazy — because the folder was never given a rule. Here's why it rots, and how to keep it boring.

  4. 12 min read

    The Direction of the Arrows: Dependencies Are Your Real Architecture

    You can draw whatever folder diagram you like. The honest picture of your app is which module imports which — the direction of the arrows. Get that wrong and no folder structure will save you.

  5. 10 min read

    Barrel Files: The Import You Love and the Bundle You Hate

    A barrel file makes imports look beautiful and can quietly drag half your app into a bundle that only needed one function. Here's what index.ts actually does, when it earns its place, and when it's a trap wearing a clean interface.

Boundaries & Composition

6 articles

Where one piece ends and another begins, and how that boundary survives contact with a deadline.

  1. 12 min read

    How Big Should a Component Be? Composition, Decomposition, and Handing Over Dependencies

    Split a component too early and you get a maze of tiny files. Split too late and you get a 600-line monster. The real question isn't size — it's who owns which dependency, and whether the component reaches for it or is handed it.

  2. 11 min read

    Is Container vs Presentational Dead? What Survived the Hooks Era

    The pattern that taught a generation to split 'smart' from 'dumb' components got quietly declared obsolete when hooks arrived. It wasn't. The folder convention died. The idea underneath it is more useful now than ever — including in Server Components.

  3. 11 min read

    Compound Components: Designing an API, Not Just a Component

    The moment a component grows past a handful of props, you're not writing a component anymore — you're designing an API. Compound components are how you keep that API flexible without drowning it in configuration props.

  4. 11 min read

    Headless Components: Give Away the Behavior, Keep None of the Markup

    The most reusable UI code I write renders nothing at all. Headless components, render props, and hooks-as-API are three names for one idea: separate what a component does from how it looks — and hand over the behavior without a single opinion about the markup.

  5. 11 min read

    Changing a Component Everyone Uses: Deprecation, Codemods, and No Big-Bang Rewrites

    Writing the new version of a shared component is the easy 10%. The other 90% is the hundred call sites that already depend on the old one — and the fear of touching them. Here's how I change a component everyone uses without a month-long rewrite that breaks the day it lands.

  6. 12 min read

    Keeping a UI Kit Updated Across Apps: Versioning, Contracts, and Trust

    A shared UI kit does not fail because the button component is hard to write. It fails when five applications are afraid to upgrade it. Versioning, contract tests, release channels, and migration paths are what turn a component library from a dependency into a product people can trust.

State & Data Architecture

7 articles

Where state actually lives, what persists, and how far you can push it before it turns to mud.

  1. 12 min read

    Server State Is a Cache: Normalization, Duplicates, and Invalidation You Can Trust

    The same customer shows up in a list, a detail page, and a header badge — three copies of one truth you don't own. Edit one and the others go stale. Here's when to normalize server data into one source of truth, when the query cache is enough, and how to invalidate without nuking everything.

  2. 11 min read

    localStorage Is Not State: Persistence, Hydration, and Tabs That Fight Each Other

    localStorage looks like a global variable that survives a refresh. That framing is the bug. Treat it as a persistence layer that mirrors your state — not as the state itself — and the hydration mismatches, stale tabs, and schema breakages mostly disappear.

  3. 11 min read

    Optimistic UI: Updating Before the Server Says Yes

    Optimistic UI is a small lie: you show the result before the server confirms it. Done right, the app feels instant. Done wrong, the UI quietly tells the user something that never happened. The difference is entirely in how you roll back.

  4. 12 min read

    Undo/Redo Without Losing Your Mind: The Command Pattern in React

    The instinct is to snapshot your whole state on every change and step backward through the copies. It works until it doesn't. A history of reversible commands scales further, describes what actually changed, and survives contact with a server. Here's how I build undo/redo that doesn't fall apart.

  5. 12 min read

    State Machines in React: When Booleans Start Lying to You

    isLoading, isError, isSuccess, isEditing — five booleans give you thirty-two combinations, and most of them are impossible states your code still has to survive. A state machine makes the impossible ones unrepresentable. Here's when to hand-roll one and when to reach for XState.

  6. 11 min read

    Immutable Data in React: The Rule I Stopped Arguing About

    A module I was told not to over-engineer grew into an entire application. Most of what let it survive was boring — and one of the most boring rules was never mutating state in place. Here's how immutability actually works in React, when I reach for Immer, and why I skip Immutable.js.

  7. 13 min read

    React State Management with Reatom: When useState Stops Being Enough

    Most React state doesn't need a library. Then one workflow grows into drafts, derived values, undo, optimistic steps, and cross-component coordination. This is where I reach for Reatom instead of turning TanStack Query into a client-state store.

Rendering & Delivery

7 articles

Decisions that look like performance tuning but are actually architecture wearing a disguise.

  1. 13 min read

    SSR in React: What TanStack Start Actually Changes

    Server rendering isn't a performance checkbox — it collapses the wall between frontend and backend into one framework. Here's what SSR really buys you, why the client/server line stops being where you think it is, and where TanStack Start fits next to Next.js.

  2. 11 min read

    Code-Splitting Is a Boundary Decision, Not a Bundle Trick

    Every performance guide tells you to lazy-load. Almost none tell you where to stop. Split on your file tree and you trade one big bundle for a hundred tiny chunks and a waterfall of spinners. The real question isn't how to split — it's finding the seams in the user's journey and cutting there.

  3. 13 min read

    Re-Renders Are React's Superpower, Not a Disease to Cure

    There's a particular panic I keep running into: a component re-rendered, someone saw it in the profiler, and now they're tearing the architecture apart to stop it. But rendering isn't React's flaw — it's the whole idea. The word you want is optimize, not minimize, and the difference decides whether your app stays maintainable.

  4. 11 min read

    Theming and Dark Mode Without the Flash: A Systems Problem in CSS Clothing

    Dark mode looks like a class you toggle. Then you meet the flash of the wrong theme on load, colors that drift because every component hardcodes its own, and a theme context that re-renders the whole app. Theming done right is tokens, one switch point, and a boundary — and it barely touches React at all.

  5. 11 min read

    The Command Palette Is an Architecture, Not a Widget

    Cmd+K looks like a fuzzy-search modal you bolt on at the end. Build it that way and it immediately drifts out of sync with the buttons and menus it duplicates. The real thing is a command registry: one typed source of truth for everything the app can do, feeding the palette, the shortcuts, and the menus at once.

  6. 10 min read

    Most Advanced TypeScript Isn't Worth What It Costs

    There's a point where a type stops protecting you and starts being a puzzle you have to solve again every time you touch it. I'm not a type wizard and I've stopped trying to be one — because on real React codebases, the complexity that pays for itself is a much shorter list than the internet suggests.

  7. 13 min read

    Authentication in React: Buy It, and Where the Line Really Is

    Auth looks like a login form and turns out to be an architecture decision. Where do tokens live, who guards a route, what happens when the session dies mid-request? Here's why I buy auth instead of building it, and the parts that stay yours no matter what you buy.