Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
6e513d7
feat: add Inertia.js React pages with admin user and role management
antosubash Mar 11, 2026
bd45c51
refactor: eliminate layout duplication between InertiaResult and Main…
antosubash Mar 12, 2026
075e7db
feat: enhance admin endpoints, Inertia middleware, and React pages
antosubash Mar 12, 2026
42ab718
chore: remove generated build outputs from git and add to .gitignore
antosubash Mar 12, 2026
65d067c
feat: add module-driven menu system with source generator support
antosubash Mar 12, 2026
eb1c8ed
refactor: simplify vendor builds and fix CSS cascade layers
antosubash Mar 12, 2026
7c974a6
feat: add additional Playwright permissions for enhanced browser control
antosubash Mar 12, 2026
8c61054
feat: add IEndpoint interface for automatic endpoint registration via…
antosubash Mar 12, 2026
5c8e190
feat: Implement CRUD operations for Products and Users
antosubash Mar 12, 2026
baf5c2c
feat: scaffold SimpleModule.Blazor Razor class library
antosubash Mar 13, 2026
315f27e
feat: extract shell components and InertiaPageRenderer to SimpleModul…
antosubash Mar 13, 2026
a949da2
feat: extract ModuleNav, UserDropdown, DarkModeToggle to SimpleModule…
antosubash Mar 13, 2026
aab028b
feat: extract @simplemodule/client npm package with Vite vendor plugi…
antosubash Mar 13, 2026
e701398
feat: extract @simplemodule/theme-default npm package with design sys…
antosubash Mar 13, 2026
d93e15e
feat: create Dashboard module with React pages, remove Home.razor
antosubash Mar 13, 2026
b57b90b
refactor: rename SimpleModule.Api to SimpleModule.Host
antosubash Mar 13, 2026
36cbe65
fix: configure InertiaOptions to use host's InertiaShell and remove d…
antosubash Mar 13, 2026
5cb9726
Refactor Products module to use new view structure
antosubash Mar 13, 2026
4649ff9
feat: add IViewEndpoint marker interface
antosubash Mar 16, 2026
e7c1f1a
feat: classify endpoints by IViewEndpoint interface, exclude views fr…
antosubash Mar 16, 2026
3584f75
test: update view discovery tests for IViewEndpoint interface
antosubash Mar 16, 2026
7f3b34d
refactor: migrate Products view endpoints to IViewEndpoint
antosubash Mar 16, 2026
7feb9c8
refactor: remove ConfigureEndpoints from ProductsModule
antosubash Mar 16, 2026
06da695
refactor: apply code style improvements and formatting across multipl…
antosubash Mar 16, 2026
76a79d4
refactor: extract data models from ModuleDiscovererGenerator into par…
antosubash Mar 16, 2026
bcc32c0
refactor: extract code emitters from ModuleDiscovererGenerator into p…
antosubash Mar 16, 2026
1ab8b7e
docs: add design for @simplemodule/ui shared component library
antosubash Mar 16, 2026
aa718cf
docs: add implementation plan for @simplemodule/ui library
antosubash Mar 16, 2026
0ab251d
refactor: split ModuleDiscovererGenerator into partial classes and im…
antosubash Mar 16, 2026
b5c6cf5
feat: scaffold @simplemodule/ui workspace with cn() utility
antosubash Mar 16, 2026
1a4618e
feat: add shadow tokens to theme for themeable button/danger shadows
antosubash Mar 16, 2026
41ad076
feat: add all 18 component templates and registry
antosubash Mar 16, 2026
6ca5ca7
feat: add CLI tool for adding UI components (npm run ui:add)
antosubash Mar 16, 2026
321a56b
feat: add all 18 component templates via CLI
antosubash Mar 16, 2026
516b136
feat: migrate Products/Manage to @simplemodule/ui components
antosubash Mar 16, 2026
ae9d064
feat: migrate Products/Create to @simplemodule/ui components
antosubash Mar 16, 2026
b954d02
feat: add Breadcrumb, Sheet, Accordion, Collapsible, ScrollArea templ…
antosubash Mar 16, 2026
5e63e58
feat: add Tooltip, Toast, Progress, Skeleton, Avatar, HoverCard templ…
antosubash Mar 16, 2026
6a26bd0
feat: add Slider, Command, Toggle, ToggleGroup templates
antosubash Mar 16, 2026
cdf8f78
feat: add 15 new UI components (accordion, avatar, breadcrumb, collap…
antosubash Mar 16, 2026
aba163b
feat: add Container, Stack, PageHeader, Section layout templates
antosubash Mar 16, 2026
7c6234e
feat: add Grid, Resizable, AspectRatio layout templates
antosubash Mar 16, 2026
3846147
feat: add Sidebar layout template with collapsible support
antosubash Mar 16, 2026
c79c7f2
feat: add 8 layout components (Container, Stack, Grid, PageHeader, Se…
antosubash Mar 16, 2026
c73ae09
feat(orders): migrate all pages to @simplemodule/ui components
antosubash Mar 16, 2026
a046725
feat(users): migrate all admin pages to @simplemodule/ui components
antosubash Mar 16, 2026
6256c90
feat(products): migrate Browse/Edit and clean up Manage/Create pages
antosubash Mar 16, 2026
b5e2c0e
feat(dashboard): migrate Home page to @simplemodule/ui components
antosubash Mar 16, 2026
936e630
fix: add process.env.NODE_ENV define to module Vite configs
antosubash Mar 16, 2026
f386c5d
fix: add @source for SimpleModule.UI to Tailwind CSS config
antosubash Mar 16, 2026
b5bacbb
Add new images for dashboard, orders, users, and landing pages; updat…
antosubash Mar 16, 2026
2056ff4
chore: remove unused audit and dashboard images
antosubash Mar 16, 2026
8cfee56
Refactor user management components and update authentication constants
antosubash Mar 16, 2026
5ea5d14
feat: add per-module Tailwind CSS for NuGet distribution
antosubash Mar 16, 2026
ae5aa39
fix: resolve CSS layer conflicts in per-module Tailwind setup
antosubash Mar 16, 2026
d0963ef
Remove unused CSS files and Tailwind CSS plugin from Vite configurati…
antosubash Mar 16, 2026
d9f1068
feat: enhance UserDropdown component with antiforgery token handling …
antosubash Mar 16, 2026
54d4a6f
Refactor user and admin endpoints to implement IEndpoint interface
antosubash Mar 16, 2026
85d7ed5
Restructure project layout and fix npm workspace issues
antosubash Mar 16, 2026
af39f67
Refactor code structure for improved readability and maintainability
antosubash Mar 16, 2026
1cdae57
Remove bundled React library from vendor directory
antosubash Mar 16, 2026
1f2614b
fix: update source paths in app.css for correct module references
antosubash Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 5 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
"mcp__plugin_playwright_playwright__browser_tabs",
"mcp__ide__getDiagnostics",
"mcp__plugin_playwright_playwright__browser_close",
"mcp__plugin_playwright_playwright__browser_evaluate"
"mcp__plugin_playwright_playwright__browser_evaluate",
"mcp__plugin_playwright_playwright__browser_take_screenshot",
"mcp__plugin_playwright_playwright__browser_press_key",
"mcp__plugin_playwright_playwright__browser_run_code",
"mcp__plugin_playwright_playwright__browser_network_requests"
]
}
}
2 changes: 1 addition & 1 deletion .claude/skills/new-module/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class <Name>Module : IModule
}
```

4. Add `<ProjectReference Include="..\modules\<Name>\<Name>.csproj" />` to `src/SimpleModule.Api/SimpleModule.Api.csproj`
4. Add `<ProjectReference Include="..\modules\<Name>\<Name>.csproj" />` to `src/SimpleModule.Host/SimpleModule.Host.csproj`

5. Add the project to `SimpleModule.sln` using `dotnet sln add`

Expand Down
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ generated_code = true
generated_code = true

# ---- Test project relaxations ----
[{tests,src/modules/*/tests}/**/*.cs]
[{tests,modules/*/tests}/**/*.cs]

# CA1707 — underscore in test method names (standard convention)
dotnet_diagnostic.CA1707.severity = none
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ jobs:
dotnet-version: '10.0.x'

- name: Publish AOT
run: dotnet publish src/SimpleModule.Api/SimpleModule.Api.csproj -c Release
run: dotnet publish template/SimpleModule.Host/SimpleModule.Host.csproj -c Release
14 changes: 11 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Ignore Visual Studio temporary files, build results, and
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
Expand Down Expand Up @@ -207,6 +207,9 @@ PublishScripts/
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# except our top-level packages/ directory (npm libraries)
!/packages/
!/packages/**
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
Expand Down Expand Up @@ -413,5 +416,10 @@ tools/tailwindcss*
.playwright-mcp/

# Module JS build output (generated by Vite)
src/modules/**/wwwroot/*.lib.module.js
src/modules/**/wwwroot/*.lib.module.js.map
modules/**/wwwroot/*

# Tailwind CSS build output
template/SimpleModule.Host/wwwroot/*

# Tailwind CSS module scan directory
template/SimpleModule.Host/Styles/_scan/
16 changes: 16 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
}
}
134 changes: 112 additions & 22 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,129 @@
# SimpleModule
# CLAUDE.md

Modular monolith framework for .NET with compile-time module discovery via Roslyn source generators. Fully AOT-compatible — no reflection.
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What This Is

Modular monolith framework for .NET with compile-time module discovery via Roslyn source generators. Fully AOT-compatible — no reflection. Frontend uses React 19 + Inertia.js served via Blazor SSR.

## Build & Run

```bash
dotnet build
dotnet run --project template/SimpleModule.Host # runs on https://localhost:5001
```

## Frontend (npm workspaces)

```bash
npm install # install all workspace dependencies
npm run check # biome lint + format check
npm run check:fix # auto-fix lint + formatting
npm run lint # lint only
npm run format # format only (with write)
```

Workspaces: `modules/*/src/*`, `packages/*`, and `template/SimpleModule.Host/ClientApp`.

## Testing

```bash
dotnet test # all tests
dotnet test --filter "FullyQualifiedName~ClassName" # single test class
dotnet test --filter "FullyQualifiedName~MethodName" # single test method
```

Test stack: xUnit.v3, FluentAssertions, Bogus, Microsoft.AspNetCore.Mvc.Testing. SQLite in-memory for unit tests, PostgreSQL for integration tests in CI.

## Architecture

- **SimpleModule.Core** — `IModule` interface + `[Module]` attribute. References `Microsoft.AspNetCore.App` framework.
- **SimpleModule.Generator** — Incremental source generator (`netstandard2.0`) that discovers `[Module]`-decorated classes across referenced assemblies and generates `AddModules()` / `MapModuleEndpoints()` extension methods with direct `new` calls (no DI for module resolution).
- **SimpleModule.Api** — Host app (net10.0, PublishAot). References Core, Generator (as Analyzer), and all module projects.
- **src/modules/** — Each module is a class library (net10.0) referencing Core + `Microsoft.AspNetCore.App` framework.
### .NET Backend

- **SimpleModule.Core** — `IModule` interface, `[Module]` attribute, `IEndpoint` interface, `[Dto]` attribute, menu system (`IMenuRegistry`), event bus (`IEventBus`), Inertia integration.
- **SimpleModule.Generator** — Roslyn `IIncrementalGenerator` (netstandard2.0). Scans referenced assemblies for `[Module]` classes, `IEndpoint` implementors, and `[Dto]` types. Generates: `AddModules()`, `MapModuleEndpoints()`, `CollectModuleMenuItems()`, AOT JSON serializers, TypeScript interface definitions, Razor component assembly discovery.
- **SimpleModule.Host** — Host app (net10.0, PublishAot). Calls generated extension methods in `Program.cs`. Custom Inertia middleware bridges Blazor SSR → React.

### Frontend (React + Inertia.js)

- **ClientApp** (`template/SimpleModule.Host/ClientApp/app.tsx`) — Inertia bootstrap. Resolves pages by splitting route name (e.g., `Products/Browse` → imports `/_content/Products/Products.pages.js`).
- **Module pages** — Each module builds its React pages via Vite in library mode → `{ModuleName}.pages.js` in module's `wwwroot/`. Entry point: `Pages/index.ts` exporting a `pages` record mapping route names to components.
- **Type generation** — `[Dto]` types → source generator embeds TS interfaces → `tools/extract-ts-types.mjs` writes `.ts` files to `ClientApp/types/`.

### Request Flow

1. ASP.NET route handler calls `Inertia.Render("Products/Browse", props)`
2. Inertia middleware renders Blazor SSR shell with JSON props
3. React ClientApp dynamically imports module's `pages.js` bundle
4. Component hydrates with server-provided props

## Key Constraints

- **No reflection** — everything must be AOT-compliant. The source generator emits static `new ModuleName()` calls.
- **Source generator must target netstandard2.0** with `LangVersion: latest` and `EnforceExtendedAnalyzerRules: true` (must use `IIncrementalGenerator`, not `ISourceGenerator`).
- **Module class libraries must NOT have `PublishAot`** — only the API project should. They need `<FrameworkReference Include="Microsoft.AspNetCore.App" />`.
- **No reflection** — source generator emits static `new ModuleName()` calls for AOT.
- **Source generator must target netstandard2.0** with `IIncrementalGenerator` (not `ISourceGenerator`).
- **Module class libraries must NOT have `PublishAot`** — only the Host project. Modules need `<FrameworkReference Include="Microsoft.AspNetCore.App" />`.
- **Module Vite builds use library mode** — externalize React, React-DOM, @inertiajs/react. Inline dynamic imports.
- **TreatWarningsAsErrors is enabled** globally via `Directory.Build.props` with `AnalysisLevel=latest-all` and `AnalysisMode=All`. Suppressed rules are listed in `.editorconfig`.

## Build & Run
## C# Conventions (enforced by .editorconfig)

- **Naming**: Interfaces `IFoo`, public members `PascalCase`, private fields `_camelCase`, locals/params `camelCase`, constants `PascalCase`.
- **Style**: File-scoped namespaces (error), usings outside namespace (error), prefer `var`.
- **Tests**: Underscore method names allowed (`Method_Scenario_Expected`). CA2234 (Uri overload) and xUnit1051 (CancellationToken) suppressed in test projects.

## Module Communication

- **Contracts pattern** — each module has a `.Contracts` project with a public interface (e.g., `IProductContracts`) and `[Dto]` types. Other modules depend on contracts, never implementations.
- **Event bus** — `IEventBus.PublishAsync<T>()` broadcasts to all `IEventHandler<T>` implementations. Handler failures are isolated (collected in `AggregateException`).

## Test Infrastructure

- **`SimpleModule.Tests.Shared`** provides `SimpleModuleWebApplicationFactory` — in-memory SQLite, test auth scheme with `CreateAuthenticatedClient(params Claim[] claims)`, claims passed via `X-Test-Claims` header.
- **`FakeDataGenerators`** (Bogus) — pre-built fakers for all module DTOs and request types.
- CI runs tests against both SQLite and PostgreSQL.

## Frontend Packages (`packages/`)

- **@simplemodule/client** — Vite plugin for vendoring, page resolution utility.
- **@simplemodule/ui** — Radix UI component wrappers with Tailwind. Import components from `@simplemodule/ui/components`, utils from `@simplemodule/ui/lib/utils`.
- **@simplemodule/theme-default** — Tailwind CSS base theme.

## CLI (`sm` command)

```bash
dotnet build
dotnet run --project src/SimpleModule.Api
sm new project # scaffold new SimpleModule solution
sm new module <name> # create module with contracts, endpoints, tests, events
sm new feature <name> # add feature to existing module
sm doctor [--fix] # validate project structure, auto-fix issues
```

## Database

- Multi-provider: SQLite (table prefixes), PostgreSQL/SQL Server (schemas per module).
- Each module registers `ModuleDbContextInfo` for schema isolation.
- Uses `EnsureCreated()` — for production migrations, use EF Core migrations per module.

## Adding a New Module

1. Create folder `src/modules/<Name>/`
2. Create `src/modules/<Name>/src/<Name>.Contracts/` with:
- `<Name>.Contracts.csproj` (references Core only, uses `Microsoft.NET.Sdk`)
Use `sm new module <name>` (CLI) or manually:

1. Create `modules/<Name>/`
2. Create `modules/<Name>/src/<Name>.Contracts/` with:
- `<Name>.Contracts.csproj` (references Core only, `Microsoft.NET.Sdk`)
- `I<Name>Contracts.cs` — public interface for cross-module use
- Shared DTO types marked with `[Dto]`
3. Create `src/modules/<Name>/src/<Name>/` with:
- `<Name>.csproj` (references Core + `<Name>.Contracts`; uses `Microsoft.NET.Sdk` with `<FrameworkReference Include="Microsoft.AspNetCore.App" />`)
- `<Name>Module.cs` — implements `IModule` with `[Module("Name")]`
- `Features/<FeatureName>/` folders containing endpoint and handler classes
- Register the contract interface against implementation in `ConfigureServices`
4. Create `src/modules/<Name>/tests/<Name>.Tests/` with test project
5. Add `ProjectReference` to `src/SimpleModule.Api/SimpleModule.Api.csproj` pointing to `<Name>/src/<Name>.csproj`
3. Create `modules/<Name>/src/<Name>/` with:
- `<Name>.csproj` (references Core + Contracts; `Microsoft.NET.Sdk` with `<FrameworkReference Include="Microsoft.AspNetCore.App" />`)
- `<Name>Module.cs` — implements `IModule` with `[Module("Name", RoutePrefix = "...")]`
- `Endpoints/<Name>/` — endpoint classes implementing `IEndpoint` (auto-discovered)
- `Pages/index.ts` — exports `pages` record mapping route names to React components
- `vite.config.ts` — library mode build targeting `Pages/index.ts`
- `package.json` — declare React/Inertia as peerDependencies
- Register contract interface in `ConfigureServices`
- **Escape hatch**: For non-standard routes, implement `ConfigureEndpoints` on the module class
4. Create `modules/<Name>/tests/<Name>.Tests/` with xUnit test project
5. Add `ProjectReference` to `template/SimpleModule.Host/SimpleModule.Host.csproj`
6. Add all projects to `SimpleModule.slnx`

## Linting & Formatting

Biome is configured at repo root (`biome.json`). Covers `modules/**`, `packages/**`, `template/**` except `**/wwwroot/**`. Settings: single quotes, semicolons always, 2-space indent, trailing commas, 100-char line width. Tailwind CSS directives enabled.
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<PropertyGroup>
<RepoRoot>$(MSBuildThisFileDirectory)</RepoRoot>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
30 changes: 15 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src

# Copy solution and project files for restore
COPY Directory.Build.props Directory.Packages.props ./
COPY *.slnx ./
COPY src/SimpleModule.Core/*.csproj src/SimpleModule.Core/
COPY src/SimpleModule.Database/*.csproj src/SimpleModule.Database/
COPY src/SimpleModule.Generator/*.csproj src/SimpleModule.Generator/
COPY src/SimpleModule.Api/*.csproj src/SimpleModule.Api/
COPY src/modules/Users/Users.Contracts/*.csproj src/modules/Users/Users.Contracts/
COPY src/modules/Users/Users/*.csproj src/modules/Users/Users/
COPY src/modules/Products/Products.Contracts/*.csproj src/modules/Products/Products.Contracts/
COPY src/modules/Products/Products/*.csproj src/modules/Products/Products/
COPY src/modules/Orders/Orders.Contracts/*.csproj src/modules/Orders/Orders.Contracts/
COPY src/modules/Orders/Orders/*.csproj src/modules/Orders/Orders/
RUN dotnet restore src/SimpleModule.Api/SimpleModule.Api.csproj
COPY framework/SimpleModule.Core/*.csproj framework/SimpleModule.Core/
COPY framework/SimpleModule.Database/*.csproj framework/SimpleModule.Database/
COPY framework/SimpleModule.Generator/*.csproj framework/SimpleModule.Generator/
COPY framework/SimpleModule.Blazor/*.csproj framework/SimpleModule.Blazor/
COPY template/SimpleModule.Host/*.csproj template/SimpleModule.Host/
COPY modules/Dashboard/src/Dashboard/*.csproj modules/Dashboard/src/Dashboard/
COPY modules/Users/src/Users.Contracts/*.csproj modules/Users/src/Users.Contracts/
COPY modules/Users/src/Users/*.csproj modules/Users/src/Users/
COPY modules/Products/src/Products.Contracts/*.csproj modules/Products/src/Products.Contracts/
COPY modules/Products/src/Products/*.csproj modules/Products/src/Products/
COPY modules/Orders/src/Orders.Contracts/*.csproj modules/Orders/src/Orders.Contracts/
COPY modules/Orders/src/Orders/*.csproj modules/Orders/src/Orders/
RUN dotnet restore template/SimpleModule.Host/SimpleModule.Host.csproj

# Copy everything and publish
COPY . .
RUN dotnet publish src/SimpleModule.Api/SimpleModule.Api.csproj -c Release -o /app/publish
RUN dotnet publish template/SimpleModule.Host/SimpleModule.Host.csproj -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "SimpleModule.Api.dll"]
ENTRYPOINT ["dotnet", "SimpleModule.Host.dll"]
97 changes: 96 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,96 @@
# SimpleModule
# SimpleModule

A modular monolith framework for .NET with compile-time module discovery via Roslyn source generators. Fully AOT-compatible with no reflection. Frontend uses React 19 + Inertia.js served via Blazor SSR.

## Prerequisites

- [.NET 10 SDK](https://dotnet.microsoft.com/download)
- [Node.js](https://nodejs.org/) (for frontend builds)

## Getting Started

```bash
dotnet build
npm install
dotnet run --project template/SimpleModule.Host # https://localhost:5001
```

### Docker

```bash
docker compose up
```

Runs the app on `http://localhost:8080` with PostgreSQL 16.

## Architecture

```
framework/
SimpleModule.Core # IModule, IEndpoint, [Dto], [Module], IEventBus, IMenuRegistry
SimpleModule.Generator # Roslyn source generator (netstandard2.0) — module/endpoint/DTO discovery
SimpleModule.Database # Multi-provider DB support (SQLite, PostgreSQL, SQL Server)
SimpleModule.Blazor # Blazor SSR shell for Inertia rendering
modules/
Dashboard/ # Dashboard module
Products/ # Products module (src + contracts + tests)
Orders/ # Orders module (src + contracts + tests)
Users/ # Users module (src + contracts + tests)
packages/
SimpleModule.Client # Vite plugin + page resolution for module frontends
SimpleModule.UI # Radix UI component library with Tailwind
SimpleModule.Theme.Default # Tailwind CSS base theme
template/
SimpleModule.Host # Host app (net10.0) — wires modules via generated code
cli/
SimpleModule.Cli # `sm` CLI tool for scaffolding and validation
```

### How It Works

1. Modules are .NET class libraries decorated with `[Module("Name", RoutePrefix = "...")]` implementing `IModule`
2. The Roslyn source generator scans referenced assemblies at compile time and emits static registration code — no reflection needed
3. Endpoints implement `IEndpoint` and are auto-discovered and mapped
4. Each module builds its React pages via Vite in library mode into a `{ModuleName}.pages.js` bundle
5. Inertia.js bridges the .NET backend to the React frontend: endpoints call `Inertia.Render("Module/Page", props)`, the Blazor SSR shell delivers the initial HTML, and React hydrates on the client

### Module Communication

Modules communicate through two mechanisms:

- **Contracts** — each module has a `.Contracts` project exposing a public interface (e.g., `IProductContracts`) and shared `[Dto]` types. Modules depend on contract interfaces, never on other module implementations.
- **Event bus** — `IEventBus.PublishAsync<T>()` broadcasts events to all registered `IEventHandler<T>` implementations across modules.

### Database

Each module gets its own isolated storage — table prefixes on SQLite, separate schemas on PostgreSQL/SQL Server. Modules register a `ModuleDbContextInfo` and the framework handles schema creation.

## CLI

```bash
sm new project # scaffold a new SimpleModule solution
sm new module <name> # create a module with contracts, endpoints, tests, events
sm new feature <name> # add a feature to an existing module
sm doctor [--fix] # validate project structure, auto-fix issues
```

## Testing

```bash
dotnet test # all tests
dotnet test --filter "FullyQualifiedName~ClassName" # single test class
dotnet test --filter "FullyQualifiedName~MethodName" # single test method
```

Tests use xUnit.v3, FluentAssertions, Bogus, and NSubstitute. Integration tests run against in-memory SQLite by default. CI also tests against PostgreSQL 16 using the `Database__DefaultConnection` environment variable.

## Linting & Formatting

**C#** — Analyzers enforced via `Directory.Build.props` (`TreatWarningsAsErrors`, `AnalysisLevel=latest-all`). Naming and style rules in `.editorconfig`.

**TypeScript/React** — [Biome](https://biomejs.dev/) configured at repo root. Single quotes, semicolons, 2-space indent, trailing commas, 100-char line width.

```bash
npm run check # lint + format check
npm run check:fix # auto-fix
```
Loading
Loading