Astro Integration Guide
This guide provides resources and information for integrating Sveltia CMS with Astro, a modern static site builder.
Starter Templates
Here are some starter templates built by the community using Astro:
- Astros by zanhk
- Astro i18n Starter by yacosta738
- astro-sveltia-cms by knolljo
- Nebulix by Unfolding.io
- StarFunnel by Unfolding.io
Disclaimer
These third-party resources are not necessarily reviewed by the Sveltia CMS team. We are not responsible for their maintenance or support. Please contact the respective authors for any issues or questions.
Examples
See real-world examples of Astro integrations in our Showcase. Most of the listed sites include links to their source code, so you can explore how they implemented Sveltia CMS with Astro.
Setup
Adding the Admin Page
Astro serves static files from the public folder. Create public/admin/index.html and public/admin/config.yml as described in the Getting Started guide.
The Astro development server doesn’t serve index.html for a folder path in public, so open /admin/index.html instead of /admin/ during development. On the built site, most hosting services serve the admin page at /admin/ as usual.
If your site uses the <ClientRouter /> component for view transitions, add the data-astro-reload attribute to links to the admin page, so they are opened as regular pages instead of being handled by the router:
<a href="/admin/" data-astro-reload>Edit content</a>Configuration
Astro manages Markdown content with content collections defined in src/content.config.ts. Each collection loads files with a loader like glob() and validates their front matter with a Zod schema:
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: ({ image }) =>
z.object({
title: z.string(),
description: z.string().optional(),
pubDate: z.coerce.date(),
heroImage: image().optional(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { blog };The matching Sveltia CMS entry collection uses the base folder of the loader. The following example stores each post in a folder of its own as index.md, with entry-relative media folders, so the hero image is saved next to the post and can be optimized by Astro with the image() schema helper:
media_folder: public/images
public_folder: /images
output:
omit_empty_optional_fields: true
collections:
- name: blog
label: Blog
folder: src/content/blog
path: '{{slug}}/index'
media_folder: ''
public_folder: ''
create: true
fields:
- { name: title, label: Title }
- { name: description, label: Description, required: false }
- { name: pubDate, label: Publish Date, widget: datetime }
- { name: heroImage, label: Hero Image, widget: image, required: false }
- { name: tags, label: Tags, widget: list, required: false }
- { name: body, label: Body, widget: markdown }If you store posts as single files instead, remove the path, media_folder and public_folder options from the collection. Images are then saved in the public/images folder defined at the top level, which Astro serves as is without optimization, so use z.string() instead of image() in the schema.
Omitting Empty Optional Fields
Sveltia CMS saves an empty value, such as an empty string, an empty array or null, for an optional field that is left empty. Zod’s .optional() only accepts a missing property, so these values can cause a build error like “data does not match collection schema”. Set the omit_empty_optional_fields output option to true, as in the example above, to leave empty optional fields out of the front matter.
Support for Astro
We have implemented specific features to enhance the integration of Sveltia CMS with Astro:
- Starlight: Manage a Starlight documentation site, including its folder tree, front matter and multilingual content.
- The
value_fieldRelation field option can contain a locale prefix like{{locale}}/{{slug}}, which will be replaced with the current locale. It’s intended to support i18n in Astro. (Discussion) - Localizing entry slugs: generate localized slugs for multilingual Astro sites, notably with the @astrolicious/i18n library. (Discussion)
- Omitting empty optional fields: Set the
omit_empty_optional_fieldsoutput option totrueso that content with unfilled optional fields passes content collection schema validation. (Discussion)