Skip to content

Documentation

Configuration reference

Everything Heddle knows about your company, and how far it may act, lives in a heddle/ folder in your own site's repository, so every change goes through a pull request you can review. company.json holds the facts it may claim, people.json who approves what, autonomy.json how far each agent may act and site.json how your build is read, among 14 files. heddle validate tells you when something is missing.

Four files are required. heddle/company.json, heddle/people.json, heddle/autonomy.json, heddle/personas.json. The rest are optional, and every optional field has a default. heddle validate checks them all.

heddle/company.json

Company facts, required. The company's facts with their evidence, covering what it sells, where, to whom, and what may and may not be said about it. Every agent and check reads it, and nothing Heddle writes may claim what is not here.

Field Type Required Default What it is
name string yes The company's name as readers see it. Used in titles, llms.txt, JSON-LD, reports and every agent prompt.
legalName string The registered legal name, when it differs from name. The brand kit and the Organization markup use it.
url string yes The live site's address, https://. The audit, the agents and llms.txt read the site from it.
kind one of: service, product, both yes service, product or both. Decides which page patterns suit the company and how llms.txt lists the offerings.
market object yes Where the buyers are. Research reads search volume and results pages for this country and language.
market.country string yes Two-letter country code, such as US. Search data is read for this country.
market.language string yes Two-letter language code, such as en.
market.regions list of strings Regions inside the country the company serves, when it serves only some.
description object yes How the company describes itself, in two lengths. llms.txt and the agents use them verbatim.
description.oneLine string yes One sentence: what the company does and for whom. The quote line of llms.txt.
description.short string yes A 70 to 160 character description, for meta descriptions and directory listings.
offerings list of objects yes What the company sells, each with the phrases buyers type. Research, strategy and the page planners start from these.
offerings[].id string yes A short stable id for the offering.
offerings[].name string yes The offering's name as buyers see it.
offerings[].kind one of: service, product yes service or product.
offerings[].page string The site path that sells this offering. llms.txt lists it under Services or Product.
offerings[].buyerPhrases list of strings yes What a buyer types the week before they get in touch.
offices list of objects yes Where the company has offices. llms.txt lists them, and location pages may only claim a presence listed here.
offices[].city string yes The office's city.
offices[].region string The state or region.
offices[].country string yes The country.
offices[].headquarters boolean true for the head office. The headquarters city is pinned into every location family's sibling list.
claims object yes What may be said with evidence, and wording that is never allowed. The claims check fails a page with a forbidden pattern, and the agents may only state allowed claims.
claims.allowed list of objects yes Claims the company may make, each with its evidence.
claims.forbidden list of objects yes Patterns that fail the build wherever they appear, each with the reason.
clients object yes Which clients may be named, what may be said about each, and engagements that may be described without a name. Agents never name a client not listed here.
clients.nameable list of objects yes Clients that may be named, with exactly what may be said and the evidence.
clients.unnamed list of objects Engagements that may be described but never attributed to a named client.
partners list of objects Partner relationships, what may be said about each and what never, with evidence. The claims and voice checks and the writing agents hold copy to it.
partners[].evidence string yes A URL, a document, or who confirmed it and when. No evidence, no claim.
competitors list of strings Competitors' domains. The authority, paid and research agents compare against them; propose --competitors reads what they rank for.
search object How the company is read in search tools.
search.searchConsoleProperty string The Search Console property, sc-domain:<domain> or a URL prefix. Default: sc-domain: and the site's domain.
search.brandPattern string Regex matching branded queries, so they are split from non-brand.
search.indexnowKey string An IndexNow key kept with the company's facts. site.json indexing.key is where heddle indexing key writes it.

heddle/people.json

People, required. Who approves the agents' work, who writes, who signs outreach and who gets the reports. An agent above report with no approver here only reports.

