Developer Portal

Your guide to the Luminor codebase. Everything you need to start building, testing, and debugging — without going down the wrong route.

Common Pitfalls

These mistakes waste time. Read this first.

Don't seed data by hand

Use the seed commands instead of manually clicking through the app to create test data.

mise run seed:property-mgr-setup user@test.com pass123

Don't use return false to skip logic

Use the Simulator switches to toggle behaviors like delivery failures or agent errors — no code changes needed.

/simulator

Don't run Go/templ/npm on the host

All toolchain commands run inside Docker. Only mise and Docker are required on your machine.

mise run in-app-container go test ./internal/...

Don't skip the quality gate

Always run the full check suite before pushing. It catches arch violations, lint issues, and test failures.

mise run all-checks

Start Here

Step-by-Step Tutorial

A 13-chapter hands-on guide to building a feature from scratch. You'll build a todo list vertical with event sourcing, CQRS, and architecture enforcement — the same patterns used by every production feature.

Tutorial Overview

Test Data & Simulation

Use these commands to create realistic test data. Never seed data by hand through the UI.

Seed a property manager demo

Creates an organization, property manager account, properties, tenants, and rental agreements.

mise run seed:property-mgr-setup user@example.com password123

Generate sample documents

Creates German PDF documents for the knowledge base. Add --upload email to upload them.

mise run seed:documents mise run seed:documents --upload user@example.com

Simulator

The Simulator lets you trigger business scenarios and toggle failure modes without changing code. Triggers run real business logic through the same facades the UI uses. Switches control behaviors like message delivery failures or agent workload errors.

Open Simulator

Architecture

Luminor uses vertical slice architecture with event sourcing for business aggregates. Read these before making architectural decisions.

Key rules at a glance

  • Always go through facade/ when importing across verticals
  • Event-sourced verticals must not use CRUD — the archtest enforces this
  • Domain packages have zero infrastructure imports
  • Never call time.Now() — inject a Clock
  • Define interfaces where they are consumed, not in the provider
  • Wiring happens in cmd/server/main.go — no DI container

Live Introspection

Observability & Debugging

Every request is traced end-to-end. Use Jaeger to follow the full lifecycle of a business operation.

Key capabilities

  • Stream Inspector: /inspect/{vertical}/{id} renders the full command + event timeline for any aggregate
  • Trace correlation: X-Trace-ID response header links HTTP requests to Jaeger traces
  • Job trace propagation: background jobs carry traceparent across the queue boundary
  • Structured logging: use slog.InfoContext(ctx, ...) so trace context propagates into log lines

UI & Design System

The frontend uses templ + htmx + Alpine.js with a custom design system. Always use semantic lmn-* classes — never invent CSS class names.

Living Styleguide

Interactive reference for all design system tokens, components, and patterns.

Open Styleguide

Frontend Book

Template architecture, htmx patterns, form handling, CSS classes.

Quick Reference: mise Tasks

All Go, Node, and templ execution happens inside Docker. These are the commands you'll use daily.

TaskWhat it does
mise run setupBootstrap everything (build, start, migrate, test)
mise run devHot-reload server (air + tailwind watch)
mise run buildGenerate templ + build CSS + compile Go binary
mise run qualityLint, archtest, format checks
mise run testsUnit tests with coverage threshold
mise run tests-integrationIntegration tests
mise run tests-e2eEnd-to-end tests (Playwright)
mise run all-checksFull quality gate: build + quality + security + all tests
mise run seed:property-mgr-setupSeed a full PM demo for a given user
mise run seed:documentsGenerate sample PDF documents for the knowledge base
mise run migrate-db:{db}Run migrations (business, rag, jobqueue)
mise run in-app-container {cmd}Run any command inside the app container
mise run browserOpen app + Jaeger in your browser
mise run new-worktree {name}Create an isolated worktree with its own Docker env

Run a single test or vertical

mise run in-app-container go test -run TestMyFunction ./internal/workitem/domain/ mise run in-app-container go test ./internal/workitem/...

Ready to use the application?

Go to Luminor App