Configuration
Site config, theme options, and common frontmatter fields
Configuration lives in .preactpress/config.ts at your site root.
Site metadata#
export default {
site: {
title: "My docs",
description: "Short site summary for SEO",
base: "/",
url: "https://example.com",
titleTemplate: ":title | :siteTitle",
},
};
Set site.url before production so canonical URLs, sitemap.xml, Open Graph, and hreflang alternates resolve correctly.
Content directory#
| Option | Purpose |
|---|---|
srcDir |
Folder with .md / .mdx pages (default .) |
srcExclude |
Glob patterns for non-page Markdown, e.g. ['**/README.md'] |
lastUpdatedGit |
Use git commit time for “last updated” (falls back to file mtime) |
Theme without custom code#
themeConfig drives the default layout:
nav— top links; supports nested dropdowns viaitemssidebar— flat array or path map:{ '/guide/': [...], '/reference/': [...] }; groups and items supportcollapsedand nesteditemsoutline,search,socialLinks,footer,lastUpdated,editLink,logo,labelslogo— string URL or{ light, dark }for theme-aware imagessearch—trueor{ provider: 'local' }for sidebar search;{ provider: 'algolia', options }for Algolia DocSearch in the nav barsocialLinks—{ icon, link, ariaLabel? }[]with built-in icons (github,discord,x, …) or custom{ svg }
Per-locale overrides go under locales.<key>.themeConfig.
Example nested nav and sidebar:
themeConfig: {
logo: { light: '/logo-light.svg', dark: '/logo-dark.svg' },
labels: { search: 'Find pages' },
nav: [
{ text: 'Guide', items: [{ text: 'Intro', link: '/guide/intro' }] },
{ text: 'Blog', link: '/blog' }
],
sidebar: [
{
text: 'Guide',
collapsed: false,
items: [
{ text: 'Intro', link: '/guide/intro' },
{
text: 'Advanced',
collapsed: true,
items: [{ text: 'API', link: '/guide/api' }]
}
]
}
]
}
Search providers#
Local search (default when search: true) filters the sidebar and loads preactpress-search.json at build time.
Algolia DocSearch mounts a search button in the nav bar:
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'YOUR_INDEX_NAME',
locales: {
de: { indexName: 'YOUR_DE_INDEX' }
}
}
}
}
Social links#
themeConfig: {
socialLinks: [
{ icon: "github", link: "https://github.com/kamod-ch/preactpress" },
{ icon: { svg: "<svg ...></svg>" }, link: "https://example.com", ariaLabel: "Company site" },
];
}
Global head tags#
head: [
['meta', { name: 'theme-color', content: '#0f766e' }]
],
async transformHead({ route, title, tags, site }) {
return [['meta', { name: 'pp-route', content: route }]]
}
Build hooks#
Hooks run during dev and build unless noted otherwise.
async transformPageData(page, { route, site }) {
if (page.kind !== 'markdown') return page
return {
...page,
meta: { ...page.meta, sourceRoute: route }
}
},
async transformHtml(html, { route }) {
return html.replace('</body>', `<!-- built:${route} --></body>`)
},
async buildEnd({ site, pages }) {
console.log(`Built ${pages.length} pages to ${site.outDir}`)
}
Async config#
Export a factory to load nav or sidebar from an API at config time:
import { defineConfig } from "@kamod-ch/preactpress/config";
export default defineConfig(async () => ({
site: { title: "My docs", description: "Docs from CMS" },
themeConfig: {
nav: await fetchNav(),
sidebar: await fetchSidebar(),
},
}));
Page frontmatter#
| Field | Purpose |
|---|---|
title / description |
Page title and SEO summary |
titleTemplate |
Override site template; false uses the raw page title |
head |
Extra <meta> / <link> / <script> tags for this page only |
draft: true |
Excluded from routes, search, and sitemap |
Example per-page head:
---
title: About
head:
- - meta
- name: author
content: Your Name
---
WARNING
Enable markdown.html only for trusted authors — it allows raw HTML in Markdown.