Commit graph

160 commits

Author SHA1 Message Date
Till JS
45ebfea59d refactor(docker): standardize all web Dockerfiles to use sveltekit-base
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>
2026-03-28 21:56:44 +01:00
Till JS
fb25900bff fix(docker): fix broken COPY line concatenation in all web Dockerfiles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:47:12 +01:00
Till JS
5477e6eb74 fix(docker): add eslint-config + remove stale patches from all web Dockerfiles 2026-03-28 21:42:06 +01:00
Till JS
16367384c7 fix(docker): use --no-frozen-lockfile in all web Dockerfiles
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>
2026-03-28 21:12:03 +01:00
Till JS
9643c9bb3d fix(docker): regenerate Dockerfiles for consolidated packages
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>
2026-03-28 21:09:44 +01:00
Till JS
bda77cbcb7 feat(ui): add SyncIndicator to all 19 app layouts
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>
2026-03-28 18:27:30 +01:00
Till JS
a81a1535f6 perf(web): disable SSR for all local-first apps
All 15 local-first apps now use CSR-only (ssr=false in +layout.ts).
Since all data comes from IndexedDB (not server), SSR adds unnecessary
roundtrip latency (~3-4s FCP improvement expected).

Apps affected: todo, calendar, clock, contacts, zitare, skilltree,
citycorners, inventar, photos, mukke, planta, presi, storage,
context, questions.

Chat and manacore keep SSR for SEO.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 18:14:57 +01:00
Till JS
e7bcb230be refactor(auth): centralize auth stores — 21 apps use createManaAuthStore factory
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>
2026-03-28 18:04:27 +01:00
Till JS
4aa8d870a6 chore: commit remaining changes from recent sessions
- Mana page updates across 12 apps (credit display improvements)
- Todo board view editor + view selector components
- Docker Hono server base Dockerfile
- Matrix web vite config update
- Docker compose updates
- Feedback types.ts (recovered)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:54:51 +01:00
Till JS
1f3208384b refactor(packages): consolidate 2 subscription packages into @manacore/subscriptions
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>
2026-03-28 17:40:47 +01:00
Till JS
d70ab97a66 refactor(packages): consolidate 4 help packages into @manacore/help
Merged shared-help-types + shared-help-content + shared-help-ui into
@manacore/help. Deleted shared-help-mobile (0 consumers).

Updated imports in all 20 web apps.

Package count: 53 → 49

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:36:32 +01:00
Till JS
1aeb987cb6 refactor(packages): consolidate 3 feedback packages into @manacore/feedback
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>
2026-03-28 16:27:11 +01:00
Till JS
f628026b9e fix(build): add handleHttpError for missing favicon.png in 4 apps
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>
2026-03-28 16:03:19 +01:00
Till JS
8ccf8ff818 chore: misc fixes, new services, lockfile cleanup
Assorted changes from recent sessions:
- .gitignore: add mana-sync binary, Forgejo data
- chat/web: add isSidebarMode to navigation store
- clock/web: fix alarm page markup
- contacts/mukke/presi/questions: add svelte.config.js aliases
- context/web: add missing dependency
- manacore/landing: update pricing page
- manacore/web + todo/web: update mana dashboard pages
- planta/web: fix dashboard layout
- pnpm-lock.yaml: cleanup after backend removals
- docs/APP_GAP_ANALYSIS.md: new gap analysis doc
- services/mana-analytics: add Dockerfile
- services/mana-subscriptions: new Go subscription service

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:27:35 +01:00
Till JS
79080d6654 fix(apps): use explicit AuthServiceInterface in all 21 auth stores, re-enable type-check
Replace ReturnType<typeof initializeWebAuth>['authService'] with the
explicit AuthServiceInterface in all 21 web app auth stores. This
ensures svelte-check sees all 37 auth methods instead of TS inferring
a truncated type (~27 methods visible).

Re-enabled type-check in 5 apps that were skipping it:
- chat/web: svelte-kit sync && svelte-check --threshold error
- clock/web: svelte-kit sync && svelte-check --threshold error
- context/web: svelte-kit sync && svelte-check --threshold error
- presi/web: svelte-kit sync && svelte-check --threshold error
- picture/mobile: tsc --noEmit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:15:23 +01:00
Till JS
30e124e609 feat(local-first): migrate 9 apps to reactive useLiveQuery reads
Replace manual $state + fetchX() pattern with Dexie liveQuery hooks
across 9 apps. All data reads now auto-update on IndexedDB changes
(local writes, sync, other tabs). Stores reduced to mutation-only.

