# Admin Section — Concept C Specification

Complete screen spec for the Master-Detail Command Center redesign. Covers all four entity types (Users, Groups, Tags, System) across every state: default, create, edit, delete confirmation, empty, and error. Desktop (1440px) and mobile (375px) flows for each entity. Includes a tablet addendum (sections A–D) covering the collapseable 768–1023px panel layout.

Leonie Voss · Familienarchiv Admin Spec · v1.1 · 2026-03
0
Architecture
Panel Anatomy & Navigation Model
Three persistent panels on desktop. Stacked push-navigation on mobile. All state lives in URL query params.
Desktop panel anatomy ≥1024px
ENTITY NAV · 120px
Admin
4
Users
3
Groups
3
Tags
System
LIST PANEL · 240px
All Users
+ New
🔍 Search…
reader
Leser
›
marcel
Marcel Raddatz
›
berit
Berit Cram
›
admin
Administrators
›
DETAIL PANEL · flex (all remaining width)
Edit user: reader
Last modified 2026-03-27 · Leser group
Delete…
Personal info
First name
Last name
Email address
Breakpoint behaviour

Viewport | Layout | Entity Nav
--- | --- | ---
`≥1024px` | 3 panels side-by-side | Always visible (left)
`768–1023px` | List + Detail (2 panels) | Collapsed to icon-strip top bar
`<768px` | Full-screen per step | Step 1 full-screen

URL scheme (SvelteKit query params)

State | URL
--- | ---
Admin landing | `/admin`
Users list | `/admin?v=users`
Create new user | `/admin?v=users&id=new`
Edit user | `/admin?v=users&id=<uuid>`
Groups / create | `/admin?v=groups&id=new`
Tags / edit tag | `/admin?v=tags&id=<uuid>`
System | `/admin?v=system`

🏗 Key architectural decisions

- URL params make every admin state shareable and browser-back navigable — no lost context on refresh
- Entity nav uses count badges loaded from the same server load as the page — no extra requests
- Detail panel save bar is docked to the detail panel only — not full-width — so it doesn't cover the list on wide screens
- On mobile, each panel is full-screen; `goto()` pushes the next step; the browser back button pops it
- SvelteKit: `+page.svelte` reads `$page.url.searchParams` for `v` and `id`; server load pre-fetches the selected entity

