Skip to content

Developer Guide

This guide provides technical information for developers working with LeafLock, including API documentation, testing, scripts, and development workflows.

Admin-only Swagger API documentation is available at:

  • UI: /api/v1/docs
  • Spec: /api/v1/docs/openapi.json

All endpoints are documented in backend/docs/openapi.json.

  • Add a JWT bearer token (from /auth/register or /auth/login)
  • Access requires admin role
  • Bootstrap by setting ADMIN_USER_IDS=<your-user-id> and restart backend
  • Open the UI and try the admin endpoints
  • admin: Full access to admin APIs and Swagger docs
  • moderator: Reserved for future moderation actions
  • auditor: Read-only reports in future
  • user: Default role for every user

Roles are stored in tables roles and user_roles. Users also have a boolean is_admin for quick admin flag checking.

MethodEndpointDescription
GET/api/v1/admin/healthHealth check for admin
PUT/api/v1/admin/users/:id/adminToggle admin status
GET/api/v1/admin/rolesList all roles
GET/api/v1/admin/users/:id/rolesGet user roles
POST/api/v1/admin/users/:id/rolesAdd role to user
DELETE/api/v1/admin/users/:id/roles/:roleRemove role from user

All admin endpoints require JWT and admin role.

  • Temporary allowlist via env var: ADMIN_USER_IDS=uuid1,uuid2
  • Use it to grant first admin, then set is_admin via API

To reduce abuse in non-local environments, the registration endpoint is rate-limited.

  • Endpoint: POST /api/v1/auth/register
  • Limit: 5 requests per minute per IP
  • Enabled when: APP_ENV is not development or local
  • APP_ENV=production enables limiting
  • APP_ENV=development disables limiting for local dev
  • General app rate limiting (100/min/IP) still applies globally

Use ./leaflock.sh for common tasks:

Terminal window
./leaflock.sh help
./leaflock.sh icons # regenerate icons
./leaflock.sh railway # bootstrap Railway backend+frontend
./leaflock.sh docker:up # compose up -d --build
./leaflock.sh docker:down
./leaflock.sh docker:build
./leaflock.sh k8s:deploy # wrapper for deploy-k8s.sh
./leaflock.sh health # wrapper for health-check.sh
./leaflock.sh troubleshoot # wrapper for troubleshoot.sh
./leaflock.sh test # wrapper for test-automation.sh

Advanced scripts for CI or specific workflows:

  • deploy-k8s.sh, deploy.sh, deploy-docker.sh, deploy-from-ghcr.sh
  • setup-docker.sh, setup-podman.sh, podman-kube-play.sh
  • health-check.sh, troubleshoot.sh, test-automation.sh
  • env-setup.sh, dev-setup.sh, dev-watch.sh, init-ssl*.sh

LeafLock ships with a full set of favicons and PWA icons generated from the LeafLock motif.

  • favicon.svg (scalable primary icon)
  • favicon.ico (multi-image 16/32/48)
  • favicon-16.png, favicon-32.png, favicon-48.png, favicon-64.png
  • apple-touch-icon.png (180×180)
  • icon-192.png, icon-512.png
  • icon-192-maskable.png, icon-512-maskable.png (safe padding for maskable PWAs)

If you customize branding:

Terminal window
node scripts/generate-icons.mjs

For single reference in HTML:

<link rel="icon" type="image/svg+xml" href="/favicon.svg" />

Located at .github/workflows/e2e-verify.yml

What it does:

  • Runs frontend lint, typecheck, tests
  • Builds and starts Postgres, Redis, backend, frontend via docker compose
  • Waits for readiness and tests API flow (register + list notes)
  • Smoke tests frontend (index + asset)
  • Runs backend tests with coverage gate
  • Verifies Swagger access with ADMIN_USER_IDS fallback, then via RBAC grant

Admin panel in E2E:

  • Sets VITE_ENABLE_ADMIN_PANEL=true so the UI contains the Admin section

LeafLock includes built-in startup performance optimizations for containerized deployments:

  • /api/v1/health/live: Basic liveness check (3-5 seconds)
  • /api/v1/health/ready: Full readiness check (15-30 seconds)

Environment Variables (All have optimal defaults)

Section titled “Environment Variables (All have optimal defaults)”
Terminal window
# These are enabled by default - no configuration needed
LAZY_INIT_ADMIN=true # Admin user creation runs in background
ASYNC_TEMPLATE_SEED=true # Template seeding runs in background
SKIP_MIGRATION_CHECK=false # Always run database migrations
  • Startup time: Reduced from 90+ seconds to 15-30 seconds
  • Async initialization: Non-critical operations run in background
  • Progressive health checks: Fast container health detection
  • Optimized connection pools: Faster database and Redis connections

Refer to the main CLAUDE.md file in the repository root for:

  • Environment setup
  • Development commands
  • Container operations
  • Technology stack details
  • Required environment variables

When contributing to LeafLock:

  1. Follow the existing code style and patterns
  2. Update relevant documentation
  3. Add tests for new features
  4. Update API documentation if adding new endpoints
  5. Test admin functionality if making admin-related changes

For technical questions, contact contact@leaflock.app.