The axis.json Manifest
Every project scaffolded by axs new carries an axis.json manifest at its root. It is the stable, machine-readable record of what the project chose — which starter, which layout, where things live — designed to be parsed by axs add, axs feature, axs doctor, future linting, and AI coding assistants. Its prose twin is the generated STRUCTURE.md; together they are a complete placement spec.
Why a manifest instead of inference
Section titled “Why a manifest instead of inference”Tooling needs to know where a new Lambda belongs. Inferring that from the directory tree is fragile — a freshly scaffolded project has empty directories, and a customised one has misleading ones. A manifest is honest: the values in paths and conventions are sufficient to compute placement without inspecting the tree at all.
The shape
Section titled “The shape”{ "$schema": "https://axs.axis-tech.dev/schema/axs.v1.json", "framework": "@axis-tech-co/axis-framework", "frameworkVersion": "1.x", "starter": "rest-v1", "layout": "module", "paths": { "lambdas": "lambdas/modules", "lambdaConfigs": "config/lambda-configs", "tables": "config/tables", "stacks": "cdk/lib/stacks" }, "conventions": { "lambdaGrouping": "module-then-kind", "tableLocation": "central" }}The manifest is written programmatically by axs new at scaffold time, not carried as a committed source file — so this shape is illustrative and the field-by-field contract is the schema. The complete, versioned v1 field reference (and the layout matrix that maps starter + layout to the paths/conventions values above) is the axis.json Reference.
starter/layout— the choices made ataxs newtime (see Create a Project and Layout).paths/conventions— the placement contractaxs addexecutes against. In feature layout these readlambdas/features,feature-then-name, andcolocatedinstead.$schema— a versioned, frozen identifier. The CLI validates every manifest against a bundled copy of the schema at run time, so validation never touches the network. The identifier is not yet served over HTTP, so editors cannot fetch it for completion; once the schema is published at that URL, JSON-schema-aware editors will pick it up with no change to the manifest.
Wiring: manual vs composer
Section titled “Wiring: manual vs composer”A wiring discriminator records how the app is composed:
"manual"(or absent) — the scaffoldedcdk/bin/app.tsinstantiates stacks directly, gated byconfig/features.ts. This is what the plain starters produce."composer"— the project was scaffolded with--composer:bin/app.tsis a thin call todefineAxisApp, there is noconfig/features.ts, and the manifest additionally carries a typedselectionsblock (the canonical record of which stacks and construct groups are on) plus atokensblock that letsaxs feature <name>=onre-emit a pruned feature’s config byte-identically. See The Composer.
Several commands change behaviour based on this discriminator — for example, axs feature <name>=off flips a boolean in features.ts on a manual project but performs a guarded config removal on a composer project.
Versioning rules
Section titled “Versioning rules”The v1 schema is frozen and additive: future fields may appear in v1, and v1 readers ignore unknown fields gracefully (additionalProperties: true). A breaking change — renaming a field, removing one, changing a value enum — ships as v2 with a new $schema URL, so old readers fail loudly rather than misread silently.
Who reads it — and who doesn’t
Section titled “Who reads it — and who doesn’t”The framework itself never reads axis.json. Its only contract with your code is the registries (Project Structure); the manifest is purely a contract between tooling and the project. That split is deliberate: your deployed infrastructure can never depend on a tooling metadata file.
© 2026 Axis Tech. Powered by axis-tech.co.