Scrum4Me/app/page.tsx
Janpeter Visser 3a61a8ddc1
Landing v3: van idee tot pull request + 6 nieuwe screenshots (#127)
* feat(landing): tour uitbreiden naar 6 screenshots incl. Ideas/Insights

Vervangt de oude 3 .jpg-screenshots door 6 nieuwe .png's met de huidige
visuele staat van de app. Volgorde toont de hele flow: ideeën binnen →
producten → backlog → sprint → solo → insights.

- Tour-array van 3 naar 6 figures, grid blijft lg:grid-cols-3 (2x2-rijen)
- Intro-tekst aangepast: "Zes weergaven van Scrum4Me — van inkomende
  ideeën tot persoonlijk Kanban-bord en voortgangs-inzichten"
- Bestandsnamen gehernoemd naar lowercase-dash-conventie:
  Sprint.png → sprint.png, Solo.png → solo.png, "Product Backlog.png" →
  product-backlog.png, Producten.png → producten.png, Insights.png →
  insights.png, Ideas-table.png → ideas-table.png,
  Ideas-detail.png → ideas-detail.png (alleen voorbereiding, nog niet in
  tour gebruikt)
- Oude .jpg-bestanden verwijderd

Niet onderdeel: hero/architectuur/handleiding-rewrite voor v3 — die staan
gepland onder ST-1224 en blijven open.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(landing): v3 — van idee tot pull request, met procesflow + Idea-laag

Verbreedt de landing-propositie van "executie lokaal" (v2) naar de
volledige cyclus idee → grill → plan → execute → PR. Eert M12 Ideas dat
sinds 2026-05-04 het kernconcept van het product is, plus auto-PR en
Sync-tab.

Hero:
- H1 "Van idee tot pull request — op je eigen hardware."
- Subhead benoemt grill→plan→materialise→agent→PR-cyclus en houdt het
  lokaal-anker uit v2 vast.

Nieuw §3 "Van idee tot pull request":
- 4 procesflow-kaarten (Idee/Grill/Plan/Execute) met status-chips
  (DRAFT/GRILLING/PLAN_READY/DONE→PR) en pijlen tussen kaarten op md+.
- Samenvattende paragraaf over state-machine, materializeIdeaPlanAction
  en auto-PR.

Architectuur:
- docs/diagrams/architecture.mmd Worker-label uitgebreid met
  "jobs: GRILL · PLAN · IMPL"; beide SVG's geregenereerd.
- Callout "Lokale worker" benoemt nu de drie jobsoorten expliciet.

Feature-grid (set D, 6 kaarten):
- Vervang "Hiërarchisch plannen" door "Ideas — Grill & Plan" op positie 1.
- Lokale Claude-agents: + auto-PR/SQUASH-merge zin.
- Realtime updates: + Sync-tab zin.
- Async vraagkanaal: + Grill-vragen zin.

Quickstart:
- Extra regel over UI-route (/ideas → Nieuw idee → Grill me) onder de
  bestaande MCP-installatie code-block.

Scrum-samenvatting:
- Hiërarchie wordt twee-rij-systeem: Idea (DRAFT → GRILLED → PLAN_READY)
  als bovenste rij, daaronder Product → PBI → Story → Taak met
  "materialiseert ↓"-pijl.
- Terminologie krijgt 2 nieuwe tegels (Idea, Grill/Plan).

Handleiding (10 → 12 stappen):
- Nieuwe stappen 3-5 voor Idea-route (vastleggen, grillen, plan + materialiseren),
  visueel gemarkeerd met tertiary-border en chip "Idea-route".
- Oude 7+8 (token + MCP-koppeling) samengevoegd tot stap 10.
- Stap 11 uitgebreid met Sync-tab-volgen.
- Stap 6 hernoemd "opbouwen" → "finetunen".

Plan-doc + grilling-context vastgelegd in docs/plans/landing-v3-idea-flow.md.

Tracked: ST-1224 onder PBI Marketing & Landingspagina.

Verified: lint 0 errors / 7 warnings (alle pre-existing), 564/564 tests,
productie-build slaagt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:05:22 +02:00

688 lines
39 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Link from 'next/link'
import Image from 'next/image'
import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { AppIcon } from '@/components/shared/app-icon'
import { SessionData, sessionOptions } from '@/lib/session'
import packageJson from '@/package.json'
const buildDate = process.env.NEXT_PUBLIC_BUILD_DATE
? new Date(process.env.NEXT_PUBLIC_BUILD_DATE).toLocaleDateString('nl-NL', {
day: 'numeric',
month: 'short',
year: 'numeric',
})
: '—'
const version = process.env.NEXT_PUBLIC_APP_VERSION ?? packageJson.version
export default async function LandingPage() {
const session = process.env.SESSION_SECRET
? await getIronSession<SessionData>(await cookies(), sessionOptions)
: null
const isLoggedIn = Boolean(session?.userId)
return (
<div className="h-screen bg-background text-foreground flex flex-col overflow-hidden">
{/* ── Header ─────────────────────────────────────────────────── */}
<header className="h-14 border-b border-border bg-surface-container-low flex items-center px-6 gap-4 shrink-0">
<Link href="/" className="flex items-center gap-2 font-semibold text-primary">
<AppIcon size={24} />
Scrum4Me
</Link>
{isLoggedIn ? (
<nav className="flex items-center gap-1 ml-2">
<Link
href="/dashboard"
className="px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors"
>
Producten
</Link>
<Link
href="/solo"
className="px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors"
>
Solo
</Link>
<Link
href="/todos"
className="px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors"
>
Todo&apos;s
</Link>
<Link
href="/settings"
className="px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors"
>
Instellingen
</Link>
</nav>
) : (
<nav className="ml-auto flex items-center gap-2">
<Link
href="/login"
className="px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:text-foreground hover:bg-surface-container transition-colors"
>
Inloggen
</Link>
<Link
href="/register"
className="px-4 py-1.5 rounded-md text-sm bg-primary text-primary-foreground hover:opacity-90 transition-opacity font-medium"
>
Registreren
</Link>
</nav>
)}
</header>
<main className="flex-1 overflow-y-auto">
{/* ── Hero ───────────────────────────────────────────────────── */}
<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">
Van idee tot pull request op je eigen hardware.
</h1>
<p className="text-base text-primary-container-foreground/80 leading-relaxed">
Leg een idee vast, laat Claude het kritisch bevragen, accepteer het plan en zet het
door een lokale agent uit. Code, executie en agents draaien op je eigen machine;
alleen metadata loopt via Vercel + Neon. Idee na idee, automatisch omgezet in
commits en pull requests.
</p>
<div className="flex gap-3 justify-center pt-2">
<Link
href="/register"
className="px-5 py-2.5 rounded-lg bg-primary text-primary-foreground text-sm font-medium hover:opacity-90 transition-opacity"
>
Account aanmaken
</Link>
<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"
>
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>
</p>
<p className="text-xs text-primary-container-foreground/60">
Gratis tijdens de beta · desktop-first (1024px+)
</p>
<div className="mx-auto max-w-xl rounded-lg border border-primary-container-foreground/20 bg-primary-container-foreground/10 px-4 py-3 text-left">
<p className="text-xs font-medium text-primary-container-foreground">Beta-versie</p>
<p className="mt-1 text-xs leading-relaxed text-primary-container-foreground/75">
Scrum4Me is nog in actieve ontwikkeling. Accounts en ingevoerde gegevens kunnen tijdens deze fase worden aangepast, gereset of verwijderd.
</p>
</div>
</div>
</section>
{/* ── Van idee tot PR ────────────────────────────────────────── */}
<section className="px-6 py-14 bg-background border-b border-border">
<div className="max-w-6xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Van idee tot pull request</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Vier stappen, één queue. Een idee groeit uit tot gemergde code zonder dat jij ertussen
hoeft.
</p>
<div className="grid grid-cols-1 md:grid-cols-[1fr_auto_1fr_auto_1fr_auto_1fr] gap-4 items-stretch">
{[
{
step: '1',
title: 'Idee',
chip: 'DRAFT',
chipClass: 'bg-tertiary-container text-tertiary-container-foreground',
desc: 'Leg een idee vast in twee zinnen. Status: DRAFT.',
},
{
step: '2',
title: 'Grill',
chip: 'GRILLING',
chipClass: 'bg-warning-container text-warning-container-foreground',
desc: 'Claude stelt kritische vragen via het belicoon; je antwoorden vormen de grill_md.',
},
{
step: '3',
title: 'Plan',
chip: 'PLAN_READY',
chipClass: 'bg-success-container text-success-container-foreground',
desc: 'Claude schrijft een YAML-plan. Materialiseer en je hebt PBI + stories + tasks.',
},
{
step: '4',
title: 'Execute',
chip: 'DONE → PR',
chipClass: 'bg-primary-container text-primary-container-foreground',
desc: 'Lokale agent claimt de jobs, commit, pusht en opent automatisch een PR.',
},
].flatMap((s, i, arr) => {
const card = (
<div
key={s.step}
className="bg-surface-container-low border border-border rounded-xl p-5 space-y-3 flex flex-col"
>
<div className="flex items-center gap-2">
<div className="shrink-0 w-7 h-7 rounded-full bg-primary text-primary-foreground text-sm font-semibold flex items-center justify-center">
{s.step}
</div>
<div className="text-sm font-medium text-primary">{s.title}</div>
<span className={`text-[10px] font-mono font-semibold px-1.5 py-0.5 rounded ${s.chipClass}`}>
{s.chip}
</span>
</div>
<p className="text-sm text-muted-foreground leading-relaxed">{s.desc}</p>
</div>
)
if (i === arr.length - 1) return [card]
return [
card,
<div
key={`${s.step}-arrow`}
className="hidden md:flex items-center justify-center text-muted-foreground text-2xl"
>
</div>,
]
})}
</div>
<p className="text-sm text-muted-foreground leading-relaxed max-w-3xl mt-8">
State-machine: <code className="font-mono text-xs bg-surface-container px-1 rounded">DRAFT GRILLING GRILLED PLANNING PLAN_READY PLANNED</code>.
Bij materialiseren ontstaat in één atomaire transactie precies één PBI met N stories en M taken
uit het YAML-plan. Op de laatste taak van de laatste story pusht de worker automatisch een
branch en opent of mergt een pull request geen handwerk meer tussen plan en deploy.
</p>
</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. Doet drie soorten jobs: bevragen van een idee (GRILL), plan-generatie (PLAN), taak-implementatie (IMPL) — allemaal op dezelfde machine. 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">
<h2 className="text-xl font-semibold mb-2">Bekijk Scrum4Me in actie</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Zes weergaven van Scrum4Me van inkomende ideeën tot persoonlijk Kanban-bord en
voortgangs-inzichten. Elke weergave is desktop-first en gebouwd op MD3-tokens en
shadcn-componenten.
</p>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{[
{
src: '/screenshots/ideas-table.png',
alt: 'Ideas-dashboard met idee-kaarten in DRAFT/GRILLED/PLAN_READY-statussen',
title: 'Ideas-dashboard',
caption:
'Persoonlijk overzicht van je ideeën met status (DRAFT → GRILLED → PLAN_READY → PLANNED). Klik "Grill me" of "Make plan" om een lokale agent te starten; bij materialiseren ontstaat exact één PBI met stories en taken.',
},
{
src: '/screenshots/producten.png',
alt: 'Producten-dashboard met overzicht van actieve projecten',
title: 'Producten',
caption:
'Eén overzicht van alle producten waar je toegang toe hebt — eigen producten plus die waar je als developer bent toegevoegd. Vanaf hier spring je naar Backlog, Sprint of Solo.',
},
{
src: '/screenshots/product-backlog.png',
alt: 'Product Backlog met PBIs gegroepeerd op prioriteit en stories per PBI',
title: 'Product Backlog',
caption:
'PBIs gegroepeerd op prioriteit (Kritiek → Laag) in het linkerpaneel. Klik op een PBI om de stories rechts te zien, gerangschikt per urgentie en versleepbaar.',
},
{
src: '/screenshots/sprint.png',
alt: 'Sprint Board met drie panelen: Product Backlog, Sprint Backlog en Taken',
title: 'Sprint Board',
caption:
'Drie panelen op één scherm: Product Backlog links, Sprint Backlog in het midden, taken van de geselecteerde story rechts. Stories slepen tussen panelen werkt via dnd-kit.',
},
{
src: '/screenshots/solo.png',
alt: 'Solo Paneel — persoonlijk Kanban-bord met drie statuskolommen',
title: 'Solo Paneel',
caption:
'Persoonlijk Kanban-bord per product. Toont alleen taken van stories die jij hebt geclaimd, in drie kolommen (To Do, Bezig, Klaar). Drag-and-drop tussen kolommen verandert de status.',
},
{
src: '/screenshots/insights.png',
alt: 'Insights-dashboard met voortgangsmetrics en agent-throughput',
title: 'Insights',
caption:
'Voortgang per product: doorlooptijden, agent-throughput en sprintresultaten in één blik. Helpt patronen herkennen — welke stories liepen vast, welke gingen vlot.',
},
].map((s) => (
<figure
key={s.src}
className="bg-surface-container-low border border-border rounded-xl overflow-hidden flex flex-col"
>
<div className="relative aspect-[16/10] bg-surface-container">
<Image
src={s.src}
alt={s.alt}
fill
sizes="(max-width: 1024px) 100vw, 33vw"
className="object-cover object-top"
/>
</div>
<figcaption className="p-5 space-y-2">
<div className="text-sm font-medium text-primary">{s.title}</div>
<p className="text-sm text-muted-foreground leading-relaxed">{s.caption}</p>
</figcaption>
</figure>
))}
</div>
</div>
</section>
{/* ── Wat is Scrum4Me ────────────────────────────────────────── */}
<section className="px-6 py-14 bg-background">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Wat is Scrum4Me?</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Scrum4Me is een desktop-first webapplicatie die Scrum lichtgewicht maakt zonder
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-3 gap-4">
{[
{
title: 'Ideas — Grill & Plan',
desc: 'Leg een idee vast in twee zinnen. Claude grilt het met kritische vragen, schrijft een YAML-plan en zet t om in PBI + stories + tasks. Alles via een job-queue, asynchroon.',
},
{
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. Na de laatste task pusht de worker automatisch en opent een pull request via SQUASH-merge. 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. De Sync-tab toont per idee de live status van story → push → PR-merge.',
},
{
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. Tijdens een Grill stelt Claude vragen via hetzelfde kanaal — antwoorden komen direct terug in de Idea-timeline.',
},
{
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>
{/* ── 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">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 mb-3">
Liever in de UI beginnen? Open <code className="font-mono text-xs bg-surface-container px-1 rounded">/ideas</code>,
druk op &quot;Nieuw idee&quot; en klik &quot;Grill me&quot; de eerste vraag verschijnt
binnen seconden in je belicoon.
</p>
<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>
</section>
{/* ── Scrum samenvatting ─────────────────────────────────────── */}
<section className="px-6 py-14 bg-surface-container-low border-y border-border">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Scrum in Scrum4Me</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Scrum4Me past een lichtgewicht versie van Scrum toe de essentie zonder ceremony-overhead.
Hieronder staat hoe de kernbegrippen zijn vertaald naar de app.
</p>
{/* Hiërarchie */}
<div className="mb-10">
<h3 className="text-sm font-semibold text-foreground mb-4 uppercase tracking-wide">Hiërarchie</h3>
{/* Idee-laag */}
<div className="mb-3">
<div className="bg-tertiary-container border border-tertiary/20 rounded-lg px-4 py-2.5 inline-block">
<div className="text-sm font-medium text-tertiary-container-foreground">Idea</div>
<div className="text-xs text-tertiary-container-foreground/70 leading-tight mt-0.5">
DRAFT GRILLED PLAN_READY
</div>
</div>
<div className="text-muted-foreground text-xs mt-1 ml-4">
<span className="italic">materialiseert naar</span>
</div>
</div>
{/* Scrum-laag */}
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-2">
{[
{ label: 'Product', sub: 'Een softwareproject of codebase' },
{ label: 'PBI', sub: 'Product Backlog Item — een feature of verbetering' },
{ label: 'Story', sub: 'Concrete user story binnen een PBI' },
{ label: 'Taak', sub: 'Implementatiestap binnen een story' },
].map((item, i, arr) => (
<div key={item.label} className="flex items-center gap-2">
<div className="bg-primary-container border border-primary/20 rounded-lg px-4 py-2.5 min-w-[100px]">
<div className="text-sm font-medium text-primary-container-foreground">{item.label}</div>
<div className="text-xs text-primary-container-foreground/60 leading-tight mt-0.5">{item.sub}</div>
</div>
{i < arr.length - 1 && (
<span className="text-muted-foreground text-lg hidden sm:block"></span>
)}
</div>
))}
</div>
</div>
{/* Terminologie */}
<div className="mb-10">
<h3 className="text-sm font-semibold text-foreground mb-4 uppercase tracking-wide">Terminologie</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{[
{ term: 'Idea', def: 'Een voorstel of richting voordat t een PBI is. Heeft een grill-fase (Claude bevraagt t kritisch) en een plan-fase (Claude schrijft een YAML-plan met stories en tasks). Na materialiseren ontstaat exact één PBI.' },
{ term: 'Grill / Plan', def: 'Twee asynchrone Claude-jobsoorten op een idea. Grill produceert grill_md (Q&A-transcript). Plan produceert plan_md (YAML met PBI/stories/tasks-templates) dat strikt geparseerd wordt.' },
{ term: 'Product Backlog', def: 'Geordende lijst van alle PBI\'s per product, gesorteerd op prioriteit (kritiek → laag) en positie.' },
{ term: 'Sprint', def: 'Actief tijdblok met een Sprint Goal. Per product is er maximaal één actieve Sprint tegelijk.' },
{ term: 'Sprint Backlog', def: 'De stories die voor deze Sprint zijn geselecteerd. Stories worden vanuit de Product Backlog gesleept.' },
{ term: 'Sprint Board', def: 'Drie-panelen scherm op één view: Product Backlog, Sprint Backlog en taken per geselecteerde story. Vervangt het oude losse Sprint Planning-scherm.' },
{ term: 'Solo Paneel', def: 'Persoonlijk Kanban-bord per product. Toont taken van geclaimde stories in drie kolommen (To Do, Bezig, Klaar) — drag-and-drop wijzigt de status.' },
{ term: 'Story-claim', def: 'Een developer claimt een story uit de Sprint en wordt assignee. Pull-systeem (zelf-organisatie) — niet pushed door een Scrum Master.' },
{ term: 'Story-status', def: 'OPEN → IN_SPRINT → DONE. Bepaalt zichtbaarheid in backlogs en Sprint-schermen.' },
{ term: 'Taakstatus', def: 'TO_DO → IN_PROGRESS → DONE. Wordt bijgehouden via UI of REST API door Claude Code.' },
{ term: 'Activiteitenlog', def: 'Per story worden implementatieplan, testresultaat en commit vastgelegd via de API of UI.' },
{ term: 'Sprint afronden', def: 'Bij afsluiting wordt per story gekozen: markeer als Done of zet terug naar Backlog.' },
].map(({ term, def }) => (
<div key={term} className="bg-background border border-border rounded-lg p-4">
<div className="text-sm font-medium mb-1">{term}</div>
<div className="text-xs text-muted-foreground leading-relaxed">{def}</div>
</div>
))}
</div>
</div>
{/* Rollen */}
<div>
<h3 className="text-sm font-semibold text-foreground mb-4 uppercase tracking-wide">Rollen</h3>
<div className="flex flex-wrap gap-3">
{[
{ role: 'Product Owner', desc: 'Bepaalt prioriteit van PBI\'s en beheert de Product Backlog.' },
{ role: 'Scrum Master', desc: 'Bewaakt het Scrum-proces en verwijdert obstakels.' },
{ role: 'Developer', desc: 'Voert stories en taken uit; werkt via UI of Claude Code.' },
].map(({ role, desc }) => (
<div key={role} className="bg-secondary-container border border-secondary/20 rounded-lg px-4 py-3 flex-1 min-w-[180px]">
<div className="text-sm font-medium text-secondary-container-foreground">{role}</div>
<div className="text-xs text-secondary-container-foreground/70 mt-1">{desc}</div>
</div>
))}
</div>
<p className="text-xs text-muted-foreground mt-3">
In v1 is één account gelijk aan één gebruiker met alle rollen. Teamgebruik met rolscheiding volgt in v2.
</p>
</div>
</div>
</section>
{/* ── Gebruikershandleiding ─────────────────────────────────── */}
<section className="px-6 py-14 bg-background">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">Gebruikershandleiding</h2>
<p className="text-muted-foreground text-sm mb-10 max-w-2xl">
Volg deze stappen om van een leeg account naar een volledig ingeplande Sprint te gaan.
</p>
<div className="space-y-3">
{[
{
step: '1',
title: 'Account aanmaken',
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).',
ideaRoute: false,
},
{
step: '2',
title: 'Product aanmaken',
desc: 'Klik op "Nieuw product" op het dashboard. Vul naam, optionele beschrijving, repo-URL en je Definition of Done in. Het product wordt zichtbaar op het dashboard.',
ideaRoute: false,
},
{
step: '3',
title: 'Een idee vastleggen',
desc: 'Open /ideas, klik "Nieuw idee", vul titel + één-alinea beschrijving in. Status: DRAFT.',
ideaRoute: true,
},
{
step: '4',
title: 'Laat Claude grillen',
desc: 'Klik "Grill me". Een lokale agent stelt kritische vragen via het belicoon. Beantwoord ze; Claude schrijft een gestructureerde grill_md. Status: GRILLED.',
ideaRoute: true,
},
{
step: '5',
title: 'Maak het plan + materialiseer',
desc: 'Klik "Make plan". Claude genereert een YAML-plan (PBI + stories + tasks). Klik "Materialiseer" om t atomair om te zetten naar je product-backlog. Status: PLANNED.',
ideaRoute: true,
},
{
step: '6',
title: 'Product Backlog finetunen',
desc: 'Optioneel: herorden PBI\'s en stories handmatig via drag-and-drop. Het meeste werk heeft materialise al gedaan — dit is alleen voor bijsturen of toevoegen van werk dat niet uit een idee komt.',
ideaRoute: false,
},
{
step: '7',
title: 'Sprint starten',
desc: 'Klik op "Sprint starten" op de productpagina en voer een Sprint Goal in. Per product is er maximaal één actieve Sprint tegelijk. Het Sprint-scherm wordt zichtbaar via de navigatie.',
ideaRoute: false,
},
{
step: '8',
title: 'Sprint Board — stories slepen en taken aanmaken',
desc: 'Open het Sprint-scherm. Drie panelen verschijnen op één view: Product Backlog links, Sprint Backlog in het midden, taken rechts. Sleep stories vanuit links naar het midden om ze in de Sprint te plaatsen. Selecteer een story in het middenpaneel om de taken rechts te tonen en aan te maken.',
ideaRoute: false,
},
{
step: '9',
title: 'Solo Paneel — claim stories en werk persoonlijk',
desc: 'Open Solo via de navigatie. Claim openstaande stories uit de actieve Sprint (knop "Toon openstaande stories") en werk je taken af in drie statuskolommen via drag-and-drop. Klik op een taak voor het detail-dialoog met implementatieplan.',
ideaRoute: false,
},
{
step: '10',
title: 'Claude Code koppelen',
desc: 'Maak een API-token aan in Instellingen → Tokens — hetzelfde token werkt voor MCP en REST. Aanbevolen: installeer de scrum4me-mcp-server (zie Quickstart hierboven) zodat Claude Code de tools native ziet. Alternatief: gebruik de REST API direct vanuit Codex, eigen scripts of CI-pipelines.',
ideaRoute: false,
},
{
step: '11',
title: 'Voer uit + Sync-tab volgen',
desc: 'Klik op "Voer uit" bij een story in het Solo Paneel. De story komt in de job-queue. Een lokale agent claimt de jobs, werkt taken af, commit en — na de laatste task — pusht en mergt automatisch een PR via SQUASH. Volg de voortgang in de Sync-tab op het idea-detail.',
ideaRoute: false,
},
{
step: '12',
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.',
ideaRoute: false,
},
].map(({ step, title, desc, ideaRoute }) => (
<div
key={step}
className={`flex gap-4 bg-surface-container-low border rounded-xl p-5 ${
ideaRoute ? 'border-l-4 border-l-tertiary border-y-border border-r-border' : 'border-border'
}`}
>
<div
className={`shrink-0 w-8 h-8 rounded-full text-sm font-semibold flex items-center justify-center ${
ideaRoute ? 'bg-tertiary text-tertiary-foreground' : 'bg-primary text-primary-foreground'
}`}
>
{step}
</div>
<div className="space-y-1">
<div className="text-sm font-medium flex items-center gap-2">
{title}
{ideaRoute && (
<span className="text-[10px] font-mono font-semibold px-1.5 py-0.5 rounded bg-tertiary-container text-tertiary-container-foreground">
Idea-route
</span>
)}
</div>
<div className="text-sm text-muted-foreground leading-relaxed">{desc}</div>
</div>
</div>
))}
</div>
</div>
</section>
{/* ── API-overzicht ─────────────────────────────────────────── */}
<section id="api" className="px-6 py-14 bg-surface-container-low border-t border-border">
<div className="max-w-4xl mx-auto">
<h2 className="text-xl font-semibold mb-2">REST API voor Claude Code</h2>
<p className="text-muted-foreground text-sm mb-6 max-w-2xl">
Alle API-endpoints vereisen een <code className="font-mono bg-surface-container px-1 rounded text-xs">Authorization: Bearer &lt;token&gt;</code> header.
Tokens beheer je via Instellingen Tokens.
</p>
<pre className="bg-background border border-border rounded-lg p-4 text-xs font-mono overflow-x-auto mb-8 max-w-2xl">
<code className="text-foreground">{`# Volgende story uit de actieve Sprint ophalen
curl -H "Authorization: Bearer $TOKEN" \\
https://<jouw-instance>/api/products/<product-id>/next-story`}</code>
</pre>
<div className="space-y-2">
{[
{ method: 'GET', path: '/api/products', desc: 'Lijst van actieve producten' },
{ method: 'GET', path: '/api/products/:id/next-story', desc: 'Hoogst geprioriteerde open story van de actieve Sprint' },
{ method: 'GET', path: '/api/sprints/:id/tasks?limit=10', desc: 'Eerste N taken van de Sprint op volgorde' },
{ method: 'PATCH', path: '/api/stories/:id/tasks/reorder', desc: 'Taakvolgorde aanpassen (body: { task_ids: string[] })' },
{ method: 'POST', path: '/api/stories/:id/log', desc: 'Activiteit vastleggen: implementatieplan, testresultaat of commit' },
{ method: 'PATCH', path: '/api/tasks/:id', desc: 'Taakstatus of implementatieplan bijwerken' },
{ method: 'POST', path: '/api/todos', desc: 'Todo aanmaken (body: { title, product_id })' },
].map(({ method, path, desc }) => (
<div key={path} className="flex items-start gap-3 bg-background border border-border rounded-lg px-4 py-3">
<span className={`shrink-0 text-xs font-mono font-semibold px-2 py-0.5 rounded ${
method === 'GET' ? 'bg-tertiary-container text-tertiary-container-foreground' :
method === 'POST' ? 'bg-success-container text-success-container-foreground' :
'bg-warning-container text-warning-container-foreground'
}`}>
{method}
</span>
<code className="text-xs font-mono text-foreground shrink-0">{path}</code>
<span className="text-xs text-muted-foreground">{desc}</span>
</div>
))}
</div>
</div>
</section>
</main>
{/* ── 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>
<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>
</div>
)
}