Resources
21Install
npx skillscat add freaxnx01/flowhub-cas-aise Install via the SkillsCat registry.
SKILL.md — OpenClaw Agent Skill
This skill configures OpenClaw for this project.
AI Agent Base Instructions
Canonical, stack-agnostic reference for all AI coding agents. Applies to every project regardless of language or framework. Stack-specific overlays live in .ai/stacks/<stack>.md and are loaded alongside this file. A project loads base + exactly one stack overlay. Tool-specific files (CLAUDE.md, .github/copilot-instructions.md, SKILL.md) derive from base + the chosen stack.
Clean Code Principles
Apply to all generated and modified code, regardless of language:
- Small methods/functions — each does one thing at one level of abstraction; aim for ≤20 lines
- Guard clauses — validate and return/throw early at the top; avoid nested
if/elsepyramids - Command-Query Separation — a function either performs an action (command, returns nothing) or returns data (query), never both
- No flag arguments — avoid boolean parameters that switch behaviour; split into two clearly named functions instead
- Meaningful names — names reveal intent; no abbreviations (
cnt,mgr,svc) except universally understood ones (id,url,dto) - One level of abstraction per function — don't mix high-level orchestration with low-level detail; extract helpers
- Fail fast — detect invalid state as early as possible and throw specific errors; don't let bad data travel deep into the call stack
- DRY — if the same logic exists in two places, extract it; but prefer duplication over the wrong abstraction — wait until the pattern is clear before generalising
- No dead code — delete unreachable branches, unused parameters, and vestigial methods; git has history
- No commented-out code blocks — delete them, git has history
Testing — TDD, Tests First, No Shortcuts
Applies to every language and framework:
- Write the failing test first
- Write the minimum implementation to make it pass
- Refactor
- Never modify a test to make it green — fix the implementation
- Never hardcode return values, mock results, or stub logic to satisfy a test
- Never silently swallow exceptions to make a test green
- After implementation, run the full test suite — not just the new test
- If a test fails after 3 attempts, STOP and explain what's going wrong instead of continuing to iterate
- Test naming:
MethodName_StateUnderTest_ExpectedBehavior(or the idiomatic equivalent for the target language) - E2E tests must be independent and idempotent — seed and clean up their own data
Framework-specific test project layout, mocking library choice, and assertion library live in the stack overlay.
UI Development Workflow (Mandatory Phase Order)
Never skip phases. Never write component code before wireframe approval.
| Phase | Skill | Gate |
|---|---|---|
| 1 — Brainstorm | /ui-brainstorm |
ASCII wireframe approved |
| 2 — Flow | /ui-flow |
Mermaid diagrams approved |
| 3 — Build | /ui-build |
Shell → logic → interactions → polish |
| 4 — Review | /ui-review |
Checklist passes |
Skill files live in .ai/skills/. The skills themselves are stack-neutral — UI component library preferences (e.g. MudBlazor, shadcn/ui, Material, Flutter widgets) are captured in the active stack overlay.
What to check before writing UI code
- Does a similar component already exist in a shared folder?
- Has the ASCII wireframe been approved?
- Has the Mermaid flow been approved?
- Are you building the shell first (no business logic yet)?
- Does the component need a unit/component test?
Localization (i18n) & Regional Formatting
User-facing apps must support de and en. CI tooling and developer-only utilities are exempt.
Language
- Default language resolved from the OS / browser locale at first launch
- User can override at runtime via an in-app language switcher
- The user's choice is persisted (cookie, preferences store, or user profile — stack-specific)
Regional formatting (decoupled from language)
Regional formatting (date, time, number, currency separators) is selected from the OS region — not dictated by the language.
- Auto-detect any
de-*OS region (de-CH,de-DE,de-AT, …) and use the matching culture - If the language is
debut the OS region is missing or unrecognized: fall back tode-CH - For
en: use the OS-provided region (typicallyen-US/en-GB) — do not force a default
Rules
- All date / number / currency rendering goes through the platform's localization API — never hand-format with raw
string.Format/toString()/ template literals. - Do not couple regional formatting to the UI language. A user can read German text with US formatting, or English text with Swiss formatting; both must work.
- Stack overlays specify the concrete API (
CultureInfo+RequestLocalizationfor .NET,flutter_localizations+intlfor Flutter, etc.).
Versioning (SemVer)
All projects follow Semantic Versioning 2.0.0: MAJOR.MINOR.PATCH — MAJOR = breaking, MINOR = new feature (backwards-compatible), PATCH = bug fix.
Conventional Commits mapping: BREAKING CHANGE: footer or ! after type → MAJOR; feat → MINOR; fix, perf → PATCH; chore, docs, ci, test, refactor → no bump.
- Git tags follow
v<MAJOR>.<MINOR>.<PATCH>(e.g.v1.3.0) — tag onmainafter merge - Pre-release:
v1.0.0-alpha.1,v1.0.0-beta.2,v1.0.0-rc.1 - git-cliff is the changelog and release notes tool — configured via
cliff.toml - Where the version is declared in the project (build file, manifest, etc.) is defined by the stack overlay — but it must be declared in exactly one place
Changelog
All projects maintain a CHANGELOG.md in the repo root following Keep a Changelog conventions. Sections per release: Added, Changed, Deprecated, Removed, Fixed, Security.
[Unreleased]section accumulates changes until a release is cut- Auto-generation: git-cliff with
cliff.tomlconfigured for Conventional Commits - CI integration:
orhun/git-cliff-actionin GitHub Actions generates release notes into GitHub Releases - CI can validate that
[Unreleased]is not empty before allowing a release branch
Example: `.ai/references/base/changelog-example.md`
12-Factor App Compliance
Projects follow the 12-Factor App methodology: one repo per service, all deps declared, env-var config, attached backing services, separate build/release/run stages, stateless processes, port binding, scale via replicas not threads, fast disposability, dev/prod parity, logs to stdout, admin processes as one-offs.
Stack-specific enforcement details (logging library, migrations, etc.) live in the stack overlay.
Full per-factor table: `.ai/references/base/12-factor.md`
Branching Strategy (GitHub Flow + protection rules)
main ← always deployable, protected
└── feature/<issue-id>-short-description
└── fix/<issue-id>-short-description
└── chore/<short-description>
└── release/<version> ← only if needed for staged releasesmainrequires: passing CI, at least 1 PR review, no direct push- Branch from
main, PR back tomain - Delete branch after merge
- Rebase or squash merge — no merge commits on
main
Git Worktrees
Worktree directory
- Use project-local worktrees under
.worktrees/at the repo root (hidden directory) .worktrees/must be listed in.gitignore— add and commit it before creating the first worktree in a repo- Use a random, short branch name when the user does not specify one (e.g.
wt/<8-hex-chars>); do not prompt for a branch name
Agent tooling that automates worktree creation should discover these rules from CLAUDE.md / AGENTS.md (e.g. a worktree.*director grep) and honour them without asking.
Commit Messages (Conventional Commits)
<type>(<scope>): <short summary>
[optional body]
[optional footer: Closes #<issue>]Types: feat, fix, test, refactor, chore, docs, ci, perf
Scope: module or layer name, e.g. orders, auth, infra, ui
feat(orders): add order cancellation endpoint
Implements POST /api/v1/orders/{id}/cancel.
Validates order is in Pending state before cancelling.
Closes #42- Subject line: imperative mood, ≤72 chars, no period
- Body: explain why, not what
- Breaking changes: add
BREAKING CHANGE:footer (or!after the type)
Pull Request Conventions
PR Title
Follow Conventional Commits format: feat(orders): add cancellation endpoint
PR Description Template
Body sections: Summary · Changes · Testing (unit, component/integration, E2E, local) · Checklist (tests pass, no new vulnerable deps, no secrets, migrations included if schema changed, API/OpenAPI spec still valid).
Template: `.ai/references/base/pr-description-template.md`
Review Guidelines
- PRs should be small and focused — one concern per PR
- Reviewers check: architecture adherence, test quality, security, no shortcuts that make tests green
- Auto-assign reviewers via
CODEOWNERS
CI/CD (generic outline)
Pipeline stages: build → test → security-scan → container-build → push
- Build and test run on every PR
- Vulnerable-dependency scan fails the build on HIGH/CRITICAL
- Container image built and pushed only on
mainafter tests pass - E2E tests run against the built image before it is marked as a release candidate
Concrete CI configuration (GitHub Actions YAML, commands, package scanners) lives in the stack overlay.
Documentation Structure
Repo-root docs/ contains:
design/<feature-name>/— UI wireframes (wireframe.md) & Mermaid flows (flow.md) per featureadr/— Architecture Decision Recordsai-notes/— AI agent working notes
Rules:
README.mdandCHANGELOG.mdlive in the repo root- UI design artifacts are saved per feature during the UI workflow phases
- AI agents write working notes to
docs/ai-notes/, not.ai/ .ai/is reserved for agent instructions and skill files only
Layout: `.ai/references/base/documentation-structure.md`
Security (baseline)
- Transport security enforced (HTTPS + HSTS)
- No secrets in source files or per-environment config files — environment variables or a secrets manager only
- Validate all inputs at system boundaries before any domain logic
- Run a vulnerable-dependency scan in CI — fail the build on HIGH/CRITICAL findings
- Standard security response headers on every HTTP response
Language- and framework-specific enforcement (specific scanners, validation libraries, header mechanisms) lives in the stack overlay.
Agent Guardrails
- Do not install additional packages without asking first
- Do not change the project's target runtime or framework version
- Do not modify build/project files unless the task requires it
- Do not introduce new architectural patterns unless explicitly asked
- Do not touch files outside the scope of the current task
- Keep changes minimal and focused — do not refactor unrelated code unless asked
- Never skip git hooks (
--no-verify) unless the user explicitly asks - Never commit secrets or credential files
Stack-specific guardrails (e.g. "do not add NuGet packages") live in the stack overlay.
Project Scaffold Checklist (baseline)
Init-time checklist (every project, regardless of stack) — including baseline, .NET, and WebAPI layers — lives at `.ai/references/scaffold-checklists.md`. Stack-specific additions are in the same file under their respective sections.
//: # (GENERATED FILE — do not edit directly. Source: .ai/stacks/_partials/dotnet-core.md + .ai/stacks/_layers/dotnet-blazor.md. Run scripts/build-stacks.sh to regenerate.)
.NET Core Conventions
Shared baseline for every .NET stack overlay. Composed with a layer file (dotnet-blazor or dotnet-webapi) into the published flat overlay.
Tech Stack (.NET baseline)
.NET 10 / C# · ASP.NET Core Minimal API · EF Core (SQLite small / PostgreSQL non-small) · FluentValidation · Serilog · OpenTelemetry · OpenAPI + Scalar · Docker + docker-compose (Alpine) · xUnit + FluentAssertions + NSubstitute.
Full table: `.ai/references/dotnet/tech-stack.md`
Architecture — Modular Monolith
- Separate top-level folders per module:
src/Modules/<ModuleName>/ - Each module owns its Domain / Application / Infrastructure layers
- Modules communicate via in-process interfaces — never direct project references across modules
- Shared kernel in
src/Shared/for cross-cutting types only - Modules register their own DI services via
IServiceCollectionextension methods - Apply Hexagonal (Ports & Adapters) inside a module when it has multiple infrastructure adapters (e.g. REST + messaging) or needs strong testability isolation
Directory layouts (modular-monolith and hexagonal): `.ai/references/dotnet/architecture-layout.md`
C# Conventions
Directory.Build.props at repo root pins (mandatory): TargetFramework=net10.0, Nullable=enable, ImplicitUsings=enable, TreatWarningsAsErrors=true, EnforceCodeStyleInBuild=true, AnalysisLevel=latest-recommended, DebugType=embedded, DebugSymbols=true. Full file: `.ai/references/dotnet/directory-build-props.md`
- File-scoped namespaces always
global usingfor framework namespaces in each projectrecordtypes for DTOs and value objectssealedby default on non-base classes- No
varwhen the type is not obvious from the right-hand side - Prefer primary constructors (.NET 8+)
- Central Package Management via
Directory.Packages.props— no versions in.csproj - Use
ILogger<T>for logging — neverConsole.WriteLine - Use specific exception types — not generic
catch (Exception) - Use
CancellationTokenin all async methods that call external resources - Use
async/awaitend-to-end — neverTask.Resultor.GetAwaiter().GetResult() - No
#nullable disableor warning suppressions to fix build errors - Never suppress nullable warnings with
!without a clear comment
API Design — Minimal API baseline
Every ASP.NET Core project (whether it exposes a REST surface or just a few endpoints for a Blazor app) follows these baseline conventions. The dotnet-webapi layer adds the deeper REST conventions on top.
- All endpoints grouped by module via
IEndpointRouteBuilderextension methods - One handler per file when the body is non-trivial; inline lambdas only for true one-liners
- Input validation via FluentValidation, run at the boundary before any handler logic
- Error responses are always
ProblemDetails(RFC 9457) — never raw strings, anonymous error objects, or HTML error pages - OpenAPI via
Microsoft.AspNetCore.OpenApi; Scalar UI mounted at/scalar
Scaffold: `.ai/references/dotnet/endpoint-group.md`
Entity Framework Core
- One
DbContextper module (not one global context) - Migrations in
<Module>/Infrastructure/Persistence/Migrations/ IEntityTypeConfiguration<T>per entity — no data annotations on domain models- Never use
EF.Functionsin domain/application layers — only in infrastructure queries - Always use
AsNoTracking()for read-only queries - Seed data via
IEntityTypeConfiguration.HasData()or a dedicated seeder run at startup
CLI scaffold: `.ai/references/dotnet/ef-core-cli.md`
Localization & Regional Formatting (server-side baseline)
Base rules for de / en support and regional formatting live in base-instructions.md. For every ASP.NET Core project on this stack:
- Configure
RequestLocalizationMiddlewareinProgram.cswith supported culturesde-CH, de-DE, de-AT, en-US, en-GBand defaultde-CH/de - Culture resolution order: cookie (
.AspNetCore.Culture) →Accept-Languageheader → default (de-CH/de) - For language
dewith no recognized region (or ade-*region not inSupportedCultures), fall back tode-CH— neverde-DE - Format dates / numbers / currency via
CurrentCulture— neverstring.Formatwith a hardcoded culture orCultureInfo.InvariantCulturefor user-visible text
Middleware scaffold: `.ai/references/dotnet/request-localization.md`
UI-specific localization rules (resource files for component strings, picker behaviour, language-switcher widgets) live in the Blazor layer.
Testing Strategy
The base testing rules (TDD, no test modification to make green, full suite after implementation) live in base-instructions.md.
Test project layout (baseline)
tests/
<Module>.UnitTests/ ← xUnit, no I/O
<Module>.IntegrationTests/ ← xUnit, real I/O via TestcontainersLayer-specific test projects (Blazor component tests, Playwright E2E, API integration tests with WebApplicationFactory) are added by the layer overlay.
Unit tests (xUnit)
- One test class per production class
- Naming:
MethodName_StateUnderTest_ExpectedBehavior - Use
FluentAssertionsfor assertions - Use
NSubstitutefor mocks/stubs - No
[Fact]with logic — use[Theory]+[InlineData]/[MemberData] - After implementation, run the full test suite (
dotnet test) — not just the new test
Test class scaffold: `.ai/references/dotnet/xunit-example.md`
Essential Commands
# Restore / build (warnings as errors) / run
dotnet restore
dotnet build -c Release
dotnet run --project src/Host
# Run full stack locally
docker-compose -f docker-compose.yml -f docker-compose.override.yml up --build
# Tests
dotnet test # all
dotnet test tests/<Module>.UnitTests # unit only
dotnet test tests/<Module>.IntegrationTests # integration (needs Docker)
dotnet test --collect:"XPlat Code Coverage" --results-directory ./coverage
# Security / package checks
dotnet list package --vulnerable --fail-on-severity high
dotnet list package --outdatedPDB symbols: Release builds include embedded PDB symbols (<DebugType>embedded</DebugType> in Directory.Build.props) so exception stack traces contain source file names and line numbers in production. Never strip PDB symbols from release or Docker builds.
Essential Make Targets
Projects using this stack ship a repo-root Makefile standardizing the common commands. Target names are canonical; recipe bodies may use project-local variables.
Canonical targets exist for: build/run (build, watch, run-edge), testing (test, test-unit, test-coverage), Docker Compose (docker-run, up, down, logs, rebuild), quality (lint, outdated, vuln), versioning (version, version-set, bump-major|minor|patch, bump-auto), release (changelog, release-notes, release, release-auto, push-release, package), and clean. Document each target with an inline ## <description> comment and expose a help target that greps them.
A reference Makefile lives at .ai/examples/dotnet/Makefile — copy it and customize the top-of-file variables. Host/tool/project-specific targets (run-edge, release-notes, package) ship as stubs with per-OS examples in comments.
Full target list with descriptions: `.ai/references/dotnet/makefile-targets.md`
Docker
- Runtime base:
mcr.microsoft.com/dotnet/aspnet:10.0-alpine - Build base:
mcr.microsoft.com/dotnet/sdk:10.0-alpine - Multi-stage Dockerfile always
- Run as non-root user in final stage
docker-compose.yml— production-like configdocker-compose.override.yml— local dev overrides (ports, volumes, hot-reload)- Secrets via environment variables or Docker secrets — never in image or appsettings
Dockerfile scaffold: `.ai/references/dotnet/dockerfile.md`
Logging & Observability
- Serilog configured in
Program.csviaUseSerilog() - Structured properties on every log entry:
{ModuleName},{CorrelationId} - Use
LoggerMessage.Definesource-generated logging for hot paths - Log levels:
Debuglocal,Informationproduction minimum - OpenTelemetry: export traces to OTLP collector; expose
/metrics(Prometheus format) - Health checks:
/health/live(liveness) and/health/ready(readiness, checks DB)
12-Factor enforcement points for this stack:
- Never write to the local filesystem inside a container for application state
- Never use
appsettings.Development.jsonfor secrets — always env vars - EF Core migrations must be applied as a separate init container or pre-deploy step — never auto-migrated on
app.Run() - Serilog sink in production: stdout or OTLP — never file sink in Docker
Security (stack baseline)
Base security rules live in base-instructions.md. For every project on this stack:
- HTTPS enforced in all environments; HSTS enabled
- Security response headers:
X-Content-Type-Options,X-Frame-Options,Content-Security-Policy - No secrets in
appsettings.json— useIConfigurationwith environment variable binding - Run
dotnet list package --vulnerable --fail-on-severity highin CI — fail build on HIGH/CRITICAL - Validate all inputs at the API boundary with FluentValidation before any domain logic
- Error responses use
ProblemDetails(no raw messages)
Versioning (stack binding)
Base rules (SemVer, Conventional Commits → bump mapping, git-cliff) live in base-instructions.md. For this stack:
- One global version for all assemblies — defined once in
Directory.Build.propsas<Version>, never in individual.csprojfiles - Docker images tagged with the same version +
lateston stable releases
CI/CD (GitHub Actions baseline)
Pipeline stages: build → test → security-scan → docker-build → push. Build and test run on every PR; vulnerable-dependency scan fails the build on HIGH/CRITICAL; container image built and pushed only on main after tests pass.
Layer-specific CI jobs (E2E with Playwright for Blazor, k6 perf smoke for WebAPI) are added by the layer overlay.
Workflow scaffold: `.ai/references/dotnet/github-actions.md`
Project Scaffold Checklist (.NET baseline)
.NET-specific init-time checklist (inherits the base checklist) lives at `.ai/references/scaffold-checklists.md` under ".NET baseline". Layer additions are in the same file.
Agent Guardrails (.NET baseline)
In addition to the base guardrails:
- Do not install additional NuGet packages without asking first
- Do not change project target frameworks
- Do not modify
.csprojfiles unless the task requires it - Do not introduce new patterns (e.g. MediatR, CQRS) unless explicitly asked
Never generate (this stack)
async void(except UI event handlers — see the Blazor layer)Task.Resultor.GetAwaiter().GetResult()— alwaysawait- Magic strings — use
constornameof() - Direct
HttpClientinstantiation — always viaIHttpClientFactory - Cross-module project references (use shared interfaces)
.NET Blazor Layer
ASP.NET Core projects with a Blazor + MudBlazor UI (CSR, SSR, or both). Composed on top of the shared dotnet-core partial.
Tech Stack (Blazor additions)
| Layer | Technology |
|---|---|
| Frontend | Blazor CSR or SSR (per project) |
| UI components | MudBlazor |
| Component testing | bUnit |
| End-to-end testing | Playwright |
Blazor Conventions
- CSR (WebAssembly) for full SPA, SSR for SEO-critical or auth-heavy pages
- MudBlazor as the only component library — no mixing with other UI libs
- Components in
src/Host/Components/or per-moduleComponents/folder @codeblock kept minimal — extract logic to services orViewModelclasses- Use
[Parameter]only for the public API of a component; internal state via fields EventCallback<T>for child-to-parent communication
MudBlazor Conventions
- Prefer MudBlazor components over raw HTML at all times
- Use
MudDataGridfor tabular data (notMudTableunless legacy) - Use
MudForm+MudTextField/MudSelectfor forms with validation - Use
MudDialogfor confirmations and modals (not custom overlays) - Use
MudSnackbarfor user feedback / toast messages - Use
MudSkeletonfor loading states - Layout:
MudLayout→MudAppBar+MudDrawer+MudMainContent - Icons: use
Icons.Material.Filled.*consistently
Component Conventions
- One component per file
- Component files:
PascalCase.razor - Code-behind files:
PascalCase.razor.cs(partial class) - Services injected via
@injector constructor in code-behind - No business logic in
.razorfiles — only binding and UI events - Reuse components from
/src/Shared/before creating new ones
State & Data Flow
- Components do not call APIs directly — always go through a service
- Services are registered in
Program.cswith appropriate lifetime - Use
EventCallbackfor child→parent communication - Use
CascadingParameteronly for truly global state (e.g. auth, theme)
UI workflow — stack-specific hints
The phase order and gates are defined in base-instructions.md. For Blazor projects:
- Phase 1 (wireframe): think in MudBlazor regions —
MudAppBar,MudDrawer,MudMainContent,MudDataGrid,MudForm,MudDialog. - Phase 2 (flow): use MudBlazor component names in the component & state map.
- Phase 3 (build): code-behind
.razor.csfor all logic; useMudSkeleton/MudProgressLinearfor loading,MudSnackbarfor errors,MudDialogfor destructive confirmations,MudForm+DataAnnotationsfor validation,ma-*/pa-*/MudStack/MudGridfor spacing. - Phase 4 (review): verify no raw HTML where a MudBlazor component exists;
MudDataGrid(notMudTable),MudSnackbar(not custom toast),Icons.Material.Filled.*, a bUnit test file exists for the component.
Localization & Regional Formatting (Blazor additions)
Server-side localization (RequestLocalization, culture resolution, fallback rules, CurrentCulture formatting) is covered by the dotnet-core partial. For Blazor / MudBlazor specifically:
- UI strings go through
IStringLocalizer<T>+.resxresources perde/en. Do not put translatable strings inline in.razorfiles. - MudBlazor pickers (
MudDatePicker,MudNumericField, etc.) readCurrentCultureautomatically — do not override per-component. - Provide a language switcher in the layout (
MudMenuinMudAppBar) that writes the chosen language into the.AspNetCore.Culturecookie and reloads the page.
Testing (Blazor additions)
The unit-test conventions and test project layout baseline live in the dotnet-core partial. For Blazor projects, add:
tests/
<Module>.ComponentTests/ ← bUnit
E2E/ ← PlaywrightBlazor component tests (bUnit)
- Test components in isolation using
bUnit+Bunit.Web.AngleSharp - Use
Ctx.RenderComponent<T>()with parameter builders - Assert on rendered markup and component state
- Mock services via
Ctx.Services.AddSingleton<IMyService>(mock) - Test event handlers:
cut.Find("button").Click()then assert resulting state - Test parameter changes:
cut.SetParametersAndRender(p => p.Add(x => x.Param, newValue)) - Test async lifecycle:
cut.WaitForState(() => condition)for loading states
public sealed class OrderListComponentTests : TestContext
{
[Fact]
public void OrderList_WithOrders_RendersOrderRows()
{
// Arrange
Services.AddSingleton(Substitute.For<IOrderService>());
// Act
var cut = RenderComponent<OrderList>(p =>
p.Add(c => c.Orders, [new OrderDto(Guid.NewGuid(), "Pending")]));
// Assert
cut.FindAll("tr.order-row").Should().HaveCount(1);
}
}E2E tests (Playwright)
- Tests in
tests/E2E/ - Use
Microsoft.Playwright.NUnitor an xUnit wrapper - Page Object Model (POM) pattern — no raw selectors in test methods
- Tests must be independent and idempotent (seed + teardown own data)
- Run against the
docker-composestack in CI
public sealed class OrderCreationTests : PageTest
{
[Test]
public async Task CreateOrder_ValidInput_ShowsConfirmation()
{
var page = new OrderPage(Page);
await page.GotoAsync();
await page.FillOrderFormAsync(customerId: "test-001");
await page.SubmitAsync();
await Expect(page.ConfirmationBanner).ToBeVisibleAsync();
}
}CI addition
e2e:
needs: docker
- docker-compose up -d
- dotnet test tests/E2E
- docker-compose downProject Scaffold Checklist (Blazor additions)
Inherits the dotnet-core checklist, plus:
-
MudBlazorregistered inProgram.cs(AddMudServices()) - Component test project (
<Module>.ComponentTests) using bUnit - E2E project (
tests/E2E) using Playwright, wired into CI behind the docker stack - Language switcher (
MudMenuinMudAppBar) wired to the.AspNetCore.Culturecookie -
IStringLocalizer<T>+.resxresources seeded fordeanden
Agent Guardrails (Blazor additions)
In addition to the base and dotnet-core guardrails:
- Do not mix UI component libraries — MudBlazor is the only one
- Do not put business logic in
.razorfiles — extract to code-behind, services, or view models - Do not put translatable strings inline in
.razorfiles — useIStringLocalizer<T> - Do not call APIs directly from a component — always go through a registered service
- Do not use
MudTablefor new tabular data — useMudDataGrid - Do not use custom toast / overlay widgets — use
MudSnackbarandMudDialog - Do not skip a bUnit test when adding or materially changing a component
async voidis allowed only on Blazor event handlers — never elsewhere