A Kotlin/Ktor backend that aggregates JavaZone conference and session data from Sleeping Pill and enriches speaker profiles with Norwegian postal code data from the Bring API. It serves as the API backend for frosting, enabling javaBin regions to discover potential speakers for local events.
- Language: Kotlin (JVM 22)
- Framework: Ktor
- Build: Gradle (Kotlin DSL)
- Caching: Caffeine (conference/session data) + Cache4k (postal codes)
- Auth: OIDC/JWT via configurable discovery endpoint
- Metrics: Micrometer + Prometheus
| Method | Path | Description |
|---|---|---|
GET |
/api/conferences |
Lists conferences (filtered by year, sorted by name descending) |
GET |
/api/conferences/{id}/sessions |
Sessions for a conference, with speaker postal code/city/county data |
GET |
/api/me |
Authenticated user info from OIDC token |
Additional endpoints (/login, /refresh) are handled by the OIDC layer.
./gradlew clean buildCode quality checks (Detekt, Kotlinter, JaCoCo coverage) run as part of check:
./gradlew checkThe output artifact is build/libs/cupcake.jar (fat JAR with all dependencies bundled).
Set the following environment variables (a local.env file in the root is gitignored and works well with the IntelliJ IDEA EnvFile plugin):
| Variable | Description |
|---|---|
SP_BASE_URL |
Sleeping Pill base URL (e.g. https://sleepingpill.javazone.no) |
SP_USER |
Sleeping Pill username |
SP_PASSWORD |
Sleeping Pill password |
BRING_API_KEY |
Bring API key |
BRING_API_USER |
Bring API user (email) |
JWT_ENABLED |
true to enforce JWT authentication, false to disable |
OIDC_WELL_KNOWN_URL |
Optional. OIDC discovery endpoint; defaults to the javaBin internal Cognito pool |
LOG_LEVEL |
Optional. Root log level; DEBUG by default, TRACE under ./gradlew run |
Then run:
./gradlew runThe server starts on port 8080. With JWT_ENABLED=false, no auth is required and localhost is fine.
To test with login, set JWT_ENABLED=true here and in frosting's local.env. Both use the prod Cognito pool, whose client allows http://localhost:3000/ as a callback, so you sign in with your @java.no Google account as in prod. You need to be in the helter group.
The javaBin platform builds and pushes the deployed image (see CI/CD). To build locally:
docker build -t cupcake .The image uses a multi-stage build (Eclipse Temurin 25 JDK build stage, JRE runtime stage) and runs on port 8080.
| Trigger | Workflow | What it does |
|---|---|---|
Push to main |
deploy.yaml |
The javaBin platform workflow runs ./gradlew build (which includes check: tests, kotlinter, detekt), then builds the image and deploys it. Nothing deploys if the build fails |
| Pull request | deploy.yaml |
Platform build and Terraform plan, no deploy |
| Pull request | pr.yaml |
Runs ./gradlew check (tests, linting, analysis) |
Example hostnames:
https://cupcake-backend.javazone.no → backend (this service)
https://cupcake.javazone.no → frontend (frosting)
| Variable | Value |
|---|---|
JWT_ENABLED |
true |
OIDC_WELL_KNOWN_URL |
OIDC discovery endpoint |
Users must be members of the helter Cognito group (all approved javaBin heroes).
The platform injects OIDC_WELL_KNOWN_URL from the Cognito pool (auth.env in app.yaml).
The frontend uses the same Cognito pool; see the frosting README for its configuration.
| Variable | Description |
|---|---|
SP_BASE_URL |
Sleeping Pill base URL |
SP_USER |
Username |
SP_PASSWORD |
Password |
| Variable | Description |
|---|---|
BRING_API_USER |
Bring API user (email) |
BRING_API_KEY |
Bring API key |