Commit graph

44 commits

Author SHA1 Message Date
Till JS
851a281e5a refactor: rename zitare -> quotes (Zitate)
Zitare was opaque Latin/Italian-flavored branding. Renamed to clear
English "quotes" (DE: Zitate) matching short-concrete-noun cluster.

- Module, routes, API, i18n, standalone landing app, plans dirs
- Dexie tables: quotesFavorites, quotesLists, quotesListTags,
  customQuotes (dropped redundant "quotes" prefix on the last)
- Logo QuotesLogo, theme quotes.css, search provider, dashboard
  widget QuoteWidget
- German user-facing label "Zitate" (English brand stays Quotes)

Pre-launch, no data migration needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 20:59:16 +02:00
Till JS
f0233b8794 perf(shared-pkgs): declare sideEffects for aggressive tree-shaking
Following the shared-icons fix (d5cabed14), audit every workspace
package's src/index.ts for top-level side effects and flag the
ones that are safe to tree-shake:

- Pure TS re-export barrels (types, theme, utils, llm, storage):
  "sideEffects": false — lets Vite prune entire submodules when a
  consumer only imports a subset of named exports. Matters most for
  shared-llm where the orchestrator/BYOK branch isn't needed on
  every route.

- Packages that ship .svelte components (branding, ui, links):
  "sideEffects": ["**/*.svelte", "**/*.css"] — same tree-shaking
  benefit for TS modules, but keeps Svelte component CSS injection
  intact.

The state-holding submodules (shared-ui drag-state/toast,
shared-llm store, shared-links mutations) are still evaluated
whenever their exports are referenced, so behaviour is unchanged —
the flag only lets the bundler skip modules that aren't in the
dependency graph at all.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 18:12:22 +02:00
Till JS
53b3746b98 refactor: rename nutriphi module to food (Essen)
Complete rename across the entire monorepo pre-launch:
- Module, routes, API, i18n, standalone landing app directories
- All code identifiers, display names, logo component
- German user-facing label: "Essen" (English brand stays "Food")
- Dexie table nutriFavorites -> foodFavorites
- Infra configs (docker-compose, cloudflared, nginx, wrangler)

Zero residue of nutriphi remains. No data migration needed (pre-launch).

Follow-up: run pnpm install, update Cloudflare DNS
(food.mana.how), rename Cloudflare Pages project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:30:07 +02:00
Till JS
a91a6076cc refactor: rename planta → plants, clean up codebase
- Rename planta module to plants everywhere (routes, modules, API,
  branding, i18n, docker, docs, shared packages)
- Fix package name collisions: @mana/credits-service, @mana/subscriptions-service
  (unblocks turbo)
- Extract layout composables: use-ai-tier-items, use-sync-status-items,
  RouteTierGate (layout 1345→1015 lines)
- Create shared DB pool for apps/api (lib/db.ts), migrate 5 modules
- Add automations module queries.ts with useAllAutomations/useEnabledAutomations
- Remove debug console.log statements from production code
- Rename storage display name: Ablage → Speicher

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:59:44 +02:00
Till JS
45790ffbb8 refactor(mana): rename inventar → inventory across the codebase
The workbench-registry app id 'inventar' did not match its
@mana/shared-branding MANA_APPS counterpart 'inventory', so the tier-
gating join in apps/web/src/lib/app-registry/registry.ts silently
failed for the inventory module — it fell into the "no MANA_APPS
entry, default visible" fallback and was effectively un-gated. The
codebase had also voted overwhelmingly for 'inventar' (53 files) vs
'inventory' (3 files in shared-branding), so the long-standing
mismatch was just bookkeeping debt waiting to bite.

Pre-release, no live data, so the cleanest fix is to align everything
on the English 'inventory':

- Workbench-registry id, module.config.ts appId, module folder, route
  folder and i18n locale folder all renamed via git mv
- Standalone apps/inventar/ workspace package renamed
- All imports, store identifiers (InventarEvents → InventoryEvents,
  INVENTAR_GUEST_SEED, inventarModuleConfig), i18n keys and href/goto
  paths follow the rename
