Universal Template is the shared base for new geospatial assessment applications. It contains the complete platform — authentication, workspaces, model dashboard, guided model setup, map, notifications and settings — without any project-specific domain logic or branding. A new project adds its own data, model inputs and result views on top.
- Authentication — sign-up with consent, login and password reset through Keycloak
- Workspaces & groups — organise models into workspaces; share them with users and Keycloak groups
- Model dashboard — status tabs, pinning, model versions (copies grouped under their original), search and period filters
- Guided model setup — a four-step wizard: model setup → configure (placeholder) → final review → save & calculate
- Interactive map — OpenLayers + MapLibre GL with location search and base-map layers
- Results page — model details on the map with a placeholder for project-specific output
- Guided tour and What's new — onboarding tour for first-time users and a release-notes popup
- Real-time notifications — SSE push + Asynq background jobs for run status
- Nine languages — English, German, Dutch, French, Spanish, Italian, Polish, Czech, Portuguese
- Name and branding — replace "Project Assessment" (
AppLayoutTopbar.tsx,features/authentication/index.tsx,index.html,common.appName), the placeholder logopublic/images/logo/app-logo.svg,GITHUB_URLincomponents/app-layout/app-layout/constants.ts, and "Your organisation" in the Keycloak theme (platform-core/auth-service/keycloak/themes/app). - Legal pages — fill in the
[placeholders]insrc/pages/legal/(Imprint, Privacy Policy, Declaration of Consent). - Landing page — replace the placeholder texts under
landing.*insrc/i18n/locales/en.jsonand add images inpublic/images/landing-page/. - Model inputs — replace the placeholder step
features/configurator/region-selector/components/layers/Layer2Configure.tsx; steps are listed inlayers/registry.tsx. Store the inputs in the model configuration inhooks/area-select/useModelCreation.ts. - Results — replace the placeholder in
features/model-results/ModelResultsViewer.tsxwith the project's map layers and summaries. - Backend — set the database name (
appdbby default), add project-specific handlers underapp/backend/internal/handler/, register their routes ininternal/routes/, and add migrations after041_…. - Translations — new texts go into
en.jsonfirst; other languages fall back to English until translated.
- Authentication: Frontend → Keycloak (OAuth2/OIDC) → backend validates token → Redis session
- Model creation: The wizard stores the model name, period and configuration on the model
- Calculation: Saving with "Save & run" starts a calculation on an available simulation engine (
platform-core/webservice) - Progress: Run status is pushed to the browser over SSE; finished runs trigger notifications
- Results: The results page loads the model and shows its output on the map
Frontend
- React 19 + TypeScript 5.8
- Vite 7 for build tooling
- TailwindCSS 4 + Radix UI components (
@spatialhub/ui) - TanStack Query 5 for server state, Zustand 5 for client state
- OpenLayers 10 + MapLibre GL JS 5 (2D mapping)
- React Router 7 with lazy-loaded routes
Backend
- Go 1.25 + Gin web framework
- GORM with PostgreSQL driver
- Asynq (Redis-backed) for background jobs
- Server-Sent Events (SSE) for real-time push
- Keycloak OIDC token validation
Platform Core (included in this repository)
platform-core/auth-service— authentication microserviceplatform-core/webservice— simulation engine registry, job dispatcher and capacity managerplatform-core/geoserver— result raster publishinginfrastructure/platform— shared Go libraries (server, database, worker, email, security)infrastructure/common— shared domain modelslibs/— shared React component libraries (@spatialhub/ui,auth,forms,i18n)
Infrastructure
- PostgreSQL 15 + PostGIS
- Keycloak 26 for OAuth2/OIDC
cd app/backend && go run cmd/main.go # backend
cd app/frontend && npm run dev # frontend (new terminal)Open http://localhost:3000. Default credentials after seeding:
| Field | Value |
|---|---|
admin@example.com |
|
| Password | 12345678 (change it after the first login) |
make up-app # start the app (frontend + backend)
make down-app # stop
make logs-app # follow logsServices exposed:
- Frontend:
http://localhost:3000 - Backend API:
http://localhost:8000 - Keycloak:
http://localhost:8080
| Command | Description |
|---|---|
make help |
List all targets |
make up |
Start Platform Core (Postgres, Redis, Keycloak, auth-service, webservice) |
make down |
Stop Platform Core |
make up-app |
Start the app (frontend + backend) |
make migrate |
Run backend DB migrations |
make seed |
Seed the database |
make install |
Install all npm + Go dependencies |
Copy app/backend/.env.example to app/backend/.env and adjust:
| Variable | Description |
|---|---|
APP_URL |
Public URL of the backend |
DB_HOST/PORT/DATABASE |
PostgreSQL connection |
REDIS_HOST/PORT |
Redis connection |
KEYCLOAK_URL / KEYCLOAK_REALM |
Keycloak OIDC endpoint |
CALLBACK_SECRET |
Shared secret for compute callbacks |
The frontend reads VITE_API_BASE_URL and, optionally,
VITE_CARTO_BASEMAP_API_KEY for the CARTO basemaps.
.
├── app/
│ ├── backend/ # Go API server (Gin, GORM, Asynq)
│ │ ├── cmd/ # Entrypoints: main, migrate, seed
│ │ ├── migrations/ # SQL migrations
│ │ └── internal/
│ │ └── handler/ # HTTP handlers
│ └── frontend/ # React SPA (Vite, TypeScript)
│ └── src/
│ ├── features/
│ │ ├── configurator/ # Four-step model wizard
│ │ ├── interactive-map/
│ │ ├── model-dashboard/
│ │ └── model-results/ # Results placeholder
│ ├── components/
│ └── i18n/ # Nine locales
├── platform-core/ # Platform services (auth-service, webservice, geoserver)
├── infrastructure/ # Shared Go libraries (common, platform)
├── libs/ # Shared React component libraries
├── go.work # Go workspace tying the modules together
└── Makefile # Developer workflow commands
Add a LICENSE file for your project.