Skip to content

Components

A component is a releasable unit declared as data. It says what it builds, what it produces, and how it deploys. One generic orchestrator runs it, so adding a component adds a declaration, not a pipeline. This page places the release model against the rest of chant and clears up two names that collide.

For the model’s own internals — the contract, the capability registry, wiring, and the orchestrator — start at Components Overview. This page is the conceptual placement.

chant is a deterministic synthesis core with the lifecycle built on top in layers. Components are the outermost.

RingLayerWhat it does
0Synthesis (chant build)typed TypeScript in, spec-native artifacts out
1Opsnamed, phased workflows over those artifacts
2Lifecycle dialobserve, reconcile, or apply — per environment
3Componentsa release composed from a bounded capability set

Synthesis produces the artifacts; Components turn them into a release — build once, publish at deploy time, apply, verify, roll back — driven by a generated Op. If you never author a component, none of this runs.

The two names rhyme and both are reusable units discovered from source. They belong to different rings and do different work.

CompositeComponent
Ring0 — synthesis3 — release
Authored inany .ts resource filea *.component.ts file
Isa factory that returns resourcesa release unit with a deploy composition
Expands intoDeclarables, at build timea phased deploy, at run time
Answerswhat infrastructure existshow a unit ships

A Composite such as LambdaNode or CockroachDbCluster is a plain function that returns a bundle of typed resources. chant build serializes them. A Component composes capabilities into a deploy that the orchestrator runs. One shapes the artifact. The other ships it.

A Component’s deploy uses the same phase grammar as an Op — phases, parallel, gate, onFailure. That is not a coincidence. chant build generates one orchestrator Op that reads every component and drives each composition. The orchestrator is an Op, so a component runs on the local executor by default and reaches for Temporal only when a step needs a durable gate or crash-resume (Orchestration).

So the layering is: a Component is authored declaratively, and it compiles down to an Op. You reach for a hand-written Op when a single deploy needs bespoke workflow logic. You reach for a Component when you have many releasable units and want one orchestrator to run all of them without a pipeline each. A project can hold both — *.op.ts files and *.component.ts files — and they consume the same chant-built artifacts.

search-service.component.ts
import { phase, type Component } from "@intentius/chant/components/component";
import { dockerBuild, publishImage, cfnDeploy, waitSteadyState } from "@intentius/chant/components";
export const searchService: Component = {
name: "search-service",
dependsOn: ["shared-alb"],
build: dockerBuild({ context: ".", into: "archive" }),
deploy: [
phase("Publish", [publishImage({ from: "archive", to: "$env.registry" })]),
phase("Apply", [cfnDeploy({ template: "archive:search.template.json", imageRef: "@Publish.digest" })]),
phase("Verify", [waitSteadyState({ service: "search" })]),
],
};
Terminal window
chant list --components # inventory
chant run --components search-service --env staging