Dokumente Dashboard · Final Design Spec

Redesign of the homepage (/) as an action-led document hub. Replaces the wall-of-lists approach with a warm, collaborative dashboard: personal greeting, hero "resume" card, Mission Control 3-up, Family Pulse (this week only), activity feed, and sidebar dropzone. Variant A selected from a three-concept exploration. Addresses Issue #271.

Final · Ready for implementation
Issue
#271 — Dashboard redesign
Variant
A — Resume + Family Pulse · hero-led, warm greeting, mission-control 3-up
Thumbnails
Hero only (large = legible). No thumbnails in task rows — kurrent is unreadable noise at small sizes.
Progress framing
"Diese Woche" only. Never show 1,500 total — demotivating at early state. Per-letter bars stay (clear denominator).
📐 Mockup scale notice — all font-size, height, and padding values in the mockup CSS are scaled to ~55% of actual implementation values. Do not copy sizes from mockup CSS. Use the ⚙ Implementation Reference tables after each section.
1 Full page — desktop (1280px)
Default — logged in as Marie
localhost:3000/
Familienarchiv Dokumente Personen Briefwechsel
↑ Hochladen
MR
Hallo, Marie.
Klaus hat dich gestern in einem Brief erwähnt, und Anna wartet auf deine Meinung zur „Postkarte aus Wien".
Weiter, wo du aufgehört hast Seite 2 von 4
Brief an Frieda aus dem Harz
Frieda Lehmann an Wilhelm Lehmann · Bad Sachsa, 14. März 1923
„Liebe Frieda, der Schnee ist endlich gewichen und die Wege wieder begehbar. Vater hat heute Morgen vom Markt geschrieben, daß die Preise abermals…"
Transkription 38% MR AN du und Anna
oder anderen Brief wählen
Mitmachen
Segmentieren5 offen
Seiten zu Briefen zuordnen.
Konvolut Rose, Heft III
Mappe A·14 Seiten
AN
Umschlag Mariahilf
19. Nov 1925·3 Seiten
Mappe B — unsortiert
neu, 18. Apr·27 Seiten
Briefbündel Lehrzeit
1928–1930·11 Seiten
Einzelseiten Dachboden
ohne Datum·8 Seiten
Alle anzeigen →
Transkribieren5 offen
Alte Handschriften lesen und abtippen.
Brief an Frieda aus dem Harz
14. März 1923·38%
MR
Postkarte aus Wien
2. Aug 1924·60%
OS
Geburtstagsbrief
22. Mai 1928·5%
LO
Weihnachtsgruß an die Familie
21. Dez 1931·12%
MR
Brief aus Hamburg
3. Juni 1929
Alle anzeigen →
Prüfen4 offen
Letzte Korrektur und freigeben.
Brief aus der Lehrzeit
8. Okt 1930·fertig
TH
Weihnachtsgruß
21. Dez 1931·fertig
MR
Geschäftsbrief Mariahilf
19. Nov 1925·fertig
KL
Kartengruß aus Dresden
7. Apr 1927·fertig
AN
Alle anzeigen →
Diese Woche · gemeinsam
Ihr habt zusammen 86 Seiten bearbeitet.
Du selbst hast 4 davon transkribiert.
AN KL OS MR LO 6 Mitwirkende
23
Briefe transkribiert
9
Briefe geprüft
47
Seiten hochgeladen
Kommentare & AktivitätAlle
AN
Anna hat transkribiert Postkarte aus Wien
vor 12 Min.
KL
Klaus hat dich erwähnt in Brief an Friedafür dich
vor 1 Std.
OS
Oskar hat zugeordnet Konvolut Rose, Heft III
vor 3 Std.
LO
Lotte hat geantwortet auf deinem Kommentarfür dich
gestern
TH
Theo hat 4 Scans hochgeladen Mappe B
gestern
Hochladen
Neue Scans hochladen
Hierher ziehen oder klicken
PDF, JPG, PNG bis 50 MB
Implementation Reference — Page structureroutes/+page.svelte + +page.server.ts
ElementTailwind classesReal pxNotes
Page backgroundmin-h-screen bg-canvasCanvas = #f0efe9
Main content wrappermax-w-screen-xl mx-auto px-8 py-832px padding, 1280px max
2-column layout gridgrid grid-cols-[1fr_320px] gap-5 items-start20px gap, 320px sidebarCollapses to 1-col on mobile
Main columnflex flex-col gap-520px gap between sections
Sidebarflex flex-col gap-520px gapSticky on tall viewports: sticky top-[80px] (below header)
2 Header — authenticated nav bar
Dokumente active
Familienarchiv Dokumente Personen Briefwechsel
↑ Hochladen
MR
Active nav item: white text + 2px mint border-bottom. Upload button: ghost (transparent bg, 25% white border).
Upload button — hover
Familienarchiv Dokumente Personen Briefwechsel
↑ Hochladen
MR
Hover: rgba(255,255,255,.12) bg tint on upload button.
Implementation Reference — Header (authenticated)routes/+layout.svelte (existing — minimal changes needed)
ElementTailwind classesReal pxNotes
Headersticky top-0 z-50 bg-[#012851]Already implemented — no change needed
Mint stripeh-1 bg-accent4pxAlready implemented
Nav bar heighth-16 flex items-center px-864pxAlready implemented
Upload button (new)inline-flex items-center gap-2 border border-white/25 text-white font-sans text-[11px] font-bold tracking-[.12em] uppercase px-3.5 py-1.5 rounded-sm hover:bg-white/10 transition-colors11px fontNew addition to existing header. Routes to /documents/new or triggers upload modal.
User avatarw-8 h-8 rounded-full bg-white text-ink font-sans text-[11px] font-bold flex items-center justify-center32pxShows user initials. Click → user menu (out of scope for this issue).
3 Greeting + search bar
Morning greeting (activity-aware)
Guten Morgen, Marie.
Klaus hat dich gestern in einem Brief erwähnt, und Anna wartet auf deine Meinung zur „Postkarte aus Wien".
Greeting text changes by time of day: "Guten Morgen" (<11h), "Hallo" (11–18h), "Guten Abend" (>18h).
Search — focused state
Hallo, Marie.
Klaus hat dich gestern in einem Brief erwähnt.
Implementation Reference — Greeting + Searchroutes/+page.svelte
ElementTailwind / implementationReal pxNotes
Greeting wrappermb-520px bottom margin
Greeting headlinefont-serif font-normal text-[32px] leading-tight text-ink32pxTime-of-day: getHours() < 11 → m.greeting_morning(). Uses logged-in user's first name from data.currentUser.firstName.
Greeting subtitlefont-serif text-[17px] text-ink-2 mt-2 leading-[1.45]17pxDriven by actual notification data. Priority: @mention > reply > new scan. Links to document. Falls back to a neutral welcome if no recent activity.
Search bar cardbg-surface border border-line shadow-sm rounded-sm p-5 mb-6 flex items-center gap-320px padding, 24px bottom marginSame component as existing SearchFilterBar.svelte — no change needed.
Search inputflex-1 border border-line px-3.5 py-3 font-serif text-base text-ink placeholder:text-ink-3 rounded-none focus-visible:ring-2 focus-visible:ring-focus-ring/15 focus-visible:border-ink16px font / 48px tallAlready implemented in SearchFilterBar.
4 Hero — "Weiter, wo du aufgehört hast"
Default — in-progress letter
Weiter, wo du aufgehört hast Seite 2 von 4
Brief an Frieda aus dem Harz
Frieda Lehmann an Wilhelm Lehmann · Bad Sachsa, 14. März 1923
„Liebe Frieda, der Schnee ist endlich gewichen und die Wege wieder begehbar. Vater hat heute Morgen geschrieben…"
Transkription 38% MR AN du und Anna
oder anderen Brief wählen
Thumbnail only here — 180×246px on real page. This is the only location large enough to make kurrent legible.
No in-progress letter (empty state)
Wo möchtest du anfangen?
Wähle einen Brief aus einer der Warteschlangen unten oder durchsuche das Archiv.
Shown when the user has no in-progress transcription task.
Implementation Reference — Hero resume cardlib/components/DashboardResumeStrip.svelte (refactor from existing)
ElementTailwind classesReal pxNotes
Hero cardbg-surface border border-line shadow-sm rounded-sm p-7 grid grid-cols-[180px_1fr] gap-8 items-center28px padding, 32px gapCollapses to single-column on mobile: sm:grid-cols-[180px_1fr]
Letter thumbnailw-[180px] h-[246px] rounded-sm shadow-sm flex-shrink-0180×246pxReal scan image when available; SVG placeholder when not. <img> with object-cover.
Eyebrow labelinline-flex items-center gap-2 font-sans text-[11px] font-bold tracking-[.18em] uppercase text-turquoise11pxDot: w-2 h-2 rounded-full bg-turquoise. i18n: m.dashboard_resume_label()
Page counterfont-sans text-[11px] tracking-[.12em] uppercase text-ink-311pxm.dashboard_page_of({ page, pages })
Letter titlefont-serif font-normal text-[30px] leading-tight text-ink mb-1.530pxFrom document.title
Archival captionfont-serif text-sm italic text-ink-3 mb-414px"{from} an {to} · {place}, {date}"
Excerpt pull-quotefont-serif text-[17px] italic leading-[1.55] text-ink-2 border-l-[3px] border-accent pl-4 mb-517px, 3px left border (mint)First 200 chars of transcription draft or OCR excerpt.
Progress rowflex justify-between items-center font-sans text-xs text-ink-3 mb-212pxLeft: "{pct}% transkribiert". Right: avatar stack + collaborator names.
Progress barw-full h-1.5 bg-[#eeede8] rounded-full overflow-hidden mb-56pxFill: bg-turquoise (#00c7b1). This is per-letter (clear denominator) — motivating, not crushing.
Primary CTAbg-primary text-primary-fg font-sans text-xs font-bold tracking-[.12em] uppercase px-5 py-3 rounded-sm inline-flex items-center gap-2.512pxhref="/documents/{id}/edit". i18n: m.dashboard_resume_cta()
"oder anderen Brief" linkfont-sans text-xs font-semibold text-ink-2 underline decoration-[#cdcbbf] underline-offset-[4px]12pxhref="/" (to search). Not a button — no prominent treatment.
Empty stateCentered card with envelope icon, serif heading, body, CTA buttonShown when backend returns no active transcription for current user.
5 Mission Control — 3-column task queues
Segmentieren — row states
Segmentieren5 offen
Seiten zu Briefen zuordnen.
Konvolut Rose, Heft III
Mappe A·14 Seiten
AN
Umschlag Mariahilf
19. Nov 1925·3 Seiten
Mappe B — unsortiert
neu, 18. Apr·27 Seiten
Alle anzeigen →
Row with sienna tint = hover state. Filled avatar = someone has started it. Dashed circle = nobody started yet.
Transkribieren — with % progress
Transkribieren5 offen
Alte Handschriften lesen und abtippen.
Brief an Frieda aus dem Harz
14. März 1923·38%
MR
Postkarte aus Wien
2. Aug 1924·60%
OS
Geburtstagsbrief
22. Mai 1928·5%
LO
Brief aus Hamburg
3. Juni 1929
Alle anzeigen →
Percentage shown inline in metadata for in-progress items. No progress bar in rows — that would be too heavy.
Prüfen — all complete
Prüfen4 offen
Letzte Korrektur und freigeben.
Brief aus der Lehrzeit
8. Okt 1930·fertig ✓
TH
Weihnachtsgruß
21. Dez 1931·fertig ✓
MR
Geschäftsbrief Mariahilf
19. Nov 1925·fertig ✓
KL
Alle anzeigen →
Green "fertig" label when pct === 100. Still shows in queue until someone actively reviews and archives.
Implementation Reference — Mission Controllib/components/MissionControlStrip.svelte (refactor from existing)
ElementTailwind classesReal pxNotes
3-column gridgrid grid-cols-3 gap-416px gapCollapses to 1-col on mobile
Column cardbg-surface border border-line rounded-sm overflow-hidden flex flex-col
Column header — Segmentierenp-4 border-b border-[#eeede8] bg-[rgba(160,82,45,.06)]16px paddingSienna tint
Column header — Transkribierenbg-[rgba(0,199,177,.08)]Turquoise tint
Column header — Prüfenbg-[rgba(90,138,106,.08)]Sage tint
Column labelfont-sans text-[12px] font-bold tracking-[.16em] uppercase text-ink12pxi18n: m.queue_segment(), m.queue_transcribe(), m.queue_review()
Open countfont-sans text-[11px] text-ink-311px"{n} offen"
Column blurbfont-serif text-[13px] text-ink-2 leading-snug mt-1.513pxi18n keys: m.queue_segment_blurb() etc.
Task row wrapperp-1.56pxPadding around all rows within the column body.
Task row<a> flex items-center gap-3 px-3.5 py-2.5 rounded-sm hover:bg-[#f7f6f1] transition-colors no-underline14px/10px paddingEntire row is a link to the document edit page.
Task titlefont-serif text-base text-ink truncate leading-snug16pxSingle line, truncated with ellipsis.
Task metadatafont-sans text-[12px] text-ink-3 mt-0.5 flex items-center gap-212pxHint · separator · pages or % or "fertig". "fertig" = text-[#5a8a6a] font-semibold.
Starter avatar (filled)w-[22px] h-[22px] rounded-full flex-shrink-022pxUses person's color from the persons list.
Starter avatar (empty)w-[22px] h-[22px] rounded-full border-[1.5px] border-dashed border-[#cdcbbf] flex-shrink-022pxTitle attribute: "noch niemand angefangen" (tooltip).
"Alle anzeigen" footertext-center py-2.5 font-sans text-[11px] font-bold tracking-[.12em] uppercase text-ink border-t border-[#eeede8] mt-auto block11pxLinks to filtered document list for that queue.
6 Family Pulse — sidebar "Diese Woche"
Normal week
Diese Woche · gemeinsam
Ihr habt zusammen 86 Seiten bearbeitet.
Du selbst hast 4 davon transkribiert.
AN KL OS MR LO TH 6 Mitwirkende
23
Briefe transkribiert
9
Briefe geprüft
47
Seiten hochgeladen
Quiet week (low numbers)
Diese Woche · gemeinsam
Ihr habt zusammen 4 Seiten bearbeitet.
Du selbst hast 1 davon transkribiert.
AN MR 2 Mitwirkende diese Woche
2
Briefe transkribiert
0
Briefe geprüft
2
Seiten hochgeladen
Low numbers are fine — no framing around "goal". The number grows; no ceiling. Never shows 1,500 total.
Implementation Reference — Family Pulselib/components/ (new component) — DashboardFamilyPulse.svelte
ElementTailwind classesReal pxNotes
Cardbg-surface border border-line shadow-sm rounded-sm p-624px paddingWhite card — intentionally same as other sidebar cards (no warm cream — confirmed decision).
Eyebrowfont-sans text-[11px] font-bold tracking-[.18em] uppercase text-ink-3 mb-211pxi18n: m.pulse_eyebrow() = "Diese Woche · gemeinsam"
Headlinefont-serif text-[22px] font-normal leading-snug text-ink mb-122pxi18n: m.pulse_headline({ pages }). Strong tag on the number: font-semibold.
Personal contributionfont-serif text-[14px] text-ink-3 mb-414pxi18n: m.pulse_you({ pages }). Hidden when current user's contribution = 0.
Avatar stackinline-flex items-center with -ml-2 on all except first28px avatars, -8px overlapShows contributors who participated this week. ring-2 ring-white on each.
Contributor countfont-sans text-xs text-ink-3 ml-312px"{n} Mitwirkende"
3-stat gridgrid grid-cols-3 gap-2.5 mt-410px gap, 16px top margin
Stat cardbg-[#faf9f4] border border-[#eeede8] rounded-sm p-3.514px padding
Big numberfont-serif text-[30px] font-normal text-ink leading-none flex items-baseline gap-230pxDot: w-1.5 h-1.5 rounded-full flex-shrink-0 in kind color.
Stat labelfont-sans text-[12px] text-ink-3 mt-1.512pxi18n: m.pulse_transcribed(), m.pulse_reviewed(), m.pulse_uploaded()
Data sourceNew backend endpoint: GET /api/dashboard/pulse?period=week. Returns { transcribed, reviewed, uploaded, pages, you: { pages }, contributors: Person[] }.
7 Activity feed & sidebar dropzone
Activity feed
Kommentare & AktivitätAlle
AN
Anna hat transkribiert Postkarte aus Wien
vor 12 Min.
KL
Klaus hat dich erwähnt in Brief an Friedafür dich
vor 1 Std.
LO
Lotte hat geantwortet auf deinem Kommentarfür dich
gestern
Tinted dot = activity kind (turquoise = transcribe, pink = mention, purple = reply, sienna = segment, blue = upload). "für dich" badge on @mentions and replies.
Dropzone — idle
Hochladen
Neue Scans hochladen
Hierher ziehen oder klicken
PDF, JPG, PNG bis 50 MB
Dropzone — drag active
Hochladen
Loslassen zum Hochladen
PDF, JPG, PNG bis 50 MB
Drag-over: navy border, mint tint bg, title changes to "Loslassen zum Hochladen".
Implementation Reference — Activity feed & dropzoneroutes/+page.svelte (new feed) + routes/DropZone.svelte (existing, minor tweaks)
ElementTailwind classesReal pxNotes
Feed card wrapperbg-surface border border-line shadow-sm rounded-sm p-520px padding
Feed itemflex gap-3.5 items-start py-3.5 border-b border-[#eeede8] last:border-b-014px padding, 14px gap
Feed avatarw-9 h-9 rounded-full flex-shrink-036pxColor from person's color field.
Feed textfont-serif text-[15px] leading-snug text-ink15pxName: font-sans text-[13px] font-bold. Verb: text-ink-2. Target: link text-ink underline underline-offset-[2px].
"für dich" badgeml-2 inline-block px-2 py-px border border-accent rounded-full font-sans text-[10px] font-bold tracking-[.12em] uppercase text-ink bg-accent/20 align-middle10pxOnly shown when activity.you === true (mention or reply to current user).
Timestamp rowmt-1 inline-flex items-center gap-2 font-sans text-[11px] text-ink-311pxKind dot: w-1.5 h-1.5 rounded-full in kind color (see dot-color map below).
Kind → dot colortranscribe: #00c7b1 · segment: #a0522d · review: #5a8a6a · upload: #3060b0 · mention: #c0446e · reply: #7a4f9a · tag: #c17a00Purely decorative — color-blind safe because avatar + name already identify the person and action.
Dropzone — idleflex flex-col items-center gap-2.5 py-6 px-4 border border-dashed border-ink/30 rounded-sm text-center transition-allAlready implemented in DropZone.svelte. Already existing; verify styles match.
Dropzone — drag active+ border-ink bg-accent/18Title changes to m.dropzone_release().
Data source — feedNew endpoint: GET /api/dashboard/activity?limit=7. Returns recent actions across all document activity for the archive.
8 Implementation notes — backend, i18n, data model
New backend endpoints
GET /api/dashboard/*
EndpointResponseNotes
GET /api/dashboard/resume{ document, page, pages, pct, collaborators: Person[] }The current user's last-touched in-progress transcription. Returns null when none.
GET /api/dashboard/pulse?period=week{ transcribed, reviewed, uploaded, pages, you: { pages, comments }, contributors: Person[] }Aggregate stats for the current ISO week. Never exposes cumulative total.
GET /api/dashboard/activity?limit=7Activity[]{ who: Person, verb, target, targetId, when, kind, youMentioned }Recent archive-wide activity, newest first. youMentioned=true when activity targets the current user.
Existing endpoints used
EndpointUsed for
GET /api/documents?status=UPLOADED&transcriptionPct=0..99&sort=DATE&limit=5Transkribieren queue
GET /api/documents?status=PLACEHOLDER&limit=5Segmentieren queue
GET /api/documents?status=TRANSCRIBED&limit=5Prüfen queue
GET /api/documents?q=&sort=DATE&dir=descSearch bar (unchanged)
New i18n keys
messages/de.json additions
KeyDE
greeting_morningGuten Morgen, {name}.
greeting_dayHallo, {name}.
greeting_eveningGuten Abend, {name}.
dashboard_resume_labelWeiter, wo du aufgehört hast
dashboard_page_ofSeite {page} von {pages}
dashboard_resume_ctaWeitertranskribieren
dashboard_resume_otheroder anderen Brief wählen
dashboard_empty_titleWo möchtest du anfangen?
dashboard_empty_bodyWähle einen Brief aus einer Warteschlange unten oder durchsuche das Archiv.
dashboard_mission_captionMitmachen
queue_segmentSegmentieren
queue_segment_blurbSeiten zu Briefen zuordnen.
queue_transcribeTranskribieren
queue_transcribe_blurbAlte Handschriften lesen und abtippen.
queue_reviewPrüfen
queue_review_blurbLetzte Korrektur und freigeben.
queue_n_open{n} offen
queue_show_allAlle anzeigen →
pulse_eyebrowDiese Woche · gemeinsam
pulse_headlineIhr habt zusammen {pages} Seiten bearbeitet.
pulse_youDu selbst hast {pages} davon transkribiert.
pulse_contributors{n} Mitwirkende
pulse_transcribedBriefe transkribiert
pulse_reviewedBriefe geprüft
pulse_uploadedSeiten hochgeladen
feed_captionKommentare & Aktivität
feed_for_youfür dich
dropzone_releaseLoslassen zum Hochladen
Implementation sequence:
  • 1. Add GET /api/dashboard/resume, /pulse, /activity endpoints to Spring Boot
  • 2. Regenerate TypeScript types (npm run generate:api)
  • 3. Update routes/+page.server.ts to load all dashboard data in parallel
  • 4. Refactor DashboardResumeStrip.svelte — add thumb, caption, pull-quote, progress bar, new CTAs
  • 5. Refactor MissionControlStrip.svelte — 3-col grid, TaskRow with avatar-of-starter, accent headers
  • 6. Create DashboardFamilyPulse.svelte (new)
  • 7. Create DashboardActivityFeed.svelte (new) — replaces DashboardRecentDocuments
  • 8. Add greeting headline + subtitle to +page.svelte
  • 9. Add Upload button to +layout.svelte header
  • 10. Add all i18n keys to de/en/es message files