Static Site Generation
SSG (Static Site Generation) is a rendering strategy that pre-generates HTML files at build time and, instead of rendering in real time on the server when a request arrives, returns the already-built files as-is. The completed HTML can be placed on a CDN for serving from global edges. Once the JS bundle loads, hydration occurs on the client and subsequent interactions work like an SPA.
βΆArchitecture Diagram
π ProcessDashed line animations indicate the flow direction of data or requests
If the server builds HTML on every request, database queries, template rendering, and user-specific processing repeat each time. For pages like blog posts or documentation where the same content is served regardless of who requests it, this repetition is unnecessary. On the other hand, going with the SPA approach where JavaScript renders content on the client means crawlers encounter empty HTML, making SEO difficult, and time to first page load increases. SSG addresses both problems at once by shifting when rendering happens -- from request time to build time.
The early web defaulted to server-side rendering with PHP, JSP, and similar technologies. In the mid-2010s, as JS frameworks like React and Vue became mainstream, SPAs gained popularity, but SEO and initial load speed issues emerged. SSR appeared in response, rendering React on the server, but it came with per-request server computation costs. Tools like Gatsby, Jekyll, and Hugo revived the build-time generation approach, this time combining it with modern component models, and SSG took hold. When Next.js absorbed this pattern at the framework level through getStaticProps/generateStaticParams, SSG became established as one selectable rendering strategy among several.
Everything in SSG happens during the build phase before deployment. First, the build tool runs functions like getStaticPaths or generateStaticParams to determine which URL pages to generate. Then each page's data fetching function calls a CMS or API to retrieve the necessary data, combines it with components, and outputs completed HTML files. The result is pure HTML + CSS + JS bundles, and uploading these files to a CDN completes deployment. After the browser renders the HTML and the JS bundle loads, hydration occurs. Hydration is the process of attaching event handlers and state to the DOM created at server (build) time -- interactions like button clicks only work after this step completes.
SSG, SSR, and SPA are distinguished by when rendering occurs. SSG generates HTML at build time. Once content is created, there is no per-request server computation. It offers the best performance and CDN deployment ease for pages whose content changes infrequently. However, new content is not reflected without a build, so it is unsuitable for pages where data changes in real time. SSR generates HTML on the server at request time. It is appropriate when per-user data (login state, permissions, etc.) is needed or when the latest data must be reflected immediately. The tradeoff is server computation cost on every request. SPA renders HTML in the browser via JavaScript. The initial response is nearly empty HTML, and the screen fills only after JS executes. It favors interaction-heavy apps, but SEO and initial load time are weak points. Hydration happens in SSG too. After the browser renders the static HTML and the JS bundle loads, the component tree runs again to connect events and state. SSG does not 'eliminate server rendering' -- it 'moves it to build time'.
SSG is most natural when content changes on a deployment cadence. For services like developer blogs, technical docs, product landing pages, and event pages where the editing cycle is not far from the code deployment cycle, SSG alone is sufficient. HTML generated at build time allows the simplest possible cache strategy. Because filenames include content hashes, setting Cache-Control to the maximum while having caches automatically refresh on deployment is straightforward. Conversely, pages where request-time data determines the result -- personalized screens per user, real-time inventory or pricing, post-login dashboards -- cannot be handled by SSG alone. These parts are addressed either through separate client-side API calls or by switching to SSR or server components. In practice, many services mix SSG with other rendering strategies on a per-page basis.