An ORM for Markdown

Treat your folder of markdown files as a typed, queryable database. No database. No build step. Your content is the source of truth. Get a REST API, GraphQL API, and MCP server for free.

Bun TypeScript Zod unified / remark ESM
1 How It Works
stories/authentication/user-can-register.mdx
---
status: draft
points: 5
epic: authentication
---

# User Can Register

New users can create an account using
their email and password.

## Acceptance Criteria
- Users can sign up with email
- Password must be 8+ characters
- Validation errors shown inline

## Mockups
- [Sign Up Form](./mockups/signup.png)
- [Error States](./mockups/errors.png)
What Contentbase Sees
ID
stories/authentication/user-can-register
Title
User Can Register
Meta (validated)
status: "draft" points: 5 epic: "authentication"
Sections (typed)
acceptanceCriteriastring[]
mockupsRecord<string, string>
Relationships
epicbelongsTo(Epic)
Path Pattern
stories/:epic/:slug → auto-infers meta
2 Core Flow
Files on Disk
.md / .mdx
Collection
load + parse
Model Instances
typed + validated
Query + Extract
.where().fetchAll()
01
Define Models
Describe your content types with Zod schemas, sections, and relationships
02
Load Content
Point a Collection at a folder. Every markdown file becomes a typed Document
03
Query Anything
Filter by meta, traverse relationships, extract sections, validate schemas
3 Features
Z
Schema Validation
Zod schemas validate frontmatter. Catch typos, enforce types, get defaults for free. Full error reporting with field-level detail.
{}
Typed Sections
Extract structured data from markdown headings. Lists become string[], links become Record, tables become objects.
Relationships
hasMany / belongsTo links between documents. An Epic has many Stories, a Story belongs to an Epic.
?
Fluent Queries
SQL-like .where().fetchAll() with 12+ operators: eq, gt, contains, regex, in, exists, startsWith, and more.
/:
Path Patterns
Express-style :param patterns auto-infer meta from file paths. stories/:epic/:slug extracts both values.
Immutable AST Ops
Insert, remove, replace sections. Returns new Document instances by default. Opt into mutation when you need it.
fn
Computed Properties
Lazy-evaluated derived values from document data. Defined once, cached automatically, fully typed.
>_
CLI Toolkit
9 built-in commands for scaffolding, validation, inspection, extraction, and documentation generation.
()
Standalone Parsing
parse() any markdown string or file without a Collection. Full AST query, sections, and node shortcuts.
TS
Full TypeScript
Zero manual type annotations needed. Full inference flows from model definitions through queries to results.
4 Code Examples
Define a Model
const Story = defineModel("Story", {
  prefix: "stories",
  pattern: "stories/:epic/:slug",
  meta: z.object({
    status: z.enum(["draft", "ready", "shipped"])
              .default("draft"),
    points: z.number().optional(),
  }),
  sections: {
    acceptanceCriteria: section(
      "Acceptance Criteria", {
      extract: (q) =>
        q.selectAll("listItem")
         .map(toString),
      schema: z.array(z.string()),
    }),
  },
  relationships: {
    epic: belongsTo(() => Epic, {
      foreignKey: (doc) => doc.meta.epic,
    }),
  },
});
Load + Query
// Set up collection
const collection = new Collection({
  rootPath: "./content"
});
collection.register(Epic);
collection.register(Story);
await collection.load();

// Query like a database
const drafts = await collection
  .query(Story)
  .where("meta.status", "draft")
  .whereGt("meta.points", 3)
  .fetchAll();

// Traverse relationships
const epic = drafts[0]
  .relationships.epic.fetch();

// Extract typed sections
const criteria = drafts[0]
  .sections.acceptanceCriteria;
// => ["Users can sign up...", ...]

// Validate against schema
const result = await drafts[0]
  .validate();
// => { valid: true, errors: [] }
5 Architecture
Your Content API
Collection CollectionQuery defineModel() section() hasMany() belongsTo() parse()
Document Layer
Document AstQuery NodeShortcuts Validator ModelInstance
Parsing Engine
unified remark-parse remark-gfm gray-matter MDAST
File System
.md files .mdx files YAML frontmatter Folder hierarchy
CLI Commands
init scaffold project
inspect show models
validate check schemas
create new document
export JSON output
extract filter sections
summary gen docs
teach LLM bundle
action custom ops
6 CLI Toolkit
Terminal
# Scaffold a new project
$ cbase init my-content

# Create a new document from model schema
$ cbase create Story --title "User can logout"

# Validate all documents against their model schemas
$ cbase validate
  ✓ epics/authentication — valid
  ✓ stories/authentication/user-can-register — valid

# Extract specific sections from matching documents
$ cbase extract "stories/**/*" --sections "Acceptance Criteria"

# Inspect model definitions
$ cbase inspect
  Epic    prefix: epics/     2 documents   1 relationship
  Story   prefix: stories/   3 documents   2 sections

# Generate documentation
$ cbase summary    # → MODELS.md + TABLE-OF-CONTENTS.md
$ cbase teach      # → Combined LLM-friendly bundle
3-Tier Model Discovery: The CLI automatically finds your models via index.ts exports, a standalone models.ts, or auto-discovers from folder structure. Zero config needed to get started.
7 Server APIs
Coming Soon
Every collection becomes an API. Automatically.
Define your models once — get a REST API, GraphQL API, and MCP server for free. Your markdown content becomes instantly queryable by custom apps, dashboards, and AI agents.
REST API
Full CRUD endpoints generated from your model definitions. Filter, paginate, and mutate content over HTTP.
  • GET /api/stories?status=draft
  • GET /api/stories/:id/sections
  • POST /api/stories with validation
  • GET /api/epics/:id/relationships
GraphQL API
Schema auto-generated from Zod models. Query exactly the fields you need with full relationship traversal.
  • Types generated from Zod schemas
  • Nested relationship queries
  • Section extraction as fields
  • Filter + sort built in
MCP Server
Expose your content to AI agents via Model Context Protocol. Claude, GPT, and any MCP client can query and update your docs.
  • Tools for query, read, create, update
  • Resources for each model type
  • Schema-aware content generation
  • AI-native content workflows
One command.  cbase serve  spins up all three. Zero config.
8 Use Cases
Project Specs & SDLCs
Epics, stories, and tasks as markdown files in Git. Query status, validate completeness, extract acceptance criteria for sprint planning.
Documentation Sites
Typed content models for blog posts, API docs, changelogs. Schema validation catches missing fields before build.
Knowledge Bases
Queryable structure over runbooks, decision records, design docs. Search by tags, filter by status, traverse cross-references.
LLM Context Pipelines
Extract and combine document sections for LLM prompts. The teach and extract commands bundle content intelligently.