Pre-launch theme system audit found multiple parallel layers in themes.css
(--theme-X full hsl strings, --X partial shadcn aliases, --color-X populated
by runtime store with raw channels) plus dead-code companion files. The
inconsistency caused light-mode regressions when scoped-CSS consumers
wrote `var(--color-X)` standalone — the variable holds raw HSL channels
which is invalid as a color value, browser fell back to inherited (white).
Rewrite to one consistent layer:
- Source of truth: --color-X defined as raw HSL channels (e.g.
`0 0% 17%`) in :root, .dark, and all variant [data-theme="..."]
blocks. Matches the format the runtime store
(@mana/shared-theme/src/utils.ts) writes, eliminating the
static-fallback-vs-runtime mismatch and the corresponding flash
of unstyled content on hydration.
- @theme inline uses self-reference + Tailwind v4 <alpha-value>
placeholder so utility classes generate correctly AND opacity
modifiers work: `text-foreground/50` → `hsl(var(--color-foreground) / 0.5)`.
- @layer components (.btn-primary, .card, .badge, etc.) wraps
var(--color-X) refs with hsl() — they were broken in light mode
too for the same reason.
Convention going forward (also documented in the file header):
1. Markup: use Tailwind utility classes (text-foreground, bg-card, …)
2. Scoped CSS: hsl(var(--color-X)) — always wrap with hsl()
3. NEVER raw var(--color-X) in CSS — that's the bug pattern
Net file: 692 → 580 LOC. Single source layer, no indirection.
Also delete dead companion files (zero imports anywhere):
- tailwind-v4.css (had broken self-reference, never imported)
- theme-variables.css (legacy hex-based palette)
- components.css (legacy component utilities)
- index.js / preset.js / colors.js (Tailwind v3 preset format,
irrelevant under Tailwind v4)
package.json exports map shrinks accordingly to just `./themes.css`.
Consumers using `hsl(var(--color-X))` (~379 files across mana-web,
manavoxel-web, arcade-web) keep working unchanged — the public API
name `--color-X` is preserved. Only the broken pattern `var(--color-X)`
(~61 files) needs a follow-up sweep, handled in a separate commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete all 25 apps/*/apps/web-archived/ directories (superseded by unified ManaCore app)
- Remove stale +page.server.ts stubs from teams, organizations, settings (always returned empty data)
- Simplify teams and organizations pages to static empty-state (no server load dependency)
- Delete empty apps/context/apps/mobile/components/variants/index.ts
- Remove commented-out apps-archived entries from pnpm-workspace.yaml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All app compute servers have been consolidated into apps/api/ (unified
Hono/Bun server). Old servers moved to apps/*/apps/server-archived/.
Archived: cards, chat, contacts, context, calendar, guides, moodlit,
mukke, news, nutriphi, picture, planta, presi, questions, storage, todo, traces
Still active: uload (separate domain), memoro (Supabase-based)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All standalone SvelteKit web apps have been superseded by the unified
ManaCore app (apps/manacore/apps/web). Moved to web-archived/ within
each project to preserve history while removing from active workspace.
Archived: calc, cards, chat, citycorners, contacts, context, guides,
inventar, moodlit, mukke, news, nutriphi, photos, picture, planta,
presi, questions, skilltree, storage, times, zitare, todo, calendar,
uload, memoro
Moved to apps-archived/: wisekeep (not integrated, inactive)
Kept active: manacore (unified), matrix, manavoxel, arcade (separate containers)
Server, landing, and package directories remain active for each project.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove standalone app Umami website IDs from .env.development and
generate-env.mjs. Remove injectUmamiAnalytics from all 21 standalone
app hooks.server.ts files. All analytics now flow through the single
ManaCore unified app website ID with module-level segmentation.
Landing page IDs are preserved (separate Astro sites).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each app's PillNavigation now has spotlightActions with app-specific
quick actions (create, navigate, settings). Users can press Cmd+K / Ctrl+K
from any app to search apps, navigate, and trigger actions.
Apps: todo, calendar, contacts, chat, picture, clock, zitare, cards,
storage, manacore, mukke, presi, context, questions, photos, planta,
citycorners, guides, calc, moodlit, matrix, uload, arcade
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- contacts, zitare: migrate LanguageSelector to shared PillDropdown pattern
- context, times: replace local ConfirmDialog with ConfirmationModal from @manacore/shared-ui
- delete local ConfirmDialog.svelte in both apps
- map open→visible, onCancel→onClose, remove destructive prop (default in shared-ui)
- calendar, chat, contacts, presi, todo: switch AppSlider from static MANA_APPS
to getActiveManaApps() to filter inactive apps consistently
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate inline SVG icon paths to Phosphor components in chat, zitare,
times, citycorners, inventar, manacore, todo, playground, presi, and
more. Part of repo-wide icon unification effort.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces a tiered access control system so apps can be released
gradually (founder → alpha → beta → public) without extra infrastructure.
Users are gated at the AuthGate level based on their tier vs the app's
requiredTier. All apps remain deployed and reachable, but only users
with sufficient tier can enter.
- Add accessTier enum + column to users schema (default: 'public')
- Add tier claim to JWT payload in better-auth config
- Add requiredTier field to ManaApp interface + all 25 apps
- Add hasAppAccess(), getAccessibleManaApps(), ACCESS_TIER_LABELS
- Update AuthGate with tier check + access denied screen
- Update getPillAppItems + Home page to filter by user tier
- Update all 22 app layouts to pass user tier to PillNav
- Add admin API: GET/PUT /api/v1/admin/users/:id/tier
- Document access tier system in CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrate 17 app Dockerfiles from standalone builds (each copying 20+
packages individually) to use the shared sveltekit-base:local image.
Benefits:
- No more missing package COPY errors
- Single base image to maintain
- Consistent build pattern across all apps
- Faster builds (shared deps pre-installed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sed-based insertion script added the import twice. Fixed by
deduplicating with awk.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After extensive package restructuring (deletions, consolidations, new
packages), the frozen lockfile causes resolution failures in Docker.
Use --no-frozen-lockfile until lockfile stabilizes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The package consolidation (feedback, help, subscription, credits)
renamed packages but Dockerfiles still referenced old names.
Ran scripts/generate-dockerfiles.mjs to update all 16 web app
Dockerfiles with correct COPY statements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add <SyncIndicator /> from @manacore/shared-ui to every app layout.
Shows floating pill when browser goes offline ("Offline") and briefly
when reconnecting ("Wieder online"). Auto-fades after 3 seconds.
Simplified component: uses browser online/offline events instead of
sync engine coupling. Works universally without any props.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Upgraded 6 apps from SDK 52/54 to SDK 55 (matrix was already on 55).
All apps now consistently use:
- Expo SDK ~55.0.5
- React Native 0.83.2
- React 19.2.0
- expo-router ~55.0.5
- NativeWind ~4.2.3
Before: 3 different SDK versions (52, 54, 55)
After: 1 version (55) across all 7 mobile apps
Added docs/EXPO_SDK_UPGRADE.md with testing checklist.
Note: pnpm install + device testing required to validate the upgrades.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Created createManaAuthStore in @manacore/shared-auth-stores that replaces
~350 lines of duplicated auth.svelte.ts per app with a ~10 line factory call.
The factory handles: SSO, passkeys, 2FA, magic links, token management,
password reset, sign up/in/out — everything the old stores did.
Each app only provides devBackendPort and optional onAuthenticated callback.
Before: 21 apps × ~350 lines = 6,800 lines of duplicated auth code
After: 21 apps × ~10 lines = 182 lines total (97% reduction)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merged shared-subscription-types + shared-subscription-ui into
@manacore/subscriptions. Updated imports in 15 web apps.
Package count: 49 → 47
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merged shared-feedback-types + shared-feedback-service + shared-feedback-ui
into a single @manacore/feedback package. Updated imports in all 21 apps.
Before: 3 packages (types, service, ui) with cross-dependencies
After: 1 package with direct imports, no circular refs
Note: ESLint warnings from pre-existing unused vars in chat/mukke
servers are unrelated to this change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clock, Context, Chat, and Planta prerender failed because /offline
references /favicon.png which doesn't exist. Added handleHttpError
to svelte.config.js to ignore this during prerender.
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>
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>
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>
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>
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>
- 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>
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>
No external auth providers to keep authentication fully self-sovereign
and avoid dependency on third-party services. Removes Google Sign-In,
Apple Sign-In components, utilities, endpoints, translations, and
mobile dependencies across all apps and shared packages.
Google/Apple integrations for data sync (Contacts import, Calendar sync)
are intentionally preserved as they serve a different purpose.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Svelte 5 restricts {@const} to block contexts only. Use direct
isOpenNow() calls in {#if} conditions instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The MiniOnboardingModal was nested inside .layout-container (flex) divs
in Chat, Clock, Contacts, Context, ManaDeck, Picture, Presi, and Todo.
This could interfere with fixed positioning, causing the modal to render
incorrectly. Moved all modals to the same nesting level as
SessionExpiredBanner, outside layout containers.
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>