freaxnx01

SKILL.md — OpenClaw Agent Skill

No description provided

freaxnx01 0 Updated 3w ago

Resources

21
GitHub

Install

npx skillscat add freaxnx01/flowhub-cas-aise

Install via the SkillsCat registry.

SKILL.md

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/else pyramids
  • 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:

  1. Write the failing test first
  2. Write the minimum implementation to make it pass
  3. Refactor
  4. Never modify a test to make it green — fix the implementation
  5. Never hardcode return values, mock results, or stub logic to satisfy a test
  6. Never silently swallow exceptions to make a test green
  7. After implementation, run the full test suite — not just the new test
  8. If a test fails after 3 attempts, STOP and explain what's going wrong instead of continuing to iterate
  9. Test naming: MethodName_StateUnderTest_ExpectedBehavior (or the idiomatic equivalent for the target language)
  10. 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 de but the OS region is missing or unrecognized: fall back to de-CH
  • For en: use the OS-provided region (typically en-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 + RequestLocalization for .NET, flutter_localizations + intl for Flutter, etc.).

Versioning (SemVer)

All projects follow Semantic Versioning 2.0.0: MAJOR.MINOR.PATCHMAJOR = 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 on main after 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.toml configured for Conventional Commits
  • CI integration: orhun/git-cliff-action in 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 releases
  • main requires: passing CI, at least 1 PR review, no direct push
  • Branch from main, PR back to main
  • 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: buildtestsecurity-scancontainer-buildpush

  • 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
  • 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 feature
  • adr/ — Architecture Decision Records
  • ai-notes/ — AI agent working notes

Rules:

  • README.md and CHANGELOG.md live 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 IServiceCollection extension 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 using for framework namespaces in each project
  • record types for DTOs and value objects
  • sealed by default on non-base classes
  • No var when 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 — never Console.WriteLine
  • Use specific exception types — not generic catch (Exception)
  • Use CancellationToken in all async methods that call external resources
  • Use async/await end-to-end — never Task.Result or .GetAwaiter().GetResult()
  • No #nullable disable or 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 IEndpointRouteBuilder extension 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 DbContext per module (not one global context)
  • Migrations in <Module>/Infrastructure/Persistence/Migrations/
  • IEntityTypeConfiguration<T> per entity — no data annotations on domain models
  • Never use EF.Functions in 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 RequestLocalizationMiddleware in Program.cs with supported cultures de-CH, de-DE, de-AT, en-US, en-GB and default de-CH / de
  • Culture resolution order: cookie (.AspNetCore.Culture) → Accept-Language header → default (de-CH / de)
  • For language de with no recognized region (or a de-* region not in SupportedCultures), fall back to de-CH — never de-DE
  • Format dates / numbers / currency via CurrentCulture — never string.Format with a hardcoded culture or CultureInfo.InvariantCulture for 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 Testcontainers

Layer-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 FluentAssertions for assertions
  • Use NSubstitute for 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 --outdated

PDB 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 config
  • docker-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.cs via UseSerilog()
  • Structured properties on every log entry: {ModuleName}, {CorrelationId}
  • Use LoggerMessage.Define source-generated logging for hot paths
  • Log levels: Debug local, Information production 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.json for 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 — use IConfiguration with environment variable binding
  • Run dotnet list package --vulnerable --fail-on-severity high in 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.props as <Version>, never in individual .csproj files
  • Docker images tagged with the same version + latest on stable releases

CI/CD (GitHub Actions baseline)

Pipeline stages: buildtestsecurity-scandocker-buildpush. 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 .csproj files 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.Result or .GetAwaiter().GetResult() — always await
  • Magic strings — use const or nameof()
  • Direct HttpClient instantiation — always via IHttpClientFactory
  • 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-module Components/ folder
  • @code block kept minimal — extract logic to services or ViewModel classes
  • 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 MudDataGrid for tabular data (not MudTable unless legacy)
  • Use MudForm + MudTextField / MudSelect for forms with validation
  • Use MudDialog for confirmations and modals (not custom overlays)
  • Use MudSnackbar for user feedback / toast messages
  • Use MudSkeleton for loading states
  • Layout: MudLayoutMudAppBar + 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 @inject or constructor in code-behind
  • No business logic in .razor files — 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.cs with appropriate lifetime
  • Use EventCallback for child→parent communication
  • Use CascadingParameter only 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.cs for all logic; use MudSkeleton / MudProgressLinear for loading, MudSnackbar for errors, MudDialog for destructive confirmations, MudForm + DataAnnotations for validation, ma-* / pa-* / MudStack / MudGrid for spacing.
  • Phase 4 (review): verify no raw HTML where a MudBlazor component exists; MudDataGrid (not MudTable), 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> + .resx resources per de / en. Do not put translatable strings inline in .razor files.
  • MudBlazor pickers (MudDatePicker, MudNumericField, etc.) read CurrentCulture automatically — do not override per-component.
  • Provide a language switcher in the layout (MudMenu in MudAppBar) that writes the chosen language into the .AspNetCore.Culture cookie 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/                        ← Playwright

Blazor 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.NUnit or 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-compose stack 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 down

Project Scaffold Checklist (Blazor additions)

Inherits the dotnet-core checklist, plus:

  • MudBlazor registered in Program.cs (AddMudServices())
  • Component test project (<Module>.ComponentTests) using bUnit
  • E2E project (tests/E2E) using Playwright, wired into CI behind the docker stack
  • Language switcher (MudMenu in MudAppBar) wired to the .AspNetCore.Culture cookie
  • IStringLocalizer<T> + .resx resources seeded for de and en

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 .razor files — extract to code-behind, services, or view models
  • Do not put translatable strings inline in .razor files — use IStringLocalizer<T>
  • Do not call APIs directly from a component — always go through a registered service
  • Do not use MudTable for new tabular data — use MudDataGrid
  • Do not use custom toast / overlay widgets — use MudSnackbar and MudDialog
  • Do not skip a bUnit test when adding or materially changing a component
  • async void is allowed only on Blazor event handlers — never elsewhere