Client API
Everything needed to build a custom layout is exported from typerighter/client.
import {
Content,
useRoute,
useRouter,
useSiteConfig,
useSiteData,
useTdContent,
useTheme,
} from 'typerighter/client'useRoute
Returns the current route as a reactive object. Updates on every navigation.
const route = useRoute()
route.path // "/guide/introduction"
route.hash // "#getting-started"
route.data // PageData for the current pagePageData
interface PageData {
title: string
titleHtml: string // title with inline markup, safe for v-html
headings: MarkdownHeading[] // nested heading tree (h1 to h6)
frontmatter: Record<string, unknown>
schema?: string // schema type name if page uses a schema
schemaLabel?: string
label?: string // _label override
filepath: string // path relative to vault root, e.g. "guide/intro.td"
fileMetadata?: { mtime: number; ctime: number }
}MarkdownHeading
interface MarkdownHeading {
level: number // 1 to 6
title: string // plain text
titleHtml: string // HTML with inline code/math, safe for v-html
slug: string // anchor id (deduplicated)
link: string // e.g. "#getting-started"
children: MarkdownHeading[]
}Headings are returned as a nested tree. To flatten for a TOC:
function flattenHeadings(items: MarkdownHeading[], depth = 2) {
const result = []
for (const h of items) {
if (h.level <= depth) result.push(h)
result.push(...flattenHeadings(h.children, depth))
}
return result
}useSiteConfig
Returns site-wide configuration from typedown.yaml. Reactive across HMR config changes.
const config = useSiteConfig()interface TypedownSiteConfig {
title: string
description: string
basePath: string // e.g. "/" or "/docs"
origin?: string // e.g. "https://example.com"
lang: string // HTML lang attribute
rootDir: string // vault root directory name
repo?: { url: string; root: string }
author?: string
license?: string
nav: { title: string; link: string; icon?: string }[]
withBase(path: string): string // prepends basePath to a path
}withBase is useful for generating hrefs that work under a subpath deployment:
const { withBase } = useSiteConfig()
withBase('/guide/index') // returns "/docs/guide/index" if basePath is "/docs"useSiteData
Returns a reactive Ref containing the full site data. Updates via HMR when content changes.
const siteData = useSiteData()
siteData.value.ready // false until initial data loads
siteData.value.contentTree // full content tree
siteData.value.schemas // schema info by name
siteData.value.directoryListingsinterface TypedownSiteData {
ready: boolean
contentTree: ContentTree
schemas: Record<string, SchemaInfo>
directoryListings: Record<string, DirectoryListing>
}useTdContent
Sets up the provide/inject context required by <Content /> and returns reactive page bindings. Must be called once in your layout's setup function.
const { page, title, frontmatter, isDark } = useTdContent()interface TypedownData {
page: Ref<PageData>
frontmatter: Ref<Record<string, unknown>>
title: Ref<string>
isDark: Ref<boolean>
}isDark reflects the current theme state, derived from useTheme() internally.
useTheme
Controls the dark mode state. Persists the user's preference in localStorage and toggles the .dark class on <html>.
const { isDark, toggle, setTheme, effectiveTheme, theme } = useTheme(){
theme: Readonly<Ref<'light' | 'dark' | 'system'>>
effectiveTheme: ComputedRef<'light' | 'dark'> // resolved value when mode is 'system'
isDark: ComputedRef<boolean>
toggle(): void
setTheme(value: 'light' | 'dark' | 'system'): void
}'system' is the default. It reads prefers-color-scheme and updates reactively when the OS setting changes.
<button @click="toggle">Toggle dark mode</button>To style for dark mode in CSS, target the .dark class on <html>:
:root { --bg: #fff; --fg: #111; }
.dark { --bg: #111; --fg: #eee; }useRouter
Returns the router for programmatic navigation.
const router = useRouter()
await router.go('/guide/introduction')
await router.go('/guide/introduction#section', { replace: true })interface Router {
route: Route
go(to: string, options?: { replace?: boolean }): Promise<void>
onBeforeRouteChange?: (to: string) => Promise<boolean | undefined> | boolean | undefined
onAfterRouteChange?: (to: string) => Promise<void> | void
}Content
The <Content /> component renders the compiled markdown body of the current page. It has no props.
<template>
<article class="prose">
<Content />
</article>
</template>useTdContent() must be called before <Content /> renders.
Rendered output consists of standard HTML elements (h1-h6, p, ul, pre, table, etc.). Style them by wrapping with a class:
.prose h1 { font-size: 2rem; font-weight: 800; }
.prose p { line-height: 1.7; color: #555; }
.prose pre { background: #f5f5f5; border-radius: 8px; padding: 16px; }