Concepts
Contracts
The rules every write is checked against, the verdict they return, and how to write your own.
Contracts
A contract is a rule about an entry. Hollware runs the contracts of a collection on every write, and again when it publishes, and returns a verdict.
The verdict
{
"ok": false,
"phase": "write",
"errors": [
{
"contract": "schema",
"severity": "error",
"path": "/frontmatter/description",
"message": "Too big: expected string to have <=160 characters",
"fix": "Shorten the description to 160 characters or fewer."
}
],
"warnings": []
}Every violation has a path (a JSON Pointer into the entry), a message and a fix: an agent can act on it without reading your code.
Writes never fail on a contract
A draft that breaks a contract is saved, with the verdict. Work in progress is never lost, and the agent fixes it with update_draft. What a contract stops is publishing:
- an error blocks
publish, which answersblocked; - a warning asks for acknowledgement:
publishanswersneeds_acknowledgementwith the warnings, and publishes once they are sent back inacknowledgeWarnings.
validate runs the contracts on Markdown without saving anything.
Built in
These always run: the schema of the frontmatter, the components and their props, content safety (no raw HTML that runs script), and the size limit of an entry. Hollware ships more that a collection turns on:
| Contract | Checks |
|---|---|
contracts.translationPair() | the entry exists in every locale of its translation group |
contracts.internalLinksResolve() | links to other entries point at published ones, when publishing |
contracts.imagesHaveAlt() | every image has alternative text |
Each takes { severity: 'warning' } to warn instead of block.
Your own
A contract is an object with an id, a severity, a description and a check, which returns the violations of an entry:
{
id: 'seo-title-length',
severity: 'warning',
description: 'A title of at most 60 characters, which search engines show.',
check: ({ frontmatter }) =>
frontmatter.title.length <= 60
? []
: [{
path: '/frontmatter/title',
message: `The title has ${frontmatter.title.length} characters; search engines show about 60.`,
fix: 'Shorten the title to 60 characters or fewer.',
}],
}Write the fix for the agent that will read it: say what to do, not what went wrong.