diff --git a/README.md b/README.md new file mode 100644 index 0000000..0db03f5 --- /dev/null +++ b/README.md @@ -0,0 +1,164 @@ +# Marktvogt + +**The central portal for medieval markets ("Mittelaltermaerkte") in the DACH region.** + +Marktvogt connects visitors, merchants, artists, camp groups, and organizers on +one platform — replacing the patchwork of Facebook groups, phone calls, mailing +lists, and scattered websites that the scene currently runs on. + +The name comes from the historical *Marktvogt* — the keeper of order at medieval +markets. Same job, different century. + +--- + +## The Problem + +The medieval-market scene in the DACH region is large (hundreds of markets per +year) but digitally fragmented: + +- **Finding markets**: Facebook groups, `mittelalterkalender.info`, private sites +- **Bookings** (merchants, artists, camps): phone, e-mail, Facebook Messenger +- **Camp groups**: organize almost exclusively on Facebook +- **Tickets**: usually box-office-only or one-off organizer sites + +There is no single portal that brings all participants together. Marktvogt is +that portal. + +## The Solution + +A two-sided marketplace: + +- **Supply side** — organizers list markets, open plots, programs, tickets +- **Demand side** — visitors discover markets and buy tickets; merchants, + artists, and camp groups apply for spots + +Network effects: organizers attract applicants, applicants make the platform +indispensable for organizers, and visitors follow the content. + +## Roles + +Six roles, with the *Veranstalter* (organizer) as the central actor: + +| Role | Description | +|---------------|----------------------------------------------------------| +| Gast | Anonymous visitor — browse markets, no account | +| User | Registered visitor — tickets, favorites, profile | +| Haendler | Merchant group applying for plots | +| Kuenstler | Artist group applying for performance slots | +| Lager | Reenactment camp group applying for camp space | +| Veranstalter | Organizer — creates markets, reviews applications, sells tickets | + +All applicants (Haendler / Kuenstler / Lager) operate as **groups**. A solo +merchant is just a one-person group. *Mitarbeiter* (staff) is a sub-role under +Veranstalter with granular permissions. + +--- + +## Architecture + +Monorepo. Components are plain directories, not git submodules. + +| Layer | Stack | +|--------------|--------------------------------------------------------------------| +| Backend | Go REST API + WebSocket; PostgreSQL (PostGIS), Redis, S3 | +| Web | SvelteKit + Tailwind 4, SSR for SEO, runs on Bun | +| Mobile | Flutter (Android + iOS) | +| Auth | Custom (Go), e-mail+password / magic link / OAuth / 2FA | +| Payments | Stripe Connect | +| LLM | Google Gemini (`gemini-2.5-flash-lite`) for enrichment | +| CI/CD | Woodpecker (`ci.somegit.dev`) — `.gitlab-ci.yml` retained as fallback | +| Hosting | Kubernetes (`itsh.dev`), Helm chart at `helm/marktvogt/` | +| Monitoring | Prometheus, Loki, Grafana, Sentry | + +### Repo Layout + +``` +backend/ Go REST API + WebSocket chat +web/ SvelteKit frontend (SSR, Bun runtime) +app/ Flutter mobile app +helm/ Monolithic Helm chart (backend + web + Postgres + Dragonfly) +planning/ Vision, roadmap, MVP scope, feature specs (German, ASCII-only) +scripts/ Out-of-band tooling (e.g. K8s secret sync) +.woodpecker/ CI pipelines for somegit.dev +``` + +The admin dashboard lives in its own repo and will be added later. + +--- + +## Getting Started + +The repo is driven by a `Justfile`. Run `just` for the full list. + +```bash +# One-time setup: pre-commit hooks, web deps, golangci-lint +just hooks-install + +# Backend +just backend-dev # Postgres + Valkey via docker compose +just backend-run # go run ./cmd/api +just backend-test +just backend-lint + +# Web +just web-dev # SvelteKit dev server +just web-check # svelte-check (types) +just web-lint + +# Everything +just lint +just test +just fmt +``` + +For component-specific details, see `backend/README.md`, `web/README.md`, and +`app/README.md`. + +--- + +## Deployment + +Single Helm release `marktvogt` in namespace `tenant-2`, deployed from +`helm/marktvogt/` (monolithic chart covering backend, web, Postgres, and +Dragonfly). CI runs: + +```bash +helm upgrade marktvogt --reuse-values \ + --set-string backend.image.tag= \ + --set-string web.image.tag= +``` + +`--set-string` is mandatory — all-digit short SHAs get float-coerced into +scientific notation otherwise, which then fails K8s label validation. + +K8s Secrets are pre-created out-of-band by `scripts/k8s-secrets-sync.sh` +reading from `.env.helm` (gitignored). CI never touches secret values. + +The container registry (`registry.itsh.dev/vikingowl/marktvogt.de/{backend,web}`) +is Zot-backed and **requires attestations** on every pushed image. The +Woodpecker pipelines use `woodpeckerci/plugin-docker-buildx`, which handles +this by default. + +--- + +## Status + +Active development as of 2026-04-28. `backend/`, `web/`, and `app/` all contain +working code (Go API scaffolding + auth, SvelteKit pages, Flutter skeleton). + +- Current phase scope: `planning/15-mvp.md` +- Phased feature plan: `planning/17-roadmap.md` +- Vision: `planning/00-vision.md` + +Planning docs are in German and use ASCII only (no umlauts) for cross-platform +compatibility. + +--- + +## Conventions + +- **API design**: REST for CRUD, WebSocket for real-time chat +- **Auth**: custom-built using Go libraries — no external auth provider +- **Offline capability**: required for QR-ticket validation and venue maps +- **Commits**: conventional commit messages +- **Source of truth for product**: `planning/` — read it before adding features