arrow_backBack to Blog
Aug 24, 2026·Architecture

Migrating to Next.js 15 App Router

Embracing the Future of React

When we set out to build TokenDecode, we wanted a technology stack that was blazingly fast, deeply SEO-optimized, and effortlessly scalable. Next.js 15 with the App Router was the obvious choice, but the migration from the traditional Pages router involved significant architectural shifts and a steep learning curve.

Server Components by Default

The most profound change in Next.js 15 is the adoption of React Server Components (RSC) as the default rendering paradigm. In older versions of React, the entire component tree would ship to the browser as JavaScript, resulting in large bundles and slower Time to Interactive (TTI).

With RSC, our entire application skeleton, navigation bar, footer, and typography render on the server at build time. We only sprinkle in "use client" directives at the very edges of our component tree (referred to as the "leaves")—specifically where the actual token decoding logic, state management, and user interaction happens. This drastically reduced our JavaScript payload.

Asynchronous Params

Next.js 15 introduced a major breaking change: dynamic route parameters (like slug) are now asynchronous Promises. We had to refactor our dynamic blog and guide pages to explicitly await params before accessing the URL segments. While this caused a few initial 404 errors during development, it forces a much safer, concurrency-friendly data fetching model.

Tailwind CSS v4 Integration

We paired Next.js 15 with the newly released Tailwind CSS v4. The elimination of the monolithic tailwind.config.js file in favor of standard CSS imports and variables made theme management incredibly intuitive. We rely heavily on CSS custom properties (like --color-primary) for our seamless, flash-free transitions between dark and light modes.

Aggressive Static Export

Because TokenDecode is a privacy-first, client-side tool, we have absolutely no need for a Node.js runtime server. By configuring output: 'export' in our next.config.ts, Next.js pre-renders every single page—including these dynamically generated blog posts—into raw, static HTML files. This allows us to host the entire site globally on the edge via Cloudflare Pages, resulting in near-instant load times for users anywhere in the world.