Organization & People
Two things a site needs that used to be hard-coded in the SSG — who the organization is and the people behind it (authors, team) — are now mesh data. That single-sources them (the writer, the gate, and the site all agree) and sets up per-page structured data (Organization + Person).
Organization identity
A structured brand fact — not config (the engine never uses it to build the
mesh) and not a page — so it lives in foundation/organization.yaml:
name: Channel Pumps
legalName: Channel Pumps Ltd
description: …
url: https://channelpumps.example
logo: logo.png
address: { locality: …, region: …, postalCode: …, country: GB }
areaServed: [GB, IE]
sameAs: [https://www.linkedin.com/company/…]Only name is required. gtmesh page validate checks its shape; brand.md prose
stays the narrative and points at this as the structured source of truth. The SSG
reads it once:
import { loadOrganization, type Organization } from "@your-project/content-types";
const org = loadOrganization(); // → Organization | null
// → the Organization JSON-LD node, the footer, contact detailsdescription describes the organization (the Organization node / an About
blurb) — it is not the site meta description. The homepage’s meta description is
the home page’s own metaDescription, authored like any page.
People (authors & team)
Authorship is page data, not an SSG rule keyed off page_type. A page
declares its author in its own YAML:
meta:
slug: /guides/choosing-a-pump
author: paul-foster # optional — a reference to an author slugIt’s optional and per-page: guides and glossary entries carry it, product and
hub pages usually don’t. The author’s data lives in a bundle
content/people/<slug>/index.yaml — a shipped person type. It’s the general
People model (schema.org Person), so the same bundles power an “our team” / about
page, not just bylines; a page’s meta.author just references one of them.
type: person
meta: { slug: /people/paul-foster }
content:
name: Paul Foster
role: Founder
tagline: Founder, Channel Pumps. 40 years in the pump industry, formerly at Alfa Laval.
bio: … # the full biography (for a page / about section)
credentials: [ … ]
knowsAbout: [ pumps, dewatering ]
canonicalUrl: /about # where the person is shown on the site
sameAs: [ https://www.linkedin.com/in/… ]
photo: { asset: paul.jpg, alt: Paul Foster }tagline is the short byline credential line — rendered inline on an article,
distinct from the full bio you’d show on a dedicated page.
Resolve it with authorOf — this replaces the “assign the author by page_type”
hack:
import { authorOf, type PersonPage } from "@your-project/content-types";
const person = authorOf<PersonPage>(page); // → PersonPage | null (null if no meta.author)
if (person) {
// the byline: "By <name> — <tagline>"
const { name, tagline, canonicalUrl } = person.content;
// + the Person JSON-LD (sameAs, knowsAbout, photo) for structured data
}A dedicated person page is opt-in. The bio can live on /about (or a shared
team page) — the byline and Person data resolve from the bundle whether or not the
person has their own URL. To render /people/<slug> as a page, decree it with
gtmesh page add --type person … (a source: seed node); otherwise the bundle is
just referenced data. canonicalUrl points the Person at wherever the bio actually renders.
Related
- Projections (cards & lists) — where a byline card can also surface
- How the pieces fit — foundation vs content vs config
- Content-types package —
loadOrganization/authorOfin the API