diff --git a/.w4c/README.md b/.w4c/README.md new file mode 100644 index 0000000..8f8fe0e --- /dev/null +++ b/.w4c/README.md @@ -0,0 +1,180 @@ +# `.w4c/` — project folder contract + +Everything W4C needs to treat a repository as a **project** lives here. The folder is committed +with the repository, so project metadata and seed assets travel with the code. + +``` +.w4c/ +├── project.json # project metadata (source of truth in-repo) +├── template.json # present only in template repositories +├── preview.svg # catalog thumbnail for templates +└── boards/ + └── roadmap.json # board columns + seed tasks +``` + +This minimal-demo template ships **only** a board element. It deliberately has no `diagrams/` or +`workflows/` folders — the Startup Creator uses the bundled elements to decide which layers to +file and drops the heavier ones (architecture diagram, database, backend, admin, control panel, +workflows) for a single static page. + +## `project.json` + +Marks the repository as a project and carries its metadata. A repository without this file (or +without a server-side project record) is just a repository — selecting it optionally creates a +project from it. + +```jsonc +{ + "schema": 1, + "name": "Simple Todo List", + "description": "One static page with a todo list, persisted in the browser.", + "agentId": "w4c-startup", // default agent for project chats + "tags": ["web", "demo", "minimal"], + "source": { "template": "wiz4apps/templates.SimpleTodo" } +} +``` + +## `template.json` (templates only) + +Catalog descriptor for the template picker on the start page: the dialog fields the user fills in, +the dev-server startup conditions the project begins with, the prompt assembled at start, and the +list of elements to import. + +```jsonc +{ + "schema": 1, + "id": "simple-todo", + "title": "Simple Todo List", + "description": "…", + "thumbnail": ".w4c/preview.svg", + "agentId": "w4c-startup", + "defaultName": "simple-todo", // default repository name in the dialog + "skills": ["project-bootstrap"], // marketplace skills installed + attached on create + "devServer": { // static file serving, no install step + "image": "node:22-bookworm-slim", + "installCommand": "true", + "serveCommand": "npx --yes serve -s . -l {port}", + "port": 9000 + }, + "fields": [ + { "key": "projectName", "label": "Project name", "type": "text", "required": true } + ], + "promptTemplate": "…", + "elements": [ + { "kind": "board", "name": "Project roadmap", "path": ".w4c/boards/roadmap.json" } + ] +} +``` + +`fields[].type` is one of `text | textarea | number | select | boolean`. `select` fields also +declare `options`; other fields may declare `default` and `placeholder`. `promptTemplate` supports +`{{key}}` interpolation plus the service tokens `{{title}}`, `{{repoFullName}}`, `{{elements}}` +and `{{devServer}}`. + +If `elements` is omitted, the importer may discover assets by folder convention (`diagrams/`, +`boards/`, `workflows/`). This template declares its board explicitly; the absence of `diagram` / +`workflow` elements is what tells the Startup Creator to drop those layers. + +## `fields.json` — survey questions + +The create-project dialog asks the user a few questions before a project is generated. Besides the +inline `fields` in `template.json`, a repository can declare them in a **field-schema file** +`.w4c/fields.json` (override the path with the manifest's `fieldsSchema`). This is how the +template **and each page/module** add questions: + +```jsonc +{ + "schema": 1, + "fields": [ { "key": "brandTone", "label": "Brand tone", "type": "select", "options": ["Playful", "Premium"] } ], + "pages": { + "home": [ { "key": "homeHero", "label": "Hero style", "type": "select", "options": ["Split hero", "Video"] } ] + } +} +``` + +- `fields[]` extends the manifest's inline `fields`; `pages.[]` is attached to that page. +- A key is asked once (inline wins, first definition wins); a field is + `{ key, label, type: text|textarea|number|select|boolean, required?, options?, default?, placeholder? }`. +- A page's questions are asked **only while that page is selected**, and the answers are substituted + into that page's prompt (`{{homeHero}}`, …) and the starter prompt. +- The file is optional — a template without one behaves exactly as before. + +## Elements + +| Kind | Folder | Format | +|------|--------|--------| +| `diagram` | `diagrams/` | Excalidraw scene JSON (`{"type":"excalidraw", ...}`) | +| `board` | `boards/` | `{ name, columns[], tasks[] }` | +| `workflow` | `workflows/` | Workflow YAML (see `w4c-workflows-api` `WorkflowDefinition`) | +| `widget` | `widgets/` | Widget definition JSON (reserved) | + +## `boards/roadmap.json` — the build stages + +The board seed is the canonical **layer → task** list for the project. The Startup Creator +(`w4c-startup`) reads it on the first turn and materialises one board card (repository issue) per +entry in the project's own repository, then hands the user over to My Boards. A card is only "done" +when its acceptance criterion has been shown at runtime. + +```jsonc +{ + "schema": 1, + "name": "Project roadmap", + "columns": [ // the board's real grouping + { "id": "high", "name": "High Priority" }, + { "id": "low", "name": "Low Priority" }, + { "id": "none", "name": "No Priority" }, + { "id": "done", "name": "Done" } + ], + "tasks": [ + { + "icon": "💻", // unicode icon, prefixed to the card title + "title": "Frontend (code) — the single static page", + "column": "high", // target column id + "labels": ["High Priority"], + "body": "…goal, deliverables, acceptance criteria, references…" + } + ] +} +``` + +Unlike the full-size templates, this minimal demo keeps only the layers a dependency-free static +page needs (plan, frontend, run & preview, quality). Agent provisioning is deliberately **not** a +bootstrap stage — creating a specialist agent is a follow-up the user starts on purpose. + + +## `pages` — the screens of the generated app + +`template.json` may declare the screens the generated project is built from. A page is the +unit of composition: a short description, an optional preview, the **logical prompt** the +agent builds the screen from, and an optional **board task** filed for it. + +```jsonc +{ + "pages": [ + { + "id": "home", // stable id, unique across templates + the catalog + "title": "Home / storefront", + "description": "Landing with hero, featured products and search.", + "preview": ".w4c/pages/home.svg", // optional, repo-relative asset + "prompt": "Build the storefront home: ...", // the logical prompt for this screen + "task": { // optional board card for the page + "title": "Page: Home / storefront", + "body": "...deliverables, acceptance criteria...", + "priority": "high" // high | medium | low + } + } + ], + "tasks": [ // optional: prepared tasks without a page + { "title": "Publish the demo", "body": "...", "priority": "low" } + ] +} +``` + +- These pages are **exclusive to this template**. Reusable screens (account, admin, + settings, blog, pricing, contact, 404) live in the separate shared page catalog repository + `wiz4apps/templates.SharedPages` (`templates/shared-pages/.w4c/pages.json`); the template + dialog offers them as add-ons, so the catalog evolves without touching any template. +- On creation the selection is appended to the starter prompt (each page with its logical + prompt) and every page/task entry is filed as a board card with its priority label, so the + build starts from an explicit screen list instead of an implicit route list. +- Keep ids unique: a borrowed catalog page never overrides a page id this template owns.