Deployment and Best Practices
Shipping a Next.js app to production, and the habits worth carrying forward from this course.
3 min de lectura
Everything up to this point runs on your machine through next dev. Getting an app in front of real users means building it for production and choosing where that build actually runs — and Next.js is deliberately flexible about the second part.
Building for production
npm run build
npm run startnext build compiles an optimized bundle, pre-renders whatever routes it can as static HTML, and prints a summary showing exactly which routes ended up static versus dynamic — worth reading closely, since it's the fastest way to catch a page that unexpectedly opted into per-request rendering. next start then runs that build as a real Node.js server, with none of the development-only overhead (unminified code, verbose error overlays) that next dev carries.
Where it can run
Next.js supports several deployment shapes, and which one fits depends on which features your app actually uses:
- Node.js server — supports every Next.js feature, including Server Actions, Route Handlers, and ISR. This is the most capable option and works on any host that runs Node.
- Docker container — the same full feature set, packaged for container orchestration platforms.
- Static export (
output: "export") — produces plain HTML/CSS/JS with no server component at all, deployable to any static host. This trades away anything that requires a live server: Server Actions, Route Handlers, ISR, and dynamic rendering all stop working, since there's no server left to run them. - Platform adapters — hosting providers like Vercel offer adapters that map Next.js's build output onto their own infrastructure, typically supporting the full feature set with additional platform-specific optimizations (like automatic edge caching).
If you're unsure which to pick: a Node.js server or a verified platform adapter covers everything this course taught. Reach for static export specifically when you know in advance that the entire app can be static — a documentation site or a marketing page with no per-user content or mutations.
Best practices worth carrying forward
A few habits from this course are worth calling out explicitly, because they're easy to let slide as an app grows:
- Keep the
"use client"boundary as low as possible. Every file it touches ships to the browser — audit this occasionally as new features get added, since boundaries tend to creep upward over time as developers reach for the nearest client component instead of the most precise one. - Verify authorization inside every Server Action and Route Handler, not just in the UI that calls them. Both are reachable directly, regardless of what your interface shows or hides.
- Be deliberate about caching, not accidental.
force-dynamicon a page that should always be fresh,revalidatewith a tag on data that changes occasionally — know which one applies to each route rather than accepting whatever the default inference lands on. - Check the
next buildoutput regularly. It's the single fastest way to catch a route that quietly became dynamic (or stayed static when it shouldn't have) as the codebase evolves.
Where to go from here
This course covered the App Router's core model — file-system routing, Server and Client Components, data fetching, mutations, rendering strategies, and the file conventions that tie them together. From here, the natural next steps are the topics that build on this foundation: authentication, testing Server Components and Actions, and the more advanced routing patterns (parallel and intercepted routes) that power things like modal-based UIs. The mental model you've built in this course — server-first by default, opting into the client only where truly needed — is the same one those topics extend, rather than replace.