Skip to content

CommandBlock Developer Setup ​

This is what a fresh checkout needs to be productive locally.

Prerequisites ​

  • .NET 10 SDK (the API targets net10.0)
  • Docker + Docker Compose (for Postgres and Keycloak)
  • Node.js 20+ and Bun 1.3+ (the frontend uses bun as its package manager)
  • Apache Maven (only if you want to rebuild the Keycloak theme JAR, see Notes)
  • dotnet-ef global tool (only if you'll add EF migrations)

1. Backend secrets ​

Secrets live in dotnet user-secrets: they are never committed and never written to appsettings.json. The CommandBlock.API project has a UserSecretsId configured.

Set them once:

powershell
# DB connection
dotnet user-secrets --project src/CommandBlock.API set "ConnectionStrings:CommandBlockDatabase" "Host=localhost;Port=5434;Database=commandblock-dev;Username=postgres;Password=d4vpas8w0rd13!!!"

# OIDC (consumed by /api/App, which the frontend reads at startup to configure auth)
dotnet user-secrets --project src/CommandBlock.API set "Oidc:Authority" "http://localhost:8080/realms/commandblock"
dotnet user-secrets --project src/CommandBlock.API set "Oidc:RequireHttpsMetadata" "false"
dotnet user-secrets --project src/CommandBlock.API set "Oidc:ClientId" "commandblock"
dotnet user-secrets --project src/CommandBlock.API set "Oidc:RedirectUri" "http://localhost:4200/"
dotnet user-secrets --project src/CommandBlock.API set "Oidc:PostLogoutRedirectUri" "http://localhost:4200/"
dotnet user-secrets --project src/CommandBlock.API set "Oidc:Scope" "openid profile email roles"

# CORS: origins allowed to call the API
dotnet user-secrets --project src/CommandBlock.API set "Cors:AllowedOrigins:0" "http://localhost:4200"

Verify with dotnet user-secrets list --project src/CommandBlock.API.

INFO

appsettings.json and appsettings.Development.json only carry ASP.NET framework defaults (logging, allowed hosts). Application config goes in user-secrets.

2. Application config: commandblock.yaml ​

Non-secret app config lives in commandblock.yaml at the repo root. The API loads it via services.AddCommandBlockConfig(env) (see src/CommandBlock.API/Extensions/CommandBlockConfigExtensions.cs), which walks up from the content root to find the file. Override the path with the CommandBlock_CONFIG environment variable.

Currently used to declare where server worlds persist on disk:

yaml
commandblock:
  storage:
    mode: HostFolder      # or Volume
    host_path: /data/servers

Bind into a handler via IOptions<CommandBlockOptions> (in CommandBlock.Application/Options/).

3. Dev infrastructure (Postgres + Keycloak) ​

powershell
docker compose -f compose.dev.yml up -d
  • Postgres → localhost:5434, db commandblock-dev, user postgres, password d4vpas8w0rd13!!!
  • Keycloak → http://localhost:8080, admin admin / admin. The commandblock realm is auto-imported on first start from keycloak/commandblock-realm.json.

Stop with docker compose -f compose.dev.yml down. Volumes (postgres-data-dev, keycloak-data-dev) persist across restarts; drop them with -v if you want a clean slate.

4. Backend ​

powershell
dotnet run --project src/CommandBlock.API --launch-profile http

The API binds to http://localhost:5165. In Development:

  • OpenAPI document: http://localhost:5165/openapi/v1.json (AllowAnonymous)
  • Scalar API reference UI: http://localhost:5165/scalar/v1: click Authenticate to redirect to Keycloak (authorization code + PKCE against the commandblock realm/client). On return, Scalar attaches the bearer token to every request you fire from the UI.

On startup the API:

  1. Applies any pending EF migrations to the dev DB (ApplyMigrations()).
  2. Talks to the local Docker socket via DockerService (Windows named pipe / Unix socket auto-detected by Docker.DotNet).

5. Frontend: first run ​

powershell
cd src/CommandBlock.Frontend
bun install

With the backend running, generate the typed API client:

powershell
bun run apigen

This reads openapitools.json, fetches http://localhost:5165/openapi/v1.json, and writes the typescript-angular client into src/app/api/. Rerun any time the backend's contract changes.

Then start the dev server:

powershell
bun start

Frontend on http://localhost:4200.

6. Tests ​

Unit tests live in src/CommandBlock.Tests (TUnit). Run them with:

powershell
dotnet run --project src/CommandBlock.Tests

7. EF migrations ​

CommandBlock stores its own data in PostgreSQL (ConnectionStrings__CommandBlockDatabase). Migrations live in src/CommandBlock.Infrastructure/Migrations/ and are applied at API startup via ApplyMigrations(). After changing entities, add one:

powershell
dotnet ef migrations add <Name> -p src/CommandBlock.Infrastructure -s src/CommandBlock.API

dotnet ef database update is not needed for local dev. dotnet run does it on startup. Run it manually only if you want to apply migrations without booting the API.

Notes ​

  • Keycloak theme: keycloak/commandblock-realm.json references loginTheme: commandblock. The theme source lives in keycloak/keycloakify/. Build the JAR with bun run build-keycloak-theme inside keycloak/keycloakify/ (Apache Maven must be on PATH); the dev compose mounts the JAR into Keycloak. Until you build it, dev Keycloak falls back to the default theme.
  • API exploration: use the Scalar UI at /scalar/v1, the generated typescript-angular client, or any spec-aware tool against /openapi/v1.json. No Swagger UI is mounted.
  • Scalar auth wiring: OAuth2SecuritySchemeTransformer declares an OAuth2 authorization-code scheme on the OpenAPI doc (derived from Oidc:Authority); MapScalarApiReference pre-fills ClientId + PKCE. The commandblock Keycloak client whitelists http://localhost:5165/scalar/v1/oauth2-redirect.html as a valid redirect URI. If you add another API origin or path, update keycloak/commandblock-realm.json and re-import the realm (drop the keycloak-data-dev volume).
  • Docker socket: DockerService connects to the local Docker daemon. On Windows this is the Docker Desktop named pipe npipe://./pipe/docker_engine; on Linux it's unix:///var/run/docker.sock. When the API runs inside a container (prod compose), the host's socket must be mounted into it (/var/run/docker.sock:/var/run/docker.sock).
  • Architecture quick map:
    • CommandBlock.Domain: entities (ServerInstance, BackupEntry, ActivityEntry, BaseEntity), no dependencies
    • CommandBlock.Application: Mediator queries/commands + DTOs
    • CommandBlock.Infrastructure: EF DbContext + migrations + Services/ (DockerService, S3BackupStorage, ServerStatusService, ActivityLogger) + Interfaces/
    • CommandBlock.API: ASP.NET Core entry point, JWT bearer auth, CORS, OpenAPI, controllers, the Minecraft router, DI wiring via AddDocker() / AddActivityLog() / etc.
    • CommandBlock.Frontend: Angular 21 + Tailwind + Spartan UI, OIDC via angular-auth-oidc-client, typed API client generated by openapi-generator-cli.

Made with care by PianoNic.