Sites
Site-scoped settings live in either site (singular, one site) or sites (plural map, multiple sites). Each entry is a SiteConfig with the same set of fields.
Single-site
Most projects have one site:
{
"$schema": "https://refrakt.md/schemas/v0.11/refrakt.config.schema.json",
"site": {
"contentDir": "./content",
"theme": "@refrakt-md/lumina",
"target": "svelte"
}
}
The SvelteKit plugin (and other adapters) picks the lone site automatically, so single-site projects don't need to pass a site option. The legacy flat shape (without the site wrapper) still loads but is deprecated in v0.12.0 and slated for removal in v1.0 — see Migration.
Multi-site
Multi-site repos declare named entries under sites:
{
"$schema": "https://refrakt.md/schemas/v0.11/refrakt.config.schema.json",
"sites": {
"main": {
"contentDir": "./site/content",
"theme": "@refrakt-md/lumina",
"target": "svelte",
"baseUrl": "https://example.com"
},
"blog": {
"contentDir": "./blog/content",
"theme": "@refrakt-md/lumina",
"target": "svelte",
"baseUrl": "https://blog.example.com"
}
}
}
Each adapter (SvelteKit, Astro, Nuxt, Next, Eleventy) accepts a site option that selects which entry to build:
// site/vite.config.ts (SvelteKit)
import { sveltekit } from '@sveltejs/kit/vite';
import { refrakt } from '@refrakt-md/sveltekit';
export default defineConfig({
plugins: [
sveltekit(),
refrakt({ configPath: '../refrakt.config.json', site: 'main' }),
],
});
Single-site projects can omit the site option — the plugin picks the only entry automatically. Multi-site projects must pass it explicitly; the plugin throws at config-load time with the available names if it's missing.
CLI --site flag
Site-scoped commands (inspect, contracts, validate, scaffold-css, package validate) accept --site <name>:
# Pick a specific site explicitly
npx refrakt inspect hint --type=warning --site main
# Single-site projects don't need it
npx refrakt inspect hint --type=warning
Unknown site names produce a "did you mean?" suggestion. Plan-only repos (no sites declared) error with a "no site configured" message when site-scoped commands are run.
SiteConfig fields
The complete list of fields a site accepts — with types, defaults and which are required — is the configuration reference, generated from the schema. The sections below cover the two shapes that need explaining rather than listing.
Theme object form
The string form ("theme": "@refrakt-md/lumina") is shorthand for { "package": "@refrakt-md/lumina" }. Use the object form when you need any of:
presets— palette or syntax presets merged into the theme in declared order (last wins per token).tokens— site-level token overrides applied on top of the theme and any presets.modes— per-mode overlays (e.g.dark) layered on top of theme modes and preset modes.code.colorScheme— force fenced code blocks to a fixed scheme (light/dark) regardless of the page's mode.
{
"site": {
"theme": {
"package": "@refrakt-md/lumina",
"presets": ["@refrakt-md/lumina/presets/niwaki"],
"tokens": {
"color": { "primary": "#e15f80" }
},
"modes": {
"dark": { "color": { "primary": "#e8788f" } }
},
"code": { "colorScheme": "dark" }
}
}
}
Example: full site
{
"site": {
"contentDir": "./content",
"theme": {
"package": "@refrakt-md/lumina",
"presets": ["@refrakt-md/lumina/presets/niwaki"],
"code": { "colorScheme": "dark" }
},
"target": "svelte",
"baseUrl": "https://example.com",
"siteName": "My Documentation",
"logo": "/favicon-192.png",
"plugins": ["@refrakt-md/marketing", "@refrakt-md/docs"],
"routeRules": [
{ "pattern": "blog/**", "layout": "blogArticleLayout" },
{ "pattern": "docs/**", "layout": "docsLayout" },
{ "pattern": "**", "layout": "defaultLayout" }
],
"runes": {
"prefer": { "storyboard": "@refrakt-md/marketing" },
"aliases": { "callout": "hint" }
}
}
}
Path resolution
Inside a site entry, paths like contentDir: "./content" are interpreted relative to the vite app's resolved root, not the config file location. So a config at the repo root with site.contentDir: "./content" and a SvelteKit plugin running from site/ resolves content from site/content/. This matters when you split your refrakt.config.json across multiple sites with different vite roots.