---
title: "Why a content layer"
description: "What a content layer is, when you need one, and how it compares to a headless CMS or hardcoding content."
canonical_url: "https://content.comark.dev/compare/why-a-content-layer"
---
# Why a content layer

> What a content layer is, when you need one, and how it compares to a headless CMS or hardcoding content.

## What is a content layer?

A content layer is the piece of your stack between your content and your application code. It loads files (usually Markdown), parses them, and exposes them through a typed API — so your app asks for `get('/blog/hello')` or `list()` instead of reading files and parsing frontmatter by hand.

It is not a CMS backend: there is no hosted database, no admin panel, no API service. The content stays where it is; the layer indexes and serves it.

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

const content = comarkContent({
  source: fs('./content'),
})

const page = await content.get('/blog/hello') // reads ./content/blog/hello.md
page?.data.title // frontmatter
page?.nodes // parsed body, ready to render
```

## The problem it solves

Every content-driven site rebuilds the same plumbing:

- **Reading**: walk a directory, filter by extension, map file paths to routes.
- **Parsing**: split frontmatter from body, parse Markdown, highlight code.
- **Typing**: cast `data` as `any` and hope the frontmatter matches.
- **Listing**: sort posts by date, filter drafts, build navigation trees.
- **Search**: bolt on a client-side index or a search service.

A content layer replaces that with one dependency. Comark Content covers each point: [sources](https://content.comark.dev/sources) for reading, [Comark](https://comark.dev) for parsing, [generated types](https://content.comark.dev/guide/typescript) for frontmatter, [`list()`](https://content.comark.dev/guide/read-and-list) and [`navigation()`](https://content.comark.dev/guide/navigation) for listings, and opt-in [SQL queries](https://content.comark.dev/plugins/built-in/sql-query) and [full-text search](https://content.comark.dev/plugins/built-in/full-text-search).

## When you need one

Use a content layer when:

- Content is Markdown (or JSON/YAML) written by developers or technical writers.
- You want content changes live without hand-rolled parsing code in every route.
- You need listings, navigation, queries, or search over a collection of files.
- The same content should render in more than one place: a site, an RSS feed, an API, an LLM context.

You don't need one when:

- Your site has a handful of static pages — hardcode them.
- Non-technical editors need a browser editing UI and publishing workflows — use a [headless CMS](https://content.comark.dev/compare/comark-content-vs-headless-cms).

## Build time vs runtime

Most content layers ([Contentlayer](https://content.comark.dev/compare/comark-content-vs-contentlayer), [Astro Content Collections](https://content.comark.dev/compare/comark-content-vs-astro-content-collections), Velite) run at build time: they compile your files into typed data during `build`, so every content change requires a rebuild and redeploy.

Comark Content runs at runtime. Content is read from the source when your app asks, so content in a [GitHub repo](https://content.comark.dev/sources/github) can change without a rebuild of your app. How soon a push is visible depends on the source, the cache, and how you refresh: a cache TTL, a webhook, or a pinned commit that a new deployment or webhook advances. [Keep remote content up to date](https://content.comark.dev/deployment/remote-content) compares those options. If you want build-time semantics, parse once and ship a [snapshot](https://content.comark.dev/deployment/with-a-snapshot); the API stays the same.

|                     | Build-time layer            | Comark Content                                                                |
| ------------------- | --------------------------- | ----------------------------------------------------------------------------- |
| Content change      | Rebuild + redeploy          | Read at runtime; visible after the cache refreshes or a webhook fires         |
| Content location    | Local files in the app repo | Filesystem, GitHub, S3, KV, custom                                            |
| Framework coupling  | Bundler or framework plugin | Plain TypeScript, runs anywhere                                               |
| Cost of a page read | Free (precompiled)          | First read parses, then [cached](https://content.comark.dev/advanced/caching) |

## Content layer vs headless CMS

Both give your app an API over content. The difference is ownership: a headless CMS moves content into a vendor's database behind a metered API; a content layer reads content you already own. Full comparison: [Comark Content vs headless CMS](https://content.comark.dev/compare/comark-content-vs-headless-cms).

## Next steps

- [Quick start](https://content.comark.dev/getting-started/installation): a source and a `get()` in a few lines.
- [How it works](https://content.comark.dev/advanced/how-it-works): the pipeline from source to API.
- [Compare](https://content.comark.dev/compare/comark-content-vs-contentlayer): against Contentlayer, Astro Content Collections, and headless CMS.


## Sitemap

See the full [sitemap](https://content.comark.dev/sitemap.md) for all pages.
