Skip to Content

gtmesh types

Generates the SSG-facing TypeScript content-types package from schemas/, so your website compiles against the content contract.

gtmesh types [--check] [--dir <path>]

What it does

gtmesh types reads your per-type schemas in schemas/ — plus a handful of config-derived constants (the section list, per-environment render set, site base URL, facet axes, and thumbnail projection) — and emits a self-contained, buildable TypeScript package — the content-types package your website (or any TS consumer) imports. Your site’s components type-check against these generated types, so the consumer can’t drift from the content the engine produces.

With --check it writes nothing and instead verifies that the committed package still matches the schemas, exiting non-zero on drift. Wire that into CI so a schema change can’t ship without the regenerated package.

A type defined once and shared by file ($ref: "shared.schema.yaml#/definitions/hero") emits one interface, however many page types use it. Each name maps to a single TS type, so gtmesh types stops and names the files when one name carries two different types: a shared definition and a local copy that differ in any way, or two local copies that differ in structure. Local copies that differ only in titles or descriptions generate a warning instead.

Generating types is the consume step. The schemas it reads are the same ones validate and seal enforce on page content — one source of truth for both the data and its TypeScript shape.

Repo wiring

On a write (not --check), gtmesh types also wires the package into the repo so it’s usable straight away. Each file is created only if it’s missing, so your edits are kept:

  • pnpm-workspace.yaml listing the package’s parent dir, so consumers depend on it as workspace:*;
  • a root package.json with @benfoster/gtmesh as a devDependency;
  • .npmrc pointing the @benfoster scope at GitHub Packages;
  • .github/workflows/content-types.yml, the types --check CI gate.

A mesh inside a larger pnpm monorepo (a folder such as mesh/ under a repo whose own pnpm-workspace.yaml sits above it) leaves the workspace file, .npmrc and CI to that repo. The search stops at the repo root (the first folder with .git). gtmesh types writes the package and the mesh’s package.json. It warns if the outer pnpm-workspace.yaml doesn’t list the package dir (add e.g. mesh/packages/*), and if an earlier run left a workspace file, .npmrc or workflow inside the mesh (delete them). It also prints the CI step to add to the repo’s own workflow:

pnpm --dir "mesh" exec gtmesh types --check

The repo’s own .npmrc needs the @benfoster scope line from installation so CI can install gtmesh.

Keep codegen.dir inside the mesh (the default packages/content-types) in both layouts. To skip the package build step, set codegen.exports: source; see built or source entry points.

Configuration

The codegen block in gtmesh.config.yaml shapes the package. Every key is optional.

KeyDefaultWhat it sets
codegen.dirpackages/content-typesWhere the package is written, relative to the mesh. Keep it inside the mesh.
codegen.name@<project>/content-typesThe package name consumers depend on ("<name>": "workspace:*").
codegen.exportsdistWhat the package’s entry points name. dist: the compiled dist/, so consumers build the package first. source: the .ts files, compiled by each consumer’s own build, with no build step; every consumer’s tsconfig must use "moduleResolution": "bundler". See built or source entry points.
gtmesh config set codegen.exports source # then: gtmesh types

Type names

A definition in your schemas can share a name with one of the engine’s exports (a shared section definition generates Section; status generates Status). Your type takes the plain name, the engine’s stays reachable as Gtmesh.<Name>, and gtmesh types warns once per shared name, naming the import that now resolves to your type. The one reserved name is Gtmesh. See type names: yours take priority.

Arguments & flags

OptionDescriptionDefault
--checkVerify the committed package matches the schemas (CI gate); exits non-zero on drift. Writes nothingoff (generates)
--dir <path>Override the package output directoryconfig.codegen.dir

The global options (--project, --json, --quiet) also apply.

Reads & writes

  • Consumes: the per-type schemas in schemas/ (incl. any projection result schema like card.schema.yaml) and any schema file they $ref by file, plus config-derived constants from gtmesh.config.yaml — taxonomy (sections, axes, facets), environments, site (incl. site.projections and site.assets), and images (and config.codegen.dir and config.codegen.exports).
  • Produces: the generated TypeScript package on disk — unless --check, which produces only a pass/fail result. --check is read-only.
  • Commits: the regenerated package belongs in your commit; CI runs --check to confirm it’s in sync.

Examples

gtmesh types # (re)generate the package into config.codegen.dir gtmesh types --dir packages/content # generate into a specific directory gtmesh types --check # CI gate: fail if the package is stale
Last updated on