Guides

Configure your content

Describe your sites and collections in hollware.config.ts, with a schema, routes, components and a style guide.

Configure your content

hollware.config.ts is the source of truth for what your content is. Agents read it before they write, and Hollware checks every write against it. The Worker loads it at startup, so a config with a mistake stops the Worker with a message that says what to change.

Sites and collections

A deployment serves one site or more. A site has its locales and its collections; a collection is a kind of entry, such as posts or pages.

import { contracts, defineCollection, defineComponent, defineConfig } from '@hollware/core'
import * as z from 'zod'

const posts = defineCollection({
  schema: z.object({
    title: z.string().min(1),
    description: z.string().min(1).max(160),
    date: z.iso.date(),
    tags: z.array(z.string()).min(1),
    translationGroup: z.string(),
  }),
  routes: { en: '/blog/:slug/', es: '/es/blog/:slug/' },
  translations: { groupBy: 'translationGroup' },
  tags: 'tags',
  sortBy: 'date',
  styleGuide: 'Short paragraphs, one idea per section.',
})

export default defineConfig({
  sites: {
    blog: {
      locales: ['en', 'es'],
      defaultLocale: 'en',
      url: 'https://example.com',
      collections: { posts },
    },
  },
})

The schema

schema is the frontmatter of an entry, as a Zod schema or any Standard Schema with a JSON Schema. A draft whose frontmatter does not fit is saved with an error in its verdict, and cannot be published until it fits.

  • translations.groupBy names the field that ties the entries of one post in each locale.
  • tags names the field that holds the tags, which list_entries filters by.
  • sortBy names a date field: lists are newest first by it. Without it, by the date of first publication.

Routes

routes gives the path of an entry in each locale, with :slug. Links between entries are checked against them, and every locale of the site needs a route.

Components

The body of an entry is Markdown with components, written as ::name{prop="value"}. Each collection declares the components it allows, with the schema of their props; any other component is an error.

components: {
  callout: defineComponent({
    props: z.strictObject({ type: z.enum(['note', 'tip', 'warning']) }),
    description: 'A note beside the flow of the text.',
    example: '::callout{type="tip"}\nKeep slugs short.\n::',
  }),
},

The description and the example are for agents: describe_site returns them.

Contracts

contracts adds rules to a collection. Hollware ships some, and you can write your own; see Contracts.

contracts: [
  contracts.translationPair({ severity: 'warning' }),
  contracts.internalLinksResolve(),
  contracts.imagesHaveAlt(),
],

Style guides

styleGuide, on a site and on a collection, is Markdown for whoever writes. Hollware does not check it; agents read it with describe_site. Keep it short and concrete.