Configuration Reference

defineConfig()

Defined in @karaoke-cms/astro. Import:

import { defineConfig } from '@karaoke-cms/astro';

KaraokeConfig type

interface KaraokeConfig {
  vault?:       string;
  title?:       string;
  description?: string;
  theme?:       string | ThemeInstance;
  modules?:     (ModuleInstance | ModuleInstance[])[];
  collections?: Record<string, CollectionConfig>;
  comments?:    CommentsConfig;
  layout?: {
    regions?: {
      top?:    { components?: RegionComponent[] };
      left?:   { components?: RegionComponent[] };
      right?:  { components?: RegionComponent[] };
      bottom?: { components?: RegionComponent[] };
    };
  };
}

Top-level options

NameTypeRequiredDefaultDescription
vaultstringNoproject rootPath to the Obsidian vault root. Absolute or relative to the Astro project root. Set via KARAOKE_VAULT in .env.default.
titlestringNo'Karaoke'Site title — shown in browser tab and nav bar.
descriptionstringNoSite description — used in RSS feed and OG meta tags.
themestring | ThemeInstanceYesTheme instance from defineTheme(). Pass themeDefault(), themeMinimal(), etc.
modules(ModuleInstance | ModuleInstance[])[]No[]Modules to activate. karaoke() flattens nested arrays automatically.
collectionsRecord<string, CollectionConfig>NoPer-collection mode and label overrides. Merges with built-in defaults; this field takes precedence.
commentsCommentsConfigNoGiscus configuration. Also used by comments() module.
layoutobjectNoLayout region component placement.

CollectionConfig type

interface CollectionConfig {
  modes?: ('dev' | 'prod')[];
  label?: string;
}

CommentsConfig type

interface CommentsConfig {
  enabled?:    boolean;
  repo?:       string;   // "owner/repo"
  repoId?:     string;
  category?:   string;
  categoryId?: string;
}

blog()

Package: @karaoke-cms/module-blog

import { blog } from '@karaoke-cms/module-blog';

blog(config?: BlogConfig): ModuleInstance

BlogConfig options

NameTypeDefaultDescription
mountstring'' (root)URL prefix for all blog routes.
idstring'blog'Module identifier. Rarely needs changing.
enabledbooleantrueWhen false, routes and menu entries are not injected.
commentsbooleantrueDefault comments visibility for all posts. Overridable per-post via frontmatter.

Routes injected

PatternDescription
{mount}Post list (page 1)
{mount}/[slug]Individual post
{mount}/page/[page]Paginated list
SectionEntryWeight
mainBlog → {mount}10
footerRSS → /rss.xml10

docs()

Package: @karaoke-cms/module-docs

Two call signatures:

import { docs } from '@karaoke-cms/module-docs';

// Single section
docs(config?: DocsConfig): ModuleInstance

// Multiple sections
docs(sections: DocsSection[]): ModuleInstance[]

DocsConfig options (single-section form)

NameTypeDefaultDescription
mountstring'/docs'URL prefix for this docs section.
folderstringmount without leading /Vault subfolder containing markdown files.
idstringfolder with /-Astro collection name. Must be unique across all docs instances.
labelstringid in Title CaseNav label and page heading.
enabledbooleantrueWhen false, excluded from build.
commentsbooleanfalseDefault comments visibility for pages in this section. Overridable per-page via frontmatter.
layoutstring'default'Layout component override.
sidebarStylestring'tree'Sidebar style: 'flat' or 'grouped'.

DocsSection fields (array form)

Each element of the DocsSection[] array has the same fields as DocsConfig plus:

NameTypeDefaultDescription
weightnumber20Menu weight for ordering. Blog = 10, Tags = 30. Use 11–29 to appear between them.
parentstringId of a root-level nav entry to nest this section under. Single-level only. Falls back to root if not found.

Routes injected (per instance, via codegen)

PatternDescription
{mount}Docs home — list of all doc titles
{mount}/listFull docs list page
{mount}/[slug]Individual doc page with sidebar
SectionEntryWeight
main{label}{mount}weight (default 20)

tags()

Package: @karaoke-cms/module-tags

