Welcome everyone and thanks for being here. This session opens with a simple promise: clarity over hype.
First, set expectations. We will compare Remix and Next.js as they stand in 2025, focusing on practical developer experience and production realities.
Call out the “vs” as friendly rivalry. Both frameworks are excellent; the goal is to illuminate trade-offs, not crown a universal winner.
Briefly outline the path: data loading and mutations, routing and nested layouts, server actions and streaming, cache and revalidation models, edge readiness, DX tooling, and migration stories.
Flag that we will use concrete examples and benchmarks where they matter, and we will separate defaults from what requires opt-in configuration.
Invite the audience to note questions as we go; we will leave room at the end for discussion and specific scenarios.
Title: TL;DR. I’ll give a crisp positioning between Remix and Next.js.
First bullet: Remix is web standards-first. Emphasize route loaders and actions, progressive enhancement, great edge story, and predictable HTTP caching.
Second bullet: Next.js is RSC-first with the App Router. Highlight Server Actions, fetch caching with tags, and the strong developer experience especially when paired with Vercel.
Point to the grid: both frameworks cover the core boxes—routing, data, mutations, caching, deployment. The difference is philosophy and defaults, not capability gaps.
Close: Choose the mental model you prefer—standards-first with HTTP primitives (Remix) or React-first with server components and platform integration (Next.js).
Open by framing “Mental Models” as how we predict where code runs and how data moves.
Point left to Remix: show the simple Client → Server → Client diagram. Explain that Remix leans into the classic request/response flow.
- Emphasize loaders for route data and actions for mutations—clear entry points per route.
- Highlight HTML-first forms: native navigation and form semantics, with progressive enhancement layered on.
Point right to Next.js: show Server Components → Stream → Client. Explain the server-first rendering pipeline and streaming.
- Data is fetched inside server components or route handlers; think “fetch where it runs.”
- Mutations via Server Actions; caching is a core design primitive shaping data flow.
Close with the contrast: Remix models the browser–server handshake and form semantics; Next models a server-rendered graph streamed to the client. Encourage choosing the model that matches team intuition and product needs.
Title: We’re comparing how Remix and Next.js App Router organize files to define routes. First, point to the left card. In Remix, files live in routes/. _layout.tsx provides a wrapper and uses Outlet to render the active child route. Emphasize that nesting is achieved via Outlet placement rather than folder depth alone. Walk through the three files: _layout.tsx shows Outlet, users._index.tsx is the index route for /users, and users.$id.tsx handles dynamic params like /users/42. Now, the right card. In Next.js App Router, folders map directly to URL segments. layout.tsx wraps children, page.tsx is the leaf for that segment, and [id]/page.tsx declares a dynamic segment. Highlight the chips: Outlet in Remix versus [id] folders in Next. Both achieve nesting and dynamics, but through different conventions: component composition vs file system segments. Close by noting that both approaches are explicit and predictable—choose based on team preference for composition (Remix) or segment-driven structure (Next App Router).
Title: We’re comparing how Remix and Next.js model nested layouts and boundaries.
Left tree first: Remix starts with root.tsx providing a top layout and an Outlet. Emphasize that each route file can render and nest via Outlet.
Reveal the first child routes: _index.tsx is the home route; dashboard.tsx provides its own layout plus another Outlet.
Reveal deeper nodes: profile and billing are nested under dashboard and inherit layouts progressively.
Shift to the right tree: In Next.js, app/layout.tsx is the RootLayout. Each segment can define its own layout.tsx.
Reveal deeper nodes: dashboard has its own layout and page, and settings inside dashboard introduces yet another layout, composing UI by segment.
Close with bullets: Both frameworks enable co-location of layout with route/segment and allow granular composition. This leads to clearer boundaries for data, errors, and loading states at each level.
Title: Data Loading. We compare Remix loaders with Next.js Server Components to show where data work happens.
First, point to the Remix loader card. Emphasize that the loader runs per route on the server, receives params and request, and returns serialized data. It’s aligned with route boundaries and is naturally cache-friendly.
Next, move to the Next.js RSC card. Explain that server components allow you to fetch on the server during render. The key benefit: fetches are hoisted and don’t ship client bundles for data fetching.
Call out parallelism: demonstrate using two fetches and Promise.all to avoid waterfalls. Stress that in both models, reducing sequential waits matters.
Wrap up: choose the tool based on routing boundaries and where you want data to live; keep fetches parallel and close to the boundary that needs them.

