Astro
NAMCHE in an Astro site — CSS lane for content, React islands where needed.
Astro sites get both lanes of the design system, chosen per page — even per component:
- Content pages (Astro's home turf):
@namche/cssand ordinary markup in.astrocomponents. Zero client JavaScript, which is why you picked Astro. - Interactive islands: the
@namcheregistry via@astrojs/react— the same shadcn components as any product, server-rendered by default and hydrated only where you add aclient:*directive.
Content pages with @namche/css
pnpm add @namche/css/* src/styles/global.css */
@import "@namche/css";Import the stylesheet once (in your base layout or via Astro's global style handling) and write plain HTML with the documented classes. Astro's bundler resolves the package imports; nothing else is needed.
Interactive islands with the registry
Add React and Tailwind v4 to the site:
pnpm astro add react
pnpm add tailwindcss @tailwindcss/vite// astro.config.mjs
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
integrations: [react()],
vite: { plugins: [tailwindcss()] },
});Then follow the standard installation: shadcn init -b base, register @namche in components.json, shadcn add @namche/theme and
wire the global stylesheet exactly as documented there. Components land in
your own src/components/ui/ and render inside .astro files:
---
import { Button } from "@/components/ui/button";
import { Dialog, DialogTrigger, DialogContent } from "@/components/ui/dialog";
---
<Button>Static — rendered to HTML, no JS shipped</Button>
<Dialog client:load>…</Dialog>A component without a client:* directive is rendered to static HTML — free
NAMCHE styling with no hydration cost. Reserve client:load /
client:visible for components that genuinely need behaviour.
Fonts
Nothing to do with @namche/design-tokens 1.2.0 or later: every face —
Namche Shadow and Geist — loads from cdn.namche.ai via the tokens'
@font-face rules, and the token stacks already name them. The geist npm
package from the installation page is a Next.js
(next/font) alternative and does not apply here.
On older token versions Geist is the consumer's job — self-host it:
pnpm add @fontsource-variable/geist @fontsource-variable/geist-mono// in your base layout
import "@fontsource-variable/geist";
import "@fontsource-variable/geist-mono";@theme inline {
--font-sans: "Geist Variable", "Geist Sans", ui-sans-serif, system-ui;
--font-display: "Namche Shadow Sans", "Geist Variable", ui-sans-serif;
--font-mono: "Namche Shadow Mono", "Geist Mono Variable", ui-monospace;
}(On a pure CSS-lane site without Tailwind, set the same three variables in a
plain :root block instead of @theme inline.)
Dark mode
There is no next-themes here; the contract is just the dark class on
<html>. A few inline lines in the base layout keep it flash-free:
<script is:inline>
const stored = localStorage.getItem("theme");
const dark = stored ? stored === "dark"
: matchMedia("(prefers-color-scheme: dark)").matches;
document.documentElement.classList.toggle("dark", dark);
</script>Both lanes follow automatically — every colour is a variable that flips with the class.