NutriPhi meals store: Replace apiClient calls with mealCollection
reads/writes. Daily summary now computed locally from IndexedDB.
Mukke library store: Replace backend API aggregations (albums, artists,
genres, stats) with local computation from songCollection.getAll().
Server-only operations (upload, cover URLs, metadata extraction) remain
as fire-and-forget API calls.
Store migration status: All 19 apps now use IndexedDB as primary
data source. Server API calls only remain for:
- File upload/download (S3 presigned URLs)
- Image generation (Replicate API)
- AI analysis (Gemini)
- Cover art URLs (S3 presigned)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Photos NestJS backend was a proxy to mana-media that enriched
responses with local album/favorite/tag data. Now:
- Albums store → local-first via albumCollection + albumItemCollection
- Favorites → local-first via favoriteCollection (toggle in IndexedDB)
- Photo tags → local-first via photoTagCollection
- Photo listing/stats → direct mana-media API calls from frontend
- Upload → direct mana-media upload from frontend
- Delete → direct mana-media delete from frontend
Removed 27 TypeScript files, 1 Docker container, 1 port (3039).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Presi NestJS backend (40 source files, 50 deps) was a CRUD wrapper
around decks, slides, and themes — all now handled by local-first sync.
Only the share-link feature requires server-side state (public URLs
without auth), so a minimal Hono + Bun server replaces the entire
NestJS backend:
- apps/presi/apps/server/ — Hono server with share routes + GDPR admin
Uses @manacore/shared-hono for auth (JWKS), health, admin, errors
- Web app API client stripped to share-only (was 270 lines → 90 lines)
- Removed from docker-compose, CI/CD, Prometheus, env generation
- NestJS backend deleted (40 TS files, 8 test specs, 3038 lines)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Todo: Replace manual fetch/state stores with useLiveQuery() for tasks,
projects, and tags. Components use Svelte context instead of store imports.
Stores reduced to mutation-only services. Removes ~200 lines of manual
state management. Enables multi-tab sync and auto-refresh on data changes.
- Tags (all 16 apps): Migrate from API-based createTagStore() to shared
local-first IndexedDB ('manacore-tags'). Tags now work offline and in
guest mode with default seed data. All apps share the same tag DB via
tagLocalStore + useAllTags() + setContext pattern.
- Cleanup: Delete unused Todo API files (projects.ts, labels.ts,
reminders.ts), remove dead labels store, clean up barrel exports.
Apps migrated: Todo, Zitare, Questions, Planta, Clock, Presi, Mukke,
Context, CityCorners, ManaDeck, Chat, Contacts, Calendar, Picture,
Storage, Photos
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both apps are fully local-first via Dexie.js + mana-sync. Their NestJS
backends were pure CRUD wrappers (20 + 31 source files) that are no
longer needed.
Changes:
- Add packages/shared-hono: JWT auth via JWKS (jose), Drizzle DB factory,
health route, generic GDPR admin handler, error middleware
- Migrate zitare lists page from fetch() to listsStore (local-first)
- Rewrite clock timers store from API-based to timerCollection (Dexie)
- Update clock +layout.svelte CommandBar search to use local collections
- Remove zitare-backend + clock-backend from docker-compose, CI/CD,
Prometheus, env generation, setup scripts
- Add docs/TECHNOLOGY_AUDIT_2026_03.md with full repo analysis
Net result: -2 Docker containers, -2 ports, -2728 lines of code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Configure all apps with gpu-llm.mana.how as fallback when MANA_LLM_URL
is not set. This ensures apps can use the GPU server's local LLM models
(Ollama gemma3, qwen2.5-coder) instead of cloud providers.
Apps updated:
- Chat: LLM fallback to GPU server
- Context: LLM fallback (replaces Azure OpenAI dependency)
- NutriPhi: LLM + Vision fallback (replaces Google Gemini for food analysis)
- Planta: LLM + Vision fallback (replaces Google Gemini for plant analysis)
- ManaDeck: LLM + Vision fallback for card generation
- Traces: LLM fallback for AI city guides
Vision model default: ollama/gemma3:12b (multimodal, runs on RTX 3090)
Added VISION_MODEL to .env.development
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Picture App:
- Update LocalImageGenService to use GPU server (gpu-img.mana.how)
- Add API key authentication (GPU_API_KEY)
- Increase timeout to 120s (VRAM may need model loading time)
Chat App:
- Add VoiceModule with STT/TTS integration via GPU server
- POST /api/v1/voice/transcribe — Upload audio, get text + word timestamps
- POST /api/v1/voice/synthesize — Send text, get audio response
- GET /api/v1/voice/health — Check GPU voice services availability
- Supports speaker diarization and language selection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the custom IndexedDB implementation (idb package + services/storage.ts)
and rewrite skills + achievements stores to use @manacore/local-store collections.
Changes:
- Rewrite skills.svelte.ts: all CRUD via skillCollection/activityCollection
- Rewrite achievements.svelte.ts: all persistence via achievementCollection
- Delete services/storage.ts (282 lines of custom idb code)
- Remove idb dependency from package.json
- Simplify layout comments
The stores now follow the same pattern as all other migrated apps:
reads/writes go to IndexedDB (Dexie.js), sync happens automatically
via mana-sync when authenticated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Cloudflare Tunnel: api.mana.how → localhost:3060 (Go API Gateway)
- Prometheus: scrape targets for mana-api-gateway:3060 and mana-matrix-bot:4000
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add IndexedDB data layer to 5 more Tier 2 apps, bringing the total to
17/22 apps with local-first architecture.
For each app:
- Create local-store.ts with typed collections and sync config
- Create guest-seed.ts with onboarding data for guest mode
- Update layout with AuthGate allowGuest={true} + local store init
- Add GuestWelcomeModal for first-visit experience
App-specific changes:
- Chat: Add store init to existing AuthGate, keep session-based guest mode
- Questions: Replace manual onMount auth with AuthGate wrapper
- Mukke: Add allowGuest to existing AuthGate, audio files stay server-side
- Context: Replace manual onMount auth with AuthGate, AI stays server-side
- Photos: Add allowGuest to existing AuthGate, photos stay on mana-media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 21 separate NestJS Matrix bot processes (~2.1 GB RAM, ~4.2 GB Docker images)
with a single Go binary using plugin architecture (8.6 MB binary, ~30 MB RAM).
New services:
- services/mana-matrix-bot/ — Go Matrix bot with 21 plugins (mautrix-go, Redis sessions)
- services/mana-api-gateway-go/ — Go API gateway (rate limiting, API keys, credit billing)
Deleted:
- 21 services/matrix-*-bot/ directories
- packages/bot-services/ and packages/matrix-bot-common/
- Legacy deploy scripts and CI build jobs
Updated:
- docker-compose.macmini.yml: new Go services, legacy bots removed
- CI/CD: change detection + build jobs for Go services
- Root package.json: new dev:matrix, build:matrix, test:matrix scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add IndexedDB data layer (Dexie.js via @manacore/local-store) to 6 more apps,
bringing the total to 12/22 apps with local-first architecture.
For each app:
- Create local-store.ts with typed collections and sync config
- Create guest-seed.ts with onboarding data for guest mode
- Update layout with AuthGate allowGuest={true} + handleAuthReady()
- Add GuestWelcomeModal for first-visit experience
- Add @manacore/local-store dependency
App-specific changes:
- Presi: Rewrite decks store from API to IndexedDB, conditional share button
- Picture: Rewrite gallery + boards pages to read from IndexedDB
- Inventar: Replace manual auth $effect with AuthGate, keep localStorage stores
- NutriPhi: Add onReady handler to existing AuthGate
- Planta: Add allowGuest + sync init to existing AuthGate
- Storage: Add local store init to existing handleAuthReady
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Roll out @manacore/local-store to 4 more apps:
- Clock: alarms, timers, world clocks in IndexedDB with guest seed
- Calendar: calendars, events in IndexedDB with sample events
- Contacts: contacts in IndexedDB with 3 sample contacts
- ManaDeck: decks, cards in IndexedDB with onboarding flashcards
All apps: GuestWelcomeModal, login pill for guests, sync on auth.
Dev scripts: added dev:sync, dev:todo:server, dev:todo:local, dev:todo:full updated.
6 of 8 web apps are now local-first (Todo, Zitare, Clock, Calendar, Contacts, ManaDeck).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New lightweight server replacing NestJS for server-side compute:
- RRULE expansion (next occurrence, validation, DoS protection)
- Reminders (CRUD with reminder time calculation)
- Admin (GDPR user data counts + deletion)
- JWT auth middleware + service key auth for admin
- Port 3019, ~10 packages vs ~50 for NestJS
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add missing devlog for March 25 (analytics, help system, CityCorners,
ManaLink, infra). Expand March 26 devlog to include all 61 commits
(Storage sprint, Passkeys/2FA, Tags, Zitare) alongside architecture planning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Favorites and lists stores rewritten to read/write IndexedDB
- Guest seed data: 3 pre-favorited quotes + sample list
- Layout: zitareStore.initialize(), sync on login, GuestWelcomeModal
- PillNav shows login button for guests (empty userEmail)
- No auth checks in stores — all writes are local
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update branchen pages (privat, selbststaendige, vereine), memoro-de content,
and onboarding CreditsStep to use new Mana Quelle S-XXL tiers and Mana Trank prices.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Auth store starts/stops sync on login/logout
- LocalStore queues all existing records for initial sync (guest→auth transition)
- LocalCollection.queueAllForSync() creates pending inserts for all local records
- Skips initial queue if sync cursor exists (already synced before)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Session management:
- GET /auth/sessions and DELETE /auth/sessions/:id endpoints
- listSessions() and revokeSession() in shared-auth client
- SessionManager component: active sessions list with device info,
"Aktuell" badge, revoke individual or all other sessions
- Integrated in ManaCore settings page
Account lockout UX:
- Dedicated amber lockout banner (distinct from generic rate-limit)
- "Konto vorübergehend gesperrt" with MM:SS countdown
- "Passwort zurücksetzen" link as alternative action
- formatCountdown helper for clean time display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace old 3-tier model (Plus/Pro/Ultra) with 5 size-based tiers (S/M/L/XL/XXL).
New naming: "Mana Quelle" for subscriptions, "Mana Trank" for one-time purchases.
Create new Stripe products and prices, archive old ones, update all UI and seed data.
Subscription tiers: S (500 Mana, 4.99€), M (1000, 9.99€), L (2000, 19.99€),
XL (4000, 39.99€), XXL (10000, 99.99€). Yearly: 20% discount.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Password strength (zxcvbn-ts):
- PasswordStrength component with 4-segment color bar and German feedback
- Lazy-loaded with 150ms debounce to avoid SSR/bundle issues
- Integrated into RegisterPage and ChangePassword components
Magic Links (passwordless email):
- Better Auth magicLink plugin (10-minute expiry)
- sendMagicLinkEmail() in email service (German template)
- Passthrough route for /magic-link/* endpoints
- sendMagicLink() in shared-auth client
- "Login-Link per E-Mail senden" button on all 20 login pages
- All 21 auth stores have sendMagicLink() method
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement the foundational local-first data layer for ManaCore apps:
- New @manacore/local-store package (Dexie.js IndexedDB, sync engine, Svelte 5 reactive queries)
- New mana-sync Go service (sync protocol, WebSocket push, field-level LWW conflict resolution)
- Todo app migrated as pilot: stores read/write IndexedDB, guest mode with onboarding seed data
- PillNavigation: prominent login pill for unauthenticated users
- SyncIndicator component showing local/syncing/offline status
- GuestWelcomeModal on first visit for Todo app
- Removed demo-mode auth_required checks from Todo components (all writes are now local)
- CSP fix for local development (localhost:3001, localhost:3050)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrated apps with existing local tags (photos, storage, picture):
- Replace local tag stores with createTagStore wrapper
- Add shared TagStrip to layouts with tag filtering support
- Storage: new tag store, /tags management page
- Picture: migrated from Svelte 4 writables to createTagStore
New TagStrip added to 12 apps without prior tag system:
- chat, citycorners, clock, context, manadeck, manacore, matrix,
mukke, planta, presi, questions, zitare
- Each gets: tag store, Tags toggle pill in PillNav, TagStrip overlay,
/tags management page, fetchTags on auth ready
- All backed by central mana-core-auth Tags API
All 18 apps now have:
- Tags pill in PillNav (toggles TagStrip overlay)
- Shared TagStrip component from @manacore/shared-ui
- Tag store using createTagStore from @manacore/shared-stores
- /tags management page
- Cross-app tags via central mana-core-auth
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contacts:
- Replace local TagStrip with shared TagStrip from @manacore/shared-ui
- Replace local tags store with createTagStore wrapper (backward-compatible)
- Change Tags nav item from link to toggle pill (shows/hides TagStrip overlay)
Calendar:
- Replace local TagStrip in UnifiedBar with shared TagStrip component
- Replace local event-tags store with createTagStore wrapper (backward-compatible)
- Both apps now use central mana-core-auth Tags API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add createTagStore factory to @manacore/shared-stores (Svelte 5 runes, backed by @manacore/shared-tags)
- Replace Todo's local TagStrip with shared TagStrip from @manacore/shared-ui
- Replace Todo's labels store with createTagStore wrapper (backward-compatible)
- Remove "Tags" tab from PillNav TabGroup, add it as toggle pill (like Filter)
- Tags pill toggles TagStrip overlay visibility instead of navigating to /tags
- TagStrip has "Tags verwalten" pill linking to /tags management page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a small info icon next to the author name that toggles a short
biography when clicked. Bio text is displayed in the current quote
language with German as fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add inline search field and sort-by-author option to category pages.
Also extract hardcoded German strings and respect display settings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show a count badge next to the favorites title and use the global
display settings for category/source visibility on quote cards.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show clickable category pills below the search input when results
are available. Each chip shows the match count for that category.
Also respects display settings for category/source visibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add toggle switches for show/hide category and source, and a font
size selector (small/normal/large/extra large). Settings are persisted
via the existing settings store and applied to QuoteCard and home page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show toast notifications when list CRUD operations and favorite
toggling fail, instead of silently swallowing errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add spinner indicators and disable buttons during create, delete,
update, add quotes, and remove quote operations to prevent double
clicks and give visual feedback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract ~40 hardcoded German strings into de.json/en.json locale files.
Covers favorites, lists, list detail, search, and settings pages
including toasts, modals, form labels, empty states, and aria labels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Expand FAQ entries from ~5 to 8-14 per app with app-specific feature documentation
- Add comprehensive features, shortcuts, and keyboard shortcut sections
- Integrate shared getManaFAQs() in 10 apps with /mana page
- Integrate shared getPrivacyFAQs() in all 18 apps with app-specific data types
- Add unit tests for help content in all 18 apps (72 tests total)
- Tests verify: DE/EN content, matching FAQ/feature counts, unique IDs, contact info
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PillNavigation: add helpHref and themesHref props with help icon in account dropdown
- PillDropdown: add help icon (question mark circle) to iconPaths
- shared-help-types: add getManaFAQs/getManaFeature for shared Mana credit FAQs
- shared-help-types: add getPrivacyFAQs for shared privacy/GDPR/tech independence FAQs
- ManaScore: add Help-Seite and Feedback-Seite as UX criteria, shared-help-ui and
shared-feedback-ui as Core cross-app packages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents potential XSS by safely serializing env values instead of using
raw string interpolation. Also creates missing hooks.server.ts for context
app and standardizes citycorners to use the same injection pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Playwright tests that verify real API interactions:
- Create folder via UI modal
- File upload via drag zone
- Search with results/no-results handling
- File preview modal opening
- Share modal from file actions
- Trash/favorites page loading
- Settings page with real storage usage stats
Tests auto-skip if backend is not available.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Selection state in files store with toggle/selectAll/clearSelection
- Checkboxes appear on FileCard/FolderCard when selection is active
- BulkActionBar with count display, delete, select all, clear
- Click toggles selection when in selection mode, normal click otherwise
- Selection cleared on folder navigation
- Animated slide-in action bar with primary color accent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: Add endpoints for file-tag operations (GET/POST/DELETE)
Frontend: TagPicker component with:
- View/add/remove tags on files in FilePreviewModal
- Create new tags inline with random color assignment
- Dropdown with existing tags and create-new input
- Colored tag pills with remove button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fetch actual file count, total size, and favorites from /files/stats
endpoint. Replace hardcoded 2.5GB/10GB placeholder with real data
and animated progress bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>