Top-Level Fields
| Field | Type | Required | Description |
|---|---|---|---|
version |
string |
no | Spec version, e.g. launch/v1 |
generator |
string |
no | Tool that produced this file |
name |
string |
yes | App name (lowercase kebab-case, ^[a-z][a-z0-9-]*$) |
description |
string |
no | Brief human description |
repository |
string |
no | Source code URL (e.g. GitHub) |
website |
string |
no | Project homepage URL |
logo |
string |
no | Logo image URL |
keywords |
string[] |
no | Discovery tags (e.g. [blog, cms]) |
secrets |
map<string, Secret> |
no | App-wide generated secrets |
components |
map<string, Component> |
no | Named components (multi-component mode) |
When components is absent, all component-level fields (runtime, provides, requires, env, commands, etc.) are read from the top level as a single implicit component.
When components is present, top-level component fields serve as defaults inherited by each component. Inheritance is shallow and field-level: if a component defines a field, its value replaces the top-level value entirely. Arrays and objects are never deep-merged — a component's requires replaces the top-level requires, it does not append to it.
YAML anchor warning: YAML anchors (
&name/*name) resolve to deep copies at parse time — they are not references. If an anchored block contains agenerator: secretdefinition, each alias produces a separate generated value. Use$secrets.<name>for values that must be shared across components.