# New Vertical Slice

> Use this skill when asked to implement a new feature, command, query, slice, or screen in a Cratis-based project. Guides the full end-to-end workflow: C# backend → Debug+Release build → specs → React frontend → quality gates.

- Skill: `cratis/new-vertical-slice` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add cratis/new-vertical-slice`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cratis/new-vertical-slice/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Cratis (https://skillmd.com/u/cratis)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cratis/new-vertical-slice

---


Implement a complete vertical slice following this EXACT order. Never skip steps or work on multiple slices in parallel.

## Step 1 — Identify the slice type

Choose **one** of:
- **State Change** — a command that mutates state and records events (most common)
- **State View** — a query that reads from a read model
- **Automation** — a background reactor triggered by events
- **Translation** — transforms events into other events

## Step 2 — Determine the namespace root

Read `global.json` and existing `.cs` files under the app source root to find the namespace root (e.g. `Studio`, `Library`). Never hard-code it.

## Step 3 — Create the C# slice file

Place ALL backend artifacts in a single file in the slice folder: `<Feature>/<Slice>/<Slice>.cs` (under the app source root; a `<Module>/` grouping above the feature is optional — there is **no** top-level `Features/` wrapper).

File creation order within the slice:
1. Concept types (if new strongly-typed IDs are needed — see `add-concept` skill)
2. Command `record` with `Handle()` method and optional validation attributes
   - If a business rule depends on Chronicle event-sourced state, add the relevant read model as a parameter to `Handle()` — see `add-business-rule` skill (DCB pattern)
3. `CommandValidator<T>` for command-level rejection rules (see `add-business-rule`); `ConceptValidator<T>` for value invariants
4. Constraint class `<Name>Constraint` (if needed)
5. Event `record` with `[EventType]` (no arguments, no mutable properties)
6. Read model `record` with `[ReadModel]` and model-bound projection attributes (`[FromEvent<T>]`, `[Key]`, etc.)
   - Use fluent `IProjectionFor<T>` only when model-bound attributes don't fit

**Critical rules:**
- Commands are `record` types with a `Handle()` method directly on them — DO NOT create separate handler classes
- Events use `[EventType]` with NO arguments — never pass a GUID or string
- Projection: prefer model-bound attributes on the read model; if using `IProjectionFor<T>`, AutoMap is on by default — just call `.From<>()` directly
- Namespace mirrors the folder path under the source root: `<RootNamespace>.<Module>.<Feature>.<Slice>` (no `Features` segment — drop any level that isn't present)
- Copyright header on every file: `// Copyright (c) Cratis. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information.`

## Step 4 — Build

Run `dotnet build` in **both** Debug and Release. Fix ALL errors and warnings before proceeding — Debug regenerates the TypeScript proxies and compiles `#if DEBUG` spec code; build Release with `-p:CratisProxiesOutputPath=` to skip re-running proxy generation.

## Step 5 — Write specs (mandatory for every slice type)

Use the in-process scenario family — `CommandScenario` for State Change, `ReadModelScenario` for State View, `ReactorScenario` for Automation/Translation. For each command, write specs covering:
- Happy path — command succeeds, correct event appended
- Each validation failure (one spec per rule)
- Each business rule violation (one spec per DCB condition in `Handle()` that inspects a read model)
- Each constraint violation

See `write-specs` skill for the complete spec structure.

Run `dotnet test`. Fix all failures before proceeding.

## Step 6 — Implement React component(s)

Place `.tsx` files in the slice folder `<Feature>/<Slice>/`.

- Import the auto-generated command/query proxy from the same folder
- Use `CommandDialog` from `@cratis/components/CommandDialog` for command dialogs
- Use `Dialog` from `@cratis/components/Dialogs` for data-only dialogs — NEVER import from `primereact/dialog`
- Use PrimeReact CSS variables for all colors — never hard-code hex values
- Use full descriptive variable names — never abbreviations (`event` not `e`, `index` not `idx`)
- No `any` types — use `unknown` with type guards

**Command usage:**
```tsx
const [myCommand] = MyCommand.use();
const handleSubmit = async () => {
    myCommand.propertyName = value;
    const result = await myCommand.execute();
    if (result.isSuccess) closeDialog(DialogResult.Ok);
};
```

**Query with paging:**
```tsx
const pageSize = 10;
const [result, , setPage] = MyQuery.useWithPaging(pageSize);
// Use result.data, result.paging.totalItems, result.paging.page
```

Write specs for the React surface (view models, helpers, component behavior) with the **write-specs-frontend** skill.

## Step 7 — Update the composition page

Open `<Feature>/<Feature>.tsx` and add the new component. If a new page is introduced, also update the router and navigation.

## Step 8 — Quality gates

All must pass before the slice is considered done:
- `dotnet build` — zero errors/warnings
- `dotnet test` — zero failures
- `yarn lint` — zero errors
- `npx tsc -b` — zero errors
- Public-facing changes (clients, SDKs, public APIs) include associated documentation updates
- `cd Documentation/web && npm run check` passes when documentation is added or changed

---

For complete code patterns for all 4 slice types and frontend examples, see [references/PATTERNS.md](references/PATTERNS.md).