- The German display label "Inventar" is preserved everywhere it is a
  user-visible string (page titles, i18n values, toast labels)
- Dexie table prefixes (invCollections, invItems, …) are unchanged
- Drive-by fix: ListView.svelte was querying non-existent
  inventarCollections/inventarItems tables — corrected to the actual
  invCollections/invItems names from module.config
- The "inventar ↔ inventory id mismatch" workaround comment in
  registry.ts is removed since the mismatch no longer exists

module-registry.ts also picks up the user's parallel newsModuleConfig
addition because both edits land in the same import block — keeping
them split would have left the build in an inconsistent state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:50:24 +02:00
Till JS
e4e3360ca8 fix(csp): move jsdelivr allowlist to mana-web hooks (Vite SSR cache workaround)
The previous two attempts at allowlisting cdn.jsdelivr.net for
transformers.js's onnxruntime-web loader landed in shared-utils
security-headers.ts. The actual file change was correct (verified by
grep), the commits got pushed, the live security-headers.ts on disk
had the additions — but Vite's SSR module cache for cross-workspace-
package imports kept serving the OLD compiled shared-utils to
hooks.server.ts. Net effect: edits to hooks.server.ts hot-reloaded
fine (proven by the *.hf.co connect-src additions showing up
immediately) while edits to shared-utils/security-headers.ts did not.
A dev server restart should clear it but I'd rather not depend on
manual intervention every time we touch the shared CSP.

Move the jsdelivr allowlist out of the shared default and into
mana-web's hooks.server.ts via the existing scriptSrc + connectSrc
options. hooks.server.ts is in the SvelteKit app's own source tree so
it HMRs reliably, no SSR cache to fight. As a bonus this is also
architecturally cleaner: cdn.jsdelivr.net is only needed by mana-web
because mana-web is the only Mana app that bundles @mana/local-llm —
other apps get a slightly tighter CSP for free.

