Align all 20 web app auth stores to a consistent pattern:
- Use DEV_* constants with import.meta.env.DEV guard (no localhost leak in prod)
- Pass backendUrl to initializeWebAuth for automatic 401 token refresh
- Add redirectTo to forgotPassword for correct post-reset redirect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The browser error tracking hooks.client.ts added earlier requires the
shared-error-tracking package to be copied and built in the Docker image.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @sentry/browser integration via shared-error-tracking/browser export
and hooks.client.ts in every web app for client-side error reporting to GlitchTip.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create Analytics.astro component in @manacore/shared-landing-ui that
automatically tracks CTA clicks and pricing section views via Umami.
The component uses event delegation and auto-detection of section
context (hero/pricing/footer) from section IDs or DOM position,
requiring zero changes to existing landing page content.
Tracked events: cta_click (with location), pricing_viewed,
pricing_plan_selected (with plan name)
Added to all 10 landing page Layout.astro files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded Umami website IDs in all 10 Astro landing pages with
import.meta.env.PUBLIC_UMAMI_WEBSITE_ID, following the same pattern
as the web apps.
- Add UMAMI_WEBSITE_ID_*_LANDING vars for all 10 landings in .env.development
- Add landing page configs to generate-env.mjs
- Replace hardcoded IDs with env var in 7 existing Layout.astro files
- Add Umami tracking to 3 missing landings (NutriPhi, Presi, Mukke)
- Fix Todo Landing invalid ID ("todo-landing" -> proper UUID)
- Update ANALYTICS.md with new landing page IDs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create @manacore/shared-utils/security-headers with setSecurityHeaders()
utility that sets standard security headers (CSP, X-Frame-Options,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy).
CSP includes stats.mana.how (Umami) and glitchtip.mana.how by default.
Each app passes its own connectSrc origins (auth URL, backend URL, etc.).
Previously only Calendar and Storage had CSP headers - now all 17 web
apps have consistent security headers via the shared utility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The production domain is mana.how, not manacore.app. Updated all
references across shared-branding APP_URLS, app configs, landing pages,
docs, help content, calendar iCal UIDs, and deploy scripts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move Umami analytics from hardcoded script tags in app.html to
server-side injection via hooks.server.ts. Website IDs are now
managed centrally in .env.development and distributed via
generate-env.mjs as PUBLIC_UMAMI_WEBSITE_ID.
- Add @manacore/shared-utils/analytics-server with injectUmamiAnalytics()
- Add UMAMI_WEBSITE_ID_* for all 17 web apps to .env.development
- Add PUBLIC_UMAMI_WEBSITE_ID mapping in generate-env.mjs for all web apps
- Update 10 existing hooks.server.ts to use shared utility
- Create 7 new hooks.server.ts (picture, planta, presi, photos, clock,
questions, manadeck)
- Remove hardcoded Umami scripts from all 17 app.html files
- Add missing Umami tracking to Mukke and Questions
- Add shared-utils dependency to 6 web apps that lacked it
- Update ANALYTICS.md with architecture docs and "add new app" guide
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove hand-written sw.js, offline.html, and manifest.json from todo/skilltree/zitare web apps
in favor of the Workbox-based service worker generated by @vite-pwa/sveltekit. This fixes an
issue where the custom SW could get stuck serving the offline fallback page even when the server
was reachable. Also extracts the duplicated offline page (~80 lines each across 19 apps) into a
shared OfflinePage component in @manacore/shared-ui with 3 props (appName, offlineMessage,
accentColor), reducing each app's offline route to an 8-line wrapper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Changed scroll behavior to position current time ~1/3 from viewport
top instead of centering, so the red time indicator line is always
visible on load
- Added current time label (e.g. "14:30") above the red indicator line
on the right side
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Child components' onMount callbacks fire before the parent layout's auth
check in Svelte, causing API calls (todo, contacts, calendar) to fire
without a valid token on initial page load. Added appReady gate so
children only render after auth is confirmed.
Also added stats.mana.how to CSP script-src to allow Umami analytics.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add BUILD_TIME and BUILD_HASH exports to all version.ts files
- Add getBuildDefines() to all vite.config.ts for compile-time injection
- Add buildTime prop to shared LoginPage component
- Display formatted date/time next to version number (e.g. "v1.0.0 · 21.03.2026 10:30")
- Add app.d.ts type declarations for __BUILD_TIME__ and __BUILD_HASH__
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces individual QuickInputBar, DateStrip, DateStripFab, CalendarToolbar, and ViewsBar
with a single UnifiedBar component. Layers stack via flexbox, child positioning overridden
to relative. Overlay menu allows toggling layer visibility. View switcher integrated into
toolbar layer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The RecurrenceSelector was already built but only available in the full
EventForm. Now it's integrated into the QuickEventOverlay so users can
set recurring events directly when creating via grid click.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The click-to-create handler was using SNAP_INTERVAL_MINUTES (15) as the
initial event duration. Now uses DEFAULT_EVENT_DURATION_MINUTES (60) to
match the configured default. Drag behavior still uses snap interval.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace thin progress bar with animated step dots
- Add checkmark icon and stronger highlight for selected options
- Remove redundant step emoji (duplicate of header)
- Hide "Zurück" button on first step instead of just opacity:0
- Remove timezone step (auto-detect is always correct, 4 options too limited)
- Replace unsupported "day" view with "agenda" in view options
- Wire onComplete to actually apply weekStart and defaultView to settingsStore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add docker/Dockerfile.nestjs-base with all shared packages pre-built
- Convert 6 backend Dockerfiles (chat, todo, calendar, clock, contacts,
mukke) to inherit from nestjs-base:local
- Fix bugs: duplicate shared-nestjs-setup builds (mukke), unnecessary
shared-error-tracking rebuild in production stage (chat, clock)
- CD pipeline builds base image before services when backends deploy
- Net reduction: 317 lines removed, 112 added (-205 lines)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Calendar Sharing:
- Add shares store with full lifecycle (share, accept/decline, remove, permissions)
- Add missing API methods (getInvitations, getSharedWithMe)
- Create /settings/sharing page with:
- Pending invitations section with accept/decline
- "Shared with me" section
- Per-calendar share management (expandable list, add/remove shares)
- Share modal with email, permission selection
- Add link from main settings page
Error Boundaries:
- Create ServiceStatusBanner component for graceful degradation
- Integrate into main calendar page for Todo and Birthday services
- Shows warning when service unavailable with retry button
- Uses existing serviceAvailable flags from stores
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 4 tests: getReminders (success + error), createReminder with body
validation, deleteReminder endpoint
- All 120 tests passing across 13 test files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create ReminderSelector component with two modes:
- Draft mode (new events): configure reminders before save with preset
dropdown, push/email toggles, add/remove multiple reminders
- Saved mode (existing events): view reminders with status (pending/sent/
failed), add via preset dropdown, delete individual reminders
- Integrate into EventForm: default reminder pre-configured from settings,
drafts passed to parent via onSave callback for creation after event save
- Integrate into EventDetailModal: load and display reminders for existing
events, add/remove reminders directly via API, auto-refresh on change
- German UI labels for all reminder presets (Zum Zeitpunkt, 5/10/15/30 Min.,
1/2 Stunden, 1/2 Tage, 1 Woche vorher)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dockerfile, docker-compose service (port 5100), Caddy and cloudflared
routing for the WhoPixels game. PORT is now configurable via env var.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 697 lines of inline drag/drop/resize/create/keyboard handlers
in WeekView.svelte with existing composables:
- useEventDragDrop: event drag & resize (was ~220 LOC inline)
- useTaskDragDrop: task drag & resize (was ~180 LOC inline)
- useSidebarDrop: sidebar task drop (was ~70 LOC inline)
- useDragToCreate: new composable for click-drag event creation (was ~105 LOC)
- useCalendarKeyboard: Escape key cancel (was ~50 LOC inline)
Also adds getResizePreviewTime() to useEventDragDrop return value
so WeekView doesn't need access to internal resize state.
WeekView.svelte: 1600 → 903 lines (-44%)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add pnpm prune --prod and remove .ts/.map/test/docs files from
node_modules in the builder stage for chat, todo, calendar, clock,
and contacts backends. Same approach as mana-core-auth optimization.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wire RecurrenceEditDialog into EventDetailModal and QuickEventOverlay
so deleting recurring events shows "this/all/future" options
- Add external calendars section to CalendarSidebar with visibility
toggle and sync error indicator
- Update COMPLEXITY_AUDIT.md to mark sync and recurrence as implemented
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CalDAV/iCal Sync:
- Add sync API client (lib/api/sync.ts) for all external calendar endpoints
- Add external calendars store with connect, disconnect, sync operations
- Add /settings/sync page with provider selection (Google, CalDAV, iCal URL, Apple),
credentials form, CalDAV discovery, sync status display, and manual sync trigger
- Add link to sync settings from main settings page
Recurring Events:
- Add RecurrenceSelector component with preset selection (daily, weekly, monthly,
yearly, weekdays) and custom configuration (interval, weekday picker, end date)
- Integrate RecurrenceSelector into EventForm between date fields and location
- Expand recurring events into individual occurrences in events store using
generateOccurrences() from @calendar/shared
- Add recurrence-aware delete: single occurrence (exception), all occurrences,
or series update via dedicated store methods
- Add RecurrenceEditDialog component for "this/all/this and future" selection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove unnecessary complexity from the calendar web app:
- Remove tag groups system entirely (store, API client, route, components)
Tags are now a flat alphabetically-sorted list instead of grouped hierarchy
- Remove unused legacy composables (useDragDrop, useResize) that were never
imported by any component — useEventDragDrop already consolidates both
- Simplify TagStripModal from 1,452 to ~350 LOC by removing group CRUD,
drag-drop between groups, and group hierarchy rendering
- Add complexity audit report documenting remaining issues
Total: -2,170 LOC across 13 files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
getBaseUrl() always overrides baseUrl with window.__PUBLIC_BACKEND_URL__,
which breaks cross-app API clients (e.g. calendar→todo, calendar→contacts)
by routing all requests to the host app's backend.
Added useRuntimeUrl: false option to skip the runtime override when
the client already resolves its own base URL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pnpm install fails without the patches directory since the lockfile
references react-native-reanimated patch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Feedback is now a sub-item under the Konto (user) dropdown in PillNavigation
instead of a standalone pill in the nav bar. Added feedbackHref prop to
PillNavigation (defaults to /feedback) and removed feedback from nav items
in all 11 apps and shared app-routes config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add batch cover-url endpoint (POST /library/cover-urls) to efficiently
resolve multiple cover art presigned URLs in a single request. Integrate
cover art display across all UI surfaces: album grid, album detail header,
song list thumbnails, playlist grid, and playlist detail song list.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensure shared-nestjs-metrics, shared-nestjs-setup, and shared-error-tracking
are all built in correct dependency order before the backend build step.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 3 backends (calendar, contacts, todo) need these packages copied and
built in the Docker build stage for error tracking and Swagger support.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reflect production readiness improvements: Chat 74→82, Picture 72→81, Mukke 71→80.
Also fix Dockerfiles to include shared-error-tracking and shared-nestjs-setup packages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Infrastructure:
- Add GlitchTip (web + worker) to docker-compose.macmini.yml (port 8020)
- Add glitchtip.mana.how to Cloudflare Tunnel config
- Add glitchtip database to init-db SQL
- Add GLITCHTIP_DSN to .env.development
Shared Package (@manacore/shared-error-tracking):
- initErrorTracking() - Sentry-compatible init with GlitchTip DSN
- captureException(), captureMessage(), setUser(), setTag(), flush()
- SentryExceptionFilter for NestJS (captures 5xx errors only)
- Graceful no-op when DSN is not configured
Integration:
- Add instrument.ts to calendar, contacts, todo backends
- Import instrument.ts before app bootstrap in all 3 main.ts files
- Error tracking auto-initializes when GLITCHTIP_DSN env var is set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add skip-to-content link ("Zum Inhalt springen") to all 3 app layouts
- Add id="main-content" to main content areas
- Add ariaLabel prop to shared PillNavigation component
- Set aria-label="Hauptnavigation" on nav elements in all 3 apps
- Add aria-label to icon-only nav toggle button in todo
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extend shared-nestjs-setup bootstrapApp with optional swagger config
- Auto-setup Swagger/OpenAPI when swagger: true is passed
- Add @nestjs/swagger as optional peer dependency
- Enable swagger in calendar (:3014/api/docs), contacts (:3015/api/docs), todo (:3018/api/docs)
- Migrate todo main.ts from custom bootstrap to shared bootstrapApp
- JWT Bearer auth configured in Swagger UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add +error.svelte to Calendar (blue) and Todo (emerald) web apps
- Add FR, IT, ES locale files for Contacts (216 keys each)
- Add FR, IT, ES locale files for Todo (104 keys each)
- Update i18n index.ts to register new locales
All three apps now support DE, EN, FR, IT, ES
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>