1
Entity: Users
User Management
Four states: empty selection, create new, edit existing, delete confirmation. Users navigate to /admin/users/[id] in the current design — in the new design this all happens within /admin.
1a — Users selected, no item chosen 1440px Empty selection
/admin?v=users
Admin
4
Users
3
Groups
3
Tags
System
All Users
+ New
🔍 Search users…
reader
Leser
›
marcel
Marcel Raddatz
›
berit
Berit Cram
›
admin
Administrators
›
👤
Select a user to view and edit their details,
or create a new user with the button above.
No item pre-selected on first load — prompt guides user to the next action
1b — Create new user 1440px New
/admin?v=users&id=new
Admin
4
Users
3
Groups
3
Tags
System
All Users
+ New
🔍 Search…
+ New user
Unsaved
›
reader
Leser
›
marcel
Marcel Raddatz
›
Create new user
Fill in credentials and personal info below
Credentials * required
Login / Username *
Password *
Personal information
First name
Last name
Date of birth
DD.MM.YYYY
Email address
Contact details
Groups
Leser
Administrators
Editor
"+ New user" placeholder appears at top of list · Detail panel has green tint to signal create mode
1c — Edit existing user 1440px Edit
/admin?v=users&id=a1b2c3…
Admin
4
Users
3
Groups
3
Tags
System
All Users
+ New
🔍 Search…
reader
Leser
›
marcel
Marcel Raddatz
›
berit
Berit Cram
›
admin
›
Edit user: marcel
Created 2025-01-12 · Editor group · last login 2026-03-28
Delete…
Credentials
Login (username)
marcel — cannot be changed
Personal information
First name
Marcel
Last name
Raddatz
Date of birth
Email address
m.raddatz@example.com
Contact details
Groups
Leser
Administrators
Editor
Change password
New password
Repeat new password
Username is read-only in edit mode · Password fields optional · Delete button top-right of detail header
1d — Delete confirmation (inline danger zone) 1440px Delete
/admin?v=users&id=a1b2c3… — same URL, detail panel reveals danger zone
Admin
4
Users
3
Groups
All Users
+ New
marcel
Pending delete…
›
reader
berit
⚠ Delete user: marcel
This action cannot be undone
✕ Cancel
🗑 Permanently delete "marcel"
This user will be permanently removed. Their name may still appear on historical document records as sender or recipient, but they will no longer be able to log in.
Type the username to confirm: marcel
marcel
Cancel
Permanently delete user
Clicking "Delete…" in the detail header replaces the form with the danger zone · User must type the username to confirm · List item shows "Pending delete…" state
1e — Mobile navigation flow 375px
Step 1 · Entity picker
Manage
Users
4 accounts
›
Groups
3 groups
›
Tags
3 tags
›
System
›
›
Step 2 · User list
‹
Users
+ New
🔍 Search users…
reader
Leser
›
marcel
Marcel Raddatz
›
berit
Berit Cram
›
admin
Administrators
›
›
Step 3 · User detail
‹
Edit: marcel
Delete
Personal
First name
Marcel
Last name
Raddatz
Email
Groups
Leser
Administrators
Editor
Cancel
Save changes
Spec — Users entity
1.1 · Login field
Username is required on create. On edit it is displayed as a read-only chip — username changes are not allowed without an explicit admin reset flow.
1.2 · After create
On success: list refreshes, new user appears alphabetically sorted, detail panel switches to edit mode for that user. URL updates to ?v=users&id=<new-uuid>.
1.3 · After save
List item subtitle updates immediately. Save bar shows brief "Saved ✓" confirmation text for 2 seconds, then reverts to "Discard / Save changes".
1.4 · Delete confirmation
User must type the exact username to enable the confirm button. Username match is case-sensitive. After deletion: list removes item, detail shows empty-selection prompt, URL resets to ?v=users.
1.5 · Unsaved changes guard
If user clicks another list item while there are unsaved changes, show an inline warning banner at top of detail panel: "You have unsaved changes — save or discard before switching."
1.6 · Password on edit
Both "New password" fields are optional. If one is filled and the other is empty, show validation error inline before allowing save.
2
Entity: Groups
Permission Groups
Groups define what users can do. The permission matrix (5 checkboxes) is the core of the edit form. ADMIN permission is visually distinguished from safe permissions.
2a — Create new group 1440px New
/admin?v=groups&id=new
Admin
4
Users
3
Groups
3
Tags
System
All Groups
+ New
+ New group
Unsaved
›
Leser
1 permission
›
Administrators
6 permissions
›
Editor
2 permissions
›
Create new group
Define a name and assign permissions
Group name * required
Name
Permissions
Standard access
READ_ALL — read documents
WRITE_ALL — create & edit docs
ANNOTATE_ALL — add annotations
⚙ Administrative (grant carefully)
ADMIN — full admin access
ADMIN_USER — manage users
ADMIN_TAG — manage tags
ADMIN_PERMISSION — manage perms
Permissions split into "Standard" and "Administrative" sections · Admin perms shown in red with ⚙ icon
2b — Edit group: Administrators 1440px Edit
/admin?v=groups&id=b2c3d4…
Admin
4
Users
3
Groups
3
Tags
System
All Groups
+ New
Leser
1 permission · 1 user
›
Administrators
6 permissions · 1 user
›
Editor
2 permissions · 2 users
›
Edit group: Administrators
1 user in this group · 6 permissions assigned
Delete…
Group name
Name
Administrators
Standard permissions
READ_ALL
WRITE_ALL
ANNOTATE_ALL
⚙ Administrative permissions
ADMIN
ADMIN_USER
ADMIN_TAG
ADMIN_PERMISSION
Members
admin ✕
Admin permissions shown in a red-tinted box · Members shown as removable chips · Subtitle shows counts
2c — Mobile flow 375px
Group list
‹
Groups
+ New
Leser
1 permission
›
Administrators
6 permissions
›
Editor
2 permissions
›
›
Group detail
‹
Administrators
Del
Group name
Administrators
Standard
READ_ALL
WRITE_ALL
⚙ Administrative
ADMIN
ADMIN_USER
Discard
Save
3
Entity: Tags
Tag Management
Tags are simple (name only) but high-impact — renaming or deleting affects all linked documents. The detail panel shows the document count prominently and requires an explicit confirmation for destructive changes.
3a — Tag detail (rename) 1440px Edit
/admin?v=tags&id=c3d4e5…
Admin
4
Users
3
Groups
3
Tags
System
All Tags
+ New
🔍 Filter tags…
Familie
34 documents
›
Krieg
12 documents
›
Urlaub
7 documents
›
Edit tag: Krieg
Used in 12 documents
Delete…
Tag name
Name *
Krieg
⚠ Renaming this tag will update all 12 linked documents. The old name will no longer appear anywhere in the archive.
Usage
12
Documents
This tag is attached to 12 documents. You can browse them by going to Documents and filtering by this tag.
Danger zone
🗑 Delete this tag
Removes the tag from all 12 documents. Documents are not deleted — only the tag association is removed.
Delete tag…
Document count shown in list subtitle AND in detail usage card · Rename warning banner prominently above save bar
3b — Delete confirmation 1440px Delete
/admin?v=tags&id=c3d4e5… — detail panel shows danger confirmation
Admin
4
Users
3
Groups
3
Tags
System
All Tags
+ New
🔍 Filter tags…
Familie
34 documents
›
Krieg
Pending delete…
›
Urlaub
7 documents
›
⚠ Delete tag: Krieg
Used in 12 documents — this cannot be undone
✕ Cancel
🗑 Permanently delete tag "Krieg"
This will remove the "Krieg" tag from 12 documents. The documents themselves will not be affected — only the tag association will be removed.
The documents will still be searchable, but this tag will no longer appear as a filter option.
Type the tag name to confirm: Krieg
Krieg
Cancel
Delete tag and remove from 12 documents
Document count is prominently in the confirm button label — "Remove from 12 documents" — so impact is impossible to miss
3c — Create new tag (minimal form) 1440px New
/admin?v=tags&id=new
Admin
4
Users
3
Groups
3
Tags
All Tags
+ New
+ New tag
Unsaved
›
Familie
34 docs
›
Krieg
12 docs
›
Create new tag
Tag name
Name *
The tag will be immediately available for use on documents.
Tags are name-only — the create form is deliberately minimal. No over-engineering.
4
Entity: System
System Maintenance Actions
No list panel for System — the entity nav goes directly to the detail panel (single-panel mode). Destructive / intensive operations use an inline expand-to-confirm pattern. async operations show inline progress and result.
4a — System panel (idle state) 1440px
/admin?v=system
Admin
4
Users
3
Groups
3
Tags
System
System Maintenance
Run these operations carefully. They affect data across the entire archive.
Backfill history data MAINTENANCE
Creates an initial history entry for all documents that do not have one yet (e.g. imported documents). Safe to run multiple times — already-backfilled documents are skipped.
Backfill history…
Compute file hashes INTENSIVE
Computes SHA-256 hashes for all uploaded documents that do not have one yet. CPU-intensive — recommend running during off-peak hours. Correctly links annotations to file versions.
Compute file hashes…
System uses full-width content area (no list panel) · Each card styled by severity · "…" suffix on buttons signals "click to expand confirm"
4b — Backfill confirming · Hashes in progress 1440px
/admin?v=system
Admin
4
Users
3
Groups
3
Tags
System
System Maintenance
Backfill history data MAINTENANCE
Creates an initial history entry for all documents without one.
⚠ This will modify history records for documents that are missing an entry. Continue?
Cancel
Yes, run backfill now
Compute file hashes RUNNING…
Computing SHA-256 for all documents without a hash.
Processing… (this may take a few minutes)
Backfill: "Backfill now" expands inline confirm · Hash computation: button replaced by progress bar + spinner · Both operations non-blocking (page stays usable)
4c — Post-completion success state 1440px
Admin
4
Users
System
Backfill history data DONE
Already completed. Run again if new imports have been added since last run.
✓ Backfill complete — 43 documents received a history entry.
Run again…
Success banner replaces the confirm block · Shows count of affected records · "Run again" button available
5
Edge Cases
Empty, Error, and Unsaved-Change States
Every state that can occur outside the happy path — including empty lists, save errors, API failures, and navigation guards for unsaved changes.
5a — Empty list state Empty
Admin
0
Users
All Users
+ New
No users yet.
Create the first one →
👥
No users have been created yet.
Click + New to add the first user.
Empty list shows copy in both LP and DP · Count in entity nav shows 0
5b — Unsaved changes warning Guard
Admin
4
Users
All Users
● marcel
Unsaved changes
berit
Edit user: marcel
⚠ You have unsaved changes.
Save or discard before selecting a different user.
Discard changes
Save now
List item shows amber dot + "Unsaved changes" · Clicking another item triggers the inline warning (not a modal)
5c — API / save error Error
Admin
4
Users
All Users
marcel
Edit user: marcel
✕ Save failed. The server returned an error: Email address is already in use by another account.
Your changes are preserved — correct the error and try again.
Email address
duplicate@example.com
This email is already registered to another user.
Error shown inline at top of form + on the specific field · Changes are NOT lost · Save bar button changes to "Retry save"
Tablet Addendum — 768–1023px
The three-panel layout at 768px leaves the detail panel with ~408px — too cramped for a form. This addendum introduces collapseable panels: the entity nav shrinks to a 48px icon strip, and the list panel gets a one-click collapse toggle. Three states (A, B, C) plus an implementation spec (D) are defined below.
0
Problem
Space budget at 768px
Why the original spec fails at tablet width and how the three states solve it.
Before — original spec
Entity
Nav
120px
List
Panel
240px
Detail
408px ✗
360px eaten by navigation — barely enough room for a single-column form
After — reworked tablet (default state)
Icons
48px
List
Panel
200px
Detail
520px ✓
248px saved — enough for a comfortable two-column form layout

