---
title: "Comark Content vs Astro Content Collections"
description: "Astro Content Collections load and type content at build time inside Astro. Comark Content is a runtime content layer that works with any framework. Compare loaders, type safety, updates, and search."
canonical_url: "https://content.comark.dev/compare/comark-content-vs-astro-content-collections"
---
# Comark Content vs Astro Content Collections

> Astro Content Collections load and type content at build time inside Astro. Comark Content is a runtime content layer that works with any framework. Compare loaders, type safety, updates, and search.

**TL;DR**: Astro Content Collections are excellent if your whole site is Astro and your content ships with your build. Comark Content solves the same problem — typed access to Markdown collections — without the two constraints: it runs in any framework (Nuxt, Next.js, Vite, Nitro, Node, the browser) and reads content at runtime, so a Markdown push goes live without a rebuild.

## At a glance

|                           | Comark Content                                                                                                                                                                                        | Astro Content Collections                                          |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| Framework                 | Any                                                                                                                                                                                                   | Astro only                                                         |
| When content is processed | Runtime (or build time via [snapshots](https://content.comark.dev/advanced/artifacts-and-hydration))                                                                                                  | Build time                                                         |
| Content update            | Live, no rebuild                                                                                                                                                                                      | Rebuild                                                            |
| Content sources           | Filesystem, GitHub, any [unstorage](https://unstorage.unjs.io) driver, [custom](https://content.comark.dev/sources/custom)                                                                            | Built-in `glob`/`file` loaders, custom loaders (Content Layer API) |
| Schema                    | JSON Schema per source, optional                                                                                                                                                                      | Zod schema per collection                                          |
| Type safety               | Generated from content or schema                                                                                                                                                                      | Generated from schema                                              |
| Reading                   | [`get()`](https://content.comark.dev/reference/content/get), [`list()`](https://content.comark.dev/reference/content/list), [`navigation()`](https://content.comark.dev/reference/content/navigation) | `getCollection()`, `getEntry()`, `render()`                        |
| Querying                  | Optional [SQL queries](https://content.comark.dev/plugins/built-in/sql-query) over frontmatter                                                                                                        | Filter callbacks in JS                                             |
| Search                    | Optional [BM25 full-text search](https://content.comark.dev/plugins/built-in/full-text-search)                                                                                                        | None built in                                                      |
| Components in Markdown    | [Comark syntax](https://comark.dev), rendered at runtime                                                                                                                                              | MDX / Markdoc, compiled at build                                   |
| Runs in the browser       | Yes (`sqlite-wasm`, snapshots)                                                                                                                                                                        | No                                                                 |

## The core difference

Astro collections are resolved when you build. `astro build` runs your loaders, validates entries against Zod schemas, and bakes the result into the output:

```ts
// Astro: resolved at build time
import { getCollection } from 'astro:content'

const posts = await getCollection('blog', ({ data }) => !data.draft)
```

Two consequences:

1. **Content is coupled to the build.** New or edited Markdown means a new build, even with on-demand rendering — the collection data itself is fixed at build time unless you use live content collections (experimental).
2. **The API only exists inside Astro.** `astro:content` is a virtual module. You can't reuse the same content layer in a Node script, an API server, or another framework.

Comark Content is a plain TypeScript library. The same instance runs in an Astro endpoint, a Nuxt server route, a Next.js route handler, a Node script, or the browser:

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

const content = comarkContent({
  source: github({ repo: 'acme/content', branch: 'main' }),
})

const posts = await content.list()
const page = await content.get('/blog/hello')
```

Reads hit the source at runtime, so published Markdown reaches your app without a rebuild; a cache TTL or a webhook decides how soon ([Keep remote content up to date](https://content.comark.dev/deployment/remote-content)). When you want Astro-style build-time determinism, parse once and ship a [snapshot](https://content.comark.dev/deployment/with-a-snapshot).

## Loaders vs sources

Astro 5's Content Layer API introduced loaders, which pull remote content at build time. Comark Content [sources](https://content.comark.dev/sources) cover the same ground with one difference: they're consulted at runtime, not snapshotted during build. A loader gives you remote content as of the last deploy; a source gives you remote content as of the current request, with [caching](https://content.comark.dev/advanced/caching) controlling freshness.

## FAQ

### Can I use Comark Content inside an Astro project?

Yes. It's framework-agnostic TypeScript — create the instance in an Astro endpoint or middleware and render the returned tree with [`@comark/html`](https://comark.dev/rendering/html) or a framework island.

### Do Astro Content Collections work outside Astro?

No. `astro:content` is a virtual module that only resolves inside an Astro build.

### How do I get Zod-style validation with Comark Content?

Pass a JSON Schema to a source via its [`schema`](https://content.comark.dev/sources/filesystem#options-schema) option. Entries are validated on load, and the schema drives generated types and query columns.

### Which is faster?

Different trade-offs. Astro pays the cost at build time and serves static data. Comark Content parses lazily on first read and caches the parsed body; with a warm [cache](https://content.comark.dev/advanced/caching) or a [snapshot](https://content.comark.dev/advanced/artifacts-and-hydration), reads don't reparse.


## Sitemap

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