@conloca/astro-cms
@conloca/astro-cms is the main package you install to add Conloca CMS to an Astro project. It provides the
conlocaCMS() integration function, injects API routes for content operations, serves the CMS admin UI, and handles
content page routing.
Overview
@conloca/astro-cms is the main integration package that adds Conloca CMS to any Astro site. Install this package to
get visual page editing with Puck, content management, a media library, multi-locale support, and optional Cloudflare
Access request validation.
When added to your Astro config, the integration:
- Mounts the CMS admin UI at
/__cms(configurable) - Sets up content API routes for CRUD operations
- Provides Astro Content Collections loaders for build-time content access
- Supports interactive component hydration via
withHydration() - Validates Cloudflare Access requests when the relevant environment variables are set
Installation
bun add @conloca/astro-cms
Configuration
// astro.config.mjs
import { conlocaCMS } from '@conloca/astro-cms/node';
export default defineConfig({
integrations: [
conlocaCMS({
contentRoot: './content',
puckConfigPath: './src/puck.config.tsx',
assetsPath: 'src/assets/uploads',
schemasPath: './src/schemas.ts',
layout: './src/layouts/Layout.astro',
}),
],
});
ConlocaCMSOptions
| Option | Type | Default | Description |
|---|---|---|---|
contentRoot | string | required | Path to content directory |
puckConfigPath | string | required | Path to Puck component config (.tsx file) |
route | string | '/__cms' | CMS admin UI route prefix |
assetsPath | string | - | Path to assets directory (enables Media Library) |
schemasPath | string | - | Path to data/page schema definitions |
layout | string | - | Default Astro layout for content pages |
routing | RoutingConfigInput | - | Content page routing configuration |
templates | Record<string, TemplateConfig> | - | Page creation templates |
componentPaths | string[] | - | Directories to scan for hydratable components |
siteStyles | string | string[] | - | CSS files to load in the CMS editor for component preview styling |
canvasDir | string | './canvas' | Canvas directory for visual editing |
Entry Points
@conloca/astro-cms (main)
Static-safe utilities, route helpers, and schemas. Node-only Astro integration APIs live under dedicated node entry
points.
import { pageMetaSchema, blockMetaSchema } from '@conloca/astro-cms';
import { conlocaCMS } from '@conloca/astro-cms/node';
import { conlocaLoader } from '@conloca/astro-cms/node/content';
| Export | Purpose |
|---|---|
pageMetaSchema | Zod schema for page metadata |
blockMetaSchema | Zod schema for block metadata |
withHydration(component, strategy) | Wrap React components for client-side hydration |
scanForHydratableComponents(paths) | Build-time scanner for hydratable components |
extractSlugFromPathname(pathname, pattern) | Convert URL pathname to Astro slug |
pathnameFromSlug(slug, pattern) | Convert Astro slug to URL pathname |
serializeProps(props) | Serialize component props for hydration |
@conloca/astro-cms/node
Node-only Astro integration entry point.
import { conlocaCMS } from '@conloca/astro-cms/node';
| Export | Purpose |
|---|---|
conlocaCMS(options) | Astro integration factory |
@conloca/astro-cms/node/content
Node-only Astro content helpers.
import { conlocaLoader, createConlocaCollections } from '@conloca/astro-cms/node/content';
| Export | Purpose |
|---|---|
conlocaLoader(options) | Content Collections loader |
createConlocaCollections(options?) | Auto-discover and define Content Collections from indexed content |
ConlocaLoaderOptions
Options for the conlocaLoader() function:
| Field | Type | Required | Description |
|---|---|---|---|
collection | string | No | Astro content collection name to populate |
contentRoot | string | Yes | Path to the content directory (e.g., ./src/content) |
site | string | No | Site name for page collections. Omit to use the default site. |
kind | 'page' | 'block' | 'data' | No | Content kind. Inferred from collection name if omitted (blocks → block, everything else → page) |
@conloca/astro-cms/components
Rendering utilities for content pages.
import { createPageRendererWithBlocks } from '@conloca/astro-cms/components';
| Export | Purpose |
|---|---|
createPageRendererWithBlocks() | Create a page renderer that resolves block references |
@conloca/astro-cms/hydration
Client-side hydration for interactive Puck components.
import { withHydration } from '@conloca/astro-cms/hydration';
const InteractiveCounter = withHydration(Counter, 'load');
| Export | Purpose |
|---|---|
withHydration(component, strategy) | Wrap a React component for client-side hydration |
HydrationStrategy
The strategy argument is a HydrationStrategy union type:
| Value | Astro directive | Description |
|---|---|---|
'none' | (no JS shipped) | Pure static HTML — no client-side JavaScript. Default when not specified. |
'load' | client:load | Hydrate immediately on page load. |
'visible' | client:visible | Hydrate when the component enters the viewport (lazy hydration). |
'idle' | client:idle | Hydrate when the browser is idle, after higher-priority work is done. |
Only components explicitly wrapped with withHydration() ship JavaScript to the browser — unmarked components render as
static HTML.
@conloca/astro-cms/virtual-modules
TypeScript declaration file for virtual module imports used internally by the CMS handler. Add to your env.d.ts for
type support.
@conloca/astro-cms/lib/hydration-script
Client-side hydration bootstrap script. Discovers and hydrates components marked with withHydration().
Examples
Minimal Setup
// astro.config.mjs
import { conlocaCMS } from '@conloca/astro-cms/node';
export default defineConfig({
integrations: [
conlocaCMS({
contentRoot: './content',
puckConfigPath: './src/puck.config.tsx',
}),
],
});
With Media Library
// astro.config.mjs
import { conlocaCMS } from '@conloca/astro-cms/node';
export default defineConfig({
integrations: [
conlocaCMS({
contentRoot: './content',
puckConfigPath: './src/puck.config.tsx',
assetsPath: 'src/assets/uploads',
}),
],
});
Dev Branch Preview: auth
On the dev branch, conlocaCMS() also accepts an auth option. That preview API is not available on the current
branch yet.
// dev branch preview only
import { conlocaCMS } from '@conloca/astro-cms/node';
import { oauth } from '@conloca/content-api/node';
export default defineConfig({
integrations: [
conlocaCMS({
contentRoot: './content',
puckConfigPath: './src/puck.config.tsx',
auth: {
provider: oauth({
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
},
sessionSecret: process.env.SESSION_SECRET,
}),
},
}),
],
});
Content Collections
// src/content.config.ts
import { createConlocaCollections } from '@conloca/astro-cms/node/content';
export const { collections } = await createConlocaCollections({
contentRoot: './content',
site: 'default',
});
Type Reference
PageData
Passed to layout components and page handlers when routing is enabled. Contains the full page record loaded from the content directory.
| Field | Type | Description |
|---|---|---|
id | string | Unique page identifier (typically matches the URL path) |
title | string | undefined | Page title — used for <title> tag and layout heading |
description | string | undefined | Page description for SEO <meta name="description"> |
pathname | string | Full URL pathname starting with / |
puckData | Data | Puck editor data (root, content, zones) — pass to <Render /> |
collection | string | Content collection name (e.g., 'pages', 'posts') |
route | { name, pattern, meta? } | Route configuration that matched this page |
meta | Record<string, unknown> | undefined | Custom fields from the page’s frontmatter/metadata |
timestamps | { created?, modified?, published? } | Page timestamps |
PageReference
A lightweight page record used in getStaticPaths() and DataContext.pages. Does not include puckData.
| Field | Type | Description |
|---|---|---|
id | string | Page identifier |
pathname | string | Full URL pathname |
title | string | undefined | Page title |
collection | string | Content collection name |
meta | Record<string, unknown> | undefined | Author, excerpt, tags, featured image, and other fields from page metadata |
timestamps | { created?, modified? } | Page timestamps for sorting and display |
LayoutProps
Props received by layout components specified in routing.routes.{name}.layout. Layouts must accept at minimum title
and description.
| Field | Type | Description |
|---|---|---|
title | string | Page title for the document <head> |
description | string | undefined | Page description for the SEO meta tag |
children | unknown | Rendered Puck content. Use <slot /> in Astro layouts, {children} in React layouts. |
DataContext
Passed as metadata in Puck component resolveData() calls when dataBindings is configured for the route. Cast it
with metadata as DataContext to access typed fields.
| Field | Type | Description |
|---|---|---|
collections | Record<string, DataCollectionEntry[]> | Collection data keyed by collection name. Each key matches a name from dataBindings.collections. |
pages | PageReference[] | undefined | Pages matching the dataBindings.pages filter. Only present if pages is configured. |
locale | string | Current locale used for data fetching |
siteName | string | Site name from routing configuration |
DataCollectionEntry
A single entry from a data collection, as returned in DataContext.collections[name].
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the entry |
name | string | Human-readable name of the entry |
data | Record<string, unknown> | Entry data content — access fields via entry.data.fieldName |
meta | Record<string, unknown> | undefined | Optional metadata (title, description, custom fields) |