Jamstack with React means building your React app into static files ahead of time, serving them from a CDN, and calling APIs for anything dynamic, which gives you fast pages, a small attack surface and very cheap hosting for a large class of sites.
The label is old and the idea is sound. The skill is knowing which parts of your app can be pre-built and which cannot.
Table of contents
- What the Jamstack idea actually is
- Pre-rendering versus client rendering
- Where dynamic data comes from
- Routing and the single-page-app fallback
- Build and deploy workflow
- Hosting the output
- SEO, accessibility and common pitfalls
- How this fits the rest of the stack
- FAQ
What the Jamstack idea actually is
Jamstack began as shorthand for JavaScript, APIs and Markup. The architecture decouples the front end from the back end. The front end is built into static assets at deploy time. Dynamic behaviour comes from JavaScript in the browser calling APIs, whether those are third-party services or your own.
The practical effect is that the thing users hit is a set of files. There is no server rendering a page on each request, no application process to keep running and no database queried to show a marketing page. Files are cached across a CDN, so the response is fast almost everywhere.
For React, this can mean one of two shapes. A client-rendered single-page app ships a near-empty HTML file and a JavaScript bundle that builds the page in the browser. A pre-rendered site runs React at build time to produce real HTML for each route, then hydrates it in the browser so it becomes interactive.
The introduction pieces you find in search results describe it as improving performance, security and scalability by separating concerns, and that holds up. The honest caveat is the same everywhere: it suits content that does not change on every request. A dashboard full of live per-user data is not a pre-rendering candidate.
The post on Jamstack websites covers the concept more generally before React specifics.
Pre-rendering versus client rendering
The choice matters for search engines, first-load speed and complexity.
A client-rendered React app sends minimal HTML and builds the page after the bundle loads. It is simple to build and host. The cost is that the first meaningful content waits for JavaScript, and crawlers or link preview tools that do not run scripts see little. For an authenticated tool behind a login, that is acceptable. For a public marketing site or a blog, it is a handicap.
A pre-rendered approach generates complete HTML at build time. Visitors and crawlers get content immediately, and React takes over afterward. Frameworks that support this include Next.js with static export, Astro with React islands, Gatsby and Vite-based setups with a pre-rendering plugin. The build runs once per deploy, then every request is a file read.
Decide route by route. A marketing page, a documentation page and a blog post are good candidates for pre-rendering. A logged-in account page can stay client rendered. Many frameworks let you mix both in one project, which is the practical sweet spot.
Be aware of the build-time cost. A site with thousands of pages takes longer to build, and every content change triggers a rebuild. Incremental approaches and on-demand regeneration exist for that, with their own tradeoffs.
Where dynamic data comes from
A static site is not a site without data. The data arrives from three places.
At build time. Content from a headless CMS, Markdown files or an API is fetched while building and baked into the HTML. It is fresh as of the last deploy. Use this for content that changes occasionally, and trigger a rebuild with a webhook when an editor publishes.
In the browser. JavaScript calls an API after the page loads, for things like search, comments, personalised data and live prices. This is where your own backend or a third-party service comes in.
At the edge or in functions. Small server-side functions handle forms, authentication callbacks and webhooks without a full server.
A typical architecture is a static front end plus a small API service plus a managed database. Forms post to the API, which validates and stores them. Search uses a hosted index or a simple endpoint. Authentication uses tokens issued by the API and stored carefully.
The mistake to avoid is putting secrets in client code, since everything shipped to the browser is public. Anything requiring a key belongs behind your API. If you want a feel for the headless side, the existing posts on Netlify forms and the wider Jamstack discussion show common patterns.
Routing and the single-page-app fallback
Client-side routing is the most common source of confusing 404 errors on static hosting. React Router, for instance, handles URLs like /products/42 inside the browser. The server has no file at that path. On the first visit through the home page everything works. Refresh on /products/42, or share the link, and the host looks for a file that does not exist and returns a 404.
The fix is a fallback rule: for any path that is not a real file, serve index.html and let the router take over. Hosts call this a single-page-app fallback or a rewrite.
/* /index.html 200
A rewrite with status 200 keeps the URL, which is what you want. A redirect would change it.
Pre-rendered sites avoid the problem by emitting one HTML file per route, so each real path exists as a file. You can still keep a fallback for routes you chose not to pre-render.
Remember a catch: a fallback that serves your app for every unknown path will also serve it for genuinely missing pages with a 200 status, which makes them look like soft errors to search engines. Add a proper not-found route in your app and, where the host allows, a real 404 page for paths that cannot exist.
Build and deploy workflow
A healthy workflow for a Jamstack React site looks like this.
- The code lives in a Git repository.
- Each push to a branch triggers a build in a clean environment.
- The build runs
npm ciand the build script, and outputs a folder such asdistorbuild. - The host publishes that folder to its CDN atomically, so users never see a half-deployed site.
- Preview deployments for pull requests let reviewers see changes at a real URL.
- Rollback means re-publishing a previous build.
Keep environment variables for build-time configuration in the host’s settings. Remember that any variable inlined into the bundle is public, so only non-secret values belong there.
Watch bundle size. React apps grow easily. Split code by route, lazy-load heavy components, and measure the real weight of the first load. The performance advantage of static hosting is wasted if the page ships two megabytes of JavaScript.
Add basic checks to the pipeline: a build that fails on type errors, a link checker for internal links, and a Lighthouse run on key pages. They catch regressions before readers do.
Hosting the output
Static output is the cheapest kind of hosting to run, because serving files takes almost no compute. What matters is the build pipeline, custom domains and certificates, cache headers, redirects and the SPA fallback.
On RunxBuild, a static site builds from a GitHub repository, with custom domains, headers, redirects, rewrites and SPA fallback, and 120GB of bandwidth included, then $0.10 per GB. The step-by-step for a React app deploy shows the build command and output folder, and the SPA docs explain the fallback rule.
When the site later needs an API or a database, those can run as a web service and a managed MySQL or Postgres instance on the same platform, so the project can grow without changing where it lives.
SEO, accessibility and common pitfalls
Static output is a good base for search visibility, and a few details decide whether you benefit. Give every page a unique title and description, a canonical URL and a sitemap. Use real links for navigation, not click handlers, so crawlers and keyboard users can follow them. Pre-render the content you want indexed.
Avoid the usual traps: huge JavaScript bundles that delay interactivity, images without dimensions that shift the layout, hydration mismatches between the build-time HTML and the browser render, and content that only appears after an API call that crawlers may not wait for.
Test the production build, not just the development server. Serve the output folder locally with a static file server and click through the main routes, including a hard refresh on a deep link. If it survives that, it will usually survive the host.
How this fits the rest of the stack
Static hosting is cheap until the API behind it is not, so model both halves together. Put the front end, a small service and a database into the RunxBuild hosting calculator and see the monthly total. When your build output is ready, the RunxBuild dashboard is where you connect the repository.
Useful related references:
- Jamstack Website in 2026: What the Term Still Means, and Where the Backend Goes
- React 19 Features That Change How You Write Components
- Generate a PDF from a React App: A Practical Walkthrough
- Static sites on RunxBuild
FAQ
What is Jamstack with React?
It is building a React app into static files at deploy time, serving them from a CDN and using APIs for dynamic features. It trades per-request server rendering for speed, simplicity and low hosting cost.
Is a React single-page app Jamstack?
It can be, since the build output is static files. But a client-rendered app sends little HTML, which hurts search visibility and first load for public content. Pre-render the pages that need it.
How do I fix 404 errors on refresh with React Router?
Configure a single-page-app fallback that serves index.html for paths that are not real files, as a rewrite with status 200, so the client-side router can handle the URL.
How do I get dynamic data on a static site?
Fetch it at build time for slow-changing content, call APIs from the browser for live data, or use small server functions. Keep secrets on the server side, never in the bundle.
When is Jamstack the wrong choice?
For applications where almost every page depends on per-user, real-time data. Those need server rendering or an application backend more than a pre-built site.