Vite plugin
nornsCivetPlugin() compiles Civet modules and teaches Vite the Norns extensions; pugTailwindExtract() closes Tailwind's blind spot on Pug class chains.
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';
import { nornsCivetPlugin, pugTailwindExtract } from '@human-synthesis/norns/vite';
import { nornsAutoImport } from '@human-synthesis/norns/auto-import';
import { presetUI } from '@human-synthesis/norns-ui/auto-import';
const ui = presetUI();
export default defineConfig({
plugins: [
pugTailwindExtract(),
nornsCivetPlugin(),
nornsAutoImport({ components: ui.components }),
tailwindcss(),
sveltekit()
],
server: { allowedHosts: true }
});#nornsCivetPlugin()
Runs with enforce: 'pre' and does four things:
- Compiles
.cand.civetfiles through@danielx/civetwith source maps, so+page.server.c,hooks.server.c,+server.cand any module you write in Civet load like.js. - Registers the extensions
.svelte,.n,.civet,.cwith Vite's resolver, after Vite's defaults, soimport X from './Foo'findsFoo.norFoo.c. - Resolves bare sibling imports.
import { play } from 'store'(no./) resolves to a siblingstore.c/store.n/store.jswhen one exists next to the importer. Package imports are untouched because they contain a slash or a scope; imports from insidenode_modulesare never rewritten. - Workspace mode. When the framework packages resolve to symlinks outside
node_modules(the framework's own development workspace), they are excluded from dependency pre-bundling and lifted out of the watch ignore list so edits to the framework source hot-reload. Published installs never enter this branch.
#pugTailwindExtract(options?)
Tailwind v4's scanner extracts class candidates from string contexts. Pug's chained shorthand, .flex.items-center.p-4, reads as one dotted token and is dropped, and .grid.gap-6(class="...") loses the class before the paren. The page renders with the classes in the HTML but no CSS for them.
The plugin walks every .n file, extracts each shorthand class with extractPugClasses from norns-core, and writes the deduplicated set into a sidecar HTML file that Tailwind can scan. It re-runs on every .n change in dev.
| Option | Default | Notes |
|---|---|---|
root |
'src' |
directory to scan |
ext |
'.n' |
file extension |
outFile |
'node_modules/.cache/norns/tailwind-pug-classes.html' |
sidecar path, relative to the project root, taken verbatim |
Reference the sidecar from your CSS, with a path relative to the CSS file:
@import 'tailwindcss';
@source "./**/*.n";
@source "../node_modules/.cache/norns/tailwind-pug-classes.html";The first @source is the raw scan, which handles chains that end at whitespace; the sidecar covers the rest.
#Vite options worth setting
server.allowedHosts: true(or an explicit list) when the dev server sits behind any reverse proxy.norns lintwarns when it is missing.- In the framework workspace only:
resolve.dedupe: ['@sveltejs/kit']andssr.noExternal: ['@human-synthesis/norns'], so the symlinked norns package uses the app's single copy of SvelteKit instead of the fork's. A normal install does not need either.