Prerequisites¶
This page lists everything you need installed before you can build, run or deploy Cargonerds,
and—just as importantly—why each tool is required for this specific codebase. Cargonerds is a
layered, tiered ABP app
solution on .NET 10, orchestrated locally by .NET Aspire, with a separate Next.js
frontend. That combination drives the tool list below.
In a hurry?
If you just want to clone-and-run, jump straight to the Quick Start — it has the exact commands. This page is the reference that explains the why and the version pins.
At a glance¶
| Tool | Required version | Why this repo needs it |
|---|---|---|
| .NET SDK | 10.x (with the Aspire workload) | Every first-party project targets net10.0; the Aspire AppHost needs the workload. |
| Node.js | 22.x | The frontend/realtime Next.js app pins "engines": { "node": "22.x" }. |
| Docker Desktop | Latest, running | Aspire provisions SQL Server, Redis and RabbitMQ as containers; the docs site and frontend build from Dockerfiles; integration tests use Testcontainers. |
| Git | Any recent | Source control + the core.hooksPath pre-commit formatting hook. |
PowerShell 7 (pwsh) |
7.0+ | Hook installer, deploy scripts and PublishApp.ps1 require PS7 (PS5 produces zips Azure rejects). |
| ABP CLI | matches AbpVersion (10.1.1) |
abp install-libs (client libs) and proxy generation. |
Azure CLI (az) + azd |
Latest | Only for Azure deployment (Container Apps via azd, App Service via az). Not needed for local dev. |
| ABP Studio (optional) | 2.2.1 | Optional GUI for the ABP solution/module model and run/k8s profiles. |
The exact version pins for the .NET/ABP/Aspire stack are not scattered across project files —
they live in one place, common.props (see .NET 10 SDK).
.NET 10 SDK (+ Aspire workload)¶
What it is. The .NET SDK builds and runs every C# project in the solution. Cargonerds also uses .NET Aspire for local orchestration: a single AppHost process starts all backend services, the frontend, and the backing infrastructure containers.
How this repo uses it. All first-party projects target net10.0, and the version/stack is
fixed centrally in common.props:
<!-- common.props -->
<AbpProjectType>app</AbpProjectType>
<AbpVersion>10.1.1</AbpVersion>
<AspireVersion>13.2.2</AspireVersion>
<LeptonXVersion>5.1.1</LeptonXVersion>
<AbpStudioVersion>2.2.1</AbpStudioVersion>
The Aspire AppHost (src/Cargonerds.AppHost/Cargonerds.AppHost.csproj) is what makes the SDK +
Aspire workload mandatory:
<!-- src/Cargonerds.AppHost/Cargonerds.AppHost.csproj -->
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<IsAspireHost>true</IsAspireHost>
</PropertyGroup>
You run the whole stack with one command:
CI confirms the workload requirement — the deploy pipeline restores workloads before building:
# .github/workflows/azure-dev.yml
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
10.x.x
- name: Restore workloads
run: |
dotnet --info
dotnet workload restore
Locally, install the Aspire workload once with dotnet workload install aspire (or run
dotnet workload restore from the repo root, which reads what the solution needs).
Two Aspire version knobs — don't conflate them
The Aspire NuGet packages are pinned via $(AspireVersion) = 13.2.2 (in
Directory.Packages.props, resolving the variable from common.props), but the AppHost's
build SDK is hard-coded to Aspire.AppHost.Sdk 13.1.0 in the .csproj. These are two
separate settings; both must be present.
net10.0 is the truth; the ABP metadata is stale
Cargonerds.abpsln still reports TargetDotnetFramework net9.0 and AbpFramework 10.0.0, and
the root README mentions ".NET 9.0+". The build truth is common.props and the
<TargetFramework> in each .csproj — all net10.0. See
Solution Structure for the full story.
Node.js 22.x¶
What it is. Node runs the customer-facing Next.js 15 app, frontend/realtime (the Röhlig
"RT3" portal), and its shared component library @cargonerds/ui-library. This frontend is a fully
decoupled SPA that talks to the ABP backend over REST/OData, SignalR and SSE — it is not an ABP
MVC/Razor app.
Why 22.x specifically. The version is pinned in three independent places, so anything older or newer is unsupported:
# frontend/realtime/Dockerfile
ARG NODE_VERSION=22
FROM node:${NODE_VERSION}-alpine AS deps
# ... builder + runner stages all use node:22-alpine
The third place is the Aspire AppHost: it discovers the frontend and launches it through the Node
toolchain (Aspire.Hosting.JavaScript), running the workspace's aspire-dev script
(npm i --force && next dev --turbopack --hostname 0.0.0.0). See
Aspire Integration for how the AppHost wires up npm apps.
Frontend deps are installed for you by the hook installer
.githooks/install.ps1 runs npm i inside frontend/. You normally do not run npm
manually for local dev — Aspire's aspire-dev script even re-installs deps on each launch.
Docker Desktop (must be running)¶
What it is. Docker provides the Linux containers that back local development and tests.
Why this repo needs it. Three distinct uses:
- Aspire backing services. The AppHost provisions SQL Server, Redis and RabbitMQ as containers
instead of you installing them. The local SQL container is pinned (port
14330, persistent volumespark-db); see Aspire Integration. - Dockerfile builds. The documentation site is added to the Aspire graph from
docs/Dockerfile, and the frontend builds/ships fromfrontend/realtime/Dockerfile. - Integration tests. Testcontainers spins up real SQL Server / Redis / RabbitMQ / Azurite for the test suite (see Testing).
The AppHost actively guards on Docker — the very last line of Program.cs is:
If Docker Desktop is not running in local debug, startup fails fast with a clear error rather than hanging on container creation.
You do not install SQL Server, Redis or RabbitMQ yourself
When you run the AppHost it provisions them as containers (spark-db, spark-redis,
spark-rabbitmq). In Azure these map to Azure SQL, Azure Cache for Redis and RabbitMQ. You also
do not run the DbMigrator by hand — Aspire runs it as a resource and the other services
wait for it to complete.
Git + the pre-commit hook¶
What it is. Git for source control, plus a repo-managed pre-commit hook that auto-formats code.
Why it matters here. The hook is mandatory and self-modifying: it formats your staged files and re-stages them, so the committed bytes are the formatted ones, and CI enforces the same format. You enable it once via the installer:
That script (.githooks/install.ps1) does four things:
git config core.hooksPath .githooks— points Git at the repo's hooks.- Writes worktree exclusions to
.git/info/exclude(not.gitignore). dotnet tool restore— restores the local .NET tools (see next section).npm iinsidefrontend/.
Worktrees go under .claude/worktrees/ or .worktrees/ — never in .gitignore
The installer excludes those paths via .git/info/exclude on purpose. CSharpier honors
.gitignore but ignores .git/info/exclude, so git ignores the worktrees while CSharpier can
still format the C# inside them. Putting a worktree elsewhere, or gitignoring it, makes
CSharpier blind and breaks the CI format check. See AGENTS.md and
Development Workflow.
ABP / .NET local tools (CSharpier + Husky.Net)¶
You do not install these globally. They are pinned in the local tool manifest and restored by
the hook installer's dotnet tool restore:
// .config/dotnet-tools.json
{
"tools": {
"csharpier": { "version": "1.2.6", "rollForward": false },
"husky": { "version": "0.7.2" }
}
}
- CSharpier (
rollForward: falsepins it exactly) — opinionated C# formatter run over all.cson pre-commit..csharpierignoreskipsMigrations/,*.csproj,*.props,*.xml,*.config. - Husky.Net — runs the pre-commit group (CSharpier over C#, Prettier over staged
frontend/files).
You can format manually with dotnet csharpier format . (C#) and npx prettier --write . inside
frontend/.
ABP CLI¶
What it is. The ABP command-line tool. Install it globally:
Why this repo needs it. Mainly abp install-libs, which downloads the JavaScript/CSS client
libraries the Blazor/MVC UIs expect — it is a required step before running and is run in CI before
every Aspire/App Service build. The CLI also drives client-proxy generation and the abp get-source
workflow used to populate the local (git-ignored) abpSrc/ framework checkout.
Match the CLI to the framework version
The solution pins ABP 10.1.1 (AbpVersion in common.props). Keep your global ABP CLI on a
matching major/minor to avoid template/lib drift.
PowerShell 7 (pwsh)¶
What it is. PowerShell 7+ (PowerShell Core), cross-platform.
Why this repo needs it. The hook installer (.githooks/install.ps1), the helper scripts under
.scripts/, and the deployment scripts are all PowerShell. One script is hard-gated:
.scripts/PublishApp.ps1declares#requires -version 7.0. PowerShell 5'sCompress-Archiveproduces zip files that Azure App Service refuses, so PS7 is mandatory for the App Service publish path (see CI/CD and Azure App Service).
PowerShell 7 ships with recent Windows tooling; on Linux/macOS install PowerShell Core separately. (Windows PowerShell 5.1 is not sufficient for the publish scripts.)
Azure CLI + azd (deployment only)¶
You only need these to deploy to Azure — they are not required for local development or tests.
Cargonerds has two parallel Azure paths, and they use different tooling:
| Path | Tool | What it is |
|---|---|---|
Aspire → Azure Container Apps (ephemeral per-branch + stage) |
azd (Azure/setup-azd) |
azd up deploys the Aspire AppHost; azure.yaml sets host: containerapp. |
dotnet publish zip → Azure App Service (production) |
Azure CLI (az) |
az webapp deploy into deployment slots, plus slot warm-up/swap. |
Both authenticate via azure/login (OIDC) in CI. A few scripts additionally use the Az.*
PowerShell modules (e.g. custom-domain setup). See Deployment Overview
for the full picture.
Azure tooling is not needed to run the app locally
Skip this section entirely if you are only doing local development. Everything you need to run Cargonerds on your machine is .NET 10, Node 22, Docker, Git and PowerShell 7.
ABP Studio (optional)¶
What it is. ABP Studio is the official desktop IDE/companion for ABP solutions. Cargonerds ships
ABP Studio metadata (Cargonerds.abpsln, *.abpmdl) and the etc/abp-studio run/k8s profiles, and
several hosts reference the Volo.Abp.Studio.Client.AspNetCore package (pinned to
$(AbpStudioVersion) = 2.2.1): Cargonerds.HttpApi.Host, Cargonerds.AuthServer,
Cargonerds.Web.Public.
It is optional: you can build, run and debug entirely from the .NET CLI, Visual Studio or Rider without it. Use it if you want the GUI view of the module model and the bundled run/Kubernetes profiles.
Authentication certificate¶
The AuthServer (OpenIddict) needs a signing/encryption certificate, openiddict.pfx. For local
development you generate a dev cert; for production you must supply your own.
The password above is the development default only. See the Quick Start for the
full flow (including dotnet dev-certs https --trust) and the root README.md for production
guidance and Linux conversion steps. ABP's auth server is documented under
OpenIddict.
Optional developer tooling¶
- Visual Studio 2022 (17.12+) or JetBrains Rider with .NET 10 support.
- Azure Data Studio / SQL Server Management Studio for inspecting the database.
- Bruno API client — collections are checked in under
etc/bruno.
System requirements¶
- OS: Windows 10/11, macOS or Linux.
- RAM: 16 GB recommended — the AppHost runs multiple .NET hosts plus SQL/Redis/RabbitMQ containers simultaneously.
- Disk: ~15 GB free for container images, NuGet/npm caches and data volumes.
How it all fits together¶
flowchart TD
Dev["Developer machine"]
subgraph Toolchain["Required toolchain"]
DotNet[".NET 10 SDK<br/>+ Aspire workload"]
Node["Node.js 22.x"]
Docker["Docker Desktop"]
Pwsh["PowerShell 7"]
AbpCli["ABP CLI"]
end
Dev --> Toolchain
AbpCli -->|"abp install-libs"| Libs["Client JS/CSS libs"]
Pwsh -->|".githooks/install.ps1"| Hooks["core.hooksPath + tools + npm i"]
DotNet -->|"dotnet run --project<br/>src/Cargonerds.AppHost"| AppHost["Aspire AppHost"]
AppHost --> Docker
AppHost --> Node
Docker --> SQL["spark-db (SQL Server)"]
Docker --> Redis["spark-redis"]
Docker --> Rabbit["spark-rabbitmq"]
Node --> Realtime["frontend/realtime (Next.js)"]
AppHost --> Backend["AuthServer / HttpApi.Host / Blazor / DbMigrator"]
Next steps¶
- Quick Start — clone, install hooks, generate the cert, run the AppHost.
- Running Locally — environment variables (
SPARK_ENVIRONMENT) and infra-only workflows. - Solution Structure —
common.props/Directory.Packages.propscentral config and the project graph. - Aspire Integration — how the AppHost orchestrates services, containers and the frontend.
- Architecture Overview — the big picture.