Components
Any .vue file in components/ is available everywhere by its PascalCase name: components/price-card.vue or PriceCard.vue becomes <PriceCard />. No imports needed.
<script setup>
defineProps({ title: String, items: { type: Array, default: () => [] } });
</script>
<template>
<section>
<h2>{{ title }}</h2>
<slot />
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
<slot name="footer" />
</section>
</template>
<PriceCard title="Pro" :items="data.plans">
Body goes in the default slot.
<template #footer>Named slot</template>
</PriceCard>
This is plain Vue 3 (v-if, v-for, :prop, slots, <script setup>, computed, imports) rendered once at build time. Nothing is hydrated in the browser. Scaffold one with static add component price-card.
Unknown components and undefined template variables fail the build with the file and component named. Don't ignore them.
Globals in every template
| name | what |
|---|---|
site | data/site.json |
data | every other data/*.json, as data.<filename> |
env | only PUBLIC_* environment variables |
page | current page (title, url, canonical, description, post) |
navigation | nav items with url and isActive |
collections | collections.posts etc., arrays of entries |
currentYear, dev | the year, and true under static dev |
tagUrl(collection, tag) | URL of a tag page |
| frontmatter keys | everything in the page's frontmatter; the data page as variable too |
In <script setup>, get them with:
import { useStatic } from '@static';
const { site, data, page } = useStatic();
Browser JavaScript
<script setup> only runs at build time. For code that runs in the browser (a lightbox, a menu toggle) add a separate <script client> block to a component or page. It is minified and emitted once per page, and only on pages where the component rendered:
<template><button id="menuBtn">Menu</button></template>
<script client>
document.getElementById('menuBtn').addEventListener('click', () => { /* ... */ });
</script>
Built-in components
A project component with the same name overrides a built-in.
| component | use |
|---|---|
<Image src="hero.jpg" alt="..." sizes="..." priority /> | <picture> with AVIF/WebP srcset, width and height, lazy loading, for files in images/ and note media |
<Icon name="PieChart" class="size-6" /> | inline Lucide icon, PascalCase or kebab-case |
<ThemeToggle /> | dark/light switch; the theme is applied before first paint |
<Lightbox :images="[...]" alt="Name" noun="screenshot" /> | scrolling thumbnails and a full-screen viewer (arrow keys, Esc) |
<NoteImages :images="post.images" /> | the image grid used by notes |
<BlogPost />, <BlogList /> | default layouts for collection entries and listings |
The built-ins live in the CLI (lib/builtins/components/). To customise one, create a project component with the same name, optionally starting from a copy of the original.