Field Type Required Default What it is
approvers list of objects yes People who approve agents' pull requests and drafts through signed links, each with the agents they approve for.
approvers[].name string yes The approver's name.
approvers[].email string yes Where the approval links are sent.
approvers[].approves list of values yes Agent ids this person approves. validate fails an agent at propose or merge that nobody approves.
authors list of objects People who write under their own name. The author pages, bylines and Person markup come from here.
authors[].id string yes A short id used in post front matter and the author page's path.
authors[].name string yes The author's name as it appears in the byline.
authors[].role string yes The author's role, shown on the author page.
authors[].sameAs list of strings The author's own profiles elsewhere (LinkedIn, GitHub), for the Person's sameAs. The author page on the site is the Person's url.
outreachSigner object The person whose name signs pitches to publications. Required before the authority agent runs at propose or merge.
reportsTo list of strings yes Email addresses that get every run's report, the watchdog's alerts and the canary's failures.

heddle/autonomy.json

Autonomy and budget, required. How far each agent may act (off, report, propose, merge), its kill switch and schedule, the monthly budget and floors, and where the agents' models and approvals run. playbook/autonomy.md explains each level.

Field Type Required Default What it is
budget object yes Money the agents may spend. They read the remaining credit before each run, stop at the floor and never top up.
budget.monthlyUsd number yes The monthly budget for model and data spend, all agents together.
budget.floorUsd number yes Agents stop drafting when the AI Gateway's credit falls under this. Must be below monthlyUsd.
budget.dataFloorUsd number Agents skip paid search data when DataForSEO's prepaid balance falls under this, and say so.
promoteAfterCleanRuns integer 5 How many clean runs in a row an agent configured at merge needs before it merges; until then it proposes. One unclean run resets the count. Default 5.
recommendations object The recommendations ledger, heddle/recommendations.json (playbook/recommendations.md)
recommendations.maxOpenDays integer 7 The watchdog flags a recommendation still open after this many days
agents object yes One entry per agent in lib/agents/suite.mjs. heddle validate warns when one is missing.
runtime object Where the agents' models and approvals run. Only environment variable names live here, never values.
runtime.gateway object Cloudflare AI Gateway on unified billing, through which the agents reach Claude.
runtime.models object Claude model per role. seo, writer and editor have defaults; any agent id may name its own, and falls back to editor.
runtime.approvals object Signed approval links. The secret is shared with the install's Worker (templates/worker).
runtime.notify object How reports and approval links reach people. Without a key they are written to the report and the pull request only.
runtime.leads object Where the follow-up agent reads new enquiries: the site Worker endpoint and the bearer token variable.
runtime.video object The video agent's settings. Secrets are named by variable, never written here. playbook/video.md lists the accounts an install needs.
runtime.ideas object Blog ideas by email (playbook/ideas-by-email.md). Authors are people.json authors with an email; only they may file ideas.
publish object Whether agent-sourced posts (the writer's drafts of the content agent's briefs) publish themselves. A post a person asked for (ideas by email) always waits for that person's signed approval, whatever this says.
publish.agentSourced one of: auto, approve "approve" auto: at level merge, the writer merges a post once every gate passes. approve: an approver merges each one.
publish.dailyFloor integer 0 Posts the writer aims to publish a day. A day's queue that cannot reach it is reported, so the content agent's briefs are looked at.
publish.bylines list of strings people.json author ids (or names) who have agreed that agent-sourced posts may publish under their name without approving each one. Any other auto-published post carries the company's name as its byline.

heddle/personas.json

Personas, required. The readers the site is written for. The buyer and helpful gates read each page as its persona (site.json pagePersonas says which), and the writing agents draft for them.

Field Type Required Default What it is
id string yes A short id that site.json pagePersonas refers to.
who string yes Who this reader is, in a sentence: role, company size, situation.
wants string yes What they came to the page to get done.
knows string What they already know, so pages do not explain it to them.
doesNotKnow string What they do not know yet, so pages explain it instead of assuming it.

heddle/targets.json

Tracked search targets, optional. The searches the site is tracked on, each with the page meant to win it and its measured demand. heddle research track and the SEO agent read positions for these.

