Quick start
Get a styled page running in five minutes — with a CDN script, a bundler plugin, or the standalone CLI.
Pick the path that matches your project. All three produce the same CSS; they differ only in when it is generated.
Path | Best for | CSS is generated |
|---|---|---|
A · CDN | Prototypes, static pages, CodePen, learning | In the browser, by a 23 kB script |
B · Bundler | Vite, Next.js, Nuxt, SvelteKit, Astro, Angular | At build time, into a real |
C · CLI | Rails, Django, Laravel, PHP, hand-written HTML | By a command, into |
A · CDN — no build step#
Create an index.html and open it in a browser:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 1. Optional: tokens and component recipes -->
<script type="application/json" data-nib-config>
{
"darkMode": "class",
"tokens": { "color": { "brand": "#4F52D9" }, "space": { "md": "16px" } },
"components": {
"btn": "d=inline-flex; ali=center; g=8px; p=10px $space.md; bdrd=8px; bd=none; cur=pointer; ftw=600; bgc=$color.brand; cl=#fff; hover:bgc=#3A3DBF"
}
}
</script>
<!-- 2. The runtime. Keep it in <head>, without defer / async / type="module". -->
<script src="https://cdn.jsdelivr.net/npm/@nibcss/runtime@1"></script>
</head>
<body nib="ftf=system-ui, sans-serif; p=32px; dark:bgc=#0b0f19; dark:cl=#e2e8f0">
<h1 nib="fts=32px; ftw=800; mb=16px">Hello, NibCSS</h1>
<button nib="btn" onclick="Nib.toggleDarkMode()">Toggle dark mode</button>
</body>
</html>That is the whole setup. Elements added later — by your own scripts or by a framework — are styled automatically.
B · Bundler — Vite, Next.js, Nuxt, SvelteKit, Astro#
1. Install the build plugin and the runtime:
npm i -D @nibcss/unplugin
npm i @nibcss/runtime2. Add the plugin to your bundler:
// vite.config.ts — also SvelteKit, Astro, SolidStart, Qwik, Remix
import { defineConfig } from "vite";
import nib from "@nibcss/unplugin/vite";
export default defineConfig({
plugins: [nib()],
});3. Import the generated stylesheet once, in your entry file:
// src/main.ts, app/layout.tsx, …
import "@nibcss/styles.css";4. Create nibcss.config.ts at the project root. The plugin creates a fully commented one on first run if it is missing — replace its body with:
import { defineConfig } from "@nibcss/core";
export default defineConfig({
darkMode: "class",
tokens: {
color: { brand: "#4F52D9", ink: "#0f172a" },
space: { sm: "8px", md: "16px", lg: "24px" },
},
components: {
btn: "d=inline-flex; ali=center; g=8px; p=8px $space.md; bdrd=8px; cur=pointer; ftw=500",
"btn-primary": "btn; bgc=$color.brand; cl=#fff; hover:bgc=#3A3DBF",
},
});5. Write markup. Every nib="…" in .html, .jsx, .tsx, .vue, .svelte and .astro files is extracted at build time:
export function Hero() {
return (
<section nib="p=48px 24px; txa=center">
<h1 nib="fts=40px; ftw=800">Ship faster</h1>
<a nib="btn-primary; mt=16px" href="/start">Get started</a>
</section>
);
}C · CLI — no bundler#
For Rails, Django, Laravel, PHP or plain HTML files:
npx @nibcss/cli init # writes a commented nibcss.config.ts
npx @nibcss/cli build # scans the project and writes nib.css
npx @nibcss/cli watch # rebuilds on every change<link rel="stylesheet" href="/nib.css" />
<button nib="btn-primary; hover:bgc=#2540b8">Save</button>Check that it works#
Break something on purpose — write trf=rotate(3deg) instead of tf=…. With debug: true in the config you get:
[nib] src/App.tsx:12:18
<div nib="trf=rotate(3deg)">
Unknown utility "trf" — did you mean "t", "tf", "trn"?No CSS is emitted for an unknown shorthand, so a typo never ships broken styles. More on debugging →