- **Deployment**: single container serving both the API and the built SPA, plus Docker Compose, Podman and Kubernetes manifests.
## Quick start
### 1. Backend
```bash
cd backend
go mod download
go run ./cmd/kereru-forms --listen-addr 0.0.0.0 --port 8080
```
The API listens on <http://localhost:8080>. The SQLite database (`kereru.db`) and its schema are created automatically.
### 2. Frontend
```bash
cd frontend
npm install
npm run dev
```
Open <http://localhost:5173>. Vite proxies `/api/*` to `http://localhost:8080/api/*`. The API is also available without the `/api` prefix for probes and direct clients.
With no OIDC provider configured, management sign-in uses the local development password `admin` and grants both admin and view roles. Change `auth.localPassword` (or `KERERU_AUTH_LOCAL_PASSWORD`) before exposing the service.
Management is always protected. Two modes are supported:
- **Local password fallback** when `auth.oidc.issuerUrl` is empty. The configured password grants both `admin` and `view` roles, which is intended for local development and testing.
- **OAuth/OIDC** when an issuer is configured. The React SPA uses the authorization-code flow with PKCE and presents the provider's ID token as a bearer token. Configure a **public SPA client** in Okta/Keycloak and register the frontend callback URL, for example `http://localhost:5173/auth/callback` in development or `https://forms.example.com/auth/callback` in production.
The backend validates the ID token signature, issuer, audience, expiry and configured role claim. Role mappings are configurable:
-`adminRole` (`admin` by default) is required for form create/update/delete, activation, versioning and access-code management.
-`viewRole` (`view` by default) is required to list or read submissions. An admin-only token is deliberately denied submission viewing.
-`requireSubmissionAuth: true` requires any authenticated user (no role) to list/open forms and submit responses.
Common role claim examples: `roles`, `groups`, or `realm_access.roles` for Keycloak. Set `localTokenSecret` to a stable value if local-password tokens must survive restarts or multiple replicas.
Local tokens and OIDC ID tokens are kept in browser `sessionStorage` and sent as `Authorization: Bearer …`.
Interactive API documentation is available at <http://localhost:5173/docs>. Swagger UI and the OpenAPI specification are bundled with the frontend, so the docs work without an internet connection. Forms support optional linked PDFs, digital signatures, external reference identifiers and offline PDF uploads.