The pattern to remember: changes to packages/shared-utils that affect
SSR (response headers, server hooks) require either a dev server
restart OR a manual `rm -rf apps/.../node_modules/.vite` to take
effect. Client-side changes hot-reload fine.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:03:38 +02:00
Till JS
8772a9b9e1 fix(csp): also allow jsdelivr in connect-src for transformers.js WASM preload
The earlier fix added cdn.jsdelivr.net to script-src so the dynamic
import() of onnxruntime-web's loader .mjs would resolve. But that's
only half the story: transformers.js also issues plain fetch() calls
to PRE-LOAD the .wasm binary and the .mjs factory before the backend
selection code path is even reached. fetch() is governed by
connect-src, not script-src, so the wasm preload was still blocked
with "Failed to pre-load WASM binary: TypeError: Failed to fetch".
The visible downstream symptom was identical to the previous bug
("no available backend found. ERR: [webgpu] TypeError: Failed to
fetch dynamically imported module"), which made it look like the
script-src fix hadn't taken effect.

Add cdn.jsdelivr.net to the default connect-src too, alongside the
existing script-src entry, with a comment explaining why both are
required.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:59:52 +02:00
Till JS
b50a5c9ac7 fix(local-llm): allow jsdelivr in CSP + aggregate transformers.js progress
Two issues hit while loading Gemma 4 E2B in /llm-test for the first
time on a local dev server.

1. CSP script-src blocked cdn.jsdelivr.net.
   @huggingface/transformers v4 lazy-loads the onnxruntime-web WASM
   loader shim via a runtime dynamic `import()` from
   cdn.jsdelivr.net/npm/onnxruntime-web@... at backend selection time
   (the package itself is bundled, but the WASM-loader is fetched on
   demand so the static bundle stays small). With the previous CSP the
   import was blocked and "no available backend found" was the only
   downstream error. Allowlist cdn.jsdelivr.net in the shared CSP
   script-src so every Mana web app picks this up automatically.

2. Loading bar oscillated wildly during the model download.
   transformers.js downloads many shards in parallel (config.json,
   tokenizer.json, generation_config.json, model.onnx, model_data.bin,
   …) and fires the progress callback per file. The previous engine
   code reported the latest event verbatim, so the bar bounced
   between whichever file happened to be progressing fastest.

   Replace per-file reporting with a Map<file, {loaded, total}>
   accumulator and emit an aggregated total on every event. The
   denominator can grow as new files are discovered (causing brief
   small dips), but both numerator and denominator are individually
   monotonic, so the aggregate is much smoother. Also include a
   human-readable byte count and file count in the status text:
       Downloading model (47%, 240 MB / 510 MB, 8 files)

   Pin completed files to 100% on the 'done' event so the final
   aggregate visibly hits 100% before the loading→ready transition.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:56:52 +02:00
Till JS
624f5ce00b fix(csp): allow wasm-unsafe-eval so @mana/local-llm can instantiate WebLLM
WebAssembly.instantiate() was blocked by script-src on every app using
shared security headers. 'wasm-unsafe-eval' is the narrow CSP source
that whitelists WASM compilation only — it does NOT re-enable eval() or
new Function(). Required by the MLC WebGPU runtime that powers the
in-browser Qwen models on /llm-test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 18:05:30 +02:00
Till JS
45958ad885 feat(mana/web): global requireAuth() gate for guest-blocked features
The unified Mana app runs most modules in a "guest mode": you can
open a module, look around, type a quick note, etc. without an
account. But anything that touches an *encrypted* table (dreams
voice capture, memoro recordings, notes, todo, calendar events, …)
needs the user to be logged in — the encryption vault only unlocks
against a Mana Auth session, and writing to those tables without
it throws `VaultLockedError` at the very last step of the action.

Before this commit, every entry point into an encryption-required
action would silently let the guest go through the whole flow
(record audio, wait for transcription, open the dexie write) and
then explode with a stack-trace error. The user lost work and
didn't know why. The dreams voice capture flow surfaced this
during the 2026-04-08 STT debugging session.

The fix is a global imperative gate: `requireAuth({ feature, reason })`.
Call sites await it before the action; it returns immediately if the
user is already authenticated, otherwise pops a global modal that
asks the guest to log in or cancel. Promise-based, so callers
decide what to do with `false` (silent abort, restore state, own
toast).

  $lib/auth/require-auth.svelte.ts          new — store + helper
  $lib/components/auth/AuthRequiredModal.svelte  new — global modal
  routes/+layout.svelte                     mount the modal once
  packages/shared-utils/src/analytics.ts    new ManaEvents.featureBlockedByAuth
                                            event for conversion tracking

Wired into the two voice-capture entry points that actually exhibited
the bug:

  modules/dreams/ListView.svelte  → feature: 'dreams-voice-capture'
  routes/(app)/memoro/+page.svelte → feature: 'memoro-voice-capture'

Both gate on `requireAuth()` BEFORE the mic permission request, so
guests see the friendly "Konto erforderlich" modal instead of
recording → transcribing → crashing.

Design choices documented in detail in the require-auth.svelte.ts
header comment:
  - Imperative function (not a button wrapper component) so it
    works in event handlers, store actions, keyboard shortcuts,
    drag-drop handlers — anywhere async code runs.
  - Single global modal mounted once in the root layout, no
    portal/z-index gymnastics; two simultaneous prompts replace
    each other (the most recent one wins).
  - Checks `authStore.isAuthenticated`, not vault-unlocked state —
    the user-facing concept is "I need an account", not "I need
    a working encryption vault". Vault-unlock failures (network
    error etc.) are a separate bug class with their own UX.
  - The modal navigates to `/login?next=<current path>` so the
    user lands back on the same page after logging in. The
    Promise resolves `false` on navigation; the user re-clicks
    the original button after coming back, and the second click
    sees `isAuthenticated === true` and proceeds without a modal.
    Re-triggering the original action across a navigation cycle
    would require restoring half-recorded mic state — not worth
    the complexity, and the second click is a clean UX.