Apps migrated:
- Zitare: favorites, lists
- Contacts: contacts
- Calendar: calendars, events
- Chat: conversations, templates
- Clock: alarms, timers, worldClocks
- ManaDeck: decks, cards
- Presi: decks, slides
- Context: spaces, documents
- Storage: files, folders

Pattern per app:
1. New queries.ts with useLiveQuery hooks + pure filter helpers
2. Stores slimmed to mutation-only (no $state arrays, no fetch methods)
3. Layout sets context via setContext() for child components
4. Components use getContext() for reactive reads

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 02:27:46 +01:00
Till JS
5c33962439 feat(local-first): migrate tags + task stores to reactive liveQuery across all apps
- 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>
2026-03-28 02:02:52 +01:00
Till JS
32939fbfb5 refactor(infra): remove zitare + clock NestJS backends, add shared-hono package
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>
2026-03-27 22:43:46 +01:00
Till JS
2c9a36828f feat(apps): migrate Calendar, Clock, Contacts, ManaDeck to local-first
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>
2026-03-27 13:10:07 +01:00
Till JS
cc50c0c2ab feat(auth): add password strength indicator and magic links
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>
2026-03-27 11:23:09 +01:00
Till JS
91116bf0f1 feat(apps): integrate shared TagStrip into all 15 remaining apps
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>
2026-03-26 21:41:14 +01:00
Till JS
f5a9edcfb6 feat(auth): add TOTP two-factor authentication across all apps
Uses Better Auth's built-in twoFactor plugin for TOTP + backup codes:

