The .n file
A .n file is Pug on top, a Civet script block below, and an optional style block — no wrappers, no lang attributes.
section.space-y-4
h1.text-4xl.font-bold Notes
+each('data.notes as note (note.id)')
Card(href!="/notes/{note.id}")
.font-semibold {note.title}
<script>
{ data } := $props()
</script>#What the preprocessor does with it
The norns-default-langs step runs first on every file whose name ends in .n:
- Auto-close. If the file ends inside a
<script>or<style>block with no closing tag, the tag is appended. The reference apps use this: a component can end with the script block and nothing else. - Rewrites.
+ifchains,+snippetblocks and class shorthand are rewritten (next pages). - Auto-wrap. When there is no
<template>tag, everything outside<script>and<style>blocks is wrapped in<template lang="pug">and the blocks are appended after it. - Defaults. A
<script>withoutlanggetslang="civet"; a<template>withoutlanggetslang="pug".
Then norns-civet-script compiles every <script lang="civet"> (or lang="cv") block to JavaScript with source maps and drops the lang attribute so svelte-preprocess does not look for a Civet transformer. Finally svelte-preprocess renders the Pug template (and handles lang="ts" scripts, should you write one).
#Writing it explicitly
All of these are equivalent to the defaults and allowed:
<template lang="pug">
section ...
</template>
<script lang="civet">
</script>A .svelte file never goes through the .n defaults; it is compiled exactly as Svelte would, even with this preprocessor installed. Use that when you want a plain Svelte component next to your .n ones.
#Styles
<style> blocks work as in Svelte and are scoped. Both reference apps keep styling in Tailwind utilities and per-feature CSS files instead.