Skip to content

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

sh
bun add vitepress vue scavold

Or with npm:

sh
npm install vitepress vue scavold

2. 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.json

3. .cratly.config.yaml

Scavold reads site structure from this file at the project root.

yaml
version: 0

pages_folder: pages
media_folder: media
static_folder: public

augmentConfig() reads these paths and wires them into VitePress automatically — you do not need to set srcDir or vite.publicDir manually.

4. .vitepress/config.js

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 function

Setting 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:

js
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.

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:

js
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.

vue
<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

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

json
{
  "scripts": {
    "dev":     "bunx --bun vitepress dev",
    "build":   "bunx --bun vitepress build",
    "preview": "bunx --bun vitepress preview"
  }
}

9. Run

sh
bun run dev

VitePress starts the dev server. Changes to Markdown files hot-reload automatically.


Next steps