Skip to content

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:

dotnet run --project src/Cargonerds.AppHost

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/package.json
{ "engines": { "node": "22.x" } }
# 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:

  1. 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 volume spark-db); see Aspire Integration.
  2. Dockerfile builds. The documentation site is added to the Aspire graph from docs/Dockerfile, and the frontend builds/ships from frontend/realtime/Dockerfile.
  3. 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:

// src/Cargonerds.AppHost/Program.cs
builder.Build().EnsureDockerRunningIfLocalDebug().Run();

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:

pwsh .githooks/install.ps1

That script (.githooks/install.ps1) does four things:

  1. git config core.hooksPath .githooks — points Git at the repo's hooks.
  2. Writes worktree exclusions to .git/info/exclude (not .gitignore).
  3. dotnet tool restore — restores the local .NET tools (see next section).
  4. npm i inside frontend/.

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: false pins it exactly) — opinionated C# formatter run over all .cs on pre-commit. .csharpierignore skips Migrations/, *.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:

dotnet tool install -g Volo.Abp.Cli

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.ps1 declares #requires -version 7.0. PowerShell 5's Compress-Archive produces 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.

dotnet dev-certs https -v -ep openiddict.pfx -p d9efcd01-fbd8-42b1-a9d1-a5cf44afe714

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