Skip to content

Astro

This guide walks through setting up NemCSS in an Astro project using @nemcss/vite via Astro's vite config option.

Vite plugin type compatibility

There is a known type compatibility issue between Vite plugins built against Vite 7 and Astro projects that still use Vite 6. You may see the following TypeScript error:

Type 'Plugin[]' is not assignable to type 'PluginOption'

If you hit this, add // @ts-expect-error above the plugin line in your Astro config (see Step 3), or use @nemcss/postcss instead.

See withastro/astro#14030 for more details.

Step 1: Create an Astro project

sh
npm create astro@latest
sh
pnpm create astro@latest
sh
yarn create astro

Step 2: Install @nemcss/vite

sh
npm install -D @nemcss/vite
sh
pnpm add -D @nemcss/vite
sh
yarn add -D @nemcss/vite
sh
bun add -D @nemcss/vite

Step 3: Add the plugin to your Astro config

js
// astro.config.mjs
import { defineConfig } from "astro/config";
import { nemcss } from "@nemcss/vite";

export default defineConfig({
  vite: {
    plugins: [
      // @ts-expect-error: Vite plugin type mismatch between Vite 6 (Astro) and Vite 7
      nemcss(),
    ],
  },
});

Step 4: Initialize nemcss

sh
npx nemcss init
sh
pnpm dlx nemcss init
sh
yarn dlx nemcss init

This creates a minimal nemcss.config.json and an empty design-tokens/ folder.

Step 5: Add design tokens

Create a color and a spacing token file with new-token-file. It registers each one in your config as it creates it:

sh
npx nemcss new-token-file colors --prefix color --values "hsl(0, 0%, 100%),hsl(0, 0%, 0%)" --names "white,black"
npx nemcss new-token-file spacings --prefix spacing --unit rem --values "0.5,1,1.5" --names "sm,md,lg"

Add a padding utility to the spacings entry, and a text semantic group so text-default and text-muted are available, by editing nemcss.config.json:

json
{
  "theme": {
    "spacings": {
      "prefix": "spacing",
      "source": "design-tokens/spacings.json",
      "utilities": [{ "prefix": "p", "property": "padding" }]
    }
  },
  "semantic": {
    "text": {
      "property": "color",
      "tokens": {
        "default": "{colors.black}",
        "muted": "{colors.white}"
      }
    }
  }
}

Step 6: Configure content paths

Edit nemcss.config.json to point at your Astro components and pages:

json
{
  "content": ["src/**/*.astro", "src/**/*.ts", "src/**/*.tsx"],
  "tokensDir": "design-tokens"
}

Step 7: Add the directives to a global CSS file

Create src/styles/global.css:

css
@nemcss base;
@nemcss utilities;

Step 8: Import the global CSS in your layout

astro
---
// src/layouts/Layout.astro
import '../styles/global.css'
---
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Astro site</title>
  </head>
  <body>
    <slot />
  </body>
</html>

Step 9: Use the generated classes

astro
---
// src/pages/index.astro
import Layout from '../layouts/Layout.astro'
---
<Layout>
  <h1 class="text-default">Hello NemCSS</h1>
  <p class="p-md text-muted">Styled with design tokens.</p>
</Layout>

Step 10: Start the dev server

sh
npm run dev
sh
pnpm dev
sh
yarn dev

HMR is enabled by default. Your CSS updates without a full page reload when you change a token file, your config, or any content file.