State | Entity Nav | List Panel | Detail Panel | Triggered by
--- | --- | --- | --- | ---
A · Default | 48px icon strip | 200px visible | 520px | Page load / switching entity
B · List hidden | 48px icon strip | 32px collapsed handle | 688px | Tapping ‹ in list header
C · Entity flyout | 48px strip + 160px flyout overlay | Dimmed behind flyout | Dimmed behind flyout | Tapping any entity icon

A → B
→
User clicks the ‹ collapse button in the list header. List panel slides to 32px collapsed handle. Detail panel expands to fill the freed space. Animation: 200ms ease-out slide.
B → A
→
User clicks the › expand handle on the left edge of the detail panel. List panel slides back to 200px. This restores the browsable list view.
A/B → C
→
User taps any entity icon in the 48px strip. A 160px flyout slides in from the left, overlapping the list/detail panels. Tapping an entity in the flyout navigates and dismisses. Tapping outside dismisses without navigating.
C → A/B
→
Flyout dismisses (slides out) after entity selection, or on tap-outside. Returns to previous state (A or B).
A
State A
Default — Icon strip + List + Detail
The landing state for all tablet sessions. Entity nav collapses from 120px text labels to 48px icon-only strip with count badges. List panel stays visible at 200px. Detail gets 520px — enough for a two-column form.
State A — Users: editing a user 768px Default
4
Users
3
3
Users
+ New
‹
🔍 Search…
reader
Leser
›
marcel
Marcel Raddatz
›
berit
Berit Cram
›
admin
Admins
›
Edit user: marcel
Marcel Raddatz · Editor group
Delete…
Personal info
First name
Marcel
Last name
Raddatz
Date of birth
Email address
m.raddatz@example.com
Contact details
Groups
Leser
Administrators
Editor
Change password
New password
Repeat
Entity nav shrinks from 120px → 48px (icon + count only) · ‹ collapse button visible in list header top-right · Two-column form layout fits comfortably in 520px detail · Tooltip appears on icon hover showing entity name
State A — Tags list view 768px Default
4
3
3
Tags
+ New
‹
🔍 Filter tags…
Familie
34 documents
›
Krieg
12 documents
›
Urlaub
7 documents
›
Edit tag: Krieg
Used in 12 documents
Delete…
Tag name
Name
Krieg
⚠ Renaming affects all 12 linked documents.
Tags panel: list fits compactly at 200px, detail has generous space for the rename form + warning
B
State B
List Collapsed — Maximum Detail Space
User clicks ‹ to collapse the list panel. It slides to a 32px narrow handle showing a › expand button and the rotated entity name. Detail panel grows to 688px — ideal for forms with many fields or when reading long content.
State B — Groups: editing permissions (list collapsed) 768px List collapsed
4
3
3
›
Groups
Edit group: Administrators
1 user · 6 permissions · last modified 2026-03-01
Delete…
Group name
Name
Administrators
Standard permissions
READ_ALL
WRITE_ALL
ANNOTATE_ALL
⚙ Administrative permissions
ADMIN
ADMIN_USER
ADMIN_TAG
ADMIN_PERMISSION
Members
admin ✕
List collapsed to 32px handle showing › expand button + "Groups" label rotated · Detail grows to 688px — permissions all fit in one row with breathing room · The entity strip stays visible for entity switching
State B — Users: creating a new user (list collapsed) 768px List collapsed
4
3
3
›
Users
Create new user
Fill in the details below
Credentials
Login / Username *
Password *
Personal info
First name
Last name
Date of birth
Email
Groups
Leser
Administrators
Editor
Auto-collapse: when user clicks "+ New", the list panel auto-collapses to give maximum space for the create form · User can tap › to restore the list at any time
C
State C
Entity Flyout — Temporary Navigation Overlay
Tapping any entity icon in the 48px strip slides out a 160px labeled flyout. It sits above the list and detail panels (which dim behind it). Tapping an entity navigates and auto-dismisses. Tapping outside dismisses without navigating.
State C — Entity flyout open (Groups icon tapped) 768px Flyout open
4
3
3
Users
reader
marcel
berit
Edit user: marcel
Navigate
✕
Users
4
Groups
3
Tags
3
System
160px flyout slides in from the left over the list panel · Full entity names + counts visible · Active entity (Groups) highlighted · Tap outside (dimmed area) dismisses without navigating · ✕ close button in header · List/detail dimmed to 55% to signal non-interactable state
State C — Flyout open while list is collapsed 768px Flyout + collapsed list
4
3
3
›
Edit user: marcel
Navigate
✕
Users
4
Groups
3
Tags
3
System
Flyout works identically whether list is expanded or collapsed — it always overlays from the left edge at 48px
D
Implementation
Interaction & Implementation Spec
Exact behaviour, animation timings, and SvelteKit implementation notes for each panel behaviour.
Tablet panel behaviour spec
D.1 · Entity strip — icon resolution
Each entity icon is a recognisable SVG: 👤 Users, 🔐 Groups, 🏷 Tags, ⚙ System. At 20×20px, use outline-style icons (Heroicons or Lucide). Count badge below icon, not overlapping. Tooltip on hover: `title` attribute is sufficient (no custom tooltip needed).
D.2 · List panel — collapse animation
CSS transition: `width 200ms ease-out` on `.LP`. Collapsed width: 32px. The inner content (`overflow: hidden`) disappears as the panel shrinks. The handle (`.LP-handle`) is a sibling element that becomes visible via `display: flex` when state is collapsed.
D.3 · List panel — auto-collapse on create
When user clicks "+ New", automatically collapse the list panel (set `listCollapsed = true` in Svelte state) to give the create form maximum space. Restore list when user navigates away from the create form or saves.
D.4 · Collapse state — persistence
Store collapse state in `localStorage` under key `admin_list_collapsed`. Restore on next visit. Do not persist across breakpoints — desktop always shows full panels regardless of tablet collapse state.
D.5 · Entity flyout — open/close
Flyout triggered by tapping any entity icon in the strip. CSS transition: `transform: translateX(-160px) → translateX(0)`, duration 180ms ease-out. Dim overlay: `background: rgba(0,0,0,.3)`, fade in 150ms. Tapping overlay or pressing Escape closes flyout.
D.6 · Entity flyout — after selection
After tapping an entity in the flyout: 1) update URL (`goto('/admin?v=groups')`), 2) close flyout immediately (no wait for navigation), 3) list panel loads new entity's items. If selected entity is already active, just dismiss.
D.7 · Breakpoint detection
Use a Svelte store: `isTablet = $derived(windowWidth >= 768 && windowWidth < 1024)`. On desktop (≥1024px) the entity nav always renders at full 120px with labels — the icon strip is tablet-only. On mobile (<768px) both panels are hidden and navigation is handled by push-routing.
D.8 · Accessibility
‹ collapse button: `aria-label="Collapse list panel"`, `aria-expanded` attribute toggles. Flyout: `role="dialog"`, `aria-modal="true"`, focus trapped inside while open. Flyout close button: `aria-label="Close navigation"`. Entity icons: `aria-label="Users (4 items)"`.
Updated breakpoint specification