Backend (mana-core-auth):
- twoFactor plugin in better-auth.config.ts (issuer: ManaCore)
- twoFactorEnabled field on users table, backupCodes as encrypted text
- 2FA redirect detection in signIn flow
- Passthrough controller forwards /two-factor/* to Better Auth
- Security event types for 2FA operations

Client (shared-auth):
- enableTwoFactor, disableTwoFactor, verifyTwoFactor, verifyBackupCode,
  generateBackupCodes methods with session-to-token exchange

UI (shared-auth-ui):
- LoginPage: 2FA code input view after password login, backup code toggle
- TwoFactorSetup: settings component with enable/disable/QR code/backup codes

App integration:
- All 19 auth stores have verifyTwoFactor() and verifyBackupCode()
- All 19 login pages pass onVerifyTwoFactor and onVerifyBackupCode callbacks
- ManaCore settings page has TwoFactorSetup component

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 19:55:09 +01:00
Till JS
cf9cbebd34 feat(apps): add missing help, feedback, profile, themes, auth pages for cross-app consistency
New pages created:
- Help: citycorners, matrix (with i18n help content)
- Feedback: citycorners, matrix, photos, planta, questions
- Profile: citycorners, mukke, photos, planta, questions, todo, zitare
- Themes: citycorners, photos, planta, questions, zitare
- Forgot-password: citycorners
- Reset-password: citycorners, picture, storage

PillNavigation updated in all 18 layouts:
- helpHref, profileHref, themesHref, feedbackHref consistently set
- Dependencies added (shared-profile-ui, shared-theme-ui, shared-feedback-ui)

All 17 standard apps now have: help, feedback, profile, themes, settings,
forgot-password, reset-password, offline pages. Matrix excluded for profile/themes/auth
(uses own Matrix protocol auth).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 14:33:34 +01:00
Till JS
40ace53867 feat(help): improve help content across all 18 apps, add shared Mana & Privacy FAQs
- 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>
2026-03-26 14:32:23 +01:00
Till JS
e676ba6873 fix(web): use JSON.stringify for env var injection in all hooks.server.ts
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>
2026-03-26 14:23:29 +01:00
Till JS
3091da914e feat(auth): add WebAuthn/Passkey support across all apps
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>
2026-03-26 10:30:03 +01:00
Till JS
2d11ba6248 refactor(auth): remove all Google/Apple social login code
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>
2026-03-26 09:12:30 +01:00
Till JS
3500ac5e23 fix(citycorners): replace @const with direct function calls in templates
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>
2026-03-25 16:05:37 +01:00
Till JS
491c71e2b8 fix(onboarding): move modal outside flex layout containers in 8 apps
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>
2026-03-25 15:08:34 +01:00
Till JS
3376b044bc fix(auth): resolve hardcoded localhost in user-settings across all web apps
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>
2026-03-25 12:40:30 +01:00
Till JS
7077c0a397 feat(help): add help pages to 10 remaining web apps
Add bilingual (DE/EN) help content and help page routes for Clock,
Context, ManaCore, ManaDeck, NutriPhi, Photos, Planta, Presi,
Questions, and SkillTree. Uses shared-help-types and shared-help-ui
packages consistent with already-committed help pages in other apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:36:22 +01:00
Till JS
336cfedd0b refactor(auth): centralize appReady pattern into AuthGate component
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>
2026-03-25 08:30:31 +01:00
Till JS
bf7517d24d feat(auth): add SessionExpiredBanner to all remaining web apps
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>
2026-03-24 22:35:13 +01:00
Till JS
90c438e267 feat(infra): auto-generate Dockerfile COPY statements from package.json
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>
2026-03-24 22:33:07 +01:00
Till JS
a2605e8816 feat(infra): add Dockerfile dependency validator + fix 16 missing COPYs
New script validates that all workspace deps in package.json have
matching COPY statements in Dockerfiles. Fixed missing shared-pwa,
shared-vite-config, patches/, and project-specific package COPYs
across 7 web app Dockerfiles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 20:25:54 +01:00
Till JS
61c23d5e79 fix(manacore): improve dashboard layout polish
- 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>
2026-03-24 12:21:51 +01:00
Till JS
000b74af9f fix(web): add appReady gate to prevent auth race condition in all apps
In Svelte, child onMount fires before parent onMount. Pages that fetch
data in onMount race against the layout's authStore.initialize(). Added
appReady state gate to layouts so children don't mount until auth is
confirmed. Affects: todo, contacts, clock, photos, zitare, planta.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:15:35 +01:00
Till JS
250e0b20af feat: add onboarding to 6 new apps and feature intro step to all 16 apps
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>
2026-03-23 21:58:14 +01:00
Till JS
241cb3332a refactor(auth): standardize URL resolution and token handling across all web auth stores
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>
2026-03-23 12:11:52 +01:00
Till JS
073c216652 fix(docker): add shared-error-tracking package to all 15 web Dockerfiles
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>
2026-03-23 09:08:33 +01:00
Till JS
7cad4073d4 feat(error-tracking): add browser error tracking to all 19 SvelteKit web apps
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>
2026-03-22 19:16:21 +01:00
Till JS
287bbed86e feat(analytics): add automatic CTA tracking to all 10 landing pages
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>
2026-03-22 19:13:24 +01:00
Till JS
45c11a1730 feat(analytics): add event tracking to picture, storage, clock, mukke, planta
Track key user actions in remaining web apps:

- Picture: image_generated (with model ID), generation_failed
- Storage: file_uploaded (with size in KB), folder_created
- Clock: timer_started (with timer type)
- Mukke: song_uploaded
- Planta: plant_created

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:07:06 +01:00
Till JS
cc9679dc9f refactor(analytics): centralize landing page Umami tracking via env vars
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>
2026-03-22 19:03:02 +01:00
Till JS
f5ee3aae20 feat(security): add unified CSP headers to all 17 web apps
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>
2026-03-22 18:53:40 +01:00
Till JS
e01b740dba refactor(analytics): centralize Umami tracking via env vars and shared utility
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>
2026-03-22 18:27:31 +01:00
Till JS
9bdb997394 refactor(pwa): replace custom service workers with Vite PWA plugin and centralize offline page
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>
2026-03-22 18:16:43 +01:00
Till JS
c0c11c325a feat(whopixels): major refactor with 20 improvements across architecture, gameplay, UX, security, and i18n
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>
2026-03-21 15:26:40 +01:00
Till JS
fc5dfe2f0f feat: show build date/time on login screen across all apps
- 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>
2026-03-21 12:40:57 +01:00
Till JS
683a4c5331 feat(docker): add shared NestJS builder base image
- 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>
2026-03-21 10:48:31 +01:00