feat(landing): rewrite around local-first proposition + architecture diagram

Reframe the landing page around what makes Scrum4Me unique: code execution
stays on the developer's own hardware (laptop, NAS or VM). The Vercel UI and
Neon DB are a metadata coordination layer; source code never leaves the local
worker. Adds a mermaid-rendered architecture diagram (two-zone: Scrum4Me-stack
vs Jouw kant) with light/dark variants generated via mmdc.

Page changes (app/page.tsx):
- Hero: H1 "Plannen in de cloud. Uitvoeren op je eigen machine." + new
  subhead; CTA "Hoe het werkt" replaces "Demo bekijken" (anchors to
  #architectuur).
- New section §3 "Architectuur" with light/dark SVG and 4 callout-cards
  (Vercel · Neon · Lokale worker · GitHub) honestly describing what each
  component stores or runs.
- Feature grid: 6 cards (set C) — combines Sprint Board + Solo Paneel,
  adds Lokale Claude-agents, Realtime updates, Async vraagkanaal, Todo's.
  LIVE callout removed (folded into Realtime card).
- "Twee manieren"-section replaced by a Quickstart with concrete git-clone
  snippet for the MCP-server.
- Handleiding: 9 → 10 steps; MCP recommended in step 8; new step 9
  "Story laten uitvoeren" describing the Voer-uit / job-queue flow;
  step 1 mentions QR-pairing as alternative login.
- Footer: adds link to madhura68/scrum4me-mcp alongside the app repo.

Tooling:
- New docs/diagrams/architecture.mmd (mermaid source).
- New npm script "diagrams" generates light + dark SVG via mmdc; output
  committed to public/diagrams/. No prebuild hook (manual regenerate, like
  prisma generate / docs:index).
- Plan + grilling outcomes captured in docs/plans/landing-local-first.md.

Tracked under Scrum4Me story cmoq2qoik0001qa175iynfnaa
(PBI Marketing & Landingspagina, cmoq2q50s0000qa174rmrjove).

Verified: npm run lint (0 new errors), npm test (379/379), npm run build OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-03 20:24:10 +02:00
parent 2c3c5c0ab2
commit 4ff50cb87e
7 changed files with 395 additions and 100 deletions

View file

@ -82,11 +82,12 @@ export default async function LandingPage() {
<section className="bg-primary-container px-6 py-16 text-center">
<div className="max-w-2xl mx-auto space-y-4">
<h1 className="text-3xl font-semibold text-primary-container-foreground">
Scrum planner voor solo developers en kleine teams
Plannen in de cloud. Uitvoeren op je eigen machine.
</h1>
<p className="text-base text-primary-container-foreground/80 leading-relaxed">
Houd meerdere projecten bij in één overzicht. Plan Product Backlogs, beheer Sprints
met drag-and-drop en laat Claude Code taken oppakken via een REST API.
De UI draait op Vercel, je code draait op jou. Een gedeelde job-queue laat lokale
Claude Code agents (laptop, NAS of VM) stories autonoom oppakken zonder dat je
broncode ooit de cloud hoeft te raken.
</p>
<div className="flex gap-3 justify-center pt-2">
<Link
@ -95,12 +96,12 @@ export default async function LandingPage() {
>
Account aanmaken
</Link>
<Link
href="/login"
<a
href="#architectuur"
className="px-5 py-2.5 rounded-lg border border-primary text-primary bg-transparent text-sm font-medium hover:bg-primary/10 transition-colors"
>
Demo bekijken
</Link>
Hoe het werkt
</a>
</div>
<p className="text-xs text-primary-container-foreground/60 pt-1">
Demo-login: gebruikersnaam <code className="font-mono bg-primary-container-foreground/10 px-1 rounded">demo</code> · wachtwoord <code className="font-mono bg-primary-container-foreground/10 px-1 rounded">demo1234</code>
@ -117,6 +118,65 @@ export default async function LandingPage() {
</div>
</section>
{/* ── Architectuur ───────────────────────────────────────────── */}
<section id="architectuur" className="px-6 py-14 bg-background border-b border-border">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Architectuur hoe Scrum4Me draait</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Vier componenten in twee zones. De Scrum4Me-stack (Vercel + Neon) houdt alleen
metadata bij. Jouw kant (lokale worker + GitHub) houdt de code en de uitvoering.
Het enige verkeer over de zonegrens is de job-queue zelf agents claimen werk en
rapporteren status terug.
</p>
<div className="bg-surface-container-low border border-border rounded-xl p-6 mb-6 flex justify-center">
<Image
src="/diagrams/architecture-light.svg"
alt="Scrum4Me-architectuur: Vercel en Neon Postgres in de Scrum4Me-stack; lokale worker en GitHub aan jouw kant; job-queue verbindt de twee."
width={900}
height={420}
className="dark:hidden w-full h-auto"
priority
/>
<Image
src="/diagrams/architecture-dark.svg"
alt="Scrum4Me-architectuur: Vercel en Neon Postgres in de Scrum4Me-stack; lokale worker en GitHub aan jouw kant; job-queue verbindt de twee."
width={900}
height={420}
className="hidden dark:block w-full h-auto"
priority
/>
</div>
<h3 className="text-sm font-semibold text-foreground mb-4 uppercase tracking-wide">Wat draait waar?</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{[
{
title: 'Vercel',
desc: 'Alleen UI, Server Actions en cron-jobs. Geen sourcecode, geen build-artefacten van klanten — Vercel weet niet hoe jouw code eruit ziet.',
},
{
title: 'Neon Postgres',
desc: 'Scrum-metadata: titels, statussen, plan-tekstvelden, logs en commit-hashes. Geen volledige diffs, geen broncodebestanden. Wat jij of de agent zelf in een plan of log schrijft, staat hier wel.',
},
{
title: 'Lokale worker',
desc: 'Jouw machine — laptop, NAS of VM. Claude Code via stdio-MCP, claimt jobs atomisch (FOR UPDATE SKIP LOCKED), executeert lokaal, commit lokaal, push lokaal. Meerdere workers parallel veilig.',
},
{
title: 'GitHub',
desc: 'Jouw eigen repo. Scrum4Me kent alleen de repo_url-string en de commit-hashes uit het story-log. Code en historie blijven onder jouw account.',
},
].map(({ title, desc }) => (
<div key={title} className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">{title}</div>
<p className="text-sm text-muted-foreground leading-relaxed">{desc}</p>
</div>
))}
</div>
</div>
</section>
{/* ── Tour (screenshots) ─────────────────────────────────────── */}
<section className="px-6 py-14 bg-background border-b border-border">
<div className="max-w-6xl mx-auto">
@ -182,93 +242,64 @@ export default async function LandingPage() {
de overhead van grote tools als Jira of Linear. Ontworpen voor developers die
zelf de regie willen houden over hun planning.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">Hiërarchisch plannen</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Organiseer werk in producten, Product Backlog Items, stories en taken.
Alles op één plek, gegroepeerd op prioriteit.
</p>
</div>
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">Sprint Board</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Drie-panelen layout: Product Backlog, Sprint Backlog en taken per story op
één scherm. Slepen, sorteren en statussen wisselen via dnd-kit.
</p>
</div>
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">Solo Paneel</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Persoonlijk Kanban-bord per product. Claim stories vanuit de Sprint en werk
je taken af in drie kolommen To Do, Bezig, Klaar.
</p>
</div>
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">Claude Code-integratie</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Twee opties: native MCP-server (aanbevolen) of REST API met Bearer-token.
Beide laten Claude Code stories ophalen, taken bijwerken en resultaten vastleggen.
</p>
</div>
</div>
<div className="mt-4 bg-surface-container border border-border rounded-xl p-5 flex items-start gap-4">
<div className="text-xs font-mono font-semibold text-primary shrink-0 mt-1 px-2 py-0.5 rounded bg-primary-container">
LIVE
</div>
<div className="space-y-1">
<div className="text-sm font-medium">Realtime Solo Paneel</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Wijzigingen vanuit andere tabs of Claude Code verschijnen binnen 12 seconden in je
Solo Paneel. Geen refresh nodig gebouwd op Postgres LISTEN/NOTIFY en Server-Sent Events.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{[
{
title: 'Hiërarchisch plannen',
desc: 'Organiseer werk in producten, Product Backlog Items, stories en taken — gegroepeerd op prioriteit en herrangschikbaar via drag-and-drop.',
},
{
title: 'Sprint Board + Solo Paneel',
desc: 'Twee weergaven van dezelfde data: een team-bord (Product Backlog · Sprint Backlog · taken) en een persoonlijk Kanban met geclaimde stories.',
},
{
title: 'Lokale Claude-agents',
desc: 'Een job-queue met "Voer uit"-knop. Lokale Claude Code agents claimen werk atomisch, draaien het op jouw hardware en rapporteren status terug. Meerdere workers (laptop + NAS) parallel veilig.',
},
{
title: 'Realtime updates',
desc: 'SSE bovenop Postgres LISTEN/NOTIFY. Wijzigingen vanuit andere tabs of een lokale agent verschijnen binnen 12 seconden in je Solo Paneel — geen refresh.',
},
{
title: 'Async vraagkanaal',
desc: 'Loopt een agent vast op een keuze? Hij plaatst een vraag via het bel-icoon. Jij beantwoordt hem wanneer het uitkomt; de agent pakt automatisch de draad weer op.',
},
{
title: "Todo's",
desc: 'Lichtgewicht notities los van de sprint-hiërarchie. Filter, sorteer en archiveer via een tabel-weergave — handig voor invallen die nog geen story zijn.',
},
].map(({ title, desc }) => (
<div key={title} className="bg-surface-container-low border border-border rounded-xl p-5 space-y-2">
<div className="text-sm font-medium text-primary">{title}</div>
<p className="text-sm text-muted-foreground leading-relaxed">{desc}</p>
</div>
))}
</div>
</div>
</section>
{/* ── Twee manieren om Claude Code te koppelen ─────────────── */}
{/* ── Quickstart ──────────────────────────────────────────── */}
<section className="px-6 py-14 bg-background border-t border-border">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Twee manieren om Claude Code te koppelen</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Kies de aansluiting die bij je workflow past. Beide werken naast elkaar.
<h2 className="text-xl font-semibold mb-2">Quickstart lokale agent in 3 stappen</h2>
<p className="text-muted-foreground text-sm mb-6 max-w-2xl">
De aanbevolen route: installeer de MCP-server lokaal en laat Claude Code de
Scrum4Me-tools native gebruiken.
</p>
<pre className="bg-background border border-border rounded-lg p-4 text-xs font-mono overflow-x-auto mb-4 max-w-2xl">
<code className="text-foreground">{`# 1. Clone en installeer de MCP-server
git clone https://github.com/madhura68/scrum4me-mcp
cd scrum4me-mcp && npm install
# 2. Voeg toe aan Claude Code config (zie repo-README)
# 3. Start Claude Code en vraag:
# "pak de volgende job uit de Scrum4Me-queue"`}</code>
</pre>
<p className="text-sm text-muted-foreground leading-relaxed max-w-2xl">
Liever zonder MCP? Gebruik de{' '}
<a href="#api" className="text-primary hover:underline">REST API met een Bearer-token</a>
{' '} werkt ook vanuit Codex, eigen scripts of CI-pipelines.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-3">
<div className="flex items-center gap-2">
<div className="text-sm font-medium text-primary">MCP-server</div>
<span className="text-xs px-2 py-0.5 rounded bg-primary-container text-primary-container-foreground font-medium">
Aanbevolen
</span>
</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Native Model Context Protocol-tools voor Claude Code. Geen REST-configuratie
Claude ziet producten, stories en taken als ingebouwde commando&apos;s. Eén prompt
orkestreert de hele implementatieflow: story ophalen, status updaten, plan loggen,
commit vastleggen.
</p>
<a
href="https://github.com/madhura68/scrum4me-mcp"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-xs text-primary hover:underline"
>
github.com/madhura68/scrum4me-mcp
</a>
</div>
<div className="bg-surface-container-low border border-border rounded-xl p-5 space-y-3">
<div className="text-sm font-medium text-primary">REST API</div>
<p className="text-sm text-muted-foreground leading-relaxed">
Universele HTTP-API met Bearer-token. Werkt vanuit Claude Code, Codex, eigen
scripts of CI-pipelines. Zelfde rechten als de MCP-server, maar je beheert
tokens en aanroepen zelf.
</p>
<a href="#api" className="inline-flex items-center gap-1 text-xs text-primary hover:underline">
API-endpoints bekijken
</a>
</div>
</div>
</div>
</section>
@ -363,7 +394,7 @@ export default async function LandingPage() {
{
step: '1',
title: 'Account aanmaken',
desc: 'Ga naar Registreren en kies een gebruikersnaam en wachtwoord. Na registratie word je direct doorgestuurd naar het dashboard. Wil je eerst rondkijken? Log in met de demo-account (alleen leesrechten).',
desc: 'Ga naar Registreren en kies een gebruikersnaam en wachtwoord. Na registratie word je direct doorgestuurd naar het dashboard. Liever passwordless? Paar je telefoon één keer en log voortaan in via QR. Of test eerst met de demo-account (alleen leesrechten).',
},
{
step: '2',
@ -392,16 +423,21 @@ export default async function LandingPage() {
},
{
step: '7',
title: 'API-token aanmaken voor Claude Code',
desc: 'Ga naar Instellingen → Tokens. Maak een nieuw token aan en kopieer de waarde direct — die is daarna niet meer zichtbaar. Gebruik het token als Bearer-token in Claude Code of je eigen scripts.',
title: 'API-token aanmaken',
desc: 'Ga naar Instellingen → Tokens. Maak een nieuw token aan en kopieer de waarde direct — die is daarna niet meer zichtbaar. Hetzelfde token werkt voor de MCP-server én voor de REST API.',
},
{
step: '8',
title: 'Claude Code koppelen',
desc: 'Configureer Claude Code met je API-token. Claude haalt via GET /api/products/:id/next-story de hoogst geprioriteerde open story op, werkt taken bij via PATCH /api/tasks/:id en legt het implementatieplan, testresultaten en commits vast via POST /api/stories/:id/log.',
desc: 'Aanbevolen: installeer de scrum4me-mcp-server (zie Quickstart hierboven) zodat Claude Code de Scrum4Me-tools native ziet. Alternatief: gebruik de REST API direct vanuit Codex, eigen scripts of CI-pipelines met je Bearer-token.',
},
{
step: '9',
title: 'Story laten uitvoeren — "Voer uit"-knop',
desc: 'Klik op "Voer uit" bij een story in het Solo Paneel. De story komt in de job-queue. Een lokale Claude-agent op je machine pakt \'m op via wait_for_job, werkt het implementatieplan af, commit naar je repo en zet de status op done. De NavBar toont live hoeveel workers actief zijn.',
},
{
step: '10',
title: 'Sprint afronden',
desc: 'Klik op "Sprint afronden" op het Sprint Board. Voor elke story kies je: markeer als Done of zet terug naar de Product Backlog. Daarna is een nieuwe Sprint aanmaakbaar.',
},
@ -464,14 +500,24 @@ curl -H "Authorization: Bearer $TOKEN" \\
{/* ── Footer ─────────────────────────────────────────────────── */}
<footer className="shrink-0 border-t border-border bg-surface-container-low px-6 py-4 flex items-center justify-between text-xs text-muted-foreground">
<span>© {new Date().getFullYear()} Scrum4Me</span>
<a
href="https://github.com/madhura68/Scrum4Me"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground transition-colors"
>
GitHub
</a>
<div className="flex items-center gap-4">
<a
href="https://github.com/madhura68/Scrum4Me"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground transition-colors"
>
App-repo
</a>
<a
href="https://github.com/madhura68/scrum4me-mcp"
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground transition-colors"
>
MCP-server
</a>
</div>
<span>v{version} · gebouwd op {buildDate}</span>
</footer>