The Next.js build output is a route table that tells you how each page is served. Running next build compiles the app and prints a symbol next to every route, marking it static, partially prerendered, or dynamic. Reading those symbols tells you what to expect from each page in production.
Here is a small build output:
Route (app)
┌ ○ /_not-found
└ ƒ /products/[id]
○ (Static) prerendered as static content
ƒ (Dynamic) server-rendered on demandThe route /_not-found shows ○, meaning it is prerendered as static content at build time. The route /products/[id] shows ƒ, meaning it is server-rendered on demand for each request.
The four symbols
| Symbol | Meaning |
|---|---|
| ○ | Static, prerendered at build time |
| ◐ | Partial Prerender, shell static and content streamed |
| ● | SSG, prerendered static HTML |
| ƒ | Dynamic, server-rendered on demand |
○, ●, and ƒ are the classic modes that have always existed. With Cache Components enabled, Next.js adds ◐ and makes Partial Prerendering the default, so most routes become a static shell with streamed content instead of being fully dynamic. The symbol reflects what happens at prerender time, not which configs the route exports.
What each symbol means for the user
- A static route is built once and served as is, so it loads as fast as static files can.
- A partially prerendered route shows its shell instantly and streams the rest, so the page feels immediate even when data is slow.
- A dynamic route is rendered for each request, which is slower but always fresh.
In short, the more of the page Next.js can prerender, the better the symbol is for load speed.
How routes change symbol
A route can move between symbols depending on its data. A dynamic page with uncached data shows ƒ or ◐. Exporting generateStaticParams tells Next.js which param values exist, and adding use cache moves the data lookup to build time, which turns those listed pages into static ○ rows.
The symbol is a hint, not a verdict, so the same route can change symbols after you change how it fetches data.
When a route contains cached data, the table also adds Revalidate and Expire columns. They report the shortest revalidation and expiry across the caches in that route, using the default profile when no cacheLife is set.
For what happens before and after this command, read Next.js Development vs Production Mode. To see every CLI command, read The Next.js CLI: Every Command and Flag Explained.
Rune AI
Key Insights
- next build prints a route table with one symbol per route.
- A circle means the route is prerendered static content.
- A half circle means a static shell with streamed content.
- The f symbol means the route is server-rendered on demand.
- Cache Components makes partial prerendering the default.
Frequently Asked Questions
What does the circle symbol mean in the build output?
Why does one route show a different symbol than another?
Do the symbols change between versions?
Conclusion
The build output is a map of how each route is served. Learn the four symbols, and you can tell at a glance which pages are static, streamed, or rendered on demand.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.