Skip to main content
Docs Existing Astro sites

Existing Astro sites

An Astro site that keeps its own pages, layout and components can take the kit's core alone. The core changes none of the site's pages. It adds:

  • a check that the site builds to static files, which is what Hostsmith serves;
  • a description of the site's content, .hostsmith/schema.json, for CMS editors and checks;
  • a Decap CMS config generated from it, which Decap CMS and Sveltia CMS can edit the site with;
  • page copy: the text a page writes in its markup, moved into files a CMS can edit;
  • check-fields, which reports how much of each page's text a CMS can edit, and check-urls for the old site's URLs.

It adds no routes, layout, components, styles or middleware, and sets none of the site's build options. The site keeps its own head, SEO tags and sitemap.

Add the core

  1. Install the package:
    npm install --save-exact @hostsmith/site-kit-astro
    
  2. Add the core to astro.config.mjs:
    import siteKitCore from "@hostsmith/site-kit-astro/core";
    import { defineConfig } from "astro/config";
    
    export default defineConfig({
      integrations: [siteKitCore()],
    });
    
  3. Add hostsmith.json at the site's root, with the GitHub repository a CMS saves to in cms.repo:
    {
      "kit": { "framework": "astro" },
      "site": { "id": "" },
      "build": { "command": "npm run build", "output": "dist", "node": "24" },
      "content": {
        "schema": { "source": "zod", "path": ".hostsmith/schema.json" },
        "root": "src/content"
      },
      "media": { "dir": "public/assets", "publicPath": "/assets" },
      "cms": { "repo": "OWNER/REPOSITORY" }
    }
    
  4. Write the description of the site's content and its CMS config, then build:
    npx site-kit schema
    npx site-kit decap-config
    npm run build
    

    Commit .hostsmith/schema.json and public/admin/config.yml. Run both commands again after a change to a collection's schema: the build fails while either file is out of date.

The site must build to static files. A build with output: "server", or with a page or endpoint that sets export const prerender = false, fails and names it.

Page copy

Text that a page writes in its markup, such as its hero's title, moves into a copy collection, so a CMS can edit it: one YAML file per page in src/content/copy/, each with its own schema.

// src/content.config.ts
import { pageCopy } from "@hostsmith/site-kit-astro/copy";
import { z } from "astro/zod";

export const copy = pageCopy({
  home: z.strictObject({ hero: z.strictObject({ title: z.string().min(1) }) }),
});
export const collections = { copy: copy.collection };
# src/content/copy/home.yml
hero:
  title: Fresh bread every morning
---
// src/pages/index.astro
import { copy } from "../content.config.ts";
const home = await copy.get("home");
const f = copy.fields("home");
---
<h1 {...f("hero.title")}>{home.hero.title}</h1>

copy.fields gives each element its field attribute, data-field, which tells a CMS and the checks which field the element shows. Bind the element that shows the value, not a container around it. The site's other collections bind their elements with fieldsFor("news", entry.id) from @hostsmith/site-kit-astro/field.

How much a CMS can edit

After a build:

npx site-kit check-fields

It reports, page by page, how much of the visible text is inside an element with a field attribute. Add --min 90 to fail below 90%, such as in CI. Mark text a CMS doesn't edit, such as a legal line in the footer, with data-field-ignore.

Locales

A core site in several languages lists them in hostsmith.json, and keeps its own routing, language switcher and hreflang links:

"content": { "locales": { "default": "en", "codes": ["en", "de"] } }

Each collection keeps its files in a layout a CMS can write: a folder per locale, such as news/en/a.md and news/de/a.md, or the code before the extension, such as news/a.en.md. The default locale needs its own folder or code too. With locales, each copy file holds every locale's copy under its code. When the site also sets Astro's i18n, both must name the same locales.

The README has the layouts and the options in full.

The CMS config

The generated config, public/admin/config.yml, saves to the repository in cms.repo, on its main branch. Every field gets the widget of its type, and a field can set its own, its label and its hint with Zod's .meta(). A field with no widget, such as a union of types, fails decap-config, naming it. The README lists every widget.

The build output never holds admin/, so the config stays in the repository and isn't deployed with the site.

Commands

CommandIn a core site
npx site-kit schemawrites .hostsmith/schema.json; --check only checks it
npx site-kit decap-configgenerates public/admin/config.yml from it; --check only checks it
npx site-kit check-fieldsreports the text coverage after a build; --min <percent> makes it a gate
npx site-kit check-urlschecks the old site's URLs, as in Keep old URLs
npx site-kit section-id, npx site-kit check-stylesfail: they are for kit sites

Deploy it

A core site deploys with the kit's workflow: copy .github/workflows/hostsmith.yml from the basics example, at the release the site uses, and remove its two style-check steps, "Check styles" and "Check built styles", which are for kit sites. Then set it up as Deploy with Hostsmith says.

The README has the core in full.