Replace placeholder toast with full share modal featuring:
- Access level selection (view/download/edit)
- Expiration date (1/7/30/90 days)
- Max downloads limit
- Optional password protection
- Copy-to-clipboard for generated share URL
- Works for both files and folders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace plain text empty states with themed SVG illustrations:
- files/folder: cloud folder with upload arrows
- trash: empty bin with checkmark
- favorites: star outline
- search: magnifying glass
- shared: connected nodes
Reusable EmptyState component with snippet-based action slots.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add FileSkeletonGrid and FileSkeletonList components that match the
real card/row layout. Applied to files, folders, favorites, and trash
pages with view-mode-aware skeleton selection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements passwordless authentication via passkeys using @simplewebauthn:
Backend (mana-core-auth):
- New passkeys table in auth schema (credentialId, publicKey, counter, etc.)
- PasskeyService with registration/authentication flows and challenge storage
- 7 new API endpoints (register, authenticate, list, delete, rename)
- createSessionAndTokens helper for non-password auth flows
- Security event types for passkey operations
Client (shared-auth):
- signInWithPasskey() and registerPasskey() with dynamic @simplewebauthn/browser imports
- isPasskeyAvailable() browser capability check
- Passkey management methods (list, delete, rename)
UI (shared-auth-ui):
- Passkey button on LoginPage with key icon, shown when browser supports WebAuthn
- Divider between passkey and email/password form
App integration:
- All 19 web app auth stores have isPasskeyAvailable() and signInWithPasskey()
- All 19 web app login pages pass passkeyAvailable and onSignInWithPasskey props
- rpID=mana.how in production enables cross-app passkey usage (SSO-compatible)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend FilePreviewModal with rich previews for more file types:
- Video: native <video> player with controls via presigned S3 URL
- PDF: embedded browser PDF viewer via <iframe>
- Text/Code: fetched content displayed in monospace with scroll
- Markdown: rendered to HTML with basic formatting support
- Modal widened to 700px for better content display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full audio playback system to the Storage web app, inspired by the Mukke music app:
- MiniPlayer bar at bottom with frequency visualizer, progress bar, and controls
- FullPlayer fullscreen overlay with mirrored frequency bars background
- Inline audio preview in FilePreviewModal with play button
- Audio queue from all audio files in the current folder
- Presigned S3 URLs for playback, Media Session API for OS controls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The MiniOnboardingModal was placed inside the .layout-container flex div,
which interfered with its fixed positioning and caused it to render
unstyled at the bottom of the screen. Moved it to the same level as
SessionExpiredBanner, outside the layout container.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The shared-pwa package exports from dist/ and needs to be built before
the storage-web app. Also adds shared-help-types, shared-help-ui, and
shared-help-content COPY statements for the new help pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The createUserSettingsStore was receiving a static auth URL evaluated at
module load time, before window.__PUBLIC_MANA_CORE_AUTH_URL__ was
injected by hooks.server.ts. In production this caused CSP violations
as settings API calls went to localhost:3001 instead of auth.mana.how.
Changes:
- Accept string | (() => string) for authUrl in shared-theme config
- Resolve authUrl lazily at fetch time instead of module load
- Fix fallback to empty string in non-dev environments (was localhost)
- Pass getAuthUrl as getter function in all 17 web apps
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add defaultTranslationsDE/EN and getHelpTranslations() to shared-help-ui
so apps only need to override the subtitle instead of duplicating ~80 lines
- Refactor all 6 existing help pages to use getHelpTranslations()
(Contacts, Calendar, Todo, Storage, Chat, Picture)
- Add help page to Zitare (FAQ, features, contact — no shortcuts)
- Migrate Mukke from custom SettingsPage-based help to shared HelpPage
(FAQ with audio formats, lyrics editor, playlists; features; shortcuts)
All 8 web apps now use the unified shared help system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add help pages to the remaining high-maturity production apps:
- Storage (84/100): FAQ (upload, sharing, versioning, trash, privacy),
features (cloud storage, sharing, versioning, search), shortcuts
- Chat (82/100): FAQ (AI models, spaces, templates, comparison, privacy),
features (multi-model, spaces, comparison, templates), shortcuts
- Picture (81/100): FAQ (generation, credits, moodboards, explore, privacy),
features (AI generation, gallery, moodboards, explore), shortcuts
All 6 production web apps now have standardized help pages using the
shared help system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace copy-pasted appReady/loading/redirect logic in all 13 layouts
with a shared AuthGate component. Supports guest mode, onReady callback
for app-specific data loading, and configurable login redirect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added to: clock, photos, storage, mukke, planta, picture, skilltree,
nutriphi, chat. Now all 13 web apps show a re-login banner when
token refresh permanently fails.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New script generates COPY blocks between marker comments, eliminating
manual maintenance. All 17 web Dockerfiles updated with markers.
Supports --check flag for CI validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The prerendered /offline page referenced /favicon.png which didn't exist,
causing Docker build failure. Added favicon.svg, generated all PWA icons,
and added proper PWA meta tags to app.html.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unnecessary wrapper div in WidgetContainer
- Increase grid gap from gap-4 to gap-5 for breathing room
- Add auto-rows-fr for equal row heights
- Add min-h on widget content so empty widgets aren't tiny
- Change default layout to 3 equal columns (small)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add onboarding with feature overview, preference selection, and tips to
Zitare, Mukke, Photos, Planta, SkillTree, and Questions. Insert a new
first "features" info step into all 10 existing onboarding flows so every
app now starts with a core-features overview page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- Add MetricsModule to 8 backends missing it (photos, zitare, mukke,
planta, picture, storage, presi, nutriphi)
- Enable Prometheus scraping for all 15 backends in prometheus.yml
(was only 6, with 3 commented out and 6 missing entirely)
- Update ServiceDown alert rule to cover all 15 backends
- Update Grafana dashboards (backends, master-overview, system-overview)
with all backend services in health panels
- Fix imprecise regex in application-details dashboard
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>
Build fails because @manacore/shared-pwa is imported in vite.config.ts
but not copied into the Docker build context.
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>
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>
pnpm install --frozen-lockfile fails without the patches directory
since pnpm-lock.yaml references patched packages.
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>
- Add build context to storage-web in docker-compose (was pulling from
GHCR, now builds locally like other services)
- Add storage-backend and storage-web to CD change detection and deploy
- Fix mukke health check URLs (were using wrong ports 3035/5015)
- Remove hardcoded port from Dockerfile (use PORT env var from compose)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The storage web app had hardcoded localhost:3001 (auth) and localhost:3016
(backend) URLs, causing production to try connecting to localhost. Added
hooks.server.ts for runtime URL injection and CSP headers, matching the
pattern used by calendar/chat apps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FileVersionsModal:
- Shows version history sorted by version number
- Upload new version with optional comment
- File size and date formatting for each version
- Loading state while fetching versions
- Full ARIA accessibility (dialog, modal)
Integration:
- "Versionen" button added to FilePreviewModal action bar
- Opens FileVersionsModal overlay from file preview
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rate Limiting:
- Add @nestjs/throttler with 100 req/min global limit
- Stricter limits for uploads: 20 req/min single, 10 req/min multi
File Versioning (Backend):
- GET /api/v1/files/:id/versions — list version history
- POST /api/v1/files/:id/versions — upload new version with optional comment
- Updates file metadata (size, name, storageKey) on new version
- 7 new tests for versioning service and controller
API Client (Frontend):
- Add FileVersion interface
- Add filesApi.getVersions() and filesApi.uploadVersion()
Total tests: 205 (140 backend + 65 web)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Animations:
- Staggered fade-slide-in animation on FileGrid items (30ms delay per item)
- Drag feedback: dragged items show opacity 0.5 + scale 0.95
- Drop target: folder scales up 1.02 on hover with green dashed border
- Respects prefers-reduced-motion
Integration Tests (39 new web tests, total 198):
- client-integration.test.ts: upload flow, download with fetch mock,
folder contents, search encoding, share creation, trash restore,
bulk operations, error propagation, tag operations, favorites
Docker:
- Migrate backend Dockerfile to nestjs-base:local shared builder
- Prune devDependencies and test files in production image
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split monolithic RPGScene.js (1210 lines) into modular manager classes:
- WorldManager, PlayerManager, NPCManager, ChatUI, StorageManager,
SoundManager, TouchControls
Key improvements:
- Constants config (GAME_CONFIG) replacing all magic numbers
- JSDoc types + jsconfig.json for IDE type-safety
- LocalStorage persistence for progress, stats, and custom avatars
- Synthesized sound effects via Web Audio API
- 26 NPCs (up from 10) in 3 categories
- Stats/leaderboard in main menu
- Pixel editor avatar integration with RPG game
- Mobile touch controls (virtual joystick + interact button)
- Chat UI with typing indicator and conversation history
- Interactive tutorial overlay for first-time players
- Floating question mark over NPCs in range
- Server hardened: rate limiting, input sanitization, CORS restrictions,
API timeouts, conversation history cap
- Particle effect object pooling
- i18n framework with DE/EN and language switcher
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drag & Drop:
- FileCard: draggable with type/id data transfer
- FolderCard: draggable + drop target with visual feedback (dashed green border)
- FileGrid: onMoveToFolder callback for drag-to-folder operations
- filesStore: moveFile() and moveFolder() methods via API
- Wired up in /files and /files/[folderId] pages with toast notifications
E2E Tests (Playwright):
- playwright.config.ts with multi-browser support
- auth.spec.ts: login page rendering, invalid credentials, redirect
- files.spec.ts: file list UI, view toggle, new folder modal, empty state
- navigation.spec.ts: nav items, routing, page headings
- search.spec.ts: search input, button state, initial state
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>
Tests (109 total, all passing):
- Backend (Jest, 83 tests): file, folder, trash, search, share, tag services
- Web (Vitest, 26 tests): API client coverage for all endpoints
- Mock factories for File, Folder, Share, Tag entities
File Preview Modal:
- Image preview for image/* MIME types, file info display
- Action buttons: download, rename, share, favorite, delete
- Full ARIA accessibility, responsive, escape/click-outside close
- Integrated in /files, /files/[folderId], /favorites, /search pages
Dockerfiles:
- Fix incorrect port 3019 → 3016 in backend Dockerfile and web build arg
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add meta description, Open Graph tags, theme-color, preconnect/dns-prefetch to app.html
- Add per-page meta descriptions (files, favorites, search, trash, shared, settings)
- Add ARIA attributes to all loading states (role="status", aria-live="polite")
- Add aria-label, aria-expanded, aria-haspopup to all menu buttons (FileCard, FolderCard, FileRow, FolderRow)
- Add role="menu" and role="menuitem" to all dropdown menus
- Add semantic table roles to FileList (role="table", role="columnheader", role="rowgroup")
- Add aria-label and progressbar ARIA to UploadZone
- Add role="img" with aria-label to emoji icons in trash
- Add aria-label to icon-only delete button in shared page
- Add aria-hidden to decorative SVGs and spinners
- Use type="search" with aria-label on search input
- Remove console.log statements from files, favorites, and search pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace manual validateFileSize() with maxSizeBytes in upload()
- Add upload hooks for structured logging
- Add deleteFiles() for bulk deletion via deleteMany()
- Add deleteAllUserFiles() for account deletion via deleteByPrefix()
- Remove unused validateFileSize import
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>
- Add import './instrument' to 15 remaining backend main.ts files
- Add GLITCHTIP_DSN to 10 additional backends in docker-compose.macmini.yml
- Total: 13/13 deployed backends have DSNs configured
- Total: 18/18 backends have instrument.ts + import
Backends with live error tracking after next rebuild:
chat, todo, calendar, clock, contacts, storage, presi, nutriphi,
skilltree, photos, zitare, mukke, planta
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>