Skip to content
C.W.K.
Stream
Lesson 08 of 08 · published

Production Checklist

~24 min · checklist, launch, audit

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Performance

  • Lighthouse audit — 90+ on every metric.
  • Bundle analyzer run; no surprises in client chunks.
  • Heavy libraries are in Server Components only.
  • preload on above-the-fold images.
  • next/font for all fonts.
  • Caching strategy explicit per route.

SEO

  • Metadata on every page (title, description, OG).
  • app/sitemap.ts generates sitemap.xml.
  • app/robots.ts defines crawl rules.
  • OG images render correctly (Twitter Card validator).

Security

  • Security headers (CSP, X-Frame-Options, HSTS) in next.config.ts.
  • No secrets in any NEXT_PUBLIC_ variable.
  • Server Actions validate input + check auth.
  • Latest Next.js minor for security patches.

Error handling

  • Custom not-found.tsx.
  • error.tsx at the app root.
  • global-error.tsx for the root layout.
  • Error tracker (Sentry) wired up.

Accessibility

  • All images have alt.
  • All inputs have labels.
  • Keyboard navigation works.
  • Color contrast passes WCAG AA.
  • Screen reader sweep done.

Make the production checklist release-specific and evidence-bearing. Every item should name the command, URL, screenshot, log, or metric that proves it against the current commit, plus an owner and an expiration condition for evidence that can go stale. More checked boxes do not make a release safe when the product's critical journey is absent. Start with one path from entry to completed goal, then use performance, SEO, accessibility, security, caching, and recovery checks to protect that path. Run the checklist against one deployed SHA and attach the resulting URLs or logs. Complete the critical transaction with keyboard and screen reader, inspect real response headers and error recovery, fix failures, and rerun the same checks before promotion.

Code

Security headers via next.config·ts
// next.config.ts
import type { NextConfig } from 'next';

const config: NextConfig = {
  async headers() {
    return [{
      source: '/(.*)',
      headers: [
        { key: 'X-Frame-Options', value: 'DENY' },
        { key: 'X-Content-Type-Options', value: 'nosniff' },
        { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
        { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
        { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
      ],
    }];
  },
};
export default config;
sitemap and robots·ts
// app/sitemap.ts
import type { MetadataRoute } from 'next';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const posts = await getAllPosts();
  return [
    { url: 'https://myapp.com', lastModified: new Date(), priority: 1 },
    ...posts.map(p => ({
      url: `https://myapp.com/blog/${p.slug}`,
      lastModified: p.updatedAt,
      priority: 0.7,
    })),
  ];
}

// app/robots.ts
import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: '*', allow: '/', disallow: '/admin' },
    sitemap: 'https://myapp.com/sitemap.xml',
  };
}

External links

Exercise

Take any deployed Next.js project and run the entire checklist above. Document which items pass, which fail, and pick three to fix this week.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.