---
url: /en/docs/frameworks/astro.md
description: >-
  Learn how to integrate Sveltia CMS with Astro, including the admin page setup,
  content collection configuration, starter templates and real-world examples.
---

# Astro Integration Guide

This guide provides resources and information for integrating Sveltia CMS with [Astro](https://astro.build/), a modern static site builder.

## Starter Templates

Here are some starter templates built by the community using Astro:

* [Astros](https://github.com/majesticooss/astros) by [zanhk](https://github.com/zanhk)
* [Astro i18n Starter](https://github.com/yacosta738/astro-cms) by [yacosta738](https://github.com/yacosta738)
* [astro-sveltia-cms](https://github.com/knolljo/astro-sveltia-cms) by [knolljo](https://github.com/knolljo)
* [Nebulix](https://nebulix.unfolding.io/) by [Unfolding.io](https://github.com/unfolding-io)
* [StarFunnel](https://starfunnel.unfolding.io/) by [Unfolding.io](https://github.com/unfolding-io)

::: info 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](/en/showcase?framework=astro). 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](https://docs.astro.build/en/basics/project-structure/#public). Create `public/admin/index.html` and `public/admin/config.yml` as described in the [Getting Started](/en/docs/start#manual-installation) 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 />`](https://docs.astro.build/en/guides/view-transitions/) 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:

```html
<a href="/admin/" data-astro-reload>Edit content</a>
```

## Configuration

Astro manages Markdown content with [content collections](https://docs.astro.build/en/guides/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](https://zod.dev/) schema:

```ts [src/content.config.ts]
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](/en/docs/media/internal#using-entry-relative-folders), so the hero image is saved next to the post and can be [optimized by Astro](https://docs.astro.build/en/guides/images/#images-in-content-collections) with the `image()` schema helper:

```yaml [public/admin/config.yml]
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`](/en/docs/data-output#controlling-data-output) 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](/en/docs/frameworks/starlight): Manage a Starlight documentation site, including its folder tree, front matter and multilingual content.
* The [`value_field`](/en/docs/fields/relation#value-field) Relation 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](https://github.com/sveltia/sveltia-cms/discussions/302))
* [Localizing entry slugs](/en/docs/i18n/slugs#localizing-entry-slugs): generate localized slugs for multilingual Astro sites, notably with the [@astrolicious/i18n](https://github.com/astrolicious/i18n) library. ([Discussion](https://github.com/sveltia/sveltia-cms/issues/137))
* [Omitting empty optional fields](/en/docs/data-output#controlling-data-output): Set the `omit_empty_optional_fields` output option to `true` so that content with unfilled optional fields passes [content collection schema](https://docs.astro.build/en/guides/content-collections/#defining-the-collection-schema) validation. ([Discussion](https://github.com/sveltia/sveltia-cms/issues/241))
