Gatsby vs. Bootstrap: One Builds the Pages, the Other Styles Them
Gatsby generates pages, Bootstrap styles them — they are not alternatives. Which job you are shopping for, priced against one build: 840 static pages, 84 KB of CSS.
Gatsby and Bootstrap are not alternatives. Gatsby is a React site generator: it builds pages, fetches data through a GraphQL layer, and outputs static HTML. Bootstrap is a stylesheet: it ships ready-made components and a grid, and builds nothing. Projects use both, either, or neither. Deciding between them means deciding which of the two jobs you are actually shopping for.
The comparison shows up because both get recommended in the same breath — "how do I build a fast marketing site" — and because the tutorials that rank for it are about installing Bootstrap into Gatsby. This post separates the two jobs, prices what each tool costs you per job, and uses one real build as the reference: this storefront, which does both jobs with neither tool and whose numbers were measured today.
The two jobs
| Generate the pages | Style the pages | |
|---|---|---|
| Gatsby does this | Yes — React pages, GraphQL data layer, static output | No |
| Bootstrap does this | No | Yes — components, grid, utilities |
| Alternatives | Next.js, Astro, Eleventy, Nuxt, plain React + Vite | Tailwind CSS, vanilla CSS, CSS Modules, a UI kit |
| What you lose by skipping it | Hand-maintained HTML per page, no data pipeline | Writing every component's CSS yourself |
| Where it shows up in a repo | A build config and a data layer | A stylesheet import and class names in markup |
Read the first row twice: picking Gatsby leaves styling entirely unsolved, and picking Bootstrap leaves page generation entirely unsolved. Anyone comparing them is comparing a hammer with paint.
If you only pick one, here is what breaks
Gatsby alone. You get routing, data sourcing, image handling and a static build, and an unstyled site. You will add something for CSS — Bootstrap, Tailwind, CSS Modules, styled-components. Gatsby's own documentation declines to pick for you and says it is a matter of preference.
Bootstrap alone. You get a styled site and no build. Every page is a hand-written HTML file; a nav change is a change in every file; content lives in markup. That is fine for a one-page site and painful at ten. Bootstrap 5 at least dropped the jQuery dependency its v4 components required, so "Bootstrap alone" is no longer also "jQuery alone".
Neither. Which is this site: a page generator that is not Gatsby, and a styling system that is not Bootstrap.
What one real build spends on each job
This storefront is a Next.js App Router project selling 111 templates, with 344 blog posts. Numbers from npm run build, run today:
| Measurement | Value |
|---|---|
| Static pages generated | 840 |
| Total build, from a cleared cache | 43.8s |
| Of which compile | 19.1s |
| Of which static generation | 13.1s (3 workers) |
| CSS shipped, all routes | 84,090 bytes (14,993 gzipped) |
| Runtime dependencies | 13 |
| GraphQL packages | 0 |
| jQuery packages | 0 |
The page-generation job is done by file-system routing plus typed data imports. The catalog is a TypeScript array in src/data/catalog.ts; the route reads it directly and generateStaticParams turns it into 111 product pages. No GraphQL schema, no source plugin, no gatsby-config.js. The blog does the same with an explicit map in src/lib/blog.ts — a slug-to-import record rather than a wildcard glob, deliberately, so a typo in a post's slug is a build error instead of a 404 in production.
This is the trade against Gatsby's data layer in one line: Gatsby gives you a uniform GraphQL interface over many sources, and charges a schema plus a plugin per source for it. With content that already lives in the repo as typed modules, there is nothing for that interface to unify. With content in three CMSes, a payload API and a spreadsheet, there is.
The styling job is done by Tailwind v4 with a CSS-first config. All of it — fonts, the brand and neutral colour scales, semantic tokens, the container rule — is 133 lines in src/app/globals.css:
@theme {
--font-sans: var(--font-outfit), ui-sans-serif, system-ui, sans-serif;
/* Brand / primary scale */
--color-primary: #465fff;
--color-primary-500: #465fff;
--color-primary-600: #3641f5;
/* Neutral gray scale */
--color-gray-800: #1d2939;
--color-gray-900: #101828;
}
That file is the whole design system, and the 84 KB stylesheet above is what 840 pages of it compile to. The Bootstrap comparison here is not about file size — a minified Bootstrap build is in the same order of magnitude — it is about which direction the work runs. Bootstrap gives you a finished .btn and .card and you override them toward your brand. A token file gives you your brand and you build the components. The first is faster to a page that looks like Bootstrap; the second is faster to a page that looks like yours.
The four combinations, and who each suits
| Stack | Suits | Watch out for |
|---|---|---|
| Gatsby + Bootstrap | A React team with content in a CMS that wants stock components now | The CSS conflict the install tutorials warn about; two opinionated systems to keep current |
| Gatsby + Tailwind | A React team that wants custom design and a GraphQL data layer | Gatsby's plugin ecosystem has slowed since Netlify acquired it and shut Gatsby Cloud in 2023 — check that the plugins you need are maintained |
| Next.js + Bootstrap | A team with existing Bootstrap markup to port, migrating off a server-rendered stack | React-Bootstrap wrappers lag Bootstrap releases; overrides accumulate |
| Next.js + Tailwind | Custom design, content in the repo or an API, static output | You build components rather than inheriting them — a template solves exactly this |
Nothing in the first three is wrong. The point is that "Gatsby vs Bootstrap" resolves into two independent picks, and the only pair that interferes with itself is Gatsby plus Bootstrap, because both want to own your CSS build.
For the depth on each half: React vs Gatsby is the page-generation side — what the GraphQL layer buys and what it costs — and React vs Bootstrap is the styling side, measured against this same stylesheet.
Costs neither tool lists
Gatsby's data layer is a second schema. Every source gets a plugin, and the plugin decides the node shape your queries depend on. A typed array has a schema too — the TypeScript interface — but it is the same schema your editor already autocompletes, and no build step stands between you and it.
Bootstrap's grid is a dependency in your markup. Class names like col-md-6 are a contract with a specific major version. Upgrading means a markup pass, not a stylesheet swap. A utility system has the same property, which is why this repo treats class strings as pixel-faithful and refuses to "tidy" them during refactors.
Both put build-time behaviour where you will not look for it. The defect this repo hit is a fair example from the Tailwind side: with Turbopack, editing @theme in globals.css does not hot-reload, so a newly added colour token silently generates no utility class until the dev server restarts. Nothing errors. You just get an element with no background and twenty minutes of staring at it. Every tool on this page has one of these; ask about them before you adopt, because the manual will not volunteer them.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Bootstrap styles fight the framework's own CSS | Both stylesheets load; specificity decides | Import Bootstrap first, keep overrides in one layer, do not interleave |
col-* classes do nothing | The grid CSS was not imported, only the JS bundle | Import the stylesheet, not just the components |
| A new design token generates no utility class | Dev server caching the theme block | Restart the dev server after editing theme variables |
| Build passes locally, fails in CI on types | A dev-only tolerance, like lowercase JSX element names | Run the production build locally before pushing |
| Static build cannot see new content | A new page was not registered with the route's params | Register it explicitly rather than relying on a glob |
| Pages render but the data is empty | GraphQL query shape does not match the plugin's node shape | Inspect the schema in the data explorer before writing the query |
Frequently asked questions
Can I use Bootstrap with Gatsby? Yes — install React-Bootstrap and import the stylesheet, which is what most of the tutorials ranking for this comparison actually teach. Expect a CSS conflict during setup — the tutorials name it as the one caveat — and expect to own both upgrade paths afterwards.
Is Gatsby still a good choice in 2026? It still builds static React sites well, and its content-mesh approach is genuinely useful when you have many data sources. Check maintenance on the specific plugins you need first: Netlify acquired Gatsby in 2023 and retired Gatsby Cloud, and the plugin ecosystem has been quieter since.
Is Bootstrap worth it if I already use React? Only if you want its component look. React-Bootstrap gives you the components as React, but you are still overriding a design system toward your own, and the override tax never stops. Is Tailwind worth it argues the other direction with numbers.
What replaces both? A page generator plus a token-based stylesheet — here, Next.js and Tailwind v4, 13 dependencies for 840 static pages. The honest catch is that you start with no components, which is the problem a finished template removes.
Start from a finished front end
If you are weighing these tools to get a marketing site launched, the fastest path is neither tool: start from a project that already made both picks and ships with the components built.
ASoc Coin is an online banking website template, ASoc Compound an investment platform landing page, and ASoc Cortex an AI agency website template — each statically rendered, typed end to end, and yours to edit.
Browse the full set of Next.js landing page templates, or the Tailwind landing page templates if you want the styling layer without the framework opinion.
