siterealContent & data
A content type is one schema.
Define it once and the types, the editing form and the typed queries all come out of the same definition. Collections are files in your repository, so the content travels with the code.
// src/content.config.ts
const posts = defineCollection({
loader: glob({ pattern: '**/*.md',
base: './src/content/posts' }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()),
draft: z.boolean().default(false),
}),
});One definition, four things.
- 01Typeswhat your editor reads
- 02Formwhat the Content Hub renders
- 03Querywhat a loop emits into the page
- 04Validationwhat every entry is written through
01Collections
A collection is a table you already know how to read.
Every collection sits in the rail with its count, and its entries are rows: a title, a status you switch between Live and Draft, and one column per field. Switch a collection public and each entry becomes a page with its own route.
02Fields
Thirteen field types, one click each.
Add field opens the whole list. Pick one and it is a column in the table, an input in every entry and a key a loop binds to — Title and Slug ship with every collection, and a group or a repeating item holds fields of its own.
03Loops
A loop is a query, and what repeats is ordinary markup.
Wrap a card in a Loop, point it at a collection, a JSON file or an expression, and bind the fields you want. The page emits a real query and a real .map() — the cards below are what the one card above them turns into.
04Storage
Files by default. Rows when files run out.
Files in git
Markdown, MDX, JSON or YAML in the repository: versioned with the code, diffable, and static by default. Nothing to host, nothing to migrate.
- src/content/<type>/<slug>.md
- History and review through git
- Builds with the network down
Rows in a database
For the three things files cannot do: editing without a deploy, data a visitor writes, and a collection large enough to need a query.
- libSQL or PostgreSQL, yours
- An ordinary Drizzle project in src/db
- Loops still read at build time
tags: ["release"]Taxonomies are fields
Tags and categories are terms assigned in the entry form, so a loop filtered by one is a query over the same file — no join table, no plugin.
<Condition>Conditions are elements
Wrap anything in a Condition and it emits the expression you wrote. Several clauses fold left to right, every step in brackets.
/uploads/hero.jpgMedia is the repository
Assets live under public/ with their alt text, offered as a picker, and photographs ship with a real srcset. Nothing is uploaded anywhere.
Start building the sites you’ve always wanted.
Seven days free, on your machine — and every site you build is real Astro in your own repository, yours from the first save.