Field Type Required Default What it is
term string yes The search, exactly as people type it.
page string yes The site path built to win it. A different page of ours ranking instead is reported.
location string For place terms, the location to read from, e.g. 'Dallas,Texas,United States'.
volume integer or null yes null when the tool returned nothing: unknown, never zero.
cpc number or null Cost per click when measured, in US dollars; null when unknown.
measuredOn string yes The day the volume and cost were read, YYYY-MM-DD.
unverified string Why the volume is not trusted yet: a close-variant bucket it shares with phrasings that mean something else, or an acronym whose results page is another meaning. The number stays as measured; the note stops it steering.

heddle/known-errors.json

Known errors, optional. Mistakes that have shipped before, what is true instead and where each was seen. The known-errors check fails a page that repeats one with a pattern, and the writing agents are given the list so they avoid it.

Field Type Required Default What it is
id string yes A short stable id for the mistake.
when string yes The situation the mistake turns up in, such as describing partner status.
truth string yes What is true instead. The agents are told this.
pattern string Optional case-insensitive regular expression that finds the mistake. Without one, it is a judgement for a reader and is listed as unchecked.
seen list of strings yes Where and when it shipped or was caught, as evidence.

heddle/topics.json

Content beats, optional. What the content agents watch and write about, with the beats and their feeds, the commercial phrases, what to leave out, the questions buyers ask and the pages to link to.

