A multi-tenant library catalog application with token-based authentication and asynchronous book reservations. Each organization (library) manages its own members and loans in isolation, while sharing a common book catalog.
frontend/ React 19 + TypeScript + TanStack Router/Query (Vite)
backend/ .NET 10 / ASP.NET Core / EF Core / PostgreSQL 18
python-tools/ Python CLI tool for generating overdue-loan reports
The backend exposes a REST API covering books, members, loans, overdue loans, and reservations. Authentication is handled via a login endpoint that returns a JWT-style bearer token; all endpoints except the book listing require authentication.
A background worker runs inside the API process and periodically confirms pending book reservations. When a reservation is created it starts in Pending status; a moment later (roughly 1--2 seconds) the background process picks it up and transitions it to Confirmed (or Rejected if no copies are available).
Tenant isolation is enforced server-side: each authenticated request is scoped to the user's organization, so members of one library cannot see another library's loans, reservations, or member data.
The frontend consumes the API via TanStack Query. All three services are wired together with Docker Compose.
docker compose up --build| Service | URL |
|---|---|
| API | http://localhost:8080 |
| Web UI | http://localhost:3000 |
The Python reporting tool runs on demand:
docker compose run --rm python-toolsOr bring it up with the tools profile:
docker compose --profile tools up --buildThe database is seeded with the following users on first startup. All accounts use the password P@ssw0rd.
Default Library
| Name | |
|---|---|
| Alice Johnson | alice@example.com |
| Bob Smith | bob@example.com |
| Carol Williams | carol@example.com |
Northgate Library
| Name | |
|---|---|
| Dave Martinez | dave@northgate.com |
| Eve Thompson | eve@northgate.com |
dotnet test backend/Catalog.slnxBring the stack up first, then run the E2E suite. Playwright's browsers run in a version-matched Docker container driven from the host, so this works on Arch/Linux without installing browser system dependencies:
docker compose up -d --build
./scripts/e2e.sh # run every spec
./scripts/e2e.sh reservation # or scope to one specscripts/e2e.sh starts a Playwright server container, connects the host test
runner to it over a WebSocket, and removes the container when finished.
cd python-tools
pip install -e ".[dev]"
pytest- Loan due dates are calculated relative to a fixed reference date, so the overdue-loan count is deterministic regardless of when the application is started.
- Automated test coverage is currently minimal -- just a handful of smoke tests to verify the stack boots and serves data. Both the backend test harness (Testcontainers-based
CatalogApiFactory) and the Playwright configuration are in place and ready to be extended.