Today is about how we mutate data on the web, contrasted in Remix and Next.js.
Start left with Remix: show the Form with method=post and the action function. Emphasize that the browser does the heavy lifting—submit, POST, server handles, and we redirect. This works without any client JavaScript, giving us progressive enhancement by default.
Point at the request cycle line: Form to POST to action to redirect. It is standards-first and resilient.
Move to Next.js: highlight Server Actions with "use server" directly inside the component. The form binds to the server function, keeping mutation code colocated with the UI. Explain that this is ergonomic and keeps logic near where it’s used.
Note the alternative: Route Handlers using POST if you prefer API-style endpoints or need to share across clients. Show the second, subtler flow to indicate this path.
Wrap up with guidance: both approaches use standard form POSTs and redirects. Remix leans into progressive enhancement out of the box. Next.js offers co-location via Server Actions or traditional Route Handlers. Choose based on your team’s ergonomics and the need for no-JS baseline versus tight component co-location.

We are looking at revalidation and caching patterns across Remix and Next.js. I’ll walk the grid clockwise.
Top left, Remix: after a mutation via an action, Remix automatically revalidates affected loaders. This keeps views in sync without manual cache busting. Remix also embraces standard HTTP caching. Use Cache-Control and ETag so the browser and any CDN can do the heavy lifting.
Top right, Next.js: control data freshness directly with fetch cache modes like force-cache and no-store. For fine-grained invalidation, use revalidateTag when you model data domains with tags, and revalidatePath when a route’s data needs to be refreshed after a mutation.
Bottom left: stale-while-revalidate is a great user experience lever. Serve a warm response immediately and refresh in the background so the next hit is fresh. Configure it with s-maxage and stale-while-revalidate on Cache-Control.
Bottom right: conditional requests reduce bandwidth. ETag with If-None-Match or Last-Modified with If-Modified-Since lets the server reply 304 Not Modified when nothing changed.
Takeaway: use standards for the network edge, pair them with framework-level revalidation to keep UI consistent after writes, and pick the right invalidation mechanism—tags, paths, or automatic—based on your data shape.
Open by literally shaking the word “Error” — it sets the tone that errors happen and our job is to manage them gracefully.
On the left, explain Remix’s route-first model: each route can ship its own ErrorBoundary. Emphasize useRouteError to read thrown values and isRouteErrorResponse for structured responses, like loaders/actions throwing Response. Highlight that boundaries stack with nested routes, so the closest one handles the failure.
On the right, contrast Next.js segments: error.js lives per segment and isolates failures, not-found.js handles 404s, and reset lets the user retry. Stress the similarity to Remix in spirit: keep boundaries close to where UI is rendered.
Close with the callout: localize errors near the UI. This improves resilience, user trust, and recovery without tearing down the whole page.

Set the scene: we’re comparing the major rendering modes you’ll reach for in modern React apps.
First chip: SSR. Explain that it renders HTML on the server per request. In Remix, this is the default; you can stream data using defer() and still keep SEO and fast first paint. Static output in Remix typically relies on adapters or caching. In Next.js, traditional SSR is available alongside RSC.
Second: RSC streaming. Call out that in Next.js, server components stream by default, letting you progressively reveal UI without shipping client JS for server-only parts. In Remix, you get streaming via defer(), though it’s still SSR, not RSC.
Third: SSG/ISR. Emphasize pre-rendering for speed and stability. Remix can approximate SSG via build-time adapters or smart caches at the edge. Next.js formalizes ISR with revalidate windows to keep content fresh without full rebuilds.
Fourth: CSR islands. Describe the pattern: keep most of the page server-rendered or static, then hydrate interactive “islands.” In Next.js, mark components as client to hydrate selectively; in Remix, nested routes and boundaries let you isolate interactivity.
Fifth: Edge. Talk about where the code runs. Next.js supports Edge and Node runtimes per route; combine this with ISR and RSC streaming for latency wins. Remix can deploy to edge via adapters, and caching makes SSR feel static.
Wrap up: pick the simplest mode that meets your latency and freshness needs—SSR for dynamic, RSC streaming for progressive UX, SSG/ISR for speed at scale, islands for targeted interactivity, and Edge to move computation closer to users.

