Documentation site for SurrealDB, built with Vike (React), Vite, Mantine v8,
@surrealdb/ui, and SCSS modules. Content is managed with
vike-content-collection (Zod-validated markdown collections).
bun run dev # start dev server
bun run qa # apply code quality formatting
bun run qc # check code qualityAlways run bun run qa then bun run qc before finishing any task.
- Mantine: UI
- Vike: Framework
- Vite: Build tool
- Auth0: Authentication
- vike-content-collection: Content Collection API
Apply SOLID where it fits:
- Single Responsibility — one reason to change per module, component, or function.
- Open/Closed — extend through composition and props, not by modifying existing code.
- Liskov Substitution — interchangeable components must not break consumers.
- Interface Segregation — focused prop interfaces and types; avoid catch-all types.
- Dependency Inversion — depend on abstractions (types, interfaces, callbacks).
- Prefer Mantine (
@mantine/core) and@surrealdb/uibefore creating new components. - Use
<Box>instead of<div>. Semantic elements:<Box component="section|nav|main|footer">. - Use
<Anchor>instead of<a>. - Prefer Mantine styling props (
mt,fz,gap,display) over custom CSS. - SCSS modules:
style.module.scss, kebab-case class names, imported asimport classes from "./style.module.scss". - Inline
styleonly for truly dynamic values. - Shared UI that could benefit other SurrealDB frontends belongs in
@surrealdb/ui, not here.
All user-facing text uses British English spelling (-ise, -our, -re, -ogue).
Use sentence case for multi-word headings (##, ###, ####). Do not use
Title Case on every main word.
| Pattern | Rule | Examples |
|---|---|---|
| Single word | Capitalise the word | ## Syntax, #### Parameters, #### Returns |
| Multiple words | Capitalise the first word only; lowercase the rest | ## Type parameters, ### Complete examples, ### Default response |
| Numbered lists | Same as multiple words — capitalise the first word after the number | ### 3. Don't reuse transactions, ## 1. Install the SDK |
Keep capitalised where they are names, not prose:
- Acronyms and protocols:
API,HTTP,JSON,UUID,SQL - Product and language names:
SurrealDB,SurrealQL,JavaScript - SDK types and identifiers:
RecordId,DateTime,ApiPromise - SurrealQL keywords when cited literally:
INSERT,CREATE,LIVE SELECT
Avoid AI-style Title Case in subheaders:
→### Custom Functions### Custom functions→### Basic API Calls### Basic API calls→### Type-Safe Record IDs### Type-safe record IDs
Hyphenated compounds follow sentence case on the second part unless it is a proper
name: Full-text search, Type-safe queries, Half-open ranges.
Code-block title="…" labels on fenced blocks should follow the same rules when
they describe the example (e.g. title="Method syntax", not title="Method Syntax").
The docs site mixes reference material, SDK guides, tutorials, and operational content. The voice is consistent across them:
Tone. Neutral and instructional. State what something does, when to use it, and what to watch out for. Explain rationale where it helps (security trade-offs, precision loss, scope rules) without editorialising or selling.
Structure. Lead with purpose: one or two sentences on what the page covers and who it is for. Reference pages put syntax or API surface near the top, then work through examples. Guides and quickstarts use prerequisites, numbered steps, and expected output. Troubleshooting pages follow symptom → cause → resolution.
Prose style. Short paragraphs, mostly declarative sentences. Define terms on first use. Prefer concrete claims ("datetimes drop from nanoseconds to milliseconds") over vague importance ("crucial for modern workflows"). Use tables when comparing options (codecs, deployment modes, auth methods). Link to related pages inline rather than duplicating full explanations.
Examples. Runnable code with realistic data. SurrealQL reference pages often include inline test assertions and response blocks. SDK pages show imports, configuration, and the trade-off when an option changes behaviour. Tutorials include verification steps so readers can confirm the setup worked.
Callouts. Use > [!NOTE], > [!WARNING], and > [!IMPORTANT] for
exceptions, security caveats, and breaking or easy-to-miss details.
What to avoid. Promotional language, tutorial-script openers ("Let's dive in"), padded significance, and first-person opinion in reference material. Match existing pages in the same section when unsure.
Two agent skills in .agents/skills/ support content work, and should both be used
when writing new documentation or updating existing articles in the following order:
Use this skill to determine how to structure individual articles and decide which content to include.
Follow the skill for audience-appropriate depth, heading hierarchy, worked examples, completeness (edge cases, error handling), and consistency with surrounding docs. Draft in the voice described above.
Use after drafting in order to remove AI writing patterns and make the prose more natural and human-written.
Do not run humanizer over:
- SurrealQL syntax blocks, railroad diagrams, or mostly-code reference pages
- Frontmatter, tables of parameters, or generated API listings
- Text where neutral precision is the point (security warnings, error catalogues)
Humanizer removes AI writing patterns (significance inflation, rule-of-three padding, em dashes, chatbot framing) while preserving meaning. For docs, keep the neutral reference tone; do not add casual voice or first-person editorial.
- Draft with technical-writing.
- Humanize explanatory prose.
- Check British English and links.
bun run qaandbun run qc.
Schemas, slugs, and collection metadata live in src/content/config.ts. Each
collection has a +Content.ts file in src/content/<collection>/.
contentDir:"src/content"lastModified:truedrafts.field:"draft",includeDrafts:falsessr.external: includes"vike-content-collection"
| Kind | Schema | Collections |
|---|---|---|
| Docs | abstractDoc |
doc-surrealdb, doc-cloud, doc-surrealist, doc-surrealml, doc-surrealkv, doc-surrealql, doc-integrations, doc-tutorials, doc-sdk-* |
| Labs | labCollection |
labs-items |
Every +Content.ts:
import { abstractDoc, contentSlug } from "../config";
export const Content = {
schema: abstractDoc,
};abstractDoc—title,description,position,no_page_headings,no_sidebar(all optional, strict object)labCollection—title(required),url,category,author,topics,languagescontentSlug— strips the collection prefix from the file path and removes trailing/index
urlForCollection maps collection names to URL prefixes:
doc-surrealdb→/surrealdbdoc-sdk-javascript→/sdk/javascriptlabs-items→/labs
- Create a
.mdor.mdxfile in the appropriatesrc/content/<collection>/folder. - Add YAML frontmatter matching the collection schema.
- For docs, sidebar ordering uses
positionin frontmatter and__category.jsonfiles in subdirectories.
When adding a new doc collection, also update redirect logic in
aws/viewer-request/index.js.
Doc pages follow this pattern in +data.ts:
- Resolve collection ID and slug from the URL (
getCollectionPartsFromURLfromsrc/utils/collection.ts) - Call
getCollectionEntry(id, slug)— throw 404 if not found - Parse markdown with
resolveMarkdown(entry.content)fromsrc/utils/markdown.tsx(notrenderEntry) - Build sidebar with
getSidebarItemsFromCollection(id)fromsrc/utils/sidebar.ts - Return
{ ast, headings, sidebar, contentPath }
Labs listing: sortCollection(getCollection("labs-items"), "title", "asc").
Markdown pipeline (resolveMarkdown in src/utils/markdown.tsx):
parseMarkdown→ AST (via@surrealdb/ui)- Strip leading H1
resolveAstImagesextractHeadings(custom, usesgithub-slugger)
Sidebar: getSidebarItemsFromCollection in src/utils/sidebar.ts builds trees
from getCollection(id) plus __category.json via getCategories in
src/lib/categories.ts.
Prerendering: each doc section has +onBeforePrerenderStart.ts mapping
collection entries to URL paths.
Sitemap lastmod: vite.config.ts uses getCollectionEntry for content pages;
falls back to getLastModFromGit elsewhere.
Used: getCollection, getCollectionEntry, sortCollection, vikeContentCollectionPlugin
Not used:
renderEntry/extractHeadings— rendering uses@surrealdb/ui'sparseMarkdown+RenderMarkdowngetBreadcrumbs— sidebar-based breadcrumbsgetAdjacentEntries— prev/next follows__category.jsontree ordergetEntryUrl— URLs come fromurlForCollectiongetCollectionTree— sidebar uses__category.json