Viewport | Entity nav | List panel | Detail panel | Notes
--- | --- | --- | --- | ---
`<768px` Mobile | Full-screen step 1 | Full-screen step 2 | Full-screen step 3 | Push navigation, browser back to go up
`768–1023px` Tablet | 48px icon strip (always) + 160px flyout on tap | 200px default 32px when collapsed | 520px default 688px when list collapsed | ‹ toggle in list header · state persisted to localStorage
`≥1024px` Desktop | 120px with text labels | 240px, always visible | All remaining width | No collapse functionality — all panels always visible

🏗 Design decisions for tablet

- 48px icon strip was chosen over a full collapse (0px) because completely removing the entity nav creates orientation loss — users no longer know which entity they're in without looking at the list header
- 32px collapsed list handle was chosen over 0px for the same reason — the rotated label + expand button makes the list recoverable without hunting for a menu
- Flyout overlays (not pushes) the list panel so the detail panel position doesn't jump during navigation — the user's current edit context is not disturbed
- Auto-collapse on "+ New" is an affordance designed for tablet: the most common reason to want more space is filling a form, which happens on create
- localStorage persistence means a user who prefers collapsed list doesn't have to collapse it every session

Interaction Specification — All Entities

Trigger | Entity | Behaviour | URL change
--- | --- | --- | ---
Click entity in nav | Any | Load list panel, clear detail, set list title | `?v=users`
Click list item | Any | Load detail panel for that item; highlight item in list | `?v=users&id=uuid`
Click "+ New" | Any | Add unsaved placeholder at top of list; open blank create form in detail | `?v=users&id=new`
Submit create form (success) | Any | List refreshes; new item highlighted; detail switches to edit mode | `?v=users&id=new-uuid`
Submit edit form (success) | Any | List subtitle updates; "Saved ✓" flashes in footer for 2s | Unchanged
Submit form (error) | Any | Inline error banner + field-level errors; changes preserved; button → "Retry save" | Unchanged
Click "Delete…" header button | Users, Groups, Tags | Detail panel switches to danger zone; list item turns red | Unchanged
Confirm delete (success) | Any | Item removed from list; detail → empty-selection state; count in entity nav decrements | `?v=users`
Click different list item (dirty form) | Any | Inline warning in detail: "Save or discard first"; block navigation | Unchanged
Click "Discard changes" | Any | Form resets to last saved values; unsaved indicator cleared | Unchanged
Click System in entity nav | System | List panel hidden; detail fills remaining width with maintenance cards | `?v=system`
Click "Action…" (System) | System | Inline confirm card expands below the button | Unchanged
Confirm system action | System | Button replaced by spinner + progress; on done: success banner with affected count | Unchanged
Browser back (mobile) | Any | Pop one step: detail → list → entity picker | URL pops one param
Direct URL load with params | Any | Server pre-fetches entity + item; renders correct panel state on first paint | Preserves URL