Open with the title and frame the slide: we are comparing how Remix and Next.js shape the waterfall and first byte timing.
Start on the left: Remix emphasizes parallel route loaders. Everything kicks off together, reducing classic waterfalls.
Highlight defer and Suspense: we can stream parts of the UI as data resolves, which moves the first meaningful bytes earlier.
Call out the browser HTTP cache: Remix leans on native caching, so repeat navigations or shared data show quick cache hits.
Move to the right: Next.js and React Server Components hoist fetches into the server graph. Many fetches resolve together and can be cached within that graph.
Note granular streaming: boundary-by-boundary streaming means multiple regions of the page can deliver bytes earlier.
Now point to the waterfalls: Remix shows parallel network lanes from time zero; Next shows server work overlapped with early streamed chunks and cache hits.
Draw attention to the timelines sliding in: the first byte appears earlier for the streamed paths in both, but typically earlier in the RSC graph for Next.js depending on cache hits and boundaries.
Close with the takeaway: both approaches pull first byte earlier by changing where work happens and what can stream. Choose the model that matches your team’s data boundaries and caching strategy.
Title: Dev Server and Bundling. Frame the slide as two modern stacks solving similar problems with different trade-offs.
Remix card: Start with developer loop. Emphasize Remix running on Vite with very fast HMR. Point to the speedometer to reinforce feedback speed.
Remix build: Explain that production builds go through Vite using Rollup as the bundler and esbuild for transforms, which keeps TS first-class and builds snappy.
Next.js card: Move to dev server story—Turbopack drives development with incremental compilation and fast HMR.
Next.js production: Most production builds still use Webpack today while Turbopack is evolving toward production readiness. Call out the integrated image and font pipelines as a practical advantage.
Close: Both aim to tighten the feedback loop; choose based on team needs—Remix lean Vite pipeline vs. Next’s integrated platform and evolving Turbopack.
- Introduce the theme: file-system colocation makes features easier to change and reason about.
- Point to the legend: blue is UI, green is Styles, amber is Data. We will track them on both sides.
- Walk the Remix side: the route module keeps loader and action with the component, meta and links are nearby, and links() attaches per-route CSS.
- Show the Remix folder sketch: a single route file next to its CSS makes it obvious what belongs to the feature.
- Move to Next.js: each segment has page.tsx and layout.tsx, with loading and error files right there for UX states.
- Explain styles in Next.js: CSS Modules or Tailwind are colocated with the page, so styling lives where the UI lives.
- Mention data in Next.js: fetch inside Server Components or route handlers keeps data access close to the UI.
- Close with the takeaway: put what changes together; scanning the folder should tell the story of a feature.
Introduce the slide: we’re looking at runtime targets—where our code actually executes.
Point to the faint world map watermark to set the context of global distribution.
Reveal the Remix column. Emphasize its adapter model: Express/Node, Cloudflare Workers, Deno, Netlify, and Vercel. Stress that Remix leans on standard Web APIs like Request/Response, making it naturally edge-friendly.
Reveal the Next.js column. Explain that it’s optimized for Vercel, and you can choose Node or Edge per route or handler. Call out that middleware runs at the edge for fast rewrites and auth.
Finally, bring in the pins to reinforce the idea that both approaches can be globally deployed—your choice of runtime shapes latency and cost.
Wrap up: pick runtimes intentionally—use edge where proximity and low latency matter; use Node where you need heavier compute or compatibility.
Title: Edge Constraints. Set the frame: we’re building at the network edge, so our assumptions change.
First, APIs: the Edge gives you the Web Platform—fetch, Request/Response, URL, Crypto—without Node built-ins like fs, net, or Buffer. That’s why Remix on Workers is such a natural fit: it leans into the platform.
Second, performance shape: cold starts are usually smaller, and streaming lets you send bytes immediately. With Next.js you can opt into the Edge per route, so you use it selectively where it helps most.
Third, limits: compute time and bandwidth are tight. Keep bundles lean, avoid heavy native dependencies, compress responses, and cache aggressively.
Fourth, state: the edge is ephemeral. Persist via KV, durable objects, or plain HTTP backends. Avoid in-memory state or process affinity assumptions.
Wrap up: choose routes that benefit from low latency and streaming for Edge; keep heavy work on Node or background jobs.

