Your Content,
as a typed API.
Point Comark Content at a folder, a GitHub repository, or a storage bucket. Read pages, list them, build navigation. Add types, search, and queries when you need them. No build step.
content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'
export const content = comarkContent({
source: fs('./content'), // a folder of .md files
})
// reads and parse content/about.md
const page = await content.get('/about')
page.data.title // 'About', from the frontmatter
page.nodes // the body, ready to render
// built from your folders
const nav = await content.navigation()// Start small //
One file today. Everything else when you need it.
Docs sites, blogs, changelogs, knowledge bases, content for LLM pipelines. The first result takes a few minutes, and nothing you add later changes how you read a page.
content/about.md
---
title: About
---
# About us
We write documentation for a living.index.ts
const page = await content.get('/about')
console.log(page.data.title) // About// Sources //
Bring your own source
Content can live next to your app, in a separate repository, or in any storage driver. Same API either way. This site is the proof: its pages live in a GitHub repository and go live on push, with a preview per branch.
content.ts
import { comarkContent } from 'comark-content'
import fs from 'comark-content/sources/fs'
const content = comarkContent({
source: fs('./content'),
})
const page = await content.get('/getting-started')// Typed API //
Typed, searchable, queryable
Types are generated from your actual frontmatter and narrow get, list, and query by instance and by path. Add SQLite when you want SQL queries and full-text search.
const content = comarkContent({
source: fs('./content'),
})
// Known path -> data auto-narrowed, no type parameter
const blogPost = await content.get('/posts/hello')
blogPost?.data.title // typed from your frontmatter
blogPost?.data.tags // autocompletes every field
const pages = await content.list()
// Every document in the instance// Capabilities //
A small core. Everything else is a plugin.
Works with your stack
Nuxt, Next.js, Vite, SvelteKit, Nitro, Node, or Hono: mount one handler, render with Vue, React, or Svelte.
Documents and assets, together
Images and files live next to your Markdown: query them like content, serve them where they are referenced.
Type-safe from your frontmatter
Generated types narrow
get() and query() by instance and by path. Run one CLI command, or let the Vite plugin generate them.// FAQ //
Common questions
An open source content layer for Markdown. It reads Markdown from the filesystem, GitHub, or any storage driver and exposes it through a typed API — get, list, navigation — with optional SQL queries and full-text search. It is a library, not a hosted service.
Those run at build time inside one framework, so every content change requires a rebuild. Comark Content parses content at runtime from any source and works with Nuxt, Next.js, SvelteKit, Vite, Nitro, Node, Hono, or the browser. With content in a GitHub repository, a push can reach production without a rebuild; how fast depends on the caching and refresh setup you choose.
No. The core works with a source and an in-memory cache. Add SQLite (node or WASM) only when you want SQL queries over frontmatter or BM25 full-text search.
On the filesystem next to your app, in a GitHub repository, in any unstorage driver (S3, Cloudflare KV, Redis, HTTP), or behind a custom source you implement.
Any. The Content instance returns a framework-neutral AST rendered by Comark packages for Vue, React, Svelte, Angular, or plain HTML. Step-by-step guides cover Nuxt, Next.js, SvelteKit, Vite, Nitro, Node, and Hono, and a Vite plugin does the wiring for single-page apps.
Yes. MIT-licensed open source. Your only costs are your own hosting and storage.
Add a content layer in five lines.
One source, one
get(), a printed title in a few minutes. Add search and queries when you need them, and write in Comark syntax when you need components.