Introduction

The lightweight, framework-agnostic content layer for Markdown.

Comark Content is a small, framework-agnostic content layer built on top of Comark. It turns Markdown from anywhere (your local files, a GitHub repo, or any storage driver) into a queryable, searchable, type-safe API.

You wire it once, with no folder convention, no framework lock-in, and no build step. The same instance runs on a Node server, at the edge, or entirely in the browser.

content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'

export const content = comarkContent({
  // Sourcing Markdown from the filesystem
  source: fs('./content'),
})

const page = await content.get('/getting-started/introduction')

What it does

Comark Content sits between your content and your app, and does three things:

  1. Loads Markdown from a source: filesystem, GitHub, or any unstorage driver.
  2. Parses each file with Comark: frontmatter up front to index it, the body into a structured AST on demand.
  3. Serves the result through a small, typed API: get, list, navigation, as well as optional SQL query() and full-text search().

Comark x Comark Content

Comark and Comark Content are two layers of the same stack.

Comark is used for the Markdown parser and renderer, where Comark Content is the content layer built on top of them.

ComarkComark Content
RoleMarkdown-with-components syntax, parser, and renderersContent layer over a collection of files
InputA Markdown stringA whole source: filesystem, GitHub, or unstorage
OutputA parsed MarkdownDocument, or rendered UITyped get, list, navigation, SQL, and search
ScopeOne document at a timeA source of many documents

Comark handles a single document end to end: it parses one Markdown file into a structured MarkdownDocument and renders it through the <MarkdownDocument> component provided for any frontend framework (Angular, Svelte, React and Vue).

Comark Content works one level up: it sources many files, parses each one with Comark, and serves the results through a queryable, type-safe API.

Features

Everything you need for a content layer, all opt-in:

Framework-agnostic

Plain TypeScript. Use it with Nuxt, Vite, Nitro, Node, React, or no framework at all.

Pluggable sources

Read from the filesystem, a GitHub repo, or any unstorage driver: S3, KV, Redis, HTTP.

Type-safe

Generated types narrow content.get() and content.query() by source and by path.

SQL and full-text search

Opt into a SQLite-backed query builder over frontmatter and BM25 full-text search.

Runs in the browser

Ship a static snapshot and hydrate the whole Content instance client-side with sqlite-wasm.

Streaming-aware

Built on Comark, so you can parse and persist LLM-streamed Markdown incrementally.

Architecture

Comark Content is a pipeline with two read paths. Building the manifest parses frontmatter only: a lightweight index that backs list and navigation. Each document body is parsed into an AST lazily, the first time you get() it; the optional cache keeps that parsed result so later reads skip the parse.

Everything after the source is optional, so the Content instance stays as small as one source and a get(), or grows into caching, SQL, and search as you need it.

ConceptRequiredRoleExamples
SourceWhere files come fromfs(), github(), unstorageSource()
CacheWhere parsed entries are stored and kept freshin-memory (default), any unstorage driver
DatabaseBacks the SQL query and full-text search pluginssqlite(), sqliteWasm()
PluginExtra capabilitiessqlQuery, sqliteFullTextSearch, media, json, yaml

Compare

How Comark Content relates to the tools it replaces:

Why a content layer

What a content layer is and when you need one.

vs Contentlayer

Runtime parsing from any source vs an unmaintained build-time compiler.

vs Astro Content Collections

A content layer for any framework vs one locked to Astro builds.

vs Headless CMS

Markdown in storage you own vs a hosted API with an editor.