An OpenCode generated forms solution that allows for creation and management of simple forms. A form could be a survey or a request for information. A form follows a question and answer format, where the answer can be of type: * true/false * integer * date * dropdown * text
 
 
 
 
 
 
Go to file
Tom Peltonen ca81ec7524 Merge branch 'main' of https://tea.merebox.com/Sku61/kereru-forms 2026-10-24 11:03:02 +11:00
backend Added foreignkey 2026-10-24 10:57:57 +11:00
config Added OAuth and login 2026-10-24 06:36:02 +11:00
deploy Initial commt for working copy generated 2026-10-23 23:24:54 +11:00
docker Initial commt for working copy generated 2026-10-23 23:24:54 +11:00
docs Added foreignkey 2026-10-24 10:57:57 +11:00
frontend Added foreignkey 2026-10-24 10:57:57 +11:00
.dockerignore Initial commt for working copy generated 2026-10-23 23:24:54 +11:00
.gitignore Initial commt for working copy generated 2026-10-23 23:24:54 +11:00
LICENSE Initial commit 2026-10-23 23:56:13 +00:00
README.md Added foreignkey 2026-10-24 10:57:57 +11:00

README.md

Kererū Forms

Simple, versioned surveys with a Go + OpenAPI backend and a React frontend.

  • Backend: Go 1.26, Gin, OpenAPI-generated server (oapi-codegen), SQLite via modernc.org/sqlite (pure Go), zerolog, OpenTelemetry.
  • Frontend: React 18, Vite, TypeScript, Tailwind CSS, React Router, Vitest.
  • Deployment: single container serving both the API and the built SPA, plus Docker Compose, Podman and Kubernetes manifests.

Quick start

1. Backend

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

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.

Configuration

Settings are resolved in this order (highest wins):

  1. CLI flags
  2. Environment variables
  3. .env file next to the executable, then the working directory
  4. YAML/JSON file passed with --conf
  5. Built-in defaults
kereru-forms --conf ./config/config.example.yaml
Flag Environment variable Default
--conf – –
--log-level KERERU_LOG_LEVEL info
--log-format KERERU_LOG_FORMAT console
--listen-addr KERERU_LISTEN_ADDR 0.0.0.0
--listen-addr6 KERERU_LISTEN_ADDR6 –
--port KERERU_PORT 8080
--db-driver KERERU_DB_DRIVER sqlite
--db-dsn KERERU_DB_DSN file:kereru.db?...
--static-dir KERERU_STATIC_DIR –
– KERERU_TELEMETRY_ENABLED false
– OTEL_EXPORTER_OTLP_ENDPOINT localhost:4318
– KERERU_CORS_ORIGINS http://localhost:5173
– KERERU_ENVIRONMENT development
– KERERU_AUTH_LOCAL_PASSWORD admin
– KERERU_AUTH_LOCAL_TOKEN_SECRET random per process
– KERERU_AUTH_LOCAL_TOKEN_TTL_HOURS 8
– KERERU_AUTH_REQUIRE_SUBMISSION_AUTH false
– KERERU_OIDC_ISSUER_URL –
– KERERU_OIDC_CLIENT_ID –
– KERERU_OIDC_SCOPES openid,profile,email
– KERERU_OIDC_ROLE_CLAIM roles
– KERERU_OIDC_ADMIN_ROLE admin
– KERERU_OIDC_VIEW_ROLE view

Both an IPv4 and an IPv6 listener may be configured at the same time. Set --listen-addr "" to disable the IPv4 listener.

Frontend build-time setting: VITE_API_BASE_URL (defaults to /api; set to http://localhost:8080 when the frontend is hosted separately).

Sample files live in config/.

Authentication

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 ….

API

The contract is defined in backend/openapi/openapi.yaml and the server stubs are generated with:

cd backend
oapi-codegen -config oapi-codegen.yaml openapi/openapi.yaml

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.

Key routes:

Method Path Purpose
GET /health Health and version
GET /auth/config Browser authentication mode / OIDC details
POST /auth/login Local password login fallback
GET /auth/me Current user and role flags
POST /auth/logout Stateless logout acknowledgement
GET/POST /forms List / create forms (create requires admin)
GET/PUT/DELETE /forms/{formId} Read / update / delete a form version
POST /forms/{formId}/activate Activate a form version
POST /forms/{formId}/inactivate Inactivate a form version
POST /forms/{formId}/versions Clone into a new version
GET /forms/{formId}/pdf Printable PDF of the definition
GET/POST /forms/{formId}/submissions List / submit responses
GET /submissions/{submissionId} Submission details
GET /submissions/{submissionId}/offline-pdf Download an uploaded offline PDF
GET/POST /forms/{formId}/access-codes List / generate single-use codes

The specification is served at /openapi.yaml in development and production builds.

Tests

cd backend && go test ./...
cd frontend && npm test

Docker / Podman / Kubernetes

See docs/DEPLOYMENT.md and deploy/k8s.yaml.

Documentation

Security note

Management endpoints require a bearer JWT. In local-password mode change the default admin password and set a stable localTokenSecret; in OIDC mode enforce MFA and role assignment in the identity provider. Use HTTPS in production, keep corsOrigins narrow, and enable requireSubmissionAuth if forms must not be publicly accessible. Access codes protect individual form submissions, not administration.