--- name: azure-project-scaffold description: "Scaffold the frontend, backend services, API routes, and service layer for an Azure-centric project following an approved project plan. Generates the frontend via a dedicated sub-agent running in parallel with the backend sub-agents, then hands off to the integrate agent for migrations, wiring, and runtime verification. WHEN: \"scaffold backend\", \"build services\", \"execute plan\", \"scaffold project\", \"create backend\", \"implement plan\", \"build backend\", \"scaffold services\", \"create API\", \"scaffold API\", \"preview frontend\"." license: MIT metadata: author: Microsoft version: "3.0.0" --- > **Important:** This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required. # Azure Project Scaffold > **AUTHORITATIVE — MANDATORY.** Canonical source for scaffolding Azure-centric backends from approved plans. Follow exactly; ignore prior assumptions; supersede all other sources. Do not improvise. **North Star:** produce a working, buildable Azure backend fast from the approved plan. If the plan has a frontend, generate it via a dedicated **Frontend sub-agent that runs in parallel with the backend sub-agents**. After scaffolding, write the `.azure/integration-plan.md` hand-off artifact and hand off to the `azure-project-integrate` agent — do NOT prompt the user for next steps. ## Triggers Execute approved plan; scaffold backend services; build API routes + service layer; generate frontend. ## Prerequisites Requires an approved plan. Verify before starting: - `.azure/project-plan.md` exists - Status = `Approved` (not `Planning`) - Section 8 lists API routes; Section 4 lists Azure services > If `.azure/project-plan.md` is missing or status ≠ `Approved`: **STOP** — tell the user _"No approved project plan found. Create and approve a project plan first."_ ## Autopilot mode (overrides approval gates & the Next Step question) **Active when** the invoking chat query begins with `[AUTOPILOT MODE]`, **or** `.azure/project-plan.md` contains `executionMode: auto` (front-matter or a `**Execution Mode**: auto` row). When active, run fully unattended: - **Skip the plan preview & approval** — the plan was already approved upstream; go straight to scaffolding (do NOT open the plan view or re-request approval). - **Skip the frontend preview approval gate** — do NOT call the `open_frontend_preview_view` tool; the UI is auto-approved in autopilot. - **Replace the Step 11 "Next Step" question with the integrate hand-off** — do NOT call `vscode_askQuestions`. Still write `.azure/integration-plan.md`, then hand off to the integrate agent unattended via the `start_project_integrate` tool, prefixing the `prompt` with `[AUTOPILOT MODE] `. - All scaffold quality work (frontend preview verification, build gates, `.azure/.preview-temp/` cleanup) still applies — autopilot suppresses **gates and questions only**. ## Rules > **15 core rules** govern every scaffold. Rule 0 is the load-bearing UX rule — visible feedback first. Rules 1–14 govern correctness. Details in referenced docs, consumed at relevant step. > **📁 Paths are examples, not assumptions.** Every directory shown in these instructions (`services/web/`, `services/functions/`, `services/shared/`, `services/functions/src/utils/`, …) is an **illustrative default for a fresh project**. When the workspace already has a structure, follow it. Read the actual layout first and map these roles (frontend folder, Functions project, shared types, etc.) onto the user's real folders — never assume or impose a specific path. The plan's Project Structure section, when present, is the source of truth for where things go. **If the plan names the deployable apps after the product** (e.g. `services/office-compliance-api`, `services/office-compliance-portal`), honor those names exactly — including in `workspaces`, `cd` commands, imports, and the computed `main`/`rootDir` (`dist/-api/src/functions/*.js`). The shared package stays generic (`services/shared`). 0. **Frontend-first generation (load-bearing UX rule)** — If the plan includes a frontend, the orchestrator launches the **Frontend Sub-Agent** (Step 1) at the same point it kicks off the backend track, so frontend generation runs **concurrently** with backend Phase A/B rather than blocking it. The sub-agent generates `services/web/` (mock data, pages, components), builds it, and reports back. The user already approved the design during planning (the `.azure/.preview-temp/` mock-up), so **do NOT ask the user to approve the UX during scaffolding.** If the plan has no frontend, this rule is satisfied trivially. See [sub-agent-strategy.md](.github/agents/azure-project-scaffold/references/sub-agent-strategy.md). 1. **Plan is source of truth** — Read `.azure/project-plan.md` at start. Follow route definitions, service list, types, architecture exactly. Do NOT re-ask user for plan requirements. 2. **Track progress** — Update plan status as you go: Approved → In Progress → Awaiting Integration. Do not defer status updates. (The `azure-project-integrate` agent advances it to `Integrated`.) 3. **Build-gate enforcement** — Every phase ends with build check (`tsc` / `npm run build`). If fails, iterate until clean. **Do NOT proceed until code compiles.** Most important rule. 4. **Azure Functions v4** — Always v4 programming model (Node.js v4, Python v2, .NET isolated). Prioritize Azure services. Runtimes: TypeScript, Python, C#. 5. **API auth and Azure client boundaries** — Read `API Login` from the plan. When it is `Yes`, scaffold user-facing login across the frontend and API behind a small application auth interface. Separately, put every Azure SDK client behind a client-provider interface. Handlers and domain code NEVER import Azure SDKs, inspect the environment, or choose client implementations. See [service-abstraction.md](.github/agents/shared-references/service-abstraction.md). 6. **Modular, one function per file** — Each Function own file. Each service own module. Extract shared utilities to `services/functions/src/utils/` — no duplication, no unused stubs. Prefix unused params with `_`. **DRY**: Same helper in 2+ files → extract to `services/functions/src/utils/` and import. **Proactive**: Before writing handlers, identify common patterns (password hashing, entity sanitization, response formatting) and pre-create shared utils. See [architecture.md](.github/agents/shared-references/architecture.md). 7. **Managed identity in production** — Every production client used for backend-to-Azure communication MUST authenticate with managed identity (`DefaultAzureCredential` or the runtime equivalent) and a resource endpoint. Select an emulator-backed local client only when the runtime environment is explicitly `Development`. Every other value, including missing or misspelled values, selects the managed-identity client and fails startup if its endpoint configuration is invalid. Never use account keys, connection-string secrets, API keys, or a local emulator as a production fallback. Keep the environment check in the composition root. See [service-abstraction.md](.github/agents/shared-references/service-abstraction.md). 8. **Input validation & standardized errors** — Every endpoint has validation schema (Zod/Pydantic/FluentValidation). Every route returns `{ error: { code, message, details? } }`. Error codes typed union, not strings. See [error-handling.md](.github/agents/shared-references/error-handling.md). 9. **Resilience classification** — Follow plan's Essential/Enhancement classification. Enhancement services wrapped in try/catch with fallback. **Enhancement constructors MUST NOT throw** — defer config validation to method calls or wrap in try/catch in registry. Constructor throws crash ALL handlers via `getServices()`. See [resilience.md](.github/agents/shared-references/resilience.md). 10. **Database write integrity** — Handlers performing multi-table writes MUST use `database.transaction()`. Document the collection-to-table mapping so the integrate agent can build matching schema migrations. (The integrate agent owns schema migrations and seed data; the scaffold does not create them.) See [database-integrity.md](.github/agents/shared-references/database-integrity.md). 11. **Auto-initialization** — Registry `getServices()` MUST auto-initialize with concrete implementations when nothing pre-registered. (The integrate agent's runtime smoke test confirms this — but the code must be correct here.) See [service-abstraction.md](.github/agents/shared-references/service-abstraction.md). 12. **Cross-workspace build safety** — When Functions imports `../shared/`, set `rootDir` to `".."` and **compute `main` field from actual `dist/` output after `tsc`** — never hardcode. With `rootDir: ".."`, handlers compile to `dist/functions/src/functions/X.js`. After build, list `dist/`, verify `main` matches. **#1 cause of "build passes but app won't start"**. See [architecture.md](.github/agents/shared-references/architecture.md). 13. **Deploy-ready artifact (dependency split)** — The deployed unit is the **compiled `dist/`**, not TS source; the server installs **production deps only** (`npm install --omit=dev`) and must not re-build. So every package imported by runtime code MUST be in `dependencies`, and build-only tooling (`typescript`, `@types/*`, test runners, bundlers) MUST be in `devDependencies` — a `--omit=dev` install has to satisfy every `import` in `dist/`. `dist/` must never import from `src/` or need a rebuild. Native-addon packages (`bcrypt`, `sharp`, `better-sqlite3`, Prisma engines) stay in `dependencies` (installed on the Linux host), never bundled from a local build. This is what lets the deploy agent ship a prebuilt artifact with the platform build **disabled** instead of relying on an Oryx rebuild (which runs without devDependencies and fails on missing `tsc`). **Monorepo:** keep each service self-contained — import `shared` via **relative paths** so `tsc` compiles it into the service's `dist/` (no workspace-package dependency to resolve in a per-service deploy), and resolve hoisted third-party deps with a service-level production install; single-file bundling (esbuild `--packages=external`) is an optional optimization, not the default. See [typescript.md](.github/agents/shared-references/runtimes/typescript.md) → Deployment build contract. 14. **Frontend quality contract** — If the plan has a frontend, **Section 5 (Design System & UI) of the plan is load-bearing**. Treat each region token in Section 5's Pages table (`header`, `hero`, `grid`, `form`, ...) as layout **intent** — render it using real primitives from the library named in `Component Library:`, themed by the Color Palette. **Reproduce the records from Section 5's Sample Content block** — the scaffolded page MUST show the same entities, names, values, and states the planning preview showed (the preview and the scaffold share this one content contract, so they stay in parity). Seed your mock data from Sample Content, then extend it. **Never produce raw `
` placeholders that just mimic the wireframe** — but bespoke, domain-specific components (polaroid frames, ticket stubs, gallery tiles, chat bubbles) that wrap a real library primitive and carry real content + imagery are encouraged, not banned. **Every media-bearing entity MUST render a real image from the mock data, never an empty tinted surface or solid-color block.** **The HTML preview at `.azure/.preview-temp/*.html` is a presentation-quality visual spec — reproduce it faithfully with real primitives and add the production-only layer (real photos, motion, dark mode, webfont, library elevation); never regress below it.** If a generated page looks **less** polished than the static preview (flatter surfaces, missing icons, no motion, no dark mode, no polished hero, no library elevation), you have failed the bar — go back and apply the Polish floor before claiming the page is complete. See [frontend-quality-bar.md](.github/agents/azure-project-scaffold/references/frontend-quality-bar.md) for the per-library region-token → primitive mapping, theming contract, icon contract, state-coverage contract, **Polish floor**, and **Polish self-review checklist**. If Section 5 is missing or `Component Library:` is blank, STOP — the plan must be completed before scaffolding. --- ## 📦 Context Management — read this first > Do NOT read all reference files upfront (~250KB total) — it wastes context needed for code, test output, and fixes. Read lazily: only when a step needs them. ### Step-to-Reference Mapping | Step | Read ONLY these files | Skip | |------|----------------------|------| | **Step 0** (Read Plan) | `.azure/project-plan.md` | All reference files | | **Step 1** (Frontend) | `../shared-references/frontend-patterns.md`, `references/frontend-preview-steps.md`, `references/frontend-quality-bar.md` | All other reference files | | **Sub-Agent Strategy** | `references/sub-agent-strategy.md` | | | **Step 2** (Foundation) | `../shared-references/architecture.md` | | | **Step 3** (Config) | `../shared-references/service-abstraction.md` — read only the Config Module section | | | **Step 4** (Services) | `../shared-references/service-abstraction.md` (full), selected runtime file | | | **Step 5** (Types/Validation) | `../shared-references/error-handling.md` — read only the Error Code Type Safety section | | | **Step 6** (Routes) | `../shared-references/resilience.md`, selected runtime file | | | **Step 7** (Errors) | `../shared-references/error-handling.md` (full) | | | **Step 8–10** (Health/OpenAPI/Logging) | _(instructions are in this skill, below)_ | | | **Step 11** (Wrap Up) | _(instructions are in this skill, below)_ | | ### Runtime-Specific Files — Load ONLY ONE Select based on the **backend service's Language** (its stack section, e.g. `## 2. Backend`) — not the `Runtime` row (Node / Bun / etc.). When the frontend is a different language than the backend, load the runtime reference for each language a service uses. | Selected Language | Orchestration | Load | Do NOT load | |-------------------|---------------|------|-------------| | TypeScript | docker-compose | `../shared-references/runtimes/typescript.md` | `python.md`, `dotnet.md` | | Python | docker-compose | `../shared-references/runtimes/python.md` | `typescript.md`, `dotnet.md` | | C# (.NET) | docker-compose / Functions | `../shared-references/runtimes/dotnet.md` | `typescript.md`, `python.md` | ### Context Release > After step checkpoint passes, that step's reference no longer needed. Under context pressure, prioritize current step reference + project source over completed step references. --- ## 🔁 Cross-platform command discipline — read once, apply everywhere > **Every shell command in this skill MUST work on Windows (PowerShell + cmd) AND macOS / Linux (bash / zsh) unchanged.** Each `run_in_terminal` call lands in a fresh shell whose default differs by OS — assume nothing. | ❌ Non-portable pattern | ✅ Portable replacement | |------------------------|------------------------| | `cd services/web && npx vite build` | `run_in_terminal` with `cwd: "services/web"` and command `npx vite build`. If no `cwd` param, use `npm --prefix services/web run build` (or `npm --prefix services/web exec -- vite build`). | | `mkdir -p services/web/src/components` | `node -e "require('fs').mkdirSync('services/web/src/components', {recursive: true})"` | | `rm -rf .azure/.preview-temp` | `node -e "require('fs').rmSync('.azure/.preview-temp', {recursive: true, force: true})"` | | `cp -r services/shared/types services/web/src/types` | `node -e "require('fs').cpSync('services/shared/types', 'services/web/src/types', {recursive: true})"` | | `touch .env` | `node -e "require('fs').closeSync(require('fs').openSync('.env', 'a'))"` or just write the file via the file-creation tool. | | `cat .env >> .env.local` | Read with the file-read tool, write with the file-write tool. | | `export FOO=bar` followed by another call | Pass via the command line on the same call: `npx cross-env FOO=bar npm run build` (or set in `.env`). PowerShell uses `$env:FOO`, bash uses `export FOO` — they don't share. | | `ls`, `pwd`, `which X` | Don't invoke shell utilities. Use the workspace tools (`list_dir`, etc.) for read-only inspection. | **Cardinal rules:** 1. **Prefer the tool's `cwd` parameter** over `cd X && …` chains. `cd` doesn't survive across `run_in_terminal` calls and isn't equally portable. 2. **For Node-based operations**, prefer `node -e "…"` — Node is already a dependency of any frontend scaffold and is on PATH for backend scaffolds too. 3. **For npm operations in subfolders**, prefer `npm --prefix run