import { tags } from '@karaoke-cms/module-tags';

tags(config?: TagsConfig): ModuleInstance

TagsConfig options

NameTypeDefaultDescription
mountstring'/tags'URL prefix for tags routes. Cannot be '/' or empty.
enabledbooleantrueWhen false, routes are not injected.

Routes injected

PatternDescription
{mount}All-tags index
{mount}/[tag]Per-tag post list
{mount}/[tag]/rss.xmlPer-tag RSS feed
SectionEntryWeight
mainTags → {mount}30

Package: @karaoke-cms/module-search

import { search } from '@karaoke-cms/module-search';

search(config?: { mount?: string; enabled?: boolean }): ModuleInstance

Options

NameTypeDefaultDescription
mountstring'/search'URL for the search page.
enabledbooleantrueWhen false, routes are not injected.

Routes injected

PatternDescription
{mount}Full-text search page (Pagefind)
SectionEntryWeight
mainSearch → {mount}90

Notes

Runs pagefind on the built dist/ directory after astro:build:done. In dev mode, serves the pre-built Pagefind index from dist/pagefind/ — run pnpm build once first to generate the index.


comments()

Package: @karaoke-cms/module-comments

import { comments } from '@karaoke-cms/module-comments';

comments(config: CommentsConfig): ModuleInstance

CommentsConfig options

NameTypeRequiredDefaultDescription
repostringYesGitHub repo in "owner/repo" format. Must have Discussions enabled.
repoIdstringYesGitHub repo ID from giscus.app.
categorystringNo'General'GitHub Discussions category name.
categoryIdstringNo''GitHub Discussions category ID from giscus.app.
enabledbooleanNotrueWhen false, module is excluded from the build.

Routes injected

None. The Giscus widget is embedded by the theme on individual post/doc pages.

None.


seo()

Package: @karaoke-cms/module-seo

import { seo } from '@karaoke-cms/module-seo';

seo(config?: SeoConfig): ModuleInstance

SeoConfig options

NameTypeDefaultDescription
disallowstring[]['/karaoke-cms/']URL paths to block in robots.txt.
llmsTxtbooleantrue (when site is set)When false, skip /llms.txt.
llmsSiteTitlestringhostname# title in llms.txt.
llmsTxtExtrastringExtra Markdown appended to llms.txt.
contentManifestbooleantrue (when site is set)When false, skip karaoke-public-content.json.

Routes injected

None. Runs at astro:build:done to generate OG images, JSON-LD, robots.txt, optional llms.txt, and optional karaoke-public-content.json.

None.


Layout regions

Place built-in UI components into layout regions via karaoke.config.ts:

layout: {
  regions: {
    right: { components: ['recent-posts'] },
    top:   { components: ['header', 'main-menu'] },
  },
},

RegionComponent values

ValueDescription
'header'Site header with title
'main-menu'Primary navigation menu
'search'Search input
'recent-posts'Recent posts sidebar widget
'footer'Site footer

Region positions

RegionDefault contents
top
left
right
bottom

Minimal working example

// karaoke.config.ts
import { defineConfig } from '@karaoke-cms/astro';
import { loadEnv } from '@karaoke-cms/astro/env';
import { blog } from '@karaoke-cms/module-blog';
import { docs } from '@karaoke-cms/module-docs';
import { tags } from '@karaoke-cms/module-tags';
import { search } from '@karaoke-cms/module-search';
import { seo } from '@karaoke-cms/module-seo';
import { comments } from '@karaoke-cms/module-comments';
import { themeDefault } from '@karaoke-cms/theme-default';

const env = loadEnv(new URL('.', import.meta.url));

export default defineConfig({
  vault:       env.KARAOKE_VAULT,
  title:       'My Site',
  description: 'What this site is about.',
  theme:       themeDefault(),
  modules: [
    blog({ mount: '/blog', comments: true }),
    docs({ mount: '/docs' }),
    tags(),
    search(),
    seo(),
    comments({
      repo:       'owner/repo',
      repoId:     'R_...',
      category:   'General',
      categoryId: 'DIC_...',
    }),
  ],
});