Technical
The Next.js Pattern I Use for Every Landing Page
Landing pages come up in every client engagement. Some weeks I ship three. I converged on the same Next.js structure for all of them and it cut build time by half. Here is the template and the few decisions that actually matter for performance and maintainability.
The Directory Shape
app/page.tsxfor the marketing pageapp/layout.tsxwith open graph metadata defaultscomponents/marketing/for reusable sectionscontent/copy.tsfor all editable strings in one filepublic/og/for social share images, one per route
Why Copy Lives in One File
Clients change copy. They do not change layout. Putting every string in one file means edits happen without touching components. Non-engineers can review and push small changes. I have had marketing colleagues ship copy updates via pull request because the change was contained to a single file they could parse.
// content/copy.ts
export const HERO = {
headline: 'Your AI-ready stack, shipped.',
subhead: 'We build and deploy your systems.',
cta: 'Book a call',
} as const;The as const matters. It makes the strings narrow types, which means components that consume the copy get exact-match type checking rather than generic string types.
The Performance Baseline
Static generation for everything that can be static. Dynamic only for the contact form submission. That means a hard Lighthouse score above 95 with no manual optimization. Dynamic rendering on marketing pages is rarely justified and usually just means the developer did not think about caching.
The Image Discipline
Every image goes through Next.js Image. Every image has explicit width and height. No exceptions. This single rule keeps Core Web Vitals green on every client site. The number of sites failing LCP because of unoptimized hero images is embarrassing industry-wide.
What I Stopped Doing
Adding animation libraries by default. They look nice on the first visit and slow down every subsequent one. If the brand demands motion, I add it surgically. Default pages stay fast. A subtle CSS transition on hover states is enough for 90 percent of the motion clients ask for.
The Build-Time Gate
CI runs Lighthouse against every preview deploy. Scores below 90 block the merge. That gate catches performance regressions before they reach production rather than after a client complaint.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read