Title: Set the frame. We are contrasting two mental models for how React code reaches the browser. Left card (Remix): Explain that in the traditional SSR+hydrate model, the server renders HTML first, then the browser hydrates the entire component tree. Emphasize there is no RSC separation, so all component code ships to the client and the browser owns the UI after load. Right card (Next.js): Contrast with RSC-first. By default, components run on the server. Only components marked with "use client" ship interactivity code. Server-only logic stays off the client, which reduces the amount of JavaScript sent. Bar chart: Use the illustration to reinforce the idea. The taller sky bar represents the larger client surface when everything hydrates. The shorter emerald bar represents the reduced client surface when most components stay server-only. No exact numbers—just the shape of the tradeoff. Close: The key lever is intent. In RSC, you choose where interactivity is needed; everything else can remain server-rendered for smaller bundles and faster starts.

First, frame the slide as a contrast of fetching semantics in Next.js and Remix, focusing on what each runtime promises.
In the top row, explain that Next.js extends fetch globally. Emphasize request memoization, option-driven caching, tag and path revalidation, and automatic deduplication. Point to the code: highlight cache: "no-store" as a way to opt out of caching, and show next: { revalidate, tags }. Conclude with revalidateTag and revalidatePath as the invalidation levers after a mutation.
Move to the bottom row for Remix. Stress that Remix uses the native Web Fetch API in loaders and actions. Underline that response headers like ETag and Cache-Control determine caching. Call out the ETag highlight and how conditional requests enable freshness. Finish by noting that form submissions trigger revalidation automatically, as shown by the redirect from the action causing loaders to refetch.
Wrap up by summarizing: Next.js centers server-driven cache policies with explicit invalidation, while Remix centers browser and HTTP semantics, letting headers lead.
Start by framing the slide: we are comparing how Remix and Next.js handle styling and assets.
Pause on the header chips: the focus areas are CSS and images.
Move to the left column: Remix.
Explain that links() gives per-route control of CSS, so each route can attach only what it needs.
Highlight supported styling approaches: CSS Modules, Tailwind, and vanilla-extract for type-safe styles.
Emphasize preloading with link rel="preload" for critical CSS or assets to remove render delays.
Shift to the right column: Next.js.
Call out built-in CSS and SCSS support, along with CSS Modules and Tailwind for component-scoped styles.
Explain next/image: automatic responsive sizing, lazy loading, and modern formats, giving easy performance wins.
Mention font optimization via next/font to avoid layout shifts and FOIT by inlining subsets.
Conclude with the tip: keep CSS scoped per route, preload the critical few, and rely on the framework pipeline for images and fonts to stay fast by default.
Title: “Choosing Quickly.” Set the expectation—this is a fast decision aid, not a deep dive.
Left column: “Choose Remix when.” Emphasize that Remix leans into the platform—forms, headers, and the browser’s native behaviors. Call out portability to edge runtimes and the clarity of route-level data/mutation. Close with progressive enhancement as a core principle.
Right column: “Choose Next.js when.” Highlight RSC streaming for complex UI, Server Actions for straightforward mutations, cache tags/ISR for granular revalidation, and the strong developer experience on Vercel.
Wrap-up: Both are excellent. The deciding factors are often the team’s familiarity and where you’ll host. Encourage choosing based on constraints and strengths, not hype.
First, I’ll land this with a quick tour of where to go next. On the left are the core Remix links: the official docs for fundamentals, Indie and Blues Stacks to accelerate production apps, and the Cloudflare Workers template for edge deployment.
On the right, Next.js essentials: the docs, focused App Router examples to learn by doing, and a direct link to Vercel templates you can deploy in minutes.
Front and center is a single link to a curated list—scan the QR to open it, or tap the URL below. It aggregates high-signal resources for React, Remix, and Next.js so you don’t have to hunt.
I’ll pause here for a moment—feel free to scan now. As we wrap, remember: pick a starter, deploy early, and iterate with real feedback.