Cookmaid is a self-hosted meal planning app. Manage your recipes, plan meals for the week, and generate shopping lists — available on Android and as a Progressive Web App.
See the FAQ & Feature Guide for usage tips and common workflows.
The demo directory contains a self-contained Docker Compose
setup with PostgreSQL, Logto (OIDC provider), and
Cookmaid — everything you need to try the app locally.
cd demo
docker compose up -d- Wait ~15 seconds for Logto to initialize and seed
- Open http://localhost:3002 and complete the one-time Logto admin setup wizard
- Open http://localhost:8081 and log in with
testuser/CookmaidTest2026!
To stop everything: docker compose down (add -v to also remove data).
- Kotlin + Compose Multiplatform (Android, WasmJS)
- Ktor server (JVM)
- Exposed ORM + Flyway migrations on PostgreSQL
- Koin for DI, kotlinx.serialization + kotlinx.datetime
- OIDC auth via Logto
Pinned versions live in gradle/libs.versions.toml.
core/— Multiplatform library (Android, JVM, WasmJS). Data models and DTOs shared across client and server.app/shared/— Compose Multiplatform UI library (Android, WasmJS).app/webApp/— WasmJS application entry point. Progressive Web App (manifest, service worker, maskable icons).app/androidApp/— Android application entry point.server/— Ktor backend (JVM). Serves API + WasmJS static files.dev/— Docker Compose setup for local infrastructuredocker/— Production Dockerfile + entrypoint
- JDK 17+ (runtime container uses JDK 21)
- Docker & Docker Compose
cd dev
docker compose up -dThis starts:
- PostgreSQL on port 5432 (databases:
cookmaid,logto) - Logto (OIDC provider) on http://localhost:3001 (admin console on http://localhost:3002)
A seed container automatically configures the Logto application, API resource, sign-in experience, and a test user — no manual setup needed.
Log in with testuser / CookmaidTest2026!.
Logto admin console: http://localhost:3002 (one-time setup wizard on first use).
Dev OIDC settings live in local.properties (NOT checked into VCS). Add the following:
sdk.dir=<path-to-android-sdk>
oidc.discoveryUri=http://localhost:3001/oidc/.well-known/openid-configuration
oidc.clientId=cookmaid-dev
oidc.scope=openid profile email
oidc.accountUri=http://localhost:3001/account/security
oidc.resource=http://localhost:8081/api
oidc.audience=http://localhost:8081/apiThe server reads its OIDC config from application.yaml. oidc.issuer
and oidc.jwks-url default to the local Logto instance;
oidc.audience defaults to the local API resource indicator.
# Run server (port 8081)
./gradlew :server:run
# Run web app (Wasm, port 8080) — injects dev OIDC config from local.properties
./gradlew :app:webApp:wasmJsBrowserDevelopmentRun
# Run Android app
./gradlew :app:androidApp:installDevDebug# All tests
./gradlew test
# Per module
./gradlew :server:test
./gradlew :core:allTests
./gradlew :app:shared:allTests




