Appearance
The Atelier Lifecycle
Every application in Atelier follows the same path: you declare it once, Atelier generates the running experience, you fork it onto each tenant, it runs in production, and you evolve it in place. You describe what the application is — its data, its actions, its surfaces — and the platform builds, wires, and serves the rest.
This page walks the full lifecycle end to end.
1. Author
You author an application as a single declaration that spans all three planes of the platform:
| Plane | What you declare | Examples |
|---|---|---|
| Data | The entities your application stores | record types, fields, relationships |
| Execution | The actions users can take | state transitions, side effects, workflows |
| Surface | Where the application appears | public portal pages, map layers, admin views |
Alongside these you declare supporting concerns in the same place: aggregate views, notifications, authorization rules, and presentation config. Everything belongs to one application, identified by its own code.
You can write the declaration directly, or build it live in Atelier's authoring surfaces — the visual editors round-trip to exactly the same definitions, so there is one source of truth no matter how you author.
A small, illustrative slice:
yaml
identity:
code: streetlight-faults
name: Streetlight Faults
is_active: true
entities:
- entity_type: fault_report
schema:
display_name: Fault Report
tenant_scoped: true
fields:
- field_key: status
field_type:
type: enum
choices:
- { value: new, label: New }
- { value: triaged, label: Triaged }
- { value: resolved, label: Resolved }
- field_key: location
field_type: { type: geometry }
- field_key: reported_at
field_type: { type: datetime }
actions:
- key: triage_report
label: Triage
target_model: fault_report
execution_mode: engine
status: published
is_active: true
submission_criteria:
- key: must-be-new
criteria_type: field
config: { field: status, operator: eq, value: new }
order: 1
is_active: true
edits:
- { key: set-triaged, field: status, value: triaged }
side_effects:
- { key: report_triaged, type: notification, event_type: report_triaged, event: report_triaged, order: 1, is_active: true }That is the whole contract. You never write a controller, a migration, an admin screen, or a permissions check by hand.
2. Generate
When you import a declaration, Atelier runs it through a single, predictable pipeline — parse, validate, diff, apply — and provisions the application into the platform. Imports are idempotent: re-importing converges to the declared state rather than duplicating it, so you can iterate freely.
Two front doors lead to the same place: a direct import and the authoring-hub round-trip. Both produce the same generated application:
- A vocabulary of types and registries that the rest of the platform reasons about.
- A template application — a fully worked, runnable example of your application that becomes the blueprint for every tenant.
From your declaration, Atelier generates the data model, the action engine, the public and staff surfaces, the authorization policy, and the notification routing — all at once, all consistent with each other.
3. Fork
You bring a new tenant online by forking the template. In a single operation, Atelier copies every part of the application marked as forkable into the new tenant's own isolated space and rewires all the internal relationships to point within that space.
This is copy-on-create, and it is the heart of Atelier's tenancy model:
- Each tenant gets its own independent copy of the application — its own data, its own configuration, its own surfaces.
- Tenants are isolated by construction. One tenant's data and configuration are never visible to another.
- Making a new part of your application forkable is a declaration, not a code change: mark a type as forkable and it travels with every fork automatically.
Because forking copies rather than links, every tenant is free to diverge — which is exactly what makes the next stage possible.
4. Run
Once forked, the generated experiences serve real traffic.
Citizens use the portal. Public-facing pages are generated directly from your surface declarations. Every public read passes through layered admissibility and row-level authorization gates and a disclosure projection before any data leaves the platform — so the portal shows precisely what you declared as public, and nothing more.
Submissions are durable from the first millisecond. When a citizen submits, Atelier writes a durable submission record before any entity exists and acknowledges immediately. A durable workflow then materializes the full record. A submission is never lost to a transient failure.
Staff use the admin console. Generated list views, detail pages, and dashboards all render through a single shared renderer — the same rendering engine drives both the citizen portal and the staff console, so a widget looks and behaves identically wherever it appears.
Actions run through one uniform engine. When a user fires an action, Atelier runs it through a consistent pipeline every time: validate the input, check authorization and preconditions, apply the change, record an audit entry, and fan out any side effects. Because every action shares this pipeline, behavior is predictable and every change is accountable.
Notifications are routed as data. When an action emits a notification event, Atelier resolves the subscribing notification rules for that tenant, applies their filters and precedence, and dispatches each one as a durable workflow. Adding or changing a notification is an authoring change, not an engineering one.
5. Evolve
Because each tenant owns its forked copy, evolving an application is a first-class, everyday operation.
Tenant admins edit their own application. A tenant administrator opens the same editors and changes their own copy directly — they own their space, so no special mode or impersonation is involved.
Platform authors evolve the template. Authors edit the template application through the same authoring surfaces. Atelier keeps preview and live identical and compiles on save: publishing a change synchronously regenerates everything that depends on it — including the authorization rules — so the reader and the writer of every surface always agree by construction. There is no moment where a published surface is visible but not yet permissioned.
This is the loop that makes Atelier productive: declare, generate, fork, run, and evolve — each tenant a living, independently-editable instance of an application you described once.
Built-in confidence
Atelier is designed so that the running system reflects your declaration and nothing else. That guarantee is backed by capabilities built into the platform rather than bolted on after the fact:
- Idempotent, convergent imports mean re-applying a declaration always lands the system in the declared state.
- Validation at author time catches malformed declarations before they ever reach a tenant.
- Build-time checks verify that surfaces are correctly rooted, placements resolve, and navigation is wired — so a generated application is coherent before it serves a single request.
- Fail-closed authorization ensures that when a policy can't be resolved, access is denied, never granted.
- End-to-end audit records every action, giving you a complete, queryable history of what changed and who changed it.
The result is an application you can trust on day one and keep evolving with confidence — because the platform proves the system matches the declaration at every step of the lifecycle.