Optimizing Next.js 16 RSC Payloads and Embracing Brutalist Design
Photo by Unsplash Contributor via Unsplash.
When building a high-performance portfolio, the difference between acceptable and exceptional lies in the invisible details: the size of a React Server Component (RSC) payload, the precision of an animation timeline, and the strict adherence to a unified design language.
Recently, I conducted a rigorous audit of my Next.js 16 App Router codebase. My goal was twofold: achieve peak performance and enforce a strict System-Terminal Brutalist aesthetic. Here is the technical breakdown of how I transformed the system.
1. Slashing Server Serialization Bloat
One of the most insidious performance killers in Next.js 13+ is accidentally serializing massive data structures from Server Components into Client Components.
In my original implementation, the RootLayout fetched all blog posts (including their entire markdown content) and passed the raw array into a client-side <Navigation> component. This forced Next.js to serialize the entire text of every blog post into the HTML payload on every page load.
The Fix:
I mapped the blogPosts array on the server down to exactly what the client needed: the slug and title only.
// app/layout.tsx const allPosts = getBlogPosts() const navigationPosts = allPosts.map(post => ({ slug: post.slug, title: post.title })) // ... <Navigation blogPosts={navigationPosts} />
By filtering the data prior to the Client Component boundary, my initial HTML payload size dropped dramatically.
2. Deterministic Data Fetching with React.cache()
In a dynamic Next.js App Router context, any function reading from the filesystem synchronously can become a bottleneck. My markdown parser in lib/mdx.ts was doing exactly that: running fs.readFileSync for every post, multiple times across the React tree.
By wrapping my getBlogPosts function in React.cache(), I ensured that the filesystem read and markdown parsing operations happen exactly once per request.
// lib/mdx.ts import { cache } from "react" import fs from "fs" export const getBlogPosts = cache((): BlogPost[] => { if (!fs.existsSync(CONTENT_DIR)) return [] // Process and sort markdown files })
This single line of code leverages the native React request cache. It eliminates redundant parsing cycles and accelerates Server Component rendering.
3. Strict Motion Timings with GSAP
Premium interfaces are defined by their motion. Following Disney's 12 principles of animation and strict design engineering standards, motion should be snappy and physics-driven.
My GSAP scroll-triggered animations had a duration of 0.5s and a stagger of 0.08s. This created a lazy cascade effect that felt disjointed from a high-tech brutalist aesthetic.
The Fix:
I slashed the duration to <300ms and tightened the stagger.
const tween = gsap.to(items, { autoAlpha: 1, y: 0, duration: 0.25, // Snappy physics-driven timing ease: "power2.out", stagger: 0.04, // Minimal stagger force3D: true, // ... })
The result is a responsive, instantaneous feel that respects the user's time and matches the raw aesthetic of the site.
4. Embracing Industrial Brutalism
The previous iteration of my portfolio suffered from a tonal mismatch. It utilized soft radial gradients, heavy backdrop blurs, and rounded corners (rounded-xl), which leaned more toward a friendly software product look than an elite engineering showcase.
To align with an Industrial Brutalist design system, I stripped out the visual noise:
- Removed Radial Glows: Eliminated
bg-[radial-gradient(...)]andblur-[80px]elements. - Sharp Geometry: Replaced all
rounded-xlclasses withrounded-noneto enforce sharp, aggressive corners. - Raw Borders: Applied
border-2 border-borderto cards and badges for a structured, blueprint-like feel. - Semantic OKLCH Tokens: Stripped hardcoded
teal-*utility classes, replacing them with dynamic, semanticoklchtokens (e.g.,text-primary,bg-background).
<SpotlightCard className="flex h-full flex-col p-6 rounded-none border-2 border-border">
Conclusion
Performance and design are intrinsically linked. A brutalist, industrial interface naturally demands an architecture that is just as rigid, fast, and uncompromising. By taking absolute control of my RSC payloads, memoizing my server reads, and stripping away decorative visual bloat, I built an application that does not just look like a piece of high-end software. It performs like one.
Want to discuss this further? Great?
I'm always happy to chat about software engineering, cloud architecture, AI/ML, and DevOps.