Skip to content

Admin UI

The admin is runtime-rendered from your schema. No generated page files, add a field and it appears immediately.

Configure which columns appear in the list view via views in the collection definition:

defineCollection({
slug: "posts",
views: {
list: {
columns: ["title", "category", "_status", "_updatedAt"],
defaultSort: { field: "_updatedAt", direction: "desc" },
},
},
fields: { ... },
});

Fields go to the content area by default. Set admin.position: "sidebar" to place a field in the sidebar:

fields: {
title: fields.text({ required: true }), // → content
body: fields.richText(), // → content
slug: fields.slug({ admin: { position: "sidebar" } }), // → sidebar
category: fields.text({ admin: { position: "sidebar" } }), // → sidebar
}
PositionDescription
"content"Main area (left column on desktop) — default
"sidebar"Side panel (right column on desktop)

Collections with pathPrefix get a Preview link automatically. For collections without a prefix, add preview: true. For singletons, set preview to the URL:

// Automatic — pathPrefix enables preview
defineCollection({ slug: "posts", pathPrefix: "blog", ... });
// Explicit — no pathPrefix, needs opt-in
defineCollection({ slug: "pages", preview: true, ... });
// Singleton — set the URL directly
defineCollection({ slug: "front-page", singleton: true, preview: "/", ... });

The Preview link opens the public page in a new tab with ?preview=true, which shows draft content. Save your changes in the admin, then refresh the preview tab to see them.

Use the findContent helper to handle preview mode automatically:

---
import { findContent, cacheTags } from "@/cms/core/content";
const { doc, isPreview, blocks } = await findContent("posts", Astro.params.slug, Astro.url);
if (!doc) return Astro.redirect("/");
if (!isPreview) Astro.cache.set({ tags: cacheTags("posts", doc._id) });
---
<h1>{doc.title}</h1>

findContent handles the ?preview=true detection and queries with status: "any" in preview mode, "published" otherwise.

Register a custom React component for any field:

// In your collection definition
color: fields.text({
admin: { component: "color-picker" },
});

Built-in custom components: "radio" (select as radio buttons), "taxonomy-select" (taxonomy term picker), "repeater" (JSON array editor), "menu-items", "taxonomy-terms".