Stack Innovations / Services / Web / Remix

Remix, where the network is the runtime.

Most React stacks treat the network as an afterthought — useEffect, a spinner, fingers crossed. Remix puts the request first: nested routes load loader data in parallel on the server, <Form> + action handles every mutation, and adapters let the same code ship to Vercel, Cloudflare, Node, Deno, Bun.

01 — In numbers

Five years shipping
nested routes at scale.

Each stat is a typed Remix loader. Hover any to see the function signature. Counters scrub with scroll — same primitives we use in production.

loader: projects
0+ Remix apps shipped
export async function loader() {
  return json({
    shipped: 28,
  })
}
loader: routes
0+ Nested routes composed
export async function loader() {
  return json({
    routes: 5400,
  })
}
loader: adapters
0/9 Adapters in production
export async function loader() {
  return json({
    adapters: 9,
  })
}
loader: useEffectFetches
0 useEffect data fetches
export async function loader() {
  return json({
    spinners: 0,
  })
}
02 — What we build

A full-stack Remix practice.

Click an entry on the left — the active capability opens in the Remix DevTools-feeling editor. Each pane is a working pattern we've shipped.

Stack · Remix 2.x ~/stack/remix/app/routes/_index.tsx vite · ready R S
app/routes file-based · nested · layouts SHIPPED

Nested routes & layouts, URL is the architecture.

uid: routes.nested updated: 09:42 today by: stack-eng
summary · what this gets you

Flat-file routing with dot-segmented filenames: posts.$slug.tsx nests inside posts.tsx nests inside _layout.tsx. Each level keeps its own loader, header chrome, error boundary. Navigating between siblings only re-runs the loaders that actually changed.

items · what we customize
  • _layout.tsx · pathless wrappers
  • $param.tsx · dynamic segments
  • ($optional).tsx · i18n-ready
  • <Outlet /> with shared chrome
  • handle exports for breadcrumbs
loader() parallel · typed · cacheable SSR

Loaders & data fetching, parallel by default.

uid: data.loaders updated: yesterday by: stack-eng
summary

Each route exports a loader. On navigation Remix runs all matched loaders in parallel server-side, returns JSON for the client, hydrates without a single useEffect. defer() streams slow data via <Await /> so the shell paints first. Cache headers from headers().

items
  • useLoaderData<typeof loader>()
  • defer({ slow: promise })
  • <Await resolve={slow}>
  • headers() · CDN tagging
  • shouldRevalidate · skip on hop
action() FormData · Request · Response SERVER

Actions & mutations, web-standard FormData.

uid: data.actions updated: 2d ago by: stack-eng
summary

Mutations are POSTs. action() receives a real Request, parses formData(), validates with Zod, writes, returns redirect() or JSON. After an action all loaders on the page automatically revalidate — UI is fresh without state-management gymnastics.

items
  • request.formData()
  • Zod validation · typed payload
  • redirect() · PRG by default
  • useActionData() · field errors
  • Auto-revalidation post-mutation
<Form /> progressive · useFetcher · optimistic JS-OPTIONAL

Forms & pending UI, works without JS.

uid: ui.forms updated: 4d ago by: stack-eng
summary

<Form> is just an HTML form — with JS off, the browser submits it the normal way. useFetcher lets you submit without navigating (likes, follows, inline saves). useNavigation() exposes the in-flight intent so pending UI is one hook, not a state machine.

items
  • <Form method="post">
  • fetcher.submit(formData)
  • navigation.state · idle / loading / submitting
  • fetcher.formData · optimistic input
  • List of fetchers for parallel mutations
ErrorBoundary per-route · nested · isolated RESILIENT

Error boundaries, scoped to the route.

uid: ui.errors updated: 1w ago by: stack-eng
summary

Each route can export an ErrorBoundary. A loader throws — only that segment's UI swaps to the error view; the parent layout, nav, and surrounding content stay rendered. Both runtime errors and explicit Response throws (404, 401, 500) route here. Source maps in dev show the actual server stack.

items
  • throw new Response("Not found", { status: 404 })
  • useRouteError() · typed
  • isRouteErrorResponse() guard
  • Sentry / OTel hooks in entry.server
  • Friendly fallbacks per route
session cookie · flash · CSRF SECURE

Sessions, cookies, auth, HTTP, not localStorage.

uid: auth.session updated: 2w ago by: stack-eng
summary

Sessions ride a signed, HTTP-only cookie — no client tokens floating around localStorage. createCookieSessionStorage handles the round-trip; flash messages survive one redirect; OAuth + Remix-Auth slot in cleanly. Per-runtime backends: KV on Cloudflare, durable on Node, in-memory in tests.

items
  • createCookieSessionStorage()
  • HTTP-only, SameSite, Secure
  • session.flash() for one-shot UI
  • CSRF token via hidden field
  • Multi-strategy auth via remix-auth
03 — loader → waterfall

Pick a loader strategy.
Waterfall updates.

This is what makes Remix itself: nested routes load in parallel, not waterfalled like client-fetch React. Click each route's loader pill — toggle await, defer, or none. The waterfall on the right rebuilds, TTFB and total payload recompute, and the rendered page on the far right swaps in skeletons or streamed chunks accordingly.

