shadcn.io is an independent project built on shadcn/ui
Gatsby takes more setup than the other frameworks: its starter installs Tailwind CSS v3, which can't build these components, and its webpack doesn't read TypeScript's aliases. Both are fixable in a few files. For a new site, Next.js or Astro start with everything in place.
Tailwind CSS v4 and React 19
The components use Tailwind CSS v4 and are written for React 19. Steps 2 and 4 below move a Gatsby site to v4 and check its React version.
Set up a Gatsby site
Create the site, if you need one
npm init gatsbyAnswer TypeScript when it asks for a language: the components are .tsx files. Skip the styling system question; the next step sets up Tailwind CSS v4.
Set up Tailwind CSS v4 with PostCSS
bun add tailwindcss @tailwindcss/postcss postcss gatsby-plugin-postcssAdd the plugin to gatsby-config.ts:
import type { GatsbyConfig } from "gatsby";
const config: GatsbyConfig = {
plugins: ["gatsby-plugin-postcss"],
};
export default config;Create postcss.config.js at the root:
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
};Create src/styles/global.css and load it on every page from gatsby-browser.tsx:
@import "tailwindcss";import "./src/styles/global.css";A site that already has Tailwind CSS v3 can run npx @tailwindcss/upgrade instead: it moves the config, the PostCSS plugin and the stylesheet to v4. Tailwind's Gatsby guide (opens in a new tab) has the same steps.
Add the @ alias for TypeScript and webpack
TypeScript reads the alias from tsconfig.json:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}Gatsby's webpack doesn't, so repeat it in gatsby-node.ts (create the file if it's missing):
import path from "node:path";
import type { GatsbyNode } from "gatsby";
export const onCreateWebpackConfig: GatsbyNode["onCreateWebpackConfig"] = ({
actions,
}) => {
actions.setWebpackConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
});
};One @ alias covers every import the components use: @/components/ui, @/lib/utils and @/hooks.
Check React
npm ls reactThe components take ref as a regular prop, the way React 19 passes it. On React 18 they render and work, but a ref you pass to one doesn't reach its element.
Run init
The CLI detects Gatsby from gatsby-config and finds src/styles/global.css by its @import "tailwindcss" line: that's where the theme goes.
Add a component and use it
import { Button } from "@/components/ui/button";
export default function IndexPage() {
return (
<main className="flex min-h-svh items-center justify-center">
<Button>Click me</Button>
</main>
);
}FAQ
Can I keep Tailwind CSS v3 in my Gatsby site?
Not for these components. They and the theme rely on v4: @theme, @custom-variant and CSS variables for every color. npx @tailwindcss/upgrade moves most sites over in one run.
Why does the build fail with “Can't resolve '@/components/ui/button'”?
The alias is only in tsconfig.json. Gatsby bundles with webpack, which needs its own alias: add onCreateWebpackConfig to gatsby-node.ts as in step 3, then restart gatsby develop.
My site is JavaScript. Can I still use the components?
The files the CLI adds are TypeScript (.tsx). Gatsby compiles TypeScript out of the box, so they run in a JavaScript site; add a tsconfig.json with the @/* alias for the CLI to read.
Do the components work with Gatsby's static rendering?
Yes. Gatsby renders each page to HTML at build time, then hydrates it. Components that need the browser (overlays, menus) do their work after hydration, so nothing touches window during the build.
What happens on React 18?
Most things work, but a ref you pass to a component doesn't reach its element: React 18 strips ref from a function component's props, and the components read it as a prop the way React 19 does. Check npm ls react before you rely on refs.
Where should the global CSS be imported?
In gatsby-browser.tsx, so it loads on every page. Import it in gatsby-ssr.tsx too if you want it in the server-rendered HTML before the bundle loads.