IT asset management system for tracking physical assets (laptops, peripherals, etc.) stored in cupboards and rooms. Users browse and reserve assets; admins manage the location hierarchy, ownership records, and reservation history.
| Layer | Stack |
|---|---|
| Frontend | Next.js, React, TypeScript, Tailwind CSS |
| Backend | ASP.NET Core 10, Entity Framework Core 10, C#, PostgreSQL |
| Auth | FreeIPA (JSON-RPC) — JWT delivered to the browser via HttpOnly cookies |
| Infra | Docker Compose |
For the full per-layer dependency lists, see HelpdeskDb/CLAUDE.md and helpdeskdb-frontend/CLAUDE.md.
project/
HelpdeskDb/ — ASP.NET Core 10 backend (REST API + MVC admin)
helpdeskdb-frontend/ — Next.js frontend (App Router)
CLAUDE.md — cross-cutting architecture / notes
Each subfolder has its own CLAUDE.md with deeper detail on commands, layering, mappers, services, and patterns.
- .NET 10 SDK — verify with
dotnet --list-sdks - Node.js 20+ and npm — verify with
node --version - PostgreSQL — the backend will not start without a reachable DB. Either:
- install Postgres natively (typical:
localhost:5432), or - use the bundled
docker-composePostgres (requires Docker / Docker Desktop)
- install Postgres natively (typical:
- FreeIPA credentials for
ipa.lapikud.ee— needed to log in to the running app and to populate theIpaServiceAccount__*env vars
Copy the two example env files and fill in real values:
# Backend env (from HelpdeskDb/)
cp .env.example .env
# Frontend env (from helpdeskdb-frontend/)
cp .env.local.example .env.localBackend .env keys you must set:
POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD— credentials for the Postgres instanceConnectionStrings__DefaultConnection— used bydotnet run(host =localhost)DOCKER_DB_CONNECTION— used by the backend container (host =lapikudhelpdesk-db-postgres)JWTSecurity__Key— long random string (e.g.openssl rand -base64 64)AllowedOrigins__0— CORS allowlist entry, e.g.http://localhost:3000IpaServiceAccount__Username/IpaServiceAccount__Password— IPA service account used to re-sync roles on/renewRefreshToken
Frontend .env.local keys:
NEXT_PUBLIC_BACKEND_URL— defaults tohttp://localhost:5018; this is the rewrite destination for/api/*
HelpdeskDb/.env contains two connection strings, and both must point at the same Postgres instance with matching credentials:
| Variable | When it's used | Host | Port |
|---|---|---|---|
ConnectionStrings__DefaultConnection |
Local dotnet run |
localhost |
match your Postgres |
DOCKER_DB_CONNECTION |
Backend running inside docker-compose |
lapikudhelpdesk-db-postgres (docker service name) |
5432 (container-internal) |
Pick a Postgres source and align the local port:
- Your own Postgres on
localhost:5432— set both connection strings toPort=5432. You do not need to rundocker-compose up db. - Bundled
docker-composePostgres —docker-compose.ymlpublishes the container on host port5433("5433:5432"). SetConnectionStrings__DefaultConnectiontoPort=5433for localdotnet run. (If5433is taken on your machine, edit the mapping indocker-compose.ymland keep the connection string in sync.)
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB in .env must match the Username= / Password= / Database= segments inside both connection strings — otherwise the db container initializes with one set of credentials while the backend tries to connect with another.
Either your own local Postgres, or bring up the bundled one:
# from HelpdeskDb/
docker-compose up dbOption A — backend and frontend both run locally (most common for dev):
# Terminal 1 (from HelpdeskDb/)
dotnet run --project WebApp/WebApp.csproj
# → http://localhost:5018
# Terminal 2 (from helpdeskdb-frontend/)
npm install # first time only
npm run dev
# → http://localhost:3000Option B — backend in Docker, frontend local:
# from HelpdeskDb/
docker-compose up
# Postgres + backend come up together; backend on host port 80
# from helpdeskdb-frontend/ (separate terminal)
npm run devIn dev, Next.js proxies /api/* to the backend (rewrites() in next.config.ts), so the browser stays same-origin and CORS never fires. On startup, the backend's DataSeeder applies migrations and seeds roles + sample data if the tables are empty.
Open http://localhost:3000, log in with FreeIPA credentials, and you're in.
# from HelpdeskDb/
dotnet test HelpdeskDb.slnTests are self-contained — they use SQLite in-memory and a FakeIpaAuthClient, so they do not need Postgres or network access to FreeIPA.
Login goes to POST /api/v1/account/login. The backend authenticates against FreeIPA, syncs IPA group membership into the local AppUserRole table, and sets two HttpOnly cookies (hd_jwt, hd_rt). The frontend hydrates its identity by calling GET /api/v1/account/me on app mount — the JWT itself is never exposed to JavaScript. Full flow in CLAUDE.md.
Three languages: English (en), Estonian (et), Russian (ru).
- Backend strings:
.resxfiles underHelpdeskDb/App.Resources/ - Frontend strings: JSON under
helpdeskdb-frontend/public/locales/{lang}/{namespace}.json
When adding a translation key, update all three language sets.
CLAUDE.md— cross-cutting architecture, full auth flow, CORS deployment notesHelpdeskDb/CLAUDE.md— backend layering, manual mapper chain, entity-addition checklist, testing strategyhelpdeskdb-frontend/CLAUDE.md— service layer, AuthGuard, page patterns, list-page component stack