Field Type Required Default What it is
beats list of objects yes Subjects the content agent watches, each with the feeds it reads and the question that decides whether a story fits.
commercialTerms list of strings The company's own commercial phrases. The content agent seeds from them (else from targets.json), and the SEO and strategy agents add them to their plans.
exclude list of strings Words that rule a topic out. The content agent drops any suggestion containing one.
buyerQuestions list of objects The questions buyers put to answer engines ("best X for Y", "how do I..."), each with the page that answers it. agent-ready fails a page that does not ask the question in a heading or an FAQ, and warns about a question no page answers yet.
buyerQuestions[].volume integer or null Monthly searches where measured; null when unknown, never 0 for unknown.
buyerQuestions[].source string Where the question came from: a measured search, a prompt seen in an answer engine, a sales call.
priorityPages list of objects Pages posts should send in-text links to (the SEO agent's link editor), each with the searches it is built to win. Without it, every page in targets.json is a priority page.

heddle/voice.json

Voice, optional. How the company talks and the words it avoids. The voice check fails public pages that use internal language or avoided spellings, and the writing agents are given the same lists.

Field Type Required Default What it is
internalLanguage list of objects Words the company uses about itself that buyers do not, each with what to say instead. The voice check fails them on public pages.
nameAvoid list of strings Wrong spellings of the company's or products' names. The voice check fails them.
notes string Free notes on the house voice, for the people and agents who write.
doorClosers list of objects Phrases that turn work away, added to the built-in list in lib/checks/voice.mjs. State the preference, never the condition.
clientDown list of strings Words that write a client down ("chaos", "nobody owned"), checked on clientRoutes. Replaces the built-in list.
clientRoutes list of strings Route regexes for pages that describe a client's work. Default: case studies.

heddle/site.json

How Heddle reads this site's build, optional. Every field has a default, so a site that builds to out/ needs no file at all.

Field Type Required Default What it is
outDir string "out" Built HTML, relative to the site repository.
contentDirs list of strings [] Markdown and MDX sources, relative to the site repository. Prose checks read these as well as the built pages.
contentRoutes list of strings [] Route regexes for pages built from contentDirs. Prose checks judge those once, as source, and read every other built page as HTML.
pagesDir string Where the writer puts a landing page a person asked for (an idea whose brief kind is "page"), relative to the site repository. Kept out of contentDirs: these are pages at the site root, not posts.
proseExempt list of arrays [route, reason] pairs for pages whose text nobody here may rewrite (legal terms). Left out of every prose check.
baseUrl string Defaults to company.json url.
model object Where the judging model runs. Only the environment variable names live here, never values.
model.gatewayEnv string Names the AI Gateway, for agents that bill through one. The checks call Workers AI directly.
pagePersonas list of objects Which reader each page is written for, first match wins. Without it, the first persona in personas.json reads every page.
pagePersonas[].match string yes Regular expression over the route.
pagePersonas[].persona string or null yes A personas.json id, or null to exempt the page (then why is required).
pagePersonas[].sells boolean true false: the page is there to be believed, not to ask for the call, so the buyer test skips 'talk'.
pagePersonas[].kind one of: sales, reference "sales" reference: the page answers a search (a comparison, a definition, a catalog entry) rather than selling. The buyer test holds it only to the internal-language question; the answers check judges whether it answers its search.
meta object Options for the meta check: titles, descriptions, canonicals, breadcrumbs and Markdown twins on the built pages.
meta.exempt list of arrays [route, reason] pairs.
meta.requireMarkdownTwin boolean false Fail a page with no <route>.md beside it, for sites that publish Markdown mirrors for answer engines.
meta.runtimePaths list of strings Path prefixes served at runtime rather than from the build, so an og:image there is not looked for on disk.
meta.thinWords integer 120 A page whose body (its <main>, or its one <article>) has fewer words than this is thin: the meta check warns unless it carries noindex.
meta.titleSuffix string The brand suffix the layout adds to titles (" · Brand"). With it set, a route matching bareTitles fails if its title ends with it: a post spends every character on its topic.
meta.bareTitles list of strings Route regexes whose titles never carry titleSuffix. Default: surface.posts.
density object Options for the density check, which fails long paragraphs outside articles.
density.articles list of strings Route regexes for authored articles, exempt from the paragraph-length rule. Default: blog, case studies, legal pages.
humanizer object Options for the humanizer check: rules the house style does not use, exempt pages, and names it must not flag.
humanizer.disable list of strings Rule ids this company's house style does not use, e.g. em-dash.
humanizer.exempt list of arrays [file or route, reason]: whole-document rules off, for generated reference pages.
humanizer.names list of strings Product and company names that match a banned word ("Profound"); matched case-sensitively and skipped.
answers object Options for the answers gate, which asks the model whether openings and FAQ answers answer their question.
answers.gate boolean false false reports weak openings without failing, as on the source site.
searchSurface object Options for the search-surface check, which holds titles, H1s and canonicals to a recorded surface.
searchSurface.record string "search-surface.json" The recorded surface, relative to heddle/. Rewritten by heddle check --only search-surface --update.
searchSurface.ownerPattern string Regular expression over a title whose groups 1 and 2 are the service and the place the page owns. Default: "<Service> in <Place>, ST".
urls object Options for the urls check: the legacy URLs that must still resolve and the redirects the server makes.
urls.legacy string "heddle/legacy-urls.txt" Every path the site has been indexed at, one per line, relative to the site repository. A floor, not a census: add paths found in Search Console by hand.
urls.redirects list of strings Paths the server redirects: exact, or a prefix ending in /*.
urls.unverified list of strings Path prefixes served at runtime rather than from the build, so a link into them is not called dead.
orphans object Options for the orphans check: pages the navigation must link, exemptions and inbound-link floors per family.
orphans.navRequired list of strings Route regexes for pages the navigation must link to, e.g. every service page.
orphans.exempt list of arrays [route, reason] pairs for pages meant to be reached only from outside, such as a campaign landing page.
orphans.familyFloors object Per page family, the fewest inbound links its worst-linked page and its median page should have. Under either warns.
brand object Where heddle brand writes the kit and where the site serves it.
brand.kitDir string "public/brand/kit" Relative to the site repository.
brand.page string "/brand" The brand page's route.
brand.stem string Prefix for every kit file name. Defaults to the brand name, lower case and hyphenated.
playbook object Publish Heddle's playbook on this site (lib/playbook/pages.mjs): heddle generate writes heddle/generated/playbook.json for the pages and the public Agent Skill under the route; heddle aeo lists the skill in llms.txt. templates/next/playbook/ renders it.
playbook.publicDir string "public" The folder the site serves as-is; the skill goes in <publicDir><route>/.
playbook.checks string Where this site publishes Heddle's checks, one page per check id; the checklist links each check there. Leave out when it does not.
playbook.patterns string Where this site lists the page families, when it does.
playbook.agents string Where this site describes the agents, when it does.
playbook.pages object Copy overrides per page, measured titles above all. {tactics}, {lessons}, {enforced}, {sources}, {families}, {checks} and {agents} are filled with the counts.
docs object Publish Heddle's documentation on this site (lib/docs/pages.mjs): heddle generate writes heddle/generated/docs.json with the getting-started, install, command, agents, configuration and troubleshooting pages, all generated from Heddle. templates/next/docs/ renders it.
docs.enabled boolean true false keeps the block without publishing.
docs.route string "/docs" Where the documentation lives on the site; each page is a path under it.
docs.pages object Per page (hub, getting-started, install, commands, agents, configuration, troubleshooting), copy that replaces the default: title, h1, description, answer, faqs. {commands}, {agents} and the other counts are filled in.
aeo object Options for heddle aeo: what the Markdown twins leave out, the twin size floor, the _headers file and extra llms.txt sections.
aeo.chromeClasses list of strings CSS classes on kickers, chips and labels that are page furniture, left out of the Markdown twins.
aeo.exclude list of strings Route regexes that get no twin.
aeo.minBytes integer 400 A twin shorter than this means the extraction missed the page; nothing is written.
aeo.requireQuestions boolean false Fail a page whose twin has no questions section.
aeo.headers boolean false Also write _headers (Cloudflare and Netlify format) with a Link header to each page's twin.
aeo.headLinks boolean true Write <link rel="alternate" type="text/markdown"> into each page's head, announcing its twin to a crawler that reads HTML and never headers.
aeo.llmsSections list of objects Extra sections for llms.txt, for files that are not pages (a published Agent Skill, an API spec). Each link's url is absolute or a path on the site, and a path must exist in the build.
agentReady object The agent-ready check: whether an assistant can read the site without a browser.
agentReady.crawlers list of strings User agents robots.txt must let fetch /. Defaults to GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, PerplexityBot, Google-Extended.
agentReady.answerMin integer 40 Fewest words in the paragraph under the H1.
agentReady.answerMax integer 80 Most words in the paragraph under the H1.
agentReady.minWords integer 50 Fewer words than this in the HTML's main content means it is rendered by JavaScript.
agentReady.linkHeaders one of: headers, runtime "headers" Where the Link header announcing each Markdown twin comes from: one _headers rule a page (headers), or the Worker at runtime (runtime: heddle aeo writes heddle-twins.json for templates/worker/heddle-twins.ts). Cloudflare reads 100 _headers rules, so a site past about 80 pages needs runtime.
agentReady.exempt list of arrays [route, reason] pairs for pages with nothing to offer an assistant.
agentReady.blocked list of arrays [crawler, reason] pairs: answer-engine or training crawlers robots.txt blocks on purpose. Blocking one is a business decision, allowed when written down.
legacy object heddle legacy: where the inventory of every URL the site was ever indexed at comes from.
legacy.from string The live site whose sitemap is read. Defaults to company.json url.
legacy.gscDays integer 480 Days of Search Console pages to read when credentials exist.
launch object Settings for heddle launch (playbook/launch.md). Every field has a default read from the site.
launch.worker string The Worker config, relative to the site. Default wrangler.jsonc.
launch.repo string GitHub Owner/name. Default: the origin remote.
covers object Where the covers agent reads posts and writes covers (lib/covers/site.mjs).
covers.posts string The folder of Markdown posts. Default: the first contentDirs entry.
covers.dir string "public/covers" Where <slug>.svg and the 1200x630 <slug>-og.png are written.
covers.publicPath string "/covers" The URL the dir is served at.
covers.shareField string A frontmatter field the site reads as the post's share image (e.g. "image"). When set, the proposal writes it into the post.
covers.fallback object The deterministic fallback cover (heddle covers --fallback).
helpful object The helpful-content gate (lib/checks/helpful.mjs). Floors default to the source site's measured ones.
helpful.articles list of strings Route patterns judged as articles (teach or show work); the rest are pages.
helpful.exempt list of strings Route patterns not judged (legal, forms, listings). proseExempt routes are exempt too.
indexing object Getting changed pages crawled (lib/indexing): IndexNow and the Search Console indexing request a computer-use bot performs.
indexing.key string The IndexNow key. Public by design: it only lets this host ask for a recrawl. heddle indexing key creates it and writes <key>.txt into publicDir.
surface object The surface check (lib/checks/surface.mjs, playbook/seo-aeo-geo.md).
surface.posts list of strings Route patterns for posts, which need BlogPosting, dates, a card of their own and a visible date. Default ["^/blog/[^/]+$"].
surface.allowRatings boolean Only when real reviews or ratings are shown on the page they are marked up on.
surface.timezone string The site's IANA time zone (America/Phoenix). Every date with a time must carry the offset this zone has on that day.
surface.launched string The launch day. A build on that day may date every sitemap URL with it; on any other day, every lastmod equal to the build date fails.
surface.feed string The feed's path in the build, when it is not one of rss.xml, feed.xml, atom.xml, index.xml or blog/rss.xml.
checks object Which opt-in checks run on every build for this install.
checks.include list of values Opt-in checks (they fetch the pages a post cites) that heddle check runs on every build for this install, not only with --only.
restatement object Limits for the restatement check (lib/checks/restatement.mjs). Default: the source site's calibration, the highest an approved explainer reached plus half again.
outbound object The opt-in outbound check (heddle check --only outbound): every link to another site resolves.
outbound.skip list of arrays [host, reason] pairs never fetched (a host that bans scripts).
outbound.pauseMs integer 2000 Wait before the second, slower attempt.
diagrams object Mermaid diagrams (heddle diagrams, lib/diagrams, the diagrams check).
diagrams.dir string "content/diagrams" Where rendered SVGs are committed, <key>.svg, plus index.json (key -> caption and source).
diagrams.sources list of strings Folders or files scanned for ```mermaid blocks, Markdown and JSON. Default: contentDirs plus heddle/families.
diagrams.since string Posts dated on or after this day may not embed an SVG image or raw <svg>. Default: every post.
diagrams.colors object Colour role -> brand hex. Default: read from brand.json tokens.
diagrams.font string The label face. Default: brand.json's Body type family.
diagrams.fontStack string The font-family the inlined SVG asks the page for, e.g. "var(--font-inter), Inter, sans-serif" when next/font hashes the family name.
diagrams.fonts list of objects Faces the renderer loads before measuring labels.
diagrams.require one of: either, diagram, image, both, off "either" What every post must carry in its body. On by default: a post with no diagram and no image fails.
diagrams.requireSince string Apply require only to posts dated on or after this day (for an install with an archive).
images object The images check and heddle images.
images.publicDir string "public" Where site-relative image paths are found on disk.
assets object The assets check: hosts a page may load from.
assets.allow list of arrays [host, reason] pairs a page may load assets from.
assets.banned list of arrays [pattern, reason] pairs for hosts known dead or leaving; failed even as a link.
media object Binary media in object storage (heddle media, lib/media). Only for media too large or too many for git.
media.dir string "public/media" Local media, relative to the site repository. Not a mirror of the bucket.
media.bucket string yes The R2 bucket name.
media.prefix string "media" Key prefix in the bucket, and the URL path the Worker serves it at.
media.cacheHeader string A response header that only the bucket path sets (e.g. x-media-cache), so --headers can tell an R2 answer from a bundled fallback.
data object Where the agents' search data comes from (lib/data). Agents ask for a capability (keyword volume, positions, backlinks, Core Web Vitals...); the providers named here answer. Only environment variable names live here, never values. Without this block an install keeps DataForSEO, Search Console and anonymous PageSpeed at their default variable names.
data.prefer object Per capability, the providers to try in order, e.g. { "rankTracking": ["openseo", "dataforseo"] }.
contact object The contact form's endpoint in the site Worker (templates/worker/heddle-contact.ts). Every field has a default.
contact.path string "/api/contact" Where the form posts.
contact.defaultTopic string "Enquiry" The topic when the form sends none.
contact.needMore string The error shown when neither a site nor a message of minMessage characters was given.
contact.accent string The internal email's accent colour; brand.json's --spot colour when unset.
worker object Optional routes of the site Worker (templates/worker/heddle.ts).
worker.tools boolean false Mount the free tools' fetch route, POST /api/tools/fetch (templates/worker/heddle-tools.ts).

heddle/brand.json

Brand, optional. Everything the /brand page shows and the downloadable kit carries, written once. heddle brand builds the kit from it; the site's brand page renders from it.

Field Type Required Default What it is
name string Defaults to company.json name. Set it when the brand is a product of the company, not the company.
legalName string Who owns the mark. Defaults to company.json legalName.
founded integer The year the company was founded, shown on the brand page and in the kit's manifest.
contact string yes Where to ask for permission or a file that is not in the kit.
press object Optional. A named press contact, when it is not the general contact.
permissions string What may be done with the files without asking, and what needs a conversation. Defaults to a neutral statement naming the contact.
tagline string The brand line, if there is one. Not a description: the description is boilerplate.
boilerplate object yes The canonical descriptions of the company, in a long and a short form, for press and directories.
boilerplate.long string yes The canonical paragraph, identical on GitHub, npm, LinkedIn, directories and the site's metadata.
boilerplate.short string yes Must equal company.json description.short.
boilerplate.oneLine string Must equal company.json description.oneLine when both are set.
naming object yes How the name is written, and spellings to avoid.
naming.avoid list of strings yes Spellings a reader will meet that are wrong.
naming.note string How to write the name, in a sentence.
partnerships object Approved wording for a partnership, and the words that are banned. Only when there is one.
logo object yes The wordmark and mark files, clear space, minimum size and what never to do with them.
logo.description string What the logo is, in a sentence or two, for the page.
logo.donts list of strings yes Short 'please do not' lines shown beside the logo.
logo.pngWidth integer 2048 Width of the wordmark PNGs. Marks are rendered 1024 high.
background object yes The hero image the site ships, and how to put text on it.
background.file any yes The hero image the site already ships.
background.use string yes How to put text on it.
banners object Banner and share images for the kit: reuse a file the build makes, or draw one.
banners.cover boolean true Also compose a 1584x396 LinkedIn cover.
colors list of objects yes The brand colours, each with its hex value and what it is used for. Diagrams and covers draw only in these.
colors[].use string yes Its one job. Where two similar colours exist, say how their jobs differ.
colors[].token string The CSS custom property that carries it on the site, if any.
type list of objects yes The typefaces, each with its role, weight, source and a sample.
type[].stack string The CSS font stack, when the family is a system stack rather than one face.
type[].source any yes Where to get it.
voice list of objects yes Three to six do and don't pairs on how the brand writes, shown on the brand page.
family list of objects Sibling products that share the mark, if any.
family[].script string or null The name as set in a lockup script, or null for the parent brand.
lockups string How a family product's lockup is built.
rules list of strings yes Eight at most, verbatim on the page, in the manifest and in the README.
facts list of objects The facts table for a press mention: licence, website, source, and so on.
faqs list of objects Questions and answers shown on the brand page, with FAQPage markup.
copy object Optional headings for the page's sections. The reference page has neutral defaults for every one.

heddle/agents.json

Agent manifest, optional. What each agent must produce and by when, the failures it can emit, and the smoke checks a deploy must pass. Optional. An install without heddle/agents.json is held to the defaults in lib/agents/manifest.mjs. See playbook/reliability.md.

Field Type Required Default What it is
owner string yes The email of the person who answers for the agents. Gets the daily digest and every alert.
notify list of strings Others who get alerts. people.json reportsTo is always added.
systemic object When repeated failures become one systemic alert.
systemic.perAgent integer 2 The same normalised reason on this many attempts or items of one agent inside the window.
systemic.acrossAgents integer 3 The same normalised reason this many times across two or more agents inside the window.
digest object The watchdog's daily digest email: when it is sent and what its first line counts.
digest.hourUtc integer 13 The first watchdog run at or after this hour sends the day's digest.
digest.headline list of objects The counts in the digest's first line. Defaults to posts published, drafts waiting and ideas filed.
deploy object What the post-deploy smoke and the config-change check hold the site Worker to.
deploy.config string "wrangler.jsonc" The site Worker's wrangler config, relative to the repository root.
deploy.previewRequired boolean true An upload must print a preview URL. True whenever an agent drafts against previews.
agents object yes One entry per agent. An agent left out keeps its default entry.
approvals one of: gated, ungated "gated" The install's approval setting. gated: a named person approves each post before it publishes, so a draft waiting for them is an acceptable end state. ungated: agents publish once every check passes and revise against failed checks, so only published or declined ends an item. See playbook/reliability.md.

heddle/install.json

What heddle install put into this site, optional. json, written by heddle install and heddle update and read by heddle doctor. Not edited by hand.

Field Type Required Default What it is
heddle string yes The Heddle version that wrote it.
features list of values yes The features installed: worker, next, agents, deploy, config-check, ideas, approvals, smoke. heddle update and doctor read them.
files object yes Each managed file, by its path in the site: the template it came from and the SHA-256 of the template's text as installed (header excluded), so doctor can tell a stale copy from an edited one.

heddle/recommendations.json

Recommendations ledger, optional. Every recommendation an agent made and what became of it. Written by the agents (lib/agents/recommendations.mjs) and by people closing entries by hand. playbook/recommendations.md says how.

Field Type Required Default What it is
id string yes <agent>-<hash of the agent's key>; stable, so the same finding is one entry
agent string yes The agent that raised it, or "person" for one a person added
date string yes The day it was first raised
recommendation string yes What to do, in one sentence.
evidence string or object or array or null What the agent measured or read: a string, or the agent's own record
source one of: agent, proposal, person agent: raised in result.recommendations; proposal: a draft the agent produced; person: added by hand
status one of: open, implemented, rejected, needs-person yes open, implemented, rejected or needs-person. implemented needs a pr, commit or verifiedBy; rejected needs a reason; needs-person needs the step.
pr string The pull request that implements it, or that a person must review
commit string The commit that implemented it.
verifiedBy string The run that re-read the finding and no longer found it
recheck string The agent's check that re-reads this finding every run
reason string Why it was rejected
step string Exactly what a person must do
lastSeen string The last day a run raised it again.
updated string The last day the entry changed.
closedOn string The day it left open.

heddle/families/<family>.json

Family dataset, optional. The rows of one family, which are the data each of its programmatic pages is built from. heddle generate writes the publishable rows and their sibling links into heddle/generated/.

Field Type Required Default What it is
family string yes The page pattern this dataset fills (heddle families lists them).
only list of strings Publish only these row ids, where demand measures.
hub string Index page every row in this family links to, and the page that should link to every row.
ownPages list of strings Paths on the company's own site the families agent reads for every row, so what a row says about the company's own product comes from its own pages, cited like any other source.
fields object Fields this site's pages carry beyond the family's own (an answer under the H1, a meta description, FAQs), each with a note for the drafter. A row without one is skipped like a row without a required field, because its page would build broken.
rows list of objects yes One row per page, with an id, its slug and the fields the family requires. A row missing a required field is left out.
rows[].sources list of values Where the row's facts come from: URLs, or { id, url, checked } that items cite by id. heddle validate fails a citation to a source not listed here.
rows[].visual object The row's own drawing (comparisons, alternatives).
pinned list of objects Pages kept outside this dataset that belong in its sibling lists, such as the headquarters metro's own page. Each carries a path, an anchor, and the row fields the family groups and clusters by.

Generated from the Heddle repository at ddb1b16.

Questions

How do I know my configuration is valid?

Run heddle validate with the site's path. It checks every file against its schema and the rules a schema cannot express, such as an agent above report with no approver, and exits 1 on any error.