CodeVix Labs
Engineering Team
Next.js makes it easy to build a great app. It does not make it easy to ship a production-ready one. After deploying dozens of Next.js applications, we've compiled the things teams consistently miss — the gaps between “it works on localhost” and “it works reliably for 10,000 users.”
1. Error Boundaries & not-found.tsx
Every route group needs an error.tsx and a not-found.tsx. Without them, unhandled errors show a generic white page and 404s fall through to the default Next.js error page — neither of which inspires confidence in your users.
Your error.tsx should log the error, display a helpful message, and offer a way to retry or navigate back. Your not-found.tsx should guide users to content that exists. Both should match your design system, not look like an afterthought.
2. ISR vs SSG vs SSR — Choose Per Page
One of the most common mistakes is setting export const dynamic = 'force-dynamic' globally or on pages that don't need it. Every dynamic page is a server that must respond in real time. Every static page is a CDN cache hit that responds in milliseconds.
Evaluate each page independently. Your marketing pages should be fully static. Your blog posts should use ISR with revalidate = 3600 (or similar). Your dashboard can be dynamic. Your case study pages should use generateStaticParams for known slugs with ISR for new ones. Don't pay for server-side rendering when a cached page will do.
3. Security Headers
Next.js doesn't set security headers by default. You need to configure them yourself, either in middleware or next.config.js. At minimum:
- Content-Security-Policy — Restrict script sources, style sources, connect sources. Block inline scripts unless you use nonces.
- X-Frame-Options: DENY — Prevents your site from being embedded in iframes (clickjacking protection).
- Strict-Transport-Security — Force HTTPS with a long max-age. Include subdomains.
- X-Content-Type-Options: nosniff — Prevents MIME type sniffing attacks.
- Referrer-Policy — Control what information is sent in the Referer header. Use
strict-origin-when-cross-origin.
If you use analytics tools like Vercel Analytics, remember to include their domains in your CSP (e.g., va.vercel-scripts.com in script-src).
4. Image Optimization
The next/image component is powerful but needs proper configuration. Always provide the sizes prop — without it, Next.js serves the largest image to every device. A hero image that's 1920px wide doesn't need to be served at full resolution to a 375px mobile screen.
Set up remotePatterns in your config for external image sources (Cloudinary, S3, etc.). Use priority only for above-the-fold images — it disables lazy loading. And check your image formats: Next.js serves WebP by default, but verify your CDN isn't overriding this.
Common mistake: using fill without a sized parent container. The image will have zero dimensions unless its parent has explicit width and height (or uses position: relative with defined dimensions).
5. SEO Essentials
Next.js App Router gives you generateMetadata — use it on every page. Don't rely on a global title template alone. Each page needs its own title, description, and canonical URL.
The SEO checklist that teams consistently forget:
- 1
Canonical URLs on every page
Prevent duplicate content issues. Define via alternates: { canonical } in metadata.
- 2
JSON-LD structured data
Use BlogPosting for articles, Organization for your about page, FAQPage for FAQ sections. Google uses these for rich snippets.
- 3
OG and Twitter images
Use Next.js opengraph-image.tsx to generate dynamic OG images. They drastically improve click-through rates from social shares.
- 4
sitemap.xml
Generate it dynamically using Next.js sitemap.ts. Include all public pages with lastmod dates.
- 5
robots.txt
Block admin routes, API routes, and internal pages from crawling.
6-10. Performance & Reliability
Beyond the top 5, these items are frequently overlooked but critical for production reliability:
- 6Loading states — Add
loading.tsxat route group levels. Without them, navigation feels broken when data fetching takes more than 200ms. - 7Environment variable validation — Validate all required env vars at build time. A missing
DATABASE_URLshould fail the build, not crash in production at 2 AM. - 8Bundle analysis — Run
@next/bundle-analyzerperiodically. Client bundles grow silently. A single unoptimized import can add hundreds of KB. - 9Rate limiting on API routes — Next.js API routes are public by default. Without rate limiting, a single script can overwhelm your database or exhaust API quotas.
- 10Database connection pooling — Serverless environments create a new connection per invocation. Use connection pooling (PgBouncer, Neon's pooler, or Prisma Accelerate) to avoid exhausting your database connection limit.
11-15. The Details That Compound
The last five items are the ones that separate a good deployment from a great one:
- 11Monitoring and alerting — Use Vercel Analytics, Sentry, or equivalent. Know when errors spike before your users report them.
- 12Accessibility basics — Semantic HTML, keyboard navigation, aria labels on interactive elements, sufficient color contrast. These aren't optional — they're legal requirements in many jurisdictions.
- 13Favicon and app manifest — A missing favicon is the first thing users notice. Set up
icon.tsx,apple-icon.tsx, andmanifest.tsfor proper PWA support. - 14Preview deployments — Every PR should get a preview URL. This is free on Vercel and catches visual regressions before they hit production.
- 15Dependency audit in CI — Add
npm audit --audit-level=criticalto your CI pipeline. Fail the build on critical vulnerabilities. Automate dependency updates with Renovate or Dependabot.
Production readiness isn't about perfection — it's about covering the basics so thoroughly that you can focus on building features instead of fighting fires.
Ready to discuss your project?
Book a free 15-minute technical audit with our engineering team.