Commit graph

39 commits

Author SHA1 Message Date
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
6c140c181e docs(mukke): add visualizer alternatives and technology comparison
Independent overview of all implementation approaches for music
visualization: rendering technologies (Canvas 2D, PixiJS, Three.js,
WebGL/GLSL, Babylon.js, p5.js), ready-made solutions (Butterchurn,
audiomotion-analyzer), user-generated content strategies (code editor,
shader editor, node-based, DSL, AI-generated), audio analysis options
(Meyda, essentia.js, AudioWorklet), performance strategies, and 5
architecture strategies with decision matrix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:46:58 +01:00
Till JS
2d7ca7e387 docs(mukke): add comprehensive visualizer system concept
Describes the architecture for an extensible music visualizer framework:
- Audio data layer with frequency, beat detection, and energy bands
- Registry system with discriminated union pattern for visualizer types
- 10+ planned built-in visualizations (spectrum, particles, 3D, etc.)
- Custom visualizer system with sandboxed code execution
- AI-powered code generation via mana-llm
- Fullscreen visualizer mode and community sharing
- Phased implementation roadmap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:34:42 +01:00
Till JS
0786e6bf49 feat(mukke): add real-time frequency bars visualizer
Add Web Audio API AnalyserNode integration and a Canvas 2D-based
frequency bars component. The visualizer connects to the player's
Audio element and renders frequency data in real-time using
requestAnimationFrame. Integrated into FullPlayer (mirrored, 48 bars)
and MiniPlayer (subtle 64-bar overlay behind progress bar).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:30:33 +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
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
bbc5919448 fix(mukke): redirect root page to login instead of showing landing page
Replace the marketing landing page at / with an immediate redirect:
authenticated users go to /library, others go to /login. This matches
the behavior of other apps like calendar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:19:52 +01:00
Till JS
99091ecf9e docs+test: add audio format docs and shared-storage utils tests
- Document all supported audio formats in mukke CLAUDE.md with browser
  compatibility matrix and notes on formats needing transcoding
