Quick Start
This guide walks you through setting up a new VitePress site using Scavold as its theme base.
Prerequisites
- Bun (recommended) or Node.js ≥ 18
- A new or existing project directory
1. Install dependencies
bun add vitepress vue scavoldOr with npm:
npm install vitepress vue scavold2. Folder layout
Create the following structure:
my-site/
.vitepress/
theme/
index.js ← theme entry point
Layout.vue ← root layout component
style.css ← site styles
config.js ← VitePress + Scavold config
pages/ ← Markdown content
index.md
media/ ← source images and videos
public/ ← static assets served at site root
.cratly.config.yaml
.gitignore
package.json3. .cratly.config.yaml
Scavold reads site structure from this file at the project root.
version: 0
pages_folder: pages
media_folder: media
static_folder: publicaugmentConfig() reads these paths and wires them into VitePress automatically — you do not need to set srcDir or vite.publicDir manually.
4. .vitepress/config.js
import { defineConfig } from "vitepress";
import { augmentConfig } from "scavold/config";
export default defineConfig( await augmentConfig( {
title: "My site",
description: "…",
vite: {
ssr: {
noExternal: [ "scavold" ],
},
},
} ) );Why vite.ssr.noExternal?
Scavold's theme entry (lib/index.js) uses import.meta.glob to auto-register all its Vue components. That is a Vite-specific transform that only runs on files Vite processes as source. When a package is installed in node_modules Vite normally treats it as a pre-built external module and skips the transform — causing the SSR render to fail with:
import.meta.glob is not a functionSetting noExternal: ["scavold"] tells Vite's SSR bundler to process Scavold as source rather than loading it as-is. The glob is then resolved correctly at build time relative to the package's own components/ directory.
5. .vitepress/theme/index.js
Scavold uses @cepharum/vue3-i18n for its own UI strings (breadcrumb labels, locale switcher, etc.) under the @scavold namespace. scavoldEnhanceApp sets this namespace up automatically — you do not need to configure anything for Scavold's own strings to work.
If your site has no custom translated strings of its own, the minimal setup is:
import Layout from "./Layout.vue";
import { enhanceApp as scavoldEnhanceApp } from "scavold";
import "./style.css";
export default { Layout, enhanceApp: scavoldEnhanceApp };If you write your own enhanceApp function — for any reason, not just i18n — await scavoldEnhanceApp first. It registers all Scavold components globally, so anything that depends on those components being available must come after it. Its second argument takes options for the theme; gridImageSizes sets the image sizes in a grid by column count.
If you want to add your own translated UI strings using the same @cepharum/vue3-i18n library, register a loader for your site's namespace in addition:
import Layout from "./Layout.vue";
import { enhanceApp as scavoldEnhanceApp } from "scavold";
import { useL10n } from "@cepharum/vue3-i18n";
import "./style.css";
async function enhanceApp( context ) {
await scavoldEnhanceApp( context );
useL10n().setLoader( locale =>
import( `./l10n/${locale}.json` ).catch( () => import( "./l10n/en.json" ) )
);
}
export default { Layout, enhanceApp };You are not required to use @cepharum/vue3-i18n for your site's own strings — any other i18n library works alongside Scavold's internal use of it without conflict.
6. .vitepress/theme/Layout.vue
Wrap your site shell in <ScavoldLayout> to get locale redirect handling for free. All Scavold components are globally registered so no explicit imports are needed.
<script setup>
import { useData } from "vitepress";
const { frontmatter } = useData();
</script>
<template>
<ScavoldLayout>
<header>
<ScavoldMenu :from-root="1" label="Main navigation" />
<ScavoldLocaleMenu />
</header>
<main id="main-content">
<ScavoldBreadcrumb />
<Content />
</main>
<footer>
<!-- site footer -->
</footer>
</ScavoldLayout>
</template>7. .gitignore
node_modules
.vitepress/cache
.vitepress/dist
# generated responsive image variants
public/media/**/*--*w-????????.*The glob pattern for generated image variants keeps the source images in version control while excluding the derived variants that Scavold regenerates on every build.
8. package.json scripts
{
"scripts": {
"dev": "bunx --bun vitepress dev",
"build": "bunx --bun vitepress build",
"preview": "bunx --bun vitepress preview"
}
}9. Run
bun run devVitePress starts the dev server. Changes to Markdown files hot-reload automatically.
Next steps
- Component reference — all props, slots, and composables
- Front matter reference — all recognised frontmatter keys
- Configuration reference —
augmentConfigoptions and.cratly.config.yamlschema