Resource Naming
chant discovers resources by scanning exports from your src/ files. The export name becomes the logical resource name — it’s what you see in lint output, build logs, and cross-file imports. Choosing clear, consistent names makes your project easier to navigate and maintain.
Export naming
Section titled “Export naming”Exports must use camelCase — the lint rule COR005 enforces this automatically.
// ✅ correctexport const appBucket = new Bucket({ ... });export const taskQueue = new Queue({ ... });
// ❌ rejected by COR005export const AppBucket = new Bucket({ ... });export const app_bucket = new Bucket({ ... });Descriptive names
Section titled “Descriptive names”Name exports after what the resource does, not what it is. Suffix with the resource’s role to distinguish resources of the same type.
// ✅ clear purposeexport const uploadBucket = new Bucket({ ... });export const taskQueue = new Queue({ ... });export const apiRole = new Role({ ... });
// ❌ ambiguousexport const bucket1 = new Bucket({ ... });export const myQueue = new Queue({ ... });Shared configuration
Section titled “Shared configuration”When multiple resources share naming prefixes or tags, extract them into a const object. Template literals keep physical names consistent across the stack.
import { Bucket, Queue } from "@intentius/chant-lexicon-aws";
const app = { name: "myapp", team: "platform" } as const;
export const sharedDataBucket = new Bucket({ BucketName: `${app.name}-data`, Tags: [{ Key: "Team", Value: app.team }], PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, IgnorePublicAcls: true, RestrictPublicBuckets: true, },});
export const taskQueue = new Queue({ QueueName: `${app.name}-tasks`, Tags: [{ Key: "Team", Value: app.team }],});Because the config object is as const, chant’s evaluator can resolve every value at build time.
Multiple similar resources
Section titled “Multiple similar resources”TypeScript’s native constructs replace the need for framework-level count or for_each. Use Array.map to create a set of resources, then destructure the result into named exports:
import { Bucket } from "@intentius/chant-lexicon-aws";
const envs = ["dev", "staging", "prod"] as const;
const buckets = envs.map( (env) => new Bucket({ BucketName: `myapp-${env}-data`, PublicAccessBlockConfiguration: { BlockPublicAcls: true, BlockPublicPolicy: true, IgnorePublicAcls: true, RestrictPublicBuckets: true, }, }));
export const [devData, stagingData, prodData] = buckets;Each destructured export (devData, stagingData, prodData) is a distinct named resource that can be referenced from other files via import.
Multi-environment coexistence
Section titled “Multi-environment coexistence”Two builds of the same stack produce identical physical names, so deploying both into one account collides. When a project declares more than one environment, put the environment identity into the names. There are two working shapes.
One build per environment
Section titled “One build per environment”Declare an env build parameter, bind the ownership marker to it, and interpolate params.env into every name that must be unique per instance:
export default { ownership: { stack: "billing", env: { param: "env" } }, buildParams: { env: { type: "string", default: "dev" }, }, environments: ["dev", "staging", "prod"],} satisfies ChantConfig;import { params } from "@intentius/chant/params";
export const uploadBucket = new Bucket({ bucketName: `billing-${params.env}-uploads`,});params.env resolves before any file is imported, so the template literal folds to a plain string — billing-staging-uploads — with no new machinery. Build once per environment:
chant build --param env=stagingchant build --param env=prodThe two builds yield disjoint physical names and disjoint ownership markers (chant.intentius.io/env follows the same parameter — see Build-Time Parameters), so --owned filtering, drift, and delete stay scoped to one instance each.
All environments in one build
Section titled “All environments in one build”The alternative keeps every environment in a single build and hand-threads the name per instance — instantiate the same composite once per environment, each call passing its own name (web-dev, web-staging, web-prod). This is the layered configuration pattern: a base config, per-environment overrides via object spread, one manifest containing all instances.
Choose per-env builds when environments deploy independently (separate accounts, separate pipelines, short-lived copies); choose the all-in-one shape when one apply should converge every environment at once.
--env feeds params.env through CHANT_ENV
Section titled “--env feeds params.env through CHANT_ENV”chant build --env <name> sets the CHANT_ENV environment variable before the project is discovered. A build parameter can declare that variable as its fallback, which turns --env into a validated way to supply params.env:
buildParams: { env: { type: "string", default: "dev", env: "CHANT_ENV" },},environments: ["dev", "staging", "prod"],Now chant build --env staging and chant build --param env=staging bind the same value. The --env route has one extra property: the CLI rejects an --env value that is not among the declared environments, so a typo like --env stagign fails before anything builds. --param env= takes precedence over the CHANT_ENV fallback when both are supplied, per the normal precedence rules.
File organization
Section titled “File organization”Group related resources in the same file and keep unrelated ones separate. The lint rule COR009 warns when a single file exports eight or more resources — a signal that it may be doing too much.
A typical layout:
src/ storage.ts # buckets, tables compute.ts # functions, containers networking.ts # VPCs, subnets, security groups iam.ts # roles, policiesNext steps
Section titled “Next steps”- Cross-File References — import resources from other files
- Composite Resources — group related resources into reusable units
- Build-Time Parameters — the
params.envmechanism the multi-environment patterns build on - Layered Configuration — the all-in-one multi-environment pattern in full