docs(vision): catch the spark — 4 users, single-org, plate-auth forcing function

Patrick Plate
2026-06-24 14:43:08 +02:00
parent f852a1c651
commit b25de274d2
+174
@@ -0,0 +1,174 @@
# Vision
## One-liner
> **Catch the spark before it fades.**
> A tiny shared idea board for four people, built on top of [plate-auth](https://git.plate-software.de/pplate/plate-auth/wiki).
---
## Who this is for
Exactly four humans:
1. **Patrick** — owner, admin, primary user
2. **A friend** — co-admin, primary user
3. **The friend's two sons** — members
Total seats: 4. Hard ceiling: 4 (the allowlist in `plate-auth` rejects everyone else by default).
This is _not_ a SaaS. It is _not_ a multi-tenant platform. It is **one shared organisation** ("Family Spark") with four members, running on Patrick's TrueNAS at home.
The multi-tenant machinery underneath it (`memberships.org_type`, `org_id`, `OrgValidator`, invitation flow) is real and works — it just isn't surfaced in the v1 UI because it would be noise for four people who all share one board.
---
## North star
Open Sparkboard on a phone while a thought is still fresh. Type a title and a sentence. Hit save. Walk away. Come back a week later, see whose ideas got reactions, decide together which one is worth a weekend.
Five seconds from intent to "captured". One screen. No project picker. No tag picker. No mention picker. No notification ladder. Just a feed, a "+" button, and a small fixed set of emoji reactions to say _"yes this one"_.
---
## Why this exists (strategically)
Sparkboard's job inside `plate-software` is **dual**:
1. **For its users (Patrick + family + friends):** a low-friction idea capture surface for the four of them. That is the visible value.
2. **For the platform (plate-auth):** a forcing function. The very first greenfield consumer of `plate-auth`. If Sparkboard cannot be wired up in a few hundred lines of glue code on a fresh Spring Boot 4.1 + Next.js 15 stack, then `plate-auth v0.1.0` failed and needs another iteration.
That second job is the harder one. Sparkboard's product surface is intentionally _trivial_ so that all the integration pain shows up where it actually lives — in the auth wire-up, the proxy route, the single-org configuration, the `OnboardingHook` SPI.
If [plate-auth's Vision](https://git.plate-software.de/pplate/plate-auth/wiki/Vision) is the **strategic** document, this Vision is the **tactical** one: what we ship to four humans so that the strategic document gets validated.
---
## Core value (for the four users)
| | |
|---|---|
| **Friction** | 5 seconds from app icon to captured idea |
| **Reach** | Phone, tablet, laptop — anything with a recent browser |
| **Discovery** | The other three people see your idea within a refresh, can react with one tap |
| **Memory** | The idea stays. It doesn't roll off a chat history. It doesn't drown in a Notion sidebar. |
| **Lifecycle** | An idea can be marked `EXPLORING`, `BUILDING`, `SHIPPED`, or `DEAD` — enough to know which ones moved |
---
## Non-goals (explicitly OUT for v1)
| Non-goal | Why |
|----------|-----|
| User-facing org switcher | One org. No switcher needed. |
| Invitation UI | No invitations needed — four people, seeded once. |
| Access-request flow | Allowlist is enforced silently; non-allowlisted Google logins simply fail with a generic "not authorised" page. |
| Comments / threads | Sprint 2 candidate. v1 = post + react only. |
| Tags / categories | Sprint 2+ candidate. v1 = title + description + status. |
| Free-text search | Sprint 3+ candidate. v1 list is short enough to scan. |
| Notifications (email, push, web-push) | Sprint 4+ candidate. v1 = pull-to-refresh. |
| Native mobile app | PWA in v1; Capacitor APK explored in Sprint 5 ("Wildfire"). |
| AI / LLM features | Out of scope for the family-board use case. |
| Public / shared boards | One private board. Forever, probably. |
| Multiple boards per family | One board. If we want more, that's a Sprint N+ design decision. |
---
## Mobile strategy
**PWA-first.** Sprint 1 ships a `manifest.json`, a stub service worker, app icons, and the "Add to Home Screen" affordance on both iOS Safari and Android Chrome. That is the v1 mobile story.
Native (Capacitor wrapping the Next.js build as an APK) is parked in [Sprint 5 — Wildfire](Roadmap.md#sprint-5--wildfire). It is **not** v1. It may never happen — if the PWA is good enough, the native shell never ships.
---
## Locked technical stack
Some choices are non-negotiable. They are stack inheritances from `plate-software`, not Sparkboard product decisions.
| Layer | Choice | Why |
|------|--------|-----|
| Backend language | Java 25 LTS | Plate-software standard |
| Backend framework | Spring Boot 4.1.0 | Sparkboard is the **Spring Boot 4.1 guinea pig** for plate-software; if it works here, plate-auth's 4.1 support is real |
| Auth / multi-tenancy | `de.platesoft:plate-auth-starter:0.1.0` | Single source of truth for auth across plate-software |
| Frontend | Next.js 15 (App Router) + React 19 + Tailwind + shadcn/ui | Plate-software standard; same as InspectFlow Sprint 14 |
| NextAuth | v5 (via `@platesoft/auth/next-auth` factory) | NextAuth v5 only; plate-auth provides the factory |
| Database | Postgres 16, single instance, single schema | No more H2 in production; Flyway-managed |
| Build | Maven (backend), pnpm (frontend) | Plate-software standard |
| Distribution | Gitea Package Registry (`git.plate-software.de`) | Where `plate-auth-starter` and `@platesoft/auth` are published |
| Deployment | TrueNAS Docker Compose + `frps` (port 30011) + IONOS Apache reverse proxy | Same pattern as InspectFlow + CannaManage |
| Public URL | `https://sparkboard.plate-software.de` | Subdomain on the existing IONOS wildcard cert |
What this means in practice: **Sparkboard is the first app on plate-auth and the first app on Spring Boot 4.1 in plate-software**. If either has a defect, Sparkboard finds it first.
---
## Success criteria (end of Sprint 1)
The walking skeleton is "done" when:
1. The four allowlisted users can sign in with Google.
2. Each of them is automatically a `MEMBER` of the single "Family Spark" org on first login, courtesy of `SparkboardOnboardingHook`. Patrick is `ADMIN` (Flyway seed).
3. Any signed-in user can create an idea (`title` + optional `description`, default `status=RAW`).
4. Any signed-in user can see all ideas, newest first.
5. The PWA installs on iOS Safari and Android Chrome with the Sparkboard icon and theme colour.
6. Deployed to `https://sparkboard.plate-software.de`, accessible from outside the home LAN.
That's it. No reactions, no status transitions, no archive, no profile page — those are Sprint 2.
See [Sprint 1 — Assessment](Sprint-1-Assessment.md) for the formal acceptance criteria (A1A6).
---
## Success criteria (end of Sprint ~5)
The visible product is "done" when:
- All four users actually use it weekly for a month.
- At least one idea has gone from `RAW → SHIPPED` (e.g., a weekend project the family actually built).
- The PWA is installed on every user's primary device.
- Patrick has not paged himself once about auth.
The last bullet is the most important. It is also the platform-level success criterion for `plate-auth v0.1.0`: _Sparkboard's owner, who also wrote plate-auth, never has to think about auth code while using Sparkboard._
---
## Anti-vision (what Sparkboard is NOT)
- Not Notion. There is no nesting, no database view, no rich text editor beyond a textarea.
- Not Jira. There is no assignee, no priority, no sprint, no estimate, no due date.
- Not Slack. There is no chat, no DM, no @mention, no channel.
- Not Trello. There are no columns. The status field is metadata, not a kanban lane.
- Not a SaaS. There is no signup page, no pricing page, no marketing site.
- Not multi-tenant from the user's point of view. They see _one_ board. The multi-tenancy is plate-auth's internal abstraction — invisible to Sparkboard's users.
- Not a research project. It's a working app, four people, for years.
---
## Naming & identity
- Product name: **Sparkboard**
- Theme: campfire / ember / kindling — see [Roadmap](Roadmap.md) for sprint naming
- Idea entity: **Spark** (per Sprint 1; can stay as `Idea` in the schema)
- Reactions (Sprint 2+, fixed set): 💡 ⚡ 🔥 ❓ 👀
- Primary colour: TBD in Sprint 2 design pass (see [Open Question Q08](Open-Questions.md#q08-mobile-strategy-pwa-only-vs-native-apk))
---
## Trade-offs we are accepting
| Trade-off | What we lose | Why we accept it |
|-----------|--------------|------------------|
| Locked to plate-auth | We can't swap auth providers without changing the dependency | plate-auth is ours; swap = ours to do |
| Single-org hardcoded for v1 | If a fifth person ever wants in, we have to add invitation UI | We don't expect a fifth person; four is the point |
| PWA over native | iOS push-notification limitations, slightly slower cold start than native | PWA is one codebase; native is two |
| Postgres only, no H2 | Local dev needs Docker | Postgres ergonomics for vector / FTS columns are worth it; InspectFlow proved it |
| Spring Boot 4.1 (just-released) | We hit any SB 4.1 regression before others do | Plate-software has decided 4.1 is the new baseline; someone has to go first |
---
## What this document is **not**
- It is not the [Roadmap](Roadmap.md). For sprint-by-sprint scope, go there.
- It is not the [Architecture](Architecture.md). For how it is built, go there.
- It is not the [plate-auth Vision](https://git.plate-software.de/pplate/plate-auth/wiki/Vision). For why `plate-auth` exists at all, read that one first — Sparkboard's Vision assumes you already agree with it.