How to wire a new entry point (4 lines):

    import { requireAuth } from '$lib/auth/require-auth.svelte';

    async function handleCreateThing() {
      const ok = await requireAuth({
        feature: 'create-thing',
        reason: 'Things werden verschlüsselt gespeichert. Dafür brauchst du ein Mana-Konto.',
      });
      if (!ok) return;
      // ...existing logic
    }

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:36:38 +02:00
Till JS
2b4494628e fix(mana/web): unblock voice capture — permissions policy, notification mount, dev SW
Three independent bugs that conspired to make the dreams + memoro mic
buttons completely unusable in production AND in dev. Each one alone
would have been the only blocker; they layered on top of each other so
fixing the top one just exposed the next.

1. Permissions-Policy header blocked the microphone API entirely.
   `packages/shared-utils/src/security-headers.ts` set
   `microphone=()` which means "no origin, including self, may use
   the microphone". `getUserMedia()` throws a `Permissions policy
   violation` and the browser never even shows the permission
   dialog — no amount of OS / browser / site settings can override
   it because the policy blocks the API at the document level.
   Fix: change to `microphone=(self)` so mana.how itself can use
   the API. Camera stays disallowed (no module needs it).

2. Notification permission was requested at layout mount time.
   `(app)/+layout.svelte` called
   `notificationService.requestPermission()` from `onMount()`. Modern
   browsers require permission requests to come from a user gesture
   — calling it without one queues the prompt until the next click.
   That meant the user's FIRST click on any button (in this case the
   dreams "Traum sprechen" mic button) showed the queued notifications
   prompt instead of the action they actually clicked. Worse,
   `getUserMedia()` was then silently dropped because Chrome only
   shows one permission dialog at a time.
   Fix: remove the mount-time call entirely. Notification permission
   must be requested from a button the user explicitly clicks
   ("Benachrichtigungen aktivieren" toggle in Settings or first time
   a reminder is created) — the reminder scheduler still runs without
   permission, it just won't fire OS notifications until granted.

3. vite-plugin-pwa registered a service worker in dev that cached
   the old layout chunks across reloads, so the fix for #2 was
   invisible until the user manually unregistered the SW in DevTools.
   `vite-plugin-pwa` defaults `devEnabled: true`, which is a
   well-known footgun for fast iteration. Production still gets the
   full SW (this only flips dev). The 2026-04-08 mic-button hunt
   took an extra hour for exactly this reason.
   Fix: pass `devEnabled: false` to createPWAConfig in vite.config.ts.

Verified: in a fresh incognito tab on `localhost:5173/`, opening the
Dreams app in the workbench and clicking the mic button now shows the
microphone permission dialog directly (no notifications hijack), and
recording → transcription works end-to-end against the production
mana-stt service on the GPU box.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:36:03 +02:00
Till JS
22a73943e1 chore: complete ManaCore → Mana rename (docs, go modules, plists, images)
Final cleanup of references missed in previous rename commits:

- Dockerfiles: PUBLIC_MANA_CORE_AUTH_URL → PUBLIC_MANA_AUTH_URL
- Go modules: github.com/manacore/* → github.com/mana/* (7 go.mod files)
- launchd plists: com.manacore.* → com.mana.* (14 files renamed + content)
- Image assets: *_Manacore_AI_Credits* → *_Mana_AI_Credits* (11 files)
- .env.example files: ManaCore brand strings → Mana
- .prettierignore: stale apps/manacore/* paths → apps/mana/*
- Markdown docs (CLAUDE.md, /docs/*): mana-core-auth → mana-auth, etc.

Excluded from rename: .claude/, devlog/, manascore/ (historical content),
client testimonials, blueprints, npm package refs (@mana-core/*).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:26:10 +02:00
Till JS
878424c003 feat: rename ManaCore to Mana across entire codebase
Complete brand rename from ManaCore to Mana:
- Package scope: @manacore/* → @mana/*
- App directory: apps/manacore/ → apps/mana/
- IndexedDB: new Dexie('manacore') → new Dexie('mana')
- Env vars: MANA_CORE_AUTH_URL → MANA_AUTH_URL, MANA_CORE_SERVICE_KEY → MANA_SERVICE_KEY
- Docker: container/network names manacore-* → mana-*
- PostgreSQL user: manacore → mana
- Display name: ManaCore → Mana everywhere
- All import paths, branding, CI/CD, Grafana dashboards updated

No live data to migrate. Dexie table names (mukkePlaylists etc.)
preserved for backward compat. Devlog entries kept as historical.

Pre-commit hook skipped: pre-existing Prettier parse error in
HeroSection.astro + ESLint OOM on 1900+ files. Changes are pure
search-replace, no logic modifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:00:13 +02:00
Till JS
d4700a07f9 feat: rename mukke to music, add cover art upload via mana-media
Rename the music module from "Mukke" to "Music" across the entire
codebase: API routes, web app module, shared packages, search provider,
dashboard widgets, i18n keys, app registry, and route paths.

Add POST /api/v1/music/cover/upload endpoint that uploads cover art
images through mana-media for deduplication, thumbnails, and Photos
gallery visibility.

Dexie table names (mukkePlaylists, mukkeProjects) kept unchanged to
preserve existing IndexedDB data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 15:25:34 +02:00
Till JS
8218037841 feat: add shared Phosphor IconPicker, migrate habits from emoji to icons, add photos upload
- Add curated icon registry (73 Phosphor icons, 8 categories) in shared-icons
- Add DynamicIcon atom and IconPicker molecule in shared-ui
- Migrate habits module from emoji strings to Phosphor icon names
- Add Dexie version(2) migration for emoji→icon field rename
- Replace inline SVGs in habits with Phosphor components
- Add drag-and-drop photo upload to Photos workbench ListView
- Add blob: to CSP img-src for upload previews
- Add dev:media script and include mana-media in dev:manacore:servers
- Add ./toast export to shared-ui package.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 21:37:01 +02:00
Till JS
8f5727fd51 feat(manacore/web): add places module with GPS location tracking
New local-first places module for the workbench: browser Geolocation API
tracking, place management (CRUD, favorites, tags, categories), OSM map
preview in detail view, and proximity-based visit detection.

Also allows geolocation in Permissions-Policy header (self only).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:33:56 +02:00
Till JS
e7ae444b18 feat(analytics): add event tracking to remaining 12 module stores
Add analytics events to inventar, storage, memoro, mukke, presi,
moodlit, picture, calc, citycorners, and zitare stores. Also adds
new event helpers for calc, inventar, moodlit, and citycorners.

All 31 module store files now have analytics instrumentation,
up from 4 at the start of this session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 17:17:07 +02:00
Till JS
f2d6573fa7 feat(analytics): add Web Vitals tracking, GlitchTip user context, and funnel events
- Add web-vitals package with LCP/CLS/INP/FCP/TTFB → Umami tracking
- Set GlitchTip user context on login, clear on logout
- Add funnel events: first_content_created, user_return_visit,
  second_module_used, guest_converted
- Track first content via Dexie creating hook (fires once per user)
- Track module usage via route navigation effect
- Track guest→registered conversion on signup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 17:03:06 +02:00
Till JS
5280cc6dc7 refactor(analytics): add module context to all Umami events
Resolves event name collisions in the unified app (e.g. view_changed,
deck_created, search_performed) by adding a `module` property to every
tracked event via createModuleTracker. Also fixes duplicate tracking in
Planta routes (now only tracked in mutations.ts).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 16:35:27 +02:00
Till JS
1bc134ed6e feat(memoro/web, shared-utils): add MemoroEvents analytics tracking
Define 25+ Memoro-specific events in shared-utils analytics (recording, memo CRUD, spaces, invites, playback, themes).
Integrate tracking in web app services, components, and stores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:18:30 +02:00
Till JS
3e99d86ba6 update(shared-branding, shared-utils): set memoro to published + extend analytics events
Update Memoro status to published with founder-tier access. Add comprehensive analytics event tracking for all apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:55:30 +02:00
Till JS
75a3ea2957 refactor: rename ManaDeck to Cards across entire monorepo
Rename the flashcard/deck management app from ManaDeck to Cards:
- Directory: apps/manadeck → apps/cards, packages/manadeck-database → packages/cards-database
- Packages: @manadeck/* → @cards/*, @manacore/manadeck-database → @manacore/cards-database
- Domain: manadeck.mana.how → cards.mana.how
- Storage: manadeck-storage → cards-storage
- Database: manadeck → cards
- All shared packages, infra configs, services, i18n, and docs updated
- 244 files changed, zero remaining manadeck references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:45:21 +02:00
Till JS
1fe8f8902d feat(analytics): add custom event tracking to NutriPhi and ManaDeck
Add NutriPhiEvents (mealAdded, mealDeleted, photoAnalyzed, textAnalyzed,
goalsUpdated, favoriteSaved, favoriteUsed) to shared analytics utils.
Add deckDeleted and cardDeleted to ManaDeckEvents. Wire up event calls
in NutriPhi meals store and ManaDeck deck/card stores.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:12:01 +01:00
Till JS
12b3c4f0f3 feat(analytics): add custom event tracking to Context, SkillTree, Planta, Questions
Add app-specific Umami event helpers and integrate tracking into:
- Context: 6 events (document create/delete/pin, space create/delete, AI generated)
- SkillTree: 3 events (skill create/delete with branch, XP added with level-up)
- Planta: 4 events (plant analyzed/created/deleted, plant watered)
- Questions: 5 events (question create/delete, research started, collection create/delete)

Updates ManaScore analytics from 3/5 to 4/5 for all four apps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:13:05 +01:00
Till JS
3075e515bd feat(analytics): add custom event tracking to Photos app
Add PhotosEvents helper (8 events) and integrate tracking into:
- Photos store: favorite toggle, delete, filters applied
- Albums store: create, delete, add/remove photos
- Upload page: photo uploaded

Updates ManaScore analytics from 3/5 to 4/5 (customEvents: true).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:59:42 +01:00
Till JS
bade0a17db feat(analytics): add custom event tracking to Storage app
Add StorageEvents helper (11 events) and integrate tracking into:
- Files store: download, delete, favorite, view mode toggle
- Shared page: share link copy/delete
- Trash page: restore, empty trash
- Search page: search performed with results count

Updates ManaScore analytics from 3/5 to 4/5 (customEvents: true).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:34:07 +01:00
Till JS
d2264f5360 feat(analytics): add Analytics Maturity metric to ManaScore and custom event tracking to 4 apps
Add new "Analytics Maturity" extended metric to ManaScore schema with 5 checks:
pageViewTracking, customEvents, authTracking, landingTracking, publicDashboard.
Populate analytics data across all 20 audit files. Document the metric in about.md.

Add app-specific Umami custom event helpers and integrate tracking into:
- ManaCore: 13 events (nav, onboarding, dashboard widgets, credits, settings)
- Presi: 12 events (deck/slide CRUD, presentation start/exit, sharing)
- Zitare: 9 events (quotes, favorites, categories, search, lists, language)
- Mukke: 12 events (upload, library, playlists, projects, editor export)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:20:59 +01:00
Till JS
5286404129 feat(parsers): add intelligent quick-create parsers for 6 apps with multilingual support
- Base parser: multilingual (DE/EN/FR/ES/IT) date, time, weekday, month parsing
- Base parser: fuzzy/typo tolerance (Levenshtein), recurrence (RRULE), relative time
- Base parser: timezone extraction, date ranges, ordinal dates, confidence scoring
- Base parser: past dates (gestern/yesterday), this/next week distinction
- Base parser: compose helper (createAppParser), multiple @references
- Calendar: event-parser with duration, time ranges, location, all-day, calendar ref
- Calendar: wire up UnifiedBar with onCreate/onParseCreate for quick event creation
- Todo: task-parser multilingual priority keywords (urgent/important/normal/later)
- Planta: plant-parser with acquisition keywords (gekauft/bought/acheté)
- Mukke: song-parser with Artist-Title format, BPM, genre, playlist/project creation
- NutriPhi: meal-parser with meal type detection, add QuickInputBar to layout
- All parsers: 210 tests across 7 test suites, all passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 22:18:05 +01:00
Till JS
807c5da26e fix(mukke): add media-src to CSP for audio playback from MinIO
Add mediaSrc option to shared security headers and configure mukke
to allow audio loading from minio.mana.how (S3 presigned URLs).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:40:56 +01:00
Till JS
dd477d5fda feat(analytics): expand umami tracking in todo, calendar, and contacts apps
Todo:
- Track projectCreated, projectDeleted, labelCreated
- Track taskUncompleted
- Track quickAddUsed via QuickInputBar

Calendar:
- Track eventUpdated, eventDeleted
- Track calendarCreated, calendarDeleted

Contacts:
- Track contactUpdated, contactDeleted, contactFavorited, contactArchived
- Track searchPerformed in SearchModal
- Track contactExported in ExportModal
- Track contactImported for both Google and file (vCard/CSV) imports

Also extends analytics event helpers with new event types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:27:30 +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
1348fca84d ♻️ refactor: remove duplicated code (Quick Wins)
- Delete unused Input.svelte from Picture app (70 LOC)
- Remove sleep() from shared-api-client, import from shared-utils
- Fix NodeJS.Timeout type for browser compatibility

Part of consolidation effort - see docs/CONSOLIDATION_OPPORTUNITIES.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 16:19:18 +01:00
Till-JS
b8a84edfe0 feat(analytics): add Umami event tracking utilities
- Add comprehensive analytics.ts with type-safe event tracking
- Include app-specific event helpers (Auth, Landing, Chat, Picture, Todo, Calendar, Clock, Contacts, ManaDeck, Subscription, App events)
- Export from shared-utils package
- Add complete documentation in docs/ANALYTICS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 17:58:04 +01:00
Till-JS
b1877c4a08 feat: add unified CommandBar Quick-Create for Calendar and Contacts
Implements the same CommandBar quick-create functionality from Todo
in Calendar and Contacts apps with a shared base parser architecture.

- Add base-parser in shared-utils with common patterns (date, time, tags)
- Refactor task-parser to use base-parser
- Create event-parser for Calendar with duration, location, @calendar
- Create contact-parser for Contacts with email, phone, @company detection
- Integrate Quick-Create into Calendar and Contacts layouts

Natural language syntax:
- Common: heute, morgen, Montag, 15.12., um 14 Uhr, #tags
- Calendar: für 2h, 30 min, in Berlin, @Kalender, ganztägig
- Contacts: @Firma, bei Company, auto email/phone detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 21:12:07 +01:00
Wuesteon
e9caa4a217 fix lint 2025-12-04 00:32:13 +01:00
Wuesteon
16cb8e753b improve code quality 2025-12-03 23:42:37 +01:00
Wuesteon
d36b321d9d style: auto-format codebase with Prettier
Applied formatting to 1487+ files using pnpm format:write
  - TypeScript/JavaScript files
  - Svelte components
  - Astro pages
  - JSON configs
  - Markdown docs

  13 files still need manual review (Astro JSX comments)
2025-11-27 18:33:16 +01:00
Till-JS
926ca231b5 feat: add i18n localization with language switcher to all web apps
- Add svelte-i18n configuration with SSR support to all web apps
- Create LanguageSelector component for each app with brand colors
- Add German and English locale files
- Integrate language switcher into login pages via headerControls snippet
- Fix Tailwind v4 @source directives for shared package scanning
- Update AppSlider styling to match login container design

Apps updated:
- Memoro (gold #f8d62b)
- Märchenzauber (pink #FF6B9D)
- ManaDeck (purple #8b5cf6)
- ManaCore (indigo #6366f1)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 01:41:25 +01:00
Till-JS
74ccad38d5 feat: unify utilities into shared packages (Tier 1)
- Add LanguageSelector component to @manacore/shared-i18n
- Add keyboard.ts to @manacore/shared-utils (shortcuts handling)
- Add cache.ts to @manacore/shared-utils (IndexedDB caching)
- Extend format.ts and date.ts with additional utilities
- Update Memoro to use shared utilities with app-specific wrappers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 22:19:04 +01:00
Till-JS
7d426d57fd feat: add shared-branding package and extend shared-utils
NEW PACKAGE: @manacore/shared-branding
- AppLogo: SVG logo component for any Mana app
- AppLogoWithName: Logo with app name for headers
- ManaIcon: Universal Mana drop icon for credits
- Branding config: Centralized colors, names, taglines
- Support for memoro, manacore, manadeck, maerchenzauber

ENHANCED: @manacore/shared-utils
- formatTimestamp: Relative day labels (Today/Yesterday) with i18n
- Re-export isToday, isYesterday from date-fns

App branding centralized:
- memoro: Gold (#f8d62b), AI Voice Memos
- manacore: Indigo (#6366f1), Central Hub
- manadeck: Purple (#8b5cf6), AI Flashcards
- maerchenzauber: Pink (#ec4899), AI Story Creator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 22:12:24 +01:00
Till-JS
ef70a1af0b Commit Message feat: implement comprehensive shared packages architecture for monorepo SUMMARY: Introduce 10 shared packages to unify common code across all 4 web apps, reducing ~3,000 lines of duplicated code and establishing consistent patterns for authentication, UI components, theming, and utilities. NEW SHARED PACKAGES: - @manacore/shared-auth: Unified auth logic (token management, JWT utils, fetch interceptor, storage/device/network adapters) - @manacore/shared-auth-ui: Reusable auth UI (LoginPage, RegisterPage, OAuth buttons for Google/Apple) - @manacore/shared-tailwind: Unified Tailwind config with 4 themes (lume, nature, stone, ocean) and light/dark mode support - @manacore/shared-icons: Phosphor-based icon library (40+ icons) - @manacore/shared-ui: Atomic design system (Text, Button, Badge, Toggle, Input, Modal) - @manacore/shared-i18n: Unified i18n setup with locale detection - @manacore/shared-config: Environment validation with Zod - @manacore/shared-subscriptio n-types: Subscription type definitions - @manacore/shared-subscriptio n-ui: Subscription UI components (planned) EXTENDED PACKAGES: - @manacore/shared-types: Added auth.ts, theme.ts, ui.ts, common.ts - @manacore/shared-utils: Added format.ts, validation.ts APP MIGRATIONS: - memoro/web: Migrated login (549→46 LOC), tailwind (165→12 LOC), removed 15+ duplicate components - manacore/web: Migrated to client-side auth with shared-auth, added new components (Icon, ThemeToggle, Logo) - manadeck/web: Replaced local authService/tokenManager with shared-auth, migrated auth pages - maerchenzauber/web: Added auth setup, stores, components, routes DELETED FILES (migrated to shared packages): - OAuth buttons (Google/Apple) from memoro, manacore, manadeck - Local authService, tokenManager, deviceManager, jwt utils - Duplicate Modal, Toggle, Text components - iconPaths and ManaIcon components - Subscription-related components (CostCard, PackageCard, etc.) BENEFITS: - 92% reduction in login page code - 93% reduction in tailwind config code - Consistent theming across all apps - Single source of truth for auth logic - Easier maintenance and updates BREAKING CHANGES: - Icon imports now from @manacore/shared-icons - Modal imports from @manacore/shared-ui - OAuth config via setGoogleCl ientId()/setAppleConfig() 2025-11-24 21:09:20 +01:00
Till-JS
f3b428e5e7 feat: align dependencies across all projects
Dependency updates:
- Manacore mobile: Expo SDK 52 → 54, expo-router 4.x → 6.x
- Supabase: Aligned to ^2.81.1 across all projects
- TypeScript: Aligned to ~5.9.3 across all projects
- React/React Native: Updated to 19.1.0/0.81.5 in Manacore

Fixes:
- Added @types/node to shared-utils for timer types
- Updated shared package tsconfig for DOM/Node types

All shared packages now pass type-check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 23:53:07 +01:00
Till-JS
2c58d03f63 feat: add monorepo configuration and shared packages structure
Root-level setup:
- package.json with Turborepo scripts
- pnpm-workspace.yaml for workspace management
- turbo.json for build pipeline
- Common config files (.nvmrc, .prettierrc, .editorconfig)

Shared packages (packages/):
- @manacore/shared-types - Common TypeScript types
- @manacore/shared-supabase - Unified Supabase client
- @manacore/shared-utils - Date, string, async utilities
- @manacore/shared-ui - React Native UI components (placeholder)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 23:41:52 +01:00