Docs

The versioned source-of-truth contract that fy app create and fy app add-entity read and write.

fy-app.json Spec

Every project scaffolded by fy app create carries a single fy-app.json file at its root. This file is the source of truth for the project's entities and FSM workflows — fy app add-entity reads it, validates the proposed change against the same schema, and writes the merged spec back. manifest.json, the Zod schemas, the React-Query hooks, and the CRUD pages are all derived from it; fy-app.json itself is the artifact you should hand to an LLM agent (or commit to git) when you want a stable, structured description of the app.

The schema is versioned. Today the only supported version is "1". Future incompatible shape changes will bump the version and ship a migration path in the CLI; old projects continue to build until they're explicitly migrated.

Top-level shape

{
  "fy_app_spec_version": "1",
  "name": "my-orders",
  "extension_id": "example.my-orders",
  "entities": [
    {
      "name": "Order",
      "fields": [
        { "name": "ref",    "type": "string" },
        { "name": "amount", "type": "number" }
      ],
      "fsm": {
        "initial_state": "pending",
        "states": ["pending", "fulfilled", "cancelled"],
        "transitions": [
          { "from": "pending", "to": "fulfilled", "event": "fulfill", "guard": null },
          { "from": "pending", "to": "cancelled", "event": "cancel",  "guard": null }
        ]
      }
    }
  ]
}
FieldTypeNotes
fy_app_spec_versionliteral "1"Bumped on incompatible schema changes.
namenon-empty stringUsed as the npm package name in the scaffolded package.json.
extension_idnon-empty stringIdentifier the FastYoke host registers the extension under. fy app create derives this as example.<slug> from the project name; edit it before publishing to anything real.
entitiesarray, min length 1One or more entities. Append-only via fy app add-entity.

entities[]

FieldTypeNotes
namestringPascalCase — used to generate type names, file names, and URL paths (OrderOrderList.tsx, /orders, OrderSchema).
fieldsarrayMay be empty. Order is preserved into the React form.
fsmobjectPer-entity finite state machine. See below.

entities[].fields[]

FieldTypeNotes
namestringUsed verbatim as the property name on the entity type and Zod schema.
typeenumOne of string, number, boolean, date. The enum is closed in v1; new types require a spec-version bump.

entities[].fsm

FieldTypeNotes
initial_statestringMust appear in states. Enforced by the Zod schema.
statesarray, min length 1Distinct state names. The CLI imposes a soft cap of 50 states per entity (see fy-feature-schema.json).
transitionsarrayMay be empty. See below.

entities[].fsm.transitions[]

FieldTypeNotes
fromstringSource state. Must appear in states.
tostringTarget state. May equal fromself-loops are legal and are how you model audit-only events, idempotent retries, and payload counters. See FSM Designer → self-loops.
eventstringThe event name that fires the transition. Required — the CLI rejects two-part from:to triplets.
guardobject | nullA JSONLogic predicate, or null for an unguarded transition. JSONLogic is the only guard kind supported in v1 (see fy-feature-schema.json); the runtime evaluates it through the sandboxed jsonlogic-rs evaluator, never via raw string parsing.

Headless equivalents

Every prompt in fy app create maps to a flag. The flags accept the same comma-delimited mini-DSL that the prompts use, so any spec describable in the interactive wizard is also expressible headlessly:

Spec slotFlagMini-DSL
entity name--entity <Name>PascalCase identifier
fields[]--fields "<pairs>"name:type,name:type (types string / number / boolean / date)
states[]--states "<names>"s1,s2,s3 — the value of --initial is auto-added if missing
initial_state--initial <state>single state name; required whenever --states is set
transitions[]--transitions "<triplets>"from:to:event,from:to:event — all three parts required, guard is always null in flag-driven mode

For guards, edit fy-app.json after scaffolding — the wizard does not collect them.

Feature schema

fy-feature-schema.json ships alongside capabilities.json in the npm tarball and declares the constraints that the v1 spec must satisfy:

{
  "spec_version": "1",
  "field_types": ["string", "number", "boolean", "date"],
  "fsm_constraints": {
    "max_states": 50,
    "self_loops": true,
    "guard_types": ["jsonlogic"]
  }
}

An LLM agent authoring a spec can read this file to know which field types and guard kinds are legal without running the CLI. The path is also reported by fy capabilities:

fy capabilities | jq -r .feature_schema_path
# ./fy-feature-schema.json

Validation errors

fy app create and fy app add-entity both validate the spec through the same Zod schema before writing any files. Common rejections:

  • initial_state must be a member of states — you supplied --initial review but --states "draft,published" didn't include it. Add the initial state to --states or rely on the auto-add behaviour.
  • Invalid transition format "draft:published" — expected from:to:event (all three parts required) — every transition triplet must have an event name.
  • refusing to overwrite existing file(s): … (fy app create only) — the target directory already contains scaffold output. Move or delete the colliding files, or pick a different name.
  • Entity '<Name>' already exists at src/entities/<Name>.schema.ts (fy app add-entity only) — the entity is already in the spec; pick a different name. Editing an existing entity is intentionally out of scope (see callout above).

See Command Reference for the full flag list and exit-code behaviour.

Prefer to author this file in your editor? The VS Code extension validates fy-app.json with the same rules and renders each entity's workflow as a live state-machine diagram.