request waterfall parallel
ttfb 0ms
full load 0ms
payload 0kb
rendered /posts/welcome
04 — Why us

Stack Innovations vs the typical Remix build.

Same framework, two very different ways it ends up shipping. Eight criteria your team will actually feel — in plain English, with the receipts.

  1. 01

    Performance

    × Typical
    68/100
    Lighthouse, mobile

    Default config plus a SPA-shaped client bundle. Mobile feels every kilobyte and every spinner.

    Stack Innovations
    100/100
    Lighthouse, mobile

    Lighthouse 100s as a starting line. CI fails the build on any regression.

  2. 02

    Data fetching

    × Typical
    3 hops
    waterfalled in the browser
    useEffect spinner retry parallel streamed

    Each component fetches on mount. Nested routes stack spinner on spinner before the page is usable.

    Stack Innovations
    1 round-trip
    parallel loaders, server-side
    loader parallel defer streamed typed

    All loaders fire in parallel on the server, page paints with data. Slow bits stream in via defer().

  3. 03

    Mutations

    × Typical
    ?
    "how should we manage state?"

    Custom hooks, Redux thunks, optimistic-then-rollback ladders. Errors and revalidation logic re-invented per page.

    Stack Innovations
    <Form />
    browser-native, server-handled

    Mutations are forms. Action runs server-side, all loaders revalidate, UI is fresh. Optional optimistic via useFetcher.

  4. 04

    SEO

    × Typical
    0/4
    coverage at launch
    × Sitemap × JSON-LD × Per-route meta × OG images

    Bolted on as a follow-up engagement. The "we'll get to it" version of SEO.

    Stack Innovations
    4/4
    shipped at launch
    Sitemap JSON-LD Per-route meta() OG images

    Sitemaps, structured data, per-route meta(), Open Graph images — live on day one.

  5. 05

    Deployment

    × Typical
    1 runtime
    picked once, hard to leave
    Vercel Cloudflare Netlify Node Deno Bun Fly.io

    Switching providers later means rewriting deploy pipelines and parts of the app.

    Stack Innovations
    9 adapters
    portable by default
    Vercel Cloudflare Netlify Node Deno Bun Fly.io

    Same code ships to any of them. Switching adapters is a one-file change in entry.server.

  6. 06

    Migration

    × Typical
    ×
    "out of scope"
    Old SPA New site

    You move the routes yourself. Links break, search rankings drop, customers hit 404s.

    Stack Innovations
    mapped
    redirects + SEO continuity
    CRA / Next / Rails Remix

    Route inventory, redirect map, content port, dry-run, cutover. SEO continuity holds.

  7. 07

    Editor handoff

    × Typical
    0/4
    onboarding artifacts
    × Walkthroughs × Role setup × Dry runs × In-app help

    "Good luck with the admin." Editors learn by trial and error in production.

    Stack Innovations
    4/4
    shipped with the site
    Loom walkthroughs Role setup Dry-run publishes In-context help

    Editors leave training feeling fluent. First publish goes through without a Slack ping.

  8. 08

    Care plan

    × Typical
    0 mo
    post-launch coverage
    launch silence

    Hand-off, then silence. Six months later you're two majors behind on Remix.

    Stack Innovations
    monthly cadence
    launch m+1 m+2

    Monthly version bumps, perf monitoring, real Slack channel. Features, not tickets.

05 — Adapters

One app,
any runtime.

Remix's adapter layer compiles your app to runtime-native output. Same routes, same loaders, same actions. Click any adapter — entry.server.tsx swaps to that runtime, regions and cold-start metrics update, and the build command changes. No code changes anywhere in app/.

remix adapter same code, any runtime
runtime edge-runtime
cold start ~30ms
edge regions 119
bundle size 2.1 MB
$ npm i @vercel/remix && remix vite:build


      

    Adapters are a thin layer that translates the runtime's request shape into a web-standard Request object Remix can read. Everything in app/ — loaders, actions, routes — stays untouched. The only difference between deployments is one file in server/.

    06 — How it ships

    Six weeks,
    routes first.

    1. w 01

      Audit + route inventory

      Inventory every URL. Map each to a Remix route file. Lighthouse + TTFB baseline. Pick the adapter for the runtime.

    2. w 02

      Remix scaffold

      Remix + Vite + TypeScript, design tokens, app/root.tsx, layouts, session storage, error boundaries, meta() baseline.

    3. w 02–04

      Loaders, actions, components

      Routes, layouts, typed loaders, actions with Zod-validated FormData, useFetcher patterns, optimistic UI.

    4. w 04

      Performance + adapter

      Image pipeline, prefetch tuning, JSON-LD, sitemap, OG images. headers() tagging, adapter wired, regions pinned.

    5. w 06

      Migration + launch

      Content + redirect map, dry-run on staging, remix vite:build against the target adapter, deploy, DNS cutover.

    6. Care plan

      Remix + adapter upgrades, route-level perf monitoring, error-boundary triage, monthly review.

    Booking Q3 2026 · Avg engagement: 6 weeks · Reply within 24h