- Add utils.test.ts for shared-storage: MIME type mappings, audio
  extension validation, and AUDIO_EXTENSIONS completeness checks (19 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:12:58 +01:00
Till JS
7a1ae1284c feat(mukke): support all common audio formats for upload and playback
Expand accepted audio formats beyond MP3/WAV/OGG to include FLAC, AAC,
M4A, AIFF, OPUS, WMA, WebM, ALAC, APE, WavPack, DSF, and DFF.
The HTML5 Audio player already handles whatever the browser supports.

Changes:
- BeatUploader: accept audio/* instead of hardcoded format list
- shared-storage: add MIME type mappings for all common audio formats

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:09:25 +01:00
Till JS
b51f18a910 feat(mukke): add right-click context menu to library songs
Uses the shared ContextMenu component from @manacore/shared-ui to provide
quick actions (play, edit metadata, open in editor, toggle favorite, delete)
on right-click in the song list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:05:12 +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
Till JS
15cde622e4 refactor(mukke): optimize storage usage in song and beat services
SongService:
- Use deleteMany() for batch deletion of audio + cover (was sequential)
- Add maxSizeBytes validation on cover art (10MB) and tag writing (500MB)
- Add cacheControl header on cover art uploads (immutable, 1 year)
- Add upload hooks for structured logging
- Use 'songs' subfolder for audio, 'covers' for cover art (was flat)
- Add deleteAllUserFiles() for account deletion via deleteByPrefix()
- Log storage errors instead of silently swallowing

BeatService:
- Add upload:error hook for structured logging
- Use 'beats' subfolder for organized key structure
- Log storage deletion errors instead of swallowing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:53:23 +01:00
Till JS
d9ccb5e31b feat(games): add whopixels hosting at whopxl.mana.how
Dockerfile, docker-compose service (port 5100), Caddy and cloudflared
routing for the WhoPixels game. PORT is now configurable via env var.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:57:50 +01:00
Till JS
822e75368a feat(shared): add DevBuildBadge component and getBuildDefines() helper
- shared-vite-config: getBuildDefines() injects __BUILD_HASH__ and
  __BUILD_TIME__ as compile-time constants via Vite define
- shared-ui: DevBuildBadge component shows git hash + build timestamp
  in a small fixed badge at bottom-right (click to expand)
- Integrated into mukke-web for deployment verification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:34:21 +01:00
Till JS
70b1c4429d test(mukke): add vitest setup and 34 frontend tests for player & library stores
- Set up vitest with jsdom, testing-library/svelte, and SvelteKit mocks
- Player store: 16 tests covering playSong, queue, shuffle, repeat,
  volume, error handling, clearQueue, removeFromQueue
- Library store: 18 tests covering loadSongs, loadCoverUrls (including
  non-image path filtering), albums, artists, genres, stats, favorites,
  tabs, upload, and delete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:16:47 +01:00
Till JS
a5940abfc2 feat(mukke): clickable songs in library, player error handling & cover fallbacks
- Songs in library are now clickable to play (with full queue support)
- Active song highlighted with primary color and play/pause overlay on cover
- Player store: error state, audio error listener, auto-skip on failure
- MiniPlayer: error toast bar with dismiss button
- Library store: filter non-image paths from cover URL loading
- Cover images: onerror fallback to icon when S3 file is missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:05:07 +01:00
Till JS
14b6a8934a fix(docker): add patches, shared-error-tracking, shared-nestjs-setup to all Dockerfiles
Ensures all 14 backend Dockerfiles have:
- COPY patches (for pnpm install --frozen-lockfile)
- COPY + build shared-error-tracking
- COPY + build shared-nestjs-setup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:58:29 +01:00
Till JS
2d22d14c58 feat(error-tracking): complete GlitchTip integration for all backends
- Add import './instrument' to 15 remaining backend main.ts files
- Add GLITCHTIP_DSN to 10 additional backends in docker-compose.macmini.yml
- Total: 13/13 deployed backends have DSNs configured
- Total: 18/18 backends have instrument.ts + import

Backends with live error tracking after next rebuild:
chat, todo, calendar, clock, contacts, storage, presi, nutriphi,
skilltree, photos, zitare, mukke, planta

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:47:27 +01:00
Till JS
ac9ce55128 refactor(nav): move feedback pill into user dropdown across all apps
Feedback is now a sub-item under the Konto (user) dropdown in PillNavigation
instead of a standalone pill in the nav bar. Added feedbackHref prop to
PillNavigation (defaults to /feedback) and removed feedback from nav items
in all 11 apps and shared app-routes config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:00:38 +01:00
Till JS
e848fa5342 feat(mukke): display album cover art in library, playlists, and song lists
Add batch cover-url endpoint (POST /library/cover-urls) to efficiently
resolve multiple cover art presigned URLs in a single request. Integrate
cover art display across all UI surfaces: album grid, album detail header,
song list thumbnails, playlist grid, and playlist detail song list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:59:45 +01:00
Till JS
47b9e41666 feat(error-tracking): add GlitchTip integration to all 15 remaining backends
- Create instrument.ts for: chat, clock, context, manadeck, mukke,
  nutriphi, photos, picture, planta, presi, questions, skilltree,
  storage, traces, zitare
- Add import './instrument' as first line in all main.ts files
- Add @manacore/shared-error-tracking dependency to all package.json files
- Create 10 new GlitchTip projects (mukke→18, total: 18 projects)
- All 18 backends now have error tracking (active when GLITCHTIP_DSN is set)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:38:03 +01:00
Till JS
4faa0e26d2 fix(mukke): add feedback packages to web Dockerfile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:26:49 +01:00
Till JS
442a5844f6 feat(mukke): add settings, themes, feedback, and help pages
Uses shared components: ThemePage from shared-theme-ui, SettingsPage/
SettingsSection/SettingsCard/SettingsRow from shared-ui, FeedbackPage
from shared-feedback-ui. Adds feedback and help nav items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:26:21 +01:00
Till JS
97d5b13a38 feat(versioning): add semantic versioning and changesets to all apps
Assign version numbers based on app maturity: Calendar/Contacts/Todo (1.0.0),
Chat/Picture (0.3.0), 11 beta apps (0.2.0), Context/Planta/Questions (0.1.0),
Traces (0.0.1). Set up @changesets/cli for future version management.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 16:20:18 +01:00
Till JS
08cc1ee366 fix(mukke): add shared-splitscreen to web Dockerfile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:51:30 +01:00
Till JS
1d1489273d refactor(mukke): replace custom sidebar with shared PillNavigation
Replaces the custom sidebar layout with PillNavigation, SplitPaneContainer,
and app switcher from shared packages. Adds theme variants, keyboard
shortcuts (Ctrl+1-5), and consistent bottom-pill navigation matching
other apps like calendar and contacts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:49:59 +01:00
Till JS
c1f632693d feat(mukke): add month/day fields and auto-set date from file timestamp
Adds month and day columns to songs schema. On upload, extracts the
file's lastModified date to pre-fill year/month/day. Upload form and
SongEditor now show all three date fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:31:50 +01:00
Till JS
b34e787832 fix(mukke): wire up resend verification email on login and register pages
The handlers were stubs returning success without actually calling the
auth service. Now delegates to authStore.resendVerificationEmail().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:57:56 +01:00
Till JS
8f0c747e08 fix(chat,picture,mukke): production readiness audit fixes and tests
Chat (62→82): Add DB indexes on all tables, rate limiting (ThrottlerModule),
space authorization checks (member verification, invite permissions),
input validation DTOs with @MaxLength, complete GDPR user deletion
(templates + usage logs), fix HTML injection in hooks.server.ts.
78 tests added (conversation + space services).

Picture (68→82): Add DB indexes on all tables, foreign key constraints
with cascade rules, rate limiting, webhook endpoint security (secret
header validation), input validation on generate DTO (@Min/@Max on
dimensions/steps/guidance), transaction wrapping for board duplication
and generation completion. 70 tests added (image + board services).

Mukke (62→80): Add 73 new tests (beat, marker, project services) on top
of existing 40 tests, bringing total to 113.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 14:46:29 +01:00
Till JS
3da6cf2bd4 docs(mukke): add ID3 tag endpoints to CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:42:44 +01:00
Till JS
34c6b9c973 feat(mukke): add ID3 tag extraction, editor UI, and tag writing
Auto-extract metadata (title, artist, album, genre, year, BPM, cover art)
from uploaded files using music-metadata. Add SongEditor modal for editing
metadata in the library view. Support writing ID3 tags back to MP3 files
via node-id3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:41:18 +01:00
Till JS
54c1326c14 fix(mukke): lint fixes, rate limiting, DB indexes, and prod config
- Add ThrottlerModule rate limiting to backend
- Add DB indexes on userId, songId, playlistId columns
- Lint/formatter fixes from pre-commit hooks
- Add GlitchTip error tracking to docker-compose.macmini.yml
- Add glitchtip.mana.how to cloudflared tunnel config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:54:49 +01:00
Till JS
24a6efa453 fix(mukke): add patches dir to Dockerfiles for pnpm install
pnpm install --frozen-lockfile fails without the patches directory
because pnpm-lock.yaml references react-native-reanimated patch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:11:50 +01:00
Till JS
7a56699d45 feat(mukke): rename LightWrite to Mukke and add music library, player, playlists
Combines LightWrite (beat/lyrics editor) and Mukke (iOS music player) into
a single web-based music workspace app. Archives the old Mukke mobile app.

- Rename: @lightwrite/* → @mukke/*, all branding, configs, Dockerfiles
- New DB schemas: songs, playlists, playlist_songs + songId FK on projects
- New backend modules: SongModule, PlaylistModule, LibraryModule
- New web: app shell with sidebar, library (songs/albums/artists/genres),
  web player (queue/shuffle/repeat/MediaSession), playlists, search,
  upload, dashboard, album/artist/genre detail pages
- Auth: add forgot-password + reset-password pages, extend auth store
- Tests: 40 backend unit tests (song, playlist, library services)
- Config: env generation, MinIO bucket, docker-compose prod, cloudflare
- Docs: update CLAUDE.md, auth guidelines with SvelteKit checklist

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:55:56 +01:00
Till JS
6c91805b2f feat(mukke): add offline-first iOS music player app
Mukke is a local, offline-first music player for iOS. Songs are imported
from iCloud/local files via document picker, stored on device, and played
with expo-audio including background playback and lock screen controls.

Stack: Expo SDK 55, expo-audio, expo-sqlite, expo-document-picker,
@missingcore/audio-metadata, Zustand, NativeWind, Expo Router with NativeTabs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:23:58 +01:00