Ein neuer Widget-Typ war an sieben Stellen einzutragen; vergass man eine,
fehlte die Kachel im Katalog oder die API lehnte sie mit 400 ab.
- WIDGET_TYPES/WidgetType/WIDGET_MODULE_SLUGS stehen jetzt einmal in
packages/shared; Registry, Katalog und die @IsIn-Whitelist der API
leiten davon ab
- neun wireXWidget()-Funktionen durch ein generisches registerWidget()
ersetzt (idempotent, unbekannter Typ wirft in der Entwicklung)
- der Katalog fuehrt keine zweite Typliste mehr, sondern leitet sie aus
der Registry ab und filtert nach Modulzugriff (fail-closed, wenn die
Modulliste unbekannt ist); der Abruf von /modules/active liegt auf der
Dashboard-Seite, nicht im Dialog
- widget-module-map.ts liest die geteilte Tabelle statt einer Kopie, die
oeffentliche Funktion bleibt unveraendert
Der Katalogfilter ist Komfort (T-M1H-01) — verbindlich bleibt der
serverseitige Filter in DashboardService.getWidgets.
Abweichung vom Plan: apps/web hing entgegen der Planannahme noch nicht
von @tessera/shared ab; die Abhaengigkeit wurde ergaenzt (Lockfile). Die
Dockerfiles kopieren packages/shared bereits, der Produktionsbau von
Next.js und der nest build laufen unveraendert.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Knopf (Kaefer-Symbol) unmittelbar vor dem Erscheinungsbild-Schalter; captureScreenshot() laeuft VOR dem Oeffnen, Test pinnt es im toPng-Mock
- computeCaptureSize (laengste Kante 1600 px, reine Funktion, getestet), dataUrlToBlob, sendBugReport als Multipart mit credentials und ohne Content-Type-Header
- error-buffer: Ringpuffer 20, window error/unhandledrejection, console.error (Original bleibt), fetch-Wrapper nur bei !ok ohne Anfrage-Rumpf/Suchteil/Kopfzeilen (T-M97-02), idempotent, SSR-sicher; installiert in app-shell
- Dialog mit Vorschau, Haekchen, Beschreibung, Meldungen je Status 409/413/429/502/allgemein, Admin-Link auf /admin/smtp
- i18n bugReport de/en, Allowlist um "passiert"; html-to-image exakt 1.11.13, Lockfile aktualisiert
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018N9CD3ebPKm1b32bPpBknY
- SearchWidget: provider dropdown, text input, button; opens search in new tab via window.open (D-14/D-15)
- NoteWidget: MDEditor with compact toolbar, debounced autosave (1500ms), AbortController for in-flight cancellation (D-16/D-17/D-18)
- rehype-sanitize enabled for Markdown XSS prevention (T-05-05)
- Widget registry updated with wireSearchWidget/wireNoteWidget (no more placeholders)
- dashboard-api.ts: added fetchSearchProviders, addSearchProvider, removeSearchProvider, signal support on updateWidgetConfig
- 9 new tests passing (search: 5, note: 4)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Install react-grid-layout@2.2.3 and react-resizable
- Create widget-registry.tsx with all 4 widget types, WIDGET_CONSTRAINTS, WidgetProps
- Create dashboard-api.ts with fetch/save layout and widget CRUD functions
- Create dashboard-store.ts (Zustand, NO persist — D-05) with edit mode and auto-save on exit
- Create DashboardGrid with react-grid-layout v2 Responsive, ResizeObserver width
- Create ClockWidget using Intl.DateTimeFormat (no manual UTC offsets)
- Create WidgetWrapper with drag handle and delete button in edit mode
- Create EditModeToggle (pencil/checkmark), WidgetCatalogModal (2x2 grid)
- Rewrite portal page.tsx as dashboard with grid, edit toggle, widget catalog
- Add ResizeObserver polyfill in test setup, CSS mock support in vitest config
- All 5 tests green (dashboard grid + clock widget)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add vitest, @testing-library/react, @testing-library/jest-dom, jsdom, @vitejs/plugin-react as dev deps
- Create vitest.config.ts with jsdom environment and @ path alias
- Create test setup file importing jest-dom/vitest matchers
- Add test scripts to apps/web and root package.json
- Add test task to turbo.json pipeline
- Create (auth) route group with standalone layout (no sidebar/header, D-04)
- Create (portal) route group wrapping children with AppShell
- Move dashboard page into (portal) route group
- Add Next.js middleware for JWT-based route protection using jose
- Create session.ts with verifySession/getSessionFromCookies helpers
- Create auth-actions.ts server actions: login, logout, fetchCurrentUser
- Create Zustand auth-store for client-side user state
- Install jose and zod dependencies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- OKLCH design tokens with yellow #ffed00 primary and dark gray-blue dark mode
- next-intl cookie-based locale with DE/EN message files
- next-themes provider with system/light/dark support
- Sidebar and header layout dimension tokens
- Root layout with ThemeProvider and NextIntlClientProvider wrappers
- Next.js 15 app with Tailwind CSS v4, standalone output for Docker
- Root layout with de locale, page with Tessera placeholder
- Multi-stage Dockerfile for web with monorepo root context
- Docker Compose with 4 services: traefik, web, api, db
- Three segregated networks: frontend-net, backend-net, data-net (internal)
- Traefik v2.11 reverse proxy routing / to web, /api to api
- API strip prefix middleware for clean routing
- PostgreSQL 16-alpine with health checks and named volume
- Fixed API Dockerfile for pnpm monorepo node_modules structure
- Fixed Next.js standalone path for monorepo (apps/web/server.js)
- Fixed Traefik Docker API version compatibility
- Network segmentation: web NOT on data-net, api NOT on frontend-net