From 72da55d3d0199542d204ff3c5d81dcf263445fd2 Mon Sep 17 00:00:00 2001 From: Till JS Date: Mon, 30 Mar 2026 15:03:19 +0200 Subject: [PATCH] feat(moodlit): restore from git history, migrate to local-first + Hono - Restore from git history (was deleted in 079b55a79) - Delete NestJS backend and mobile app - Create Hono/Bun server with preset moods API - Create local-first store (moods, sequences) with 8 preset moods - Rewrite web app: Moods page with color gradient cards and activation, Sequences page with CRUD, auth via shared-auth-ui with guest mode - Add CLAUDE.md, dev scripts, root CLAUDE.md entry - 0 type errors on both server and web Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 1 + apps-archived/moodlit/CLAUDE.md | 295 - .../moodlit/apps/backend/drizzle.config.ts | 12 - .../moodlit/apps/backend/nest-cli.json | 8 - .../moodlit/apps/backend/package.json | 53 - .../moodlit/apps/backend/src/app.module.ts | 20 - .../moodlit/apps/backend/src/db/connection.ts | 38 - .../apps/backend/src/db/database.module.ts | 29 - .../apps/backend/src/db/schema/index.ts | 2 - .../backend/src/db/schema/moods.schema.ts | 15 - .../backend/src/db/schema/sequences.schema.ts | 14 - .../backend/src/health/health.controller.ts | 13 - .../apps/backend/src/health/health.module.ts | 7 - .../moodlit/apps/backend/src/main.ts | 40 - .../apps/backend/src/moods/dto/index.ts | 37 - .../backend/src/moods/moods.controller.ts | 40 - .../apps/backend/src/moods/moods.module.ts | 10 - .../apps/backend/src/moods/moods.service.ts | 64 - .../apps/backend/src/sequences/dto/index.ts | 29 - .../src/sequences/sequences.controller.ts | 40 - .../backend/src/sequences/sequences.module.ts | 10 - .../src/sequences/sequences.service.ts | 63 - .../moodlit/apps/backend/tsconfig.json | 26 - apps-archived/moodlit/apps/mobile/.gitignore | 25 - apps-archived/moodlit/apps/mobile/CLAUDE.md | 95 - apps-archived/moodlit/apps/mobile/app.json | 81 - .../moodlit/apps/mobile/app/+html.tsx | 46 - .../moodlit/apps/mobile/app/+not-found.tsx | 26 - .../moodlit/apps/mobile/app/_layout.tsx | 22 - .../moodlit/apps/mobile/app/create-mood.tsx | 192 - .../apps/mobile/app/create-sequence.tsx | 249 - .../moodlit/apps/mobile/app/details.tsx | 23 - .../apps/mobile/app/edit-sequence/[id].tsx | 272 - .../moodlit/apps/mobile/app/index.tsx | 196 - .../moodlit/apps/mobile/app/mood/[id].tsx | 121 - .../moodlit/apps/mobile/app/reorder-moods.tsx | 129 - .../moodlit/apps/mobile/app/sequence/[id].tsx | 233 - .../moodlit/apps/mobile/app/sequences.tsx | 127 - .../moodlit/apps/mobile/app/settings.tsx | 212 - .../apps/mobile/assets/adaptive-icon.png | Bin 17547 -> 0 bytes .../moodlit/apps/mobile/assets/favicon.png | Bin 1466 -> 0 bytes .../moodlit/apps/mobile/assets/icon.png | Bin 22380 -> 0 bytes .../apps/mobile/assets/mood-light-logo.png | Bin 440242 -> 0 bytes .../mood-light.icon/Assets/moods-logo.png | Bin 440242 -> 0 bytes .../mobile/assets/mood-light.icon/icon.json | 31 - .../moodlit/apps/mobile/assets/splash.png | Bin 233427 -> 0 bytes .../moodlit/apps/mobile/babel.config.js | 12 - .../moodlit/apps/mobile/cesconfig.jsonc | 46 - .../components/AnimatedMoodBackground.tsx | 532 -- .../moodlit/apps/mobile/components/Button.tsx | 25 - .../apps/mobile/components/Container.tsx | 9 - .../apps/mobile/components/EditScreenInfo.tsx | 29 - .../moodlit/apps/mobile/components/Icon.tsx | 58 - .../apps/mobile/components/MoodCard.tsx | 74 - .../apps/mobile/components/ScreenContent.tsx | 26 - .../apps/mobile/components/SequenceCard.tsx | 104 - apps-archived/moodlit/apps/mobile/eas.json | 21 - .../moodlit/apps/mobile/eslint.config.js | 15 - apps-archived/moodlit/apps/mobile/global.css | 3 - .../apps/mobile/hooks/useFlashlight.ts | 177 - .../apps/mobile/hooks/useResponsive.ts | 43 - .../moodlit/apps/mobile/metro.config.js | 10 - .../moodlit/apps/mobile/nativewind-env.d.ts | 2 - .../moodlit/apps/mobile/package.json | 68 - .../moodlit/apps/mobile/prettier.config.js | 10 - .../moodlit/apps/mobile/store/store.ts | 312 -- .../moodlit/apps/mobile/tailwind.config.js | 14 - .../moodlit/apps/mobile/tsconfig.json | 11 - .../moodlit/apps/mobile/utils/supabase.ts | 14 - .../moodlit/apps/mobile/utils/theme.ts | 11 - apps-archived/moodlit/apps/web/package.json | 47 - .../moodlit/apps/web/src/lib/api/feedback.ts | 14 - .../moodlit/apps/web/src/lib/auth.ts | 172 - .../apps/web/src/lib/stores/auth.svelte.ts | 118 - .../apps/web/src/routes/(app)/+layout.svelte | 174 - .../apps/web/src/routes/(app)/+page.svelte | 177 - .../src/routes/(app)/feedback/+page.svelte | 7 - .../src/routes/(app)/sequences/+page.svelte | 206 - .../(auth)/forgot-password/+page.svelte | 36 - .../web/src/routes/(auth)/login/+page.svelte | 40 - .../src/routes/(auth)/register/+page.svelte | 37 - .../apps/web/src/routes/+layout.svelte | 10 - .../moodlit/apps/web/svelte.config.js | 12 - apps-archived/moodlit/apps/web/vite.config.ts | 43 - apps-archived/moodlit/package.json | 16 - apps/moodlit/CLAUDE.md | 37 + .../moodlit/apps/landing/astro.config.mjs | 10 +- .../moodlit/apps/landing/package.json | 0 .../apps/landing/src/layouts/Layout.astro | 0 .../apps/landing/src/pages/index.astro | 0 .../moodlit/apps/landing/tailwind.config.mjs | 0 .../moodlit/apps/landing/tsconfig.json | 0 .../moodlit/apps/landing/wrangler.toml | 0 apps/moodlit/apps/server/package.json | 21 + apps/moodlit/apps/server/src/config.ts | 16 + apps/moodlit/apps/server/src/index.ts | 17 + apps/moodlit/apps/server/src/lib/errors.ts | 19 + .../server/src/middleware/error-handler.ts | 11 + .../apps/server/src/middleware/jwt-auth.ts | 46 + apps/moodlit/apps/server/src/routes/health.ts | 10 + .../moodlit/apps/server/src/routes/presets.ts | 29 + apps/moodlit/apps/server/tsconfig.json | 16 + apps/moodlit/apps/web/package.json | 39 +- .../moodlit/apps/web/src/app.css | 0 apps/moodlit/apps/web/src/app.d.ts | 4 + .../moodlit/apps/web/src/app.html | 0 .../web/src/lib/components/AppSlider.svelte | 0 .../lib/components/LanguageSelector.svelte | 0 .../web/src/lib/components/MoodlitLogo.svelte | 11 + .../components/mood/CreateMoodDialog.svelte | 0 .../src/lib/components/mood/MoodCard.svelte | 0 .../lib/components/mood/MoodFullscreen.svelte | 0 .../apps/web/src/lib/data/default-moods.ts | 0 .../apps/web/src/lib/data/guest-seed.ts | 70 + .../apps/web/src/lib/data/local-store.ts | 38 + .../moodlit/apps/web/src/lib/i18n/index.ts | 0 .../apps/web/src/lib/i18n/locales/de.json | 0 .../apps/web/src/lib/i18n/locales/en.json | 0 .../apps/web/src/lib/stores/auth.svelte.ts | 3 + .../apps/web/src/lib/stores/moods.svelte.ts | 0 .../apps/web/src/lib/stores/navigation.ts | 0 .../web/src/lib/stores/sequences.svelte.ts | 0 .../moodlit/apps/web/src/lib/stores/theme.ts | 0 .../moodlit/apps/web/src/lib/types/auth.ts | 0 .../moodlit/apps/web/src/lib/types/mood.ts | 0 .../apps/web/src/routes/(app)/+layout.svelte | 90 + .../apps/web/src/routes/(app)/+page.svelte | 5 + .../web/src/routes/(app)/moods/+page.svelte | 173 + .../src/routes/(app)/sequences/+page.svelte | 117 + .../src/routes/(app)/settings/+page.svelte | 0 .../apps/web/src/routes/+layout.svelte | 37 + .../web/src/routes/auth/login/+page.svelte | 22 + .../web/src/routes/auth/register/+page.svelte | 16 + apps/moodlit/apps/web/svelte.config.js | 9 + .../moodlit/apps/web/tsconfig.json | 0 apps/moodlit/apps/web/vite.config.ts | 7 + apps/moodlit/package.json | 8 + package.json | 4 + pnpm-lock.yaml | 4918 ++++++++++++++++- 139 files changed, 5607 insertions(+), 5877 deletions(-) delete mode 100644 apps-archived/moodlit/CLAUDE.md delete mode 100644 apps-archived/moodlit/apps/backend/drizzle.config.ts delete mode 100644 apps-archived/moodlit/apps/backend/nest-cli.json delete mode 100644 apps-archived/moodlit/apps/backend/package.json delete mode 100644 apps-archived/moodlit/apps/backend/src/app.module.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/db/connection.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/db/database.module.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/db/schema/index.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/db/schema/moods.schema.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/db/schema/sequences.schema.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/health/health.controller.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/health/health.module.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/main.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/moods/dto/index.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/moods/moods.controller.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/moods/moods.module.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/moods/moods.service.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/sequences/dto/index.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/sequences/sequences.controller.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/sequences/sequences.module.ts delete mode 100644 apps-archived/moodlit/apps/backend/src/sequences/sequences.service.ts delete mode 100644 apps-archived/moodlit/apps/backend/tsconfig.json delete mode 100644 apps-archived/moodlit/apps/mobile/.gitignore delete mode 100644 apps-archived/moodlit/apps/mobile/CLAUDE.md delete mode 100644 apps-archived/moodlit/apps/mobile/app.json delete mode 100644 apps-archived/moodlit/apps/mobile/app/+html.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/+not-found.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/_layout.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/create-mood.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/create-sequence.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/details.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/edit-sequence/[id].tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/index.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/mood/[id].tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/reorder-moods.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/sequence/[id].tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/sequences.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/app/settings.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/assets/adaptive-icon.png delete mode 100644 apps-archived/moodlit/apps/mobile/assets/favicon.png delete mode 100644 apps-archived/moodlit/apps/mobile/assets/icon.png delete mode 100644 apps-archived/moodlit/apps/mobile/assets/mood-light-logo.png delete mode 100644 apps-archived/moodlit/apps/mobile/assets/mood-light.icon/Assets/moods-logo.png delete mode 100644 apps-archived/moodlit/apps/mobile/assets/mood-light.icon/icon.json delete mode 100644 apps-archived/moodlit/apps/mobile/assets/splash.png delete mode 100644 apps-archived/moodlit/apps/mobile/babel.config.js delete mode 100644 apps-archived/moodlit/apps/mobile/cesconfig.jsonc delete mode 100644 apps-archived/moodlit/apps/mobile/components/AnimatedMoodBackground.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/Button.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/Container.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/EditScreenInfo.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/Icon.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/MoodCard.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/ScreenContent.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/components/SequenceCard.tsx delete mode 100644 apps-archived/moodlit/apps/mobile/eas.json delete mode 100644 apps-archived/moodlit/apps/mobile/eslint.config.js delete mode 100644 apps-archived/moodlit/apps/mobile/global.css delete mode 100644 apps-archived/moodlit/apps/mobile/hooks/useFlashlight.ts delete mode 100644 apps-archived/moodlit/apps/mobile/hooks/useResponsive.ts delete mode 100644 apps-archived/moodlit/apps/mobile/metro.config.js delete mode 100644 apps-archived/moodlit/apps/mobile/nativewind-env.d.ts delete mode 100644 apps-archived/moodlit/apps/mobile/package.json delete mode 100644 apps-archived/moodlit/apps/mobile/prettier.config.js delete mode 100644 apps-archived/moodlit/apps/mobile/store/store.ts delete mode 100644 apps-archived/moodlit/apps/mobile/tailwind.config.js delete mode 100644 apps-archived/moodlit/apps/mobile/tsconfig.json delete mode 100644 apps-archived/moodlit/apps/mobile/utils/supabase.ts delete mode 100644 apps-archived/moodlit/apps/mobile/utils/theme.ts delete mode 100644 apps-archived/moodlit/apps/web/package.json delete mode 100644 apps-archived/moodlit/apps/web/src/lib/api/feedback.ts delete mode 100644 apps-archived/moodlit/apps/web/src/lib/auth.ts delete mode 100644 apps-archived/moodlit/apps/web/src/lib/stores/auth.svelte.ts delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(app)/+layout.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(app)/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(app)/feedback/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(app)/sequences/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(auth)/forgot-password/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(auth)/login/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/(auth)/register/+page.svelte delete mode 100644 apps-archived/moodlit/apps/web/src/routes/+layout.svelte delete mode 100644 apps-archived/moodlit/apps/web/svelte.config.js delete mode 100644 apps-archived/moodlit/apps/web/vite.config.ts delete mode 100644 apps-archived/moodlit/package.json create mode 100644 apps/moodlit/CLAUDE.md rename {apps-archived => apps}/moodlit/apps/landing/astro.config.mjs (79%) rename {apps-archived => apps}/moodlit/apps/landing/package.json (100%) rename {apps-archived => apps}/moodlit/apps/landing/src/layouts/Layout.astro (100%) rename {apps-archived => apps}/moodlit/apps/landing/src/pages/index.astro (100%) rename {apps-archived => apps}/moodlit/apps/landing/tailwind.config.mjs (100%) rename {apps-archived => apps}/moodlit/apps/landing/tsconfig.json (100%) rename {apps-archived => apps}/moodlit/apps/landing/wrangler.toml (100%) create mode 100644 apps/moodlit/apps/server/package.json create mode 100644 apps/moodlit/apps/server/src/config.ts create mode 100644 apps/moodlit/apps/server/src/index.ts create mode 100644 apps/moodlit/apps/server/src/lib/errors.ts create mode 100644 apps/moodlit/apps/server/src/middleware/error-handler.ts create mode 100644 apps/moodlit/apps/server/src/middleware/jwt-auth.ts create mode 100644 apps/moodlit/apps/server/src/routes/health.ts create mode 100644 apps/moodlit/apps/server/src/routes/presets.ts create mode 100644 apps/moodlit/apps/server/tsconfig.json rename {apps-archived => apps}/moodlit/apps/web/src/app.css (100%) create mode 100644 apps/moodlit/apps/web/src/app.d.ts rename {apps-archived => apps}/moodlit/apps/web/src/app.html (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/components/AppSlider.svelte (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/components/LanguageSelector.svelte (100%) create mode 100644 apps/moodlit/apps/web/src/lib/components/MoodlitLogo.svelte rename {apps-archived => apps}/moodlit/apps/web/src/lib/components/mood/CreateMoodDialog.svelte (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/components/mood/MoodCard.svelte (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/components/mood/MoodFullscreen.svelte (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/data/default-moods.ts (100%) create mode 100644 apps/moodlit/apps/web/src/lib/data/guest-seed.ts create mode 100644 apps/moodlit/apps/web/src/lib/data/local-store.ts rename {apps-archived => apps}/moodlit/apps/web/src/lib/i18n/index.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/i18n/locales/de.json (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/i18n/locales/en.json (100%) create mode 100644 apps/moodlit/apps/web/src/lib/stores/auth.svelte.ts rename {apps-archived => apps}/moodlit/apps/web/src/lib/stores/moods.svelte.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/stores/navigation.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/stores/sequences.svelte.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/stores/theme.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/types/auth.ts (100%) rename {apps-archived => apps}/moodlit/apps/web/src/lib/types/mood.ts (100%) create mode 100644 apps/moodlit/apps/web/src/routes/(app)/+layout.svelte create mode 100644 apps/moodlit/apps/web/src/routes/(app)/+page.svelte create mode 100644 apps/moodlit/apps/web/src/routes/(app)/moods/+page.svelte create mode 100644 apps/moodlit/apps/web/src/routes/(app)/sequences/+page.svelte rename {apps-archived => apps}/moodlit/apps/web/src/routes/(app)/settings/+page.svelte (100%) create mode 100644 apps/moodlit/apps/web/src/routes/+layout.svelte create mode 100644 apps/moodlit/apps/web/src/routes/auth/login/+page.svelte create mode 100644 apps/moodlit/apps/web/src/routes/auth/register/+page.svelte create mode 100644 apps/moodlit/apps/web/svelte.config.js rename {apps-archived => apps}/moodlit/apps/web/tsconfig.json (100%) create mode 100644 apps/moodlit/apps/web/vite.config.ts create mode 100644 apps/moodlit/package.json diff --git a/CLAUDE.md b/CLAUDE.md index 76cc131a5..0e1da9f6b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,7 @@ For comprehensive guidelines on code patterns and conventions, see the `.claude/ | **wisekeep** | AI transcription & wisdom library | Server, Web, Landing | | **reader** | Text-to-Speech with offline audio | Mobile | | **bauntown** | Developer community website | Landing | +| **moodlit** | Ambient lighting & mood app | Server, Web, Landing | | **calc** | Calculator & converter | Web | | **playground** | LLM playground | Web | diff --git a/apps-archived/moodlit/CLAUDE.md b/apps-archived/moodlit/CLAUDE.md deleted file mode 100644 index a897d80a1..000000000 --- a/apps-archived/moodlit/CLAUDE.md +++ /dev/null @@ -1,295 +0,0 @@ -# Moodlit Project Guide - -## Übersicht - -**Moodlit** ist eine Ambient-Lighting-App, die es Benutzern ermöglicht, benutzerdefinierte Lichtstimmungen mit Farbverläufen und Animationen zu erstellen. Die App unterstützt sowohl bildschirmbasierte Beleuchtung als auch Geräte-Taschenlampensteuerung. - -| App | Port | URL | -|-----|------|-----| -| Backend | 3012 | http://localhost:3012 | -| Web App | 5182 | http://localhost:5182 | -| Landing Page | 4332 | http://localhost:4332 | - -## Project Structure - -``` -apps/moodlit/ -├── apps/ -│ ├── backend/ # NestJS API server (@moodlit/backend) -│ │ └── src/ -│ │ ├── main.ts -│ │ ├── app.module.ts -│ │ ├── db/ -│ │ │ ├── database.module.ts -│ │ │ ├── connection.ts -│ │ │ └── schema/ -│ │ │ ├── moods.schema.ts -│ │ │ └── sequences.schema.ts -│ │ ├── moods/ -│ │ │ ├── moods.module.ts -│ │ │ ├── moods.controller.ts -│ │ │ ├── moods.service.ts -│ │ │ └── dto/ -│ │ ├── sequences/ -│ │ │ ├── sequences.module.ts -│ │ │ ├── sequences.controller.ts -│ │ │ ├── sequences.service.ts -│ │ │ └── dto/ -│ │ └── health/ -│ │ -│ ├── web/ # SvelteKit web app (@moodlit/web) -│ │ └── src/ -│ │ ├── app.html -│ │ ├── app.css -│ │ └── routes/ -│ │ ├── +layout.svelte -│ │ └── +page.svelte -│ │ -│ ├── mobile/ # Expo React Native app (@moodlit/mobile) -│ │ ├── app/ # Expo Router routes -│ │ ├── components/ -│ │ ├── hooks/ -│ │ ├── store/ -│ │ └── utils/ -│ │ -│ └── landing/ # Astro landing page (@moodlit/landing) -│ -├── package.json -└── CLAUDE.md -``` - -## Commands - -### Root Level (from monorepo root) - -```bash -# Alle Apps starten -pnpm moodlit:dev # Run all moodlit apps - -# Einzelne Apps starten -pnpm dev:moodlit:backend # Start backend server (port 3012) -pnpm dev:moodlit:web # Start web app (port 5182) -pnpm dev:moodlit:mobile # Start mobile app -pnpm dev:moodlit:landing # Start landing page (port 4332) -pnpm dev:moodlit:app # Start web + backend together - -# Datenbank -pnpm moodlit:db:push # Push schema to database -pnpm moodlit:db:studio # Open Drizzle Studio -pnpm moodlit:db:seed # Seed initial data - -# Deploy -pnpm deploy:landing:moodlit # Deploy landing to Cloudflare Pages -``` - -### Backend (apps/moodlit/apps/backend) - -```bash -pnpm dev # Start with hot reload -pnpm build # Build for production -pnpm start:prod # Start production server -pnpm db:push # Push schema to database -pnpm db:studio # Open Drizzle Studio -``` - -### Web App (apps/moodlit/apps/web) - -```bash -pnpm dev # Start dev server -pnpm build # Build for production -pnpm preview # Preview production build -``` - -### Mobile App (apps/moodlit/apps/mobile) - -```bash -pnpm dev # Start Expo dev server -pnpm ios # Build and run iOS simulator -pnpm android # Build and run Android emulator -pnpm build:dev # EAS development build -``` - -### Landing Page (apps/moodlit/apps/landing) - -```bash -pnpm dev # Start dev server (port 4332) -pnpm build # Build for production -pnpm preview # Preview build -``` - -## Technology Stack - -| Layer | Technology | -|-------|------------| -| **Backend** | NestJS 10, Drizzle ORM, PostgreSQL | -| **Web** | SvelteKit 2.x, Svelte 5 (runes), Tailwind CSS 4 | -| **Mobile** | Expo SDK 54, React Native 0.81, NativeWind, Zustand | -| **Landing** | Astro 5.x, Tailwind CSS | -| **Auth** | Mana Core Auth (JWT) | - -## Features - -### 1. Mood Library -- Vorkonfigurierte Lichtstimmungen (Fire, Breath, Northern Lights, Thunder, etc.) -- Verschiedene Farbverläufe und Animationstypen -- Standard-Moods für jeden Benutzer - -### 2. Custom Moods -- Erstelle eigene Lichtstimmungen -- Anpassbare Farben und Animationen -- Speichern und Wiederverwenden - -### 3. Sequences -- Mehrere Moods zu einer Sequenz verketten -- Konfigurierbare Dauer und Übergänge -- Automatische Wiedergabe - -### 4. Dual Output -- Bildschirmbasierte Beleuchtung -- Geräte-Taschenlampensteuerung -- Umschalten zwischen Modi - -## API Endpoints - -### Health -``` -GET /api/v1/health # Health check -``` - -### Moods -``` -GET /api/v1/moods # List all moods -POST /api/v1/moods # Create mood -GET /api/v1/moods/:id # Get mood -PUT /api/v1/moods/:id # Update mood -DELETE /api/v1/moods/:id # Delete mood -``` - -### Sequences -``` -GET /api/v1/sequences # List all sequences -POST /api/v1/sequences # Create sequence -GET /api/v1/sequences/:id # Get sequence -PUT /api/v1/sequences/:id # Update sequence -DELETE /api/v1/sequences/:id # Delete sequence -``` - -## Database Schema - -### moods -| Column | Type | Description | -|--------|------|-------------| -| `id` | UUID | Primary key | -| `user_id` | TEXT | Owner | -| `name` | TEXT | Mood name | -| `colors` | JSONB | Array of color hex codes | -| `animation` | TEXT | Animation type | -| `is_default` | BOOLEAN | Default mood flag | -| `created_at` | TIMESTAMP | Created date | -| `updated_at` | TIMESTAMP | Updated date | - -### sequences -| Column | Type | Description | -|--------|------|-------------| -| `id` | UUID | Primary key | -| `user_id` | TEXT | Owner | -| `name` | TEXT | Sequence name | -| `mood_ids` | JSONB | Array of mood IDs | -| `duration` | INTEGER | Duration per mood (seconds) | -| `created_at` | TIMESTAMP | Created date | -| `updated_at` | TIMESTAMP | Updated date | - -## Environment Variables - -### Backend (.env) -```env -NODE_ENV=development -PORT=3012 -DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/moods -MANA_CORE_AUTH_URL=http://localhost:3001 -CORS_ORIGINS=http://localhost:5173,http://localhost:5182,http://localhost:8081 -DEV_BYPASS_AUTH=true -DEV_USER_ID=your-test-user-id -``` - -### Web (.env) -```env -PUBLIC_BACKEND_URL=http://localhost:3012 -PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001 -``` - -### Mobile (.env) -```env -EXPO_PUBLIC_BACKEND_URL=http://localhost:3012 -EXPO_PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001 -``` - -## Quick Start - -### 1. Datenbank erstellen - -```bash -# PostgreSQL Container muss laufen -docker compose -f docker-compose.dev.yml up -d postgres - -# Datenbank erstellen -PGPASSWORD=devpassword psql -h localhost -U manacore -d postgres -c "CREATE DATABASE moods;" - -# Schema pushen -pnpm moodlit:db:push -``` - -### 2. Apps starten - -```bash -# Backend + Web zusammen -pnpm dev:moodlit:app - -# Oder einzeln: -pnpm dev:moodlit:backend # Terminal 1 -pnpm dev:moodlit:web # Terminal 2 -pnpm dev:moodlit:mobile # Terminal 3 -pnpm dev:moodlit:landing # Terminal 4 (optional) -``` - -### 3. URLs öffnen - -- Web App: http://localhost:5182 -- Landing: http://localhost:4332 -- API Health: http://localhost:3012/api/v1/health - -## Testing API (mit curl) - -```bash -# Health Check -curl http://localhost:3012/api/v1/health - -# Login (get token) -TOKEN=$(curl -s -X POST http://localhost:3001/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email": "test@example.com", "password": "password"}' | jq -r '.accessToken') - -# Moods abrufen -curl http://localhost:3012/api/v1/moods \ - -H "Authorization: Bearer $TOKEN" - -# Neues Mood erstellen -curl -X POST http://localhost:3012/api/v1/moods \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"name": "Sunset", "colors": ["#ff6b6b", "#feca57", "#ff9ff3"], "animation": "gradient"}' - -# Sequence erstellen -curl -X POST http://localhost:3012/api/v1/sequences \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"name": "Evening Flow", "moodIds": ["mood-id-1", "mood-id-2"], "duration": 30}' -``` - -## Important Notes - -1. **Authentication**: Nutzt Mana Core Auth (JWT im Authorization Header) -2. **Database**: PostgreSQL mit Drizzle ORM (Port 5432) -3. **Port**: Backend läuft auf Port 3012, Web auf 5182, Landing auf 4332 -4. **Mobile**: Verwendet Expo Dev Client (nicht Expo Go) wegen nativer Dependencies -5. **Theme**: Purple/Violet als Primärfarbe für die Mood-Thematik diff --git a/apps-archived/moodlit/apps/backend/drizzle.config.ts b/apps-archived/moodlit/apps/backend/drizzle.config.ts deleted file mode 100644 index 64eae1e4c..000000000 --- a/apps-archived/moodlit/apps/backend/drizzle.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'drizzle-kit'; - -export default defineConfig({ - dialect: 'postgresql', - schema: './src/db/schema/index.ts', - out: './src/db/migrations', - dbCredentials: { - url: process.env.DATABASE_URL || 'postgresql://manacore:devpassword@localhost:5432/moods', - }, - verbose: true, - strict: true, -}); diff --git a/apps-archived/moodlit/apps/backend/nest-cli.json b/apps-archived/moodlit/apps/backend/nest-cli.json deleted file mode 100644 index 95538fb90..000000000 --- a/apps-archived/moodlit/apps/backend/nest-cli.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/nest-cli", - "collection": "@nestjs/schematics", - "sourceRoot": "src", - "compilerOptions": { - "deleteOutDir": true - } -} diff --git a/apps-archived/moodlit/apps/backend/package.json b/apps-archived/moodlit/apps/backend/package.json deleted file mode 100644 index bc2daa683..000000000 --- a/apps-archived/moodlit/apps/backend/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@moodlit/backend", - "version": "1.0.0", - "private": true, - "scripts": { - "build": "nest build", - "start": "nest start", - "dev": "nest start --watch", - "start:dev": "nest start --watch", - "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "type-check": "tsc --noEmit", - "migration:generate": "drizzle-kit generate", - "migration:run": "tsx src/db/migrate.ts", - "db:push": "drizzle-kit push", - "db:studio": "drizzle-kit studio", - "db:seed": "tsx src/db/seed.ts" - }, - "dependencies": { - "@manacore/shared-nestjs-auth": "workspace:*", - "@nestjs/common": "^10.4.15", - "@nestjs/config": "^3.3.0", - "@nestjs/core": "^10.4.15", - "@nestjs/platform-express": "^10.4.15", - "class-transformer": "^0.5.1", - "class-validator": "^0.14.1", - "dotenv": "^16.4.7", - "drizzle-kit": "^0.30.2", - "drizzle-orm": "^0.38.3", - "postgres": "^3.4.5", - "reflect-metadata": "^0.2.2", - "rxjs": "^7.8.1" - }, - "devDependencies": { - "@nestjs/cli": "^10.4.9", - "@nestjs/schematics": "^10.2.3", - "@types/express": "^5.0.0", - "@types/node": "^22.10.2", - "@typescript-eslint/eslint-plugin": "^8.18.1", - "@typescript-eslint/parser": "^8.18.1", - "eslint": "^9.17.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", - "prettier": "^3.4.2", - "source-map-support": "^0.5.21", - "ts-loader": "^9.5.1", - "ts-node": "^10.9.2", - "tsconfig-paths": "^4.2.0", - "tsx": "^4.19.2", - "typescript": "^5.7.2" - } -} diff --git a/apps-archived/moodlit/apps/backend/src/app.module.ts b/apps-archived/moodlit/apps/backend/src/app.module.ts deleted file mode 100644 index ec1932d98..000000000 --- a/apps-archived/moodlit/apps/backend/src/app.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { DatabaseModule } from './db/database.module'; -import { HealthModule } from './health/health.module'; -import { MoodsModule } from './moods/moods.module'; -import { SequencesModule } from './sequences/sequences.module'; - -@Module({ - imports: [ - ConfigModule.forRoot({ - isGlobal: true, - envFilePath: '.env', - }), - DatabaseModule, - HealthModule, - MoodsModule, - SequencesModule, - ], -}) -export class AppModule {} diff --git a/apps-archived/moodlit/apps/backend/src/db/connection.ts b/apps-archived/moodlit/apps/backend/src/db/connection.ts deleted file mode 100644 index fcdeb9016..000000000 --- a/apps-archived/moodlit/apps/backend/src/db/connection.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { drizzle } from 'drizzle-orm/postgres-js'; -import * as schema from './schema'; - -// Use require for postgres to avoid ESM/CommonJS interop issues - -const postgres = require('postgres'); - -let connection: ReturnType | null = null; -let db: ReturnType | null = null; - -export function getConnection(databaseUrl: string) { - if (!connection) { - connection = postgres(databaseUrl, { - max: 10, - idle_timeout: 20, - connect_timeout: 10, - }); - } - return connection; -} - -export function getDb(databaseUrl: string) { - if (!db) { - const conn = getConnection(databaseUrl); - db = drizzle(conn, { schema }); - } - return db; -} - -export async function closeConnection() { - if (connection) { - await connection.end(); - connection = null; - db = null; - } -} - -export type Database = ReturnType; diff --git a/apps-archived/moodlit/apps/backend/src/db/database.module.ts b/apps-archived/moodlit/apps/backend/src/db/database.module.ts deleted file mode 100644 index 5a0a033b3..000000000 --- a/apps-archived/moodlit/apps/backend/src/db/database.module.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Module, Global, OnModuleDestroy } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { getDb, closeConnection } from './connection'; -import type { Database } from './connection'; - -export const DATABASE_CONNECTION = 'DATABASE_CONNECTION'; - -@Global() -@Module({ - providers: [ - { - provide: DATABASE_CONNECTION, - useFactory: (configService: ConfigService): Database => { - const databaseUrl = configService.get('DATABASE_URL'); - if (!databaseUrl) { - throw new Error('DATABASE_URL environment variable is not set'); - } - return getDb(databaseUrl); - }, - inject: [ConfigService], - }, - ], - exports: [DATABASE_CONNECTION], -}) -export class DatabaseModule implements OnModuleDestroy { - async onModuleDestroy() { - await closeConnection(); - } -} diff --git a/apps-archived/moodlit/apps/backend/src/db/schema/index.ts b/apps-archived/moodlit/apps/backend/src/db/schema/index.ts deleted file mode 100644 index 8d2070194..000000000 --- a/apps-archived/moodlit/apps/backend/src/db/schema/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './moods.schema'; -export * from './sequences.schema'; diff --git a/apps-archived/moodlit/apps/backend/src/db/schema/moods.schema.ts b/apps-archived/moodlit/apps/backend/src/db/schema/moods.schema.ts deleted file mode 100644 index 1e31e0e3a..000000000 --- a/apps-archived/moodlit/apps/backend/src/db/schema/moods.schema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { pgTable, uuid, text, jsonb, boolean, timestamp } from 'drizzle-orm/pg-core'; - -export const moods = pgTable('moods', { - id: uuid('id').primaryKey().defaultRandom(), - userId: text('user_id').notNull(), - name: text('name').notNull(), - colors: jsonb('colors').notNull().$type(), - animation: text('animation'), - isDefault: boolean('is_default').default(false), - createdAt: timestamp('created_at').defaultNow(), - updatedAt: timestamp('updated_at').defaultNow(), -}); - -export type Mood = typeof moods.$inferSelect; -export type NewMood = typeof moods.$inferInsert; diff --git a/apps-archived/moodlit/apps/backend/src/db/schema/sequences.schema.ts b/apps-archived/moodlit/apps/backend/src/db/schema/sequences.schema.ts deleted file mode 100644 index 263238f3f..000000000 --- a/apps-archived/moodlit/apps/backend/src/db/schema/sequences.schema.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { pgTable, uuid, text, jsonb, integer, timestamp } from 'drizzle-orm/pg-core'; - -export const sequences = pgTable('sequences', { - id: uuid('id').primaryKey().defaultRandom(), - userId: text('user_id').notNull(), - name: text('name').notNull(), - moodIds: jsonb('mood_ids').notNull().$type(), - duration: integer('duration').default(30), - createdAt: timestamp('created_at').defaultNow(), - updatedAt: timestamp('updated_at').defaultNow(), -}); - -export type Sequence = typeof sequences.$inferSelect; -export type NewSequence = typeof sequences.$inferInsert; diff --git a/apps-archived/moodlit/apps/backend/src/health/health.controller.ts b/apps-archived/moodlit/apps/backend/src/health/health.controller.ts deleted file mode 100644 index 47b440bdc..000000000 --- a/apps-archived/moodlit/apps/backend/src/health/health.controller.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Controller, Get } from '@nestjs/common'; - -@Controller('health') -export class HealthController { - @Get() - check() { - return { - status: 'ok', - timestamp: new Date().toISOString(), - service: 'moods-backend', - }; - } -} diff --git a/apps-archived/moodlit/apps/backend/src/health/health.module.ts b/apps-archived/moodlit/apps/backend/src/health/health.module.ts deleted file mode 100644 index a61d8b044..000000000 --- a/apps-archived/moodlit/apps/backend/src/health/health.module.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Module } from '@nestjs/common'; -import { HealthController } from './health.controller'; - -@Module({ - controllers: [HealthController], -}) -export class HealthModule {} diff --git a/apps-archived/moodlit/apps/backend/src/main.ts b/apps-archived/moodlit/apps/backend/src/main.ts deleted file mode 100644 index 4c7ef872a..000000000 --- a/apps-archived/moodlit/apps/backend/src/main.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { NestFactory } from '@nestjs/core'; -import { ValidationPipe } from '@nestjs/common'; -import { AppModule } from './app.module'; - -async function bootstrap() { - const app = await NestFactory.create(AppModule); - - // Enable CORS for mobile and web apps - const corsOrigins = process.env.CORS_ORIGINS?.split(',').map((origin) => origin.trim()) || [ - 'http://localhost:3000', - 'http://localhost:5173', - 'http://localhost:5182', - 'http://localhost:8081', - 'exp://localhost:8081', - 'http://localhost:3001', - ]; - - app.enableCors({ - origin: corsOrigins, - methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], - credentials: true, - }); - - // Enable validation - app.useGlobalPipes( - new ValidationPipe({ - whitelist: true, - transform: true, - forbidNonWhitelisted: true, - }) - ); - - // Set global prefix for API routes - app.setGlobalPrefix('api/v1'); - - const port = process.env.PORT || 3012; - await app.listen(port); - console.log(`Moods backend running on http://localhost:${port}`); -} -bootstrap(); diff --git a/apps-archived/moodlit/apps/backend/src/moods/dto/index.ts b/apps-archived/moodlit/apps/backend/src/moods/dto/index.ts deleted file mode 100644 index 62c60e9e7..000000000 --- a/apps-archived/moodlit/apps/backend/src/moods/dto/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { IsString, IsArray, IsBoolean, IsOptional } from 'class-validator'; - -export class CreateMoodDto { - @IsString() - name: string; - - @IsArray() - @IsString({ each: true }) - colors: string[]; - - @IsString() - @IsOptional() - animation?: string; - - @IsBoolean() - @IsOptional() - isDefault?: boolean; -} - -export class UpdateMoodDto { - @IsString() - @IsOptional() - name?: string; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - colors?: string[]; - - @IsString() - @IsOptional() - animation?: string; - - @IsBoolean() - @IsOptional() - isDefault?: boolean; -} diff --git a/apps-archived/moodlit/apps/backend/src/moods/moods.controller.ts b/apps-archived/moodlit/apps/backend/src/moods/moods.controller.ts deleted file mode 100644 index cf9f98c08..000000000 --- a/apps-archived/moodlit/apps/backend/src/moods/moods.controller.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards } from '@nestjs/common'; -import { JwtAuthGuard, CurrentUser, CurrentUserData } from '@manacore/shared-nestjs-auth'; -import { MoodsService } from './moods.service'; -import { CreateMoodDto, UpdateMoodDto } from './dto'; - -@Controller('moods') -@UseGuards(JwtAuthGuard) -export class MoodsController { - constructor(private readonly moodsService: MoodsService) {} - - @Get() - async findAll(@CurrentUser() user: CurrentUserData) { - return this.moodsService.findAllByUser(user.userId); - } - - @Get(':id') - async findOne(@Param('id') id: string, @CurrentUser() user: CurrentUserData) { - return this.moodsService.findOne(id, user.userId); - } - - @Post() - async create(@Body() dto: CreateMoodDto, @CurrentUser() user: CurrentUserData) { - return this.moodsService.create(user.userId, dto); - } - - @Put(':id') - async update( - @Param('id') id: string, - @Body() dto: UpdateMoodDto, - @CurrentUser() user: CurrentUserData - ) { - return this.moodsService.update(id, user.userId, dto); - } - - @Delete(':id') - async delete(@Param('id') id: string, @CurrentUser() user: CurrentUserData) { - await this.moodsService.delete(id, user.userId); - return { success: true }; - } -} diff --git a/apps-archived/moodlit/apps/backend/src/moods/moods.module.ts b/apps-archived/moodlit/apps/backend/src/moods/moods.module.ts deleted file mode 100644 index fee9f966b..000000000 --- a/apps-archived/moodlit/apps/backend/src/moods/moods.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { MoodsController } from './moods.controller'; -import { MoodsService } from './moods.service'; - -@Module({ - controllers: [MoodsController], - providers: [MoodsService], - exports: [MoodsService], -}) -export class MoodsModule {} diff --git a/apps-archived/moodlit/apps/backend/src/moods/moods.service.ts b/apps-archived/moodlit/apps/backend/src/moods/moods.service.ts deleted file mode 100644 index 05d8df37e..000000000 --- a/apps-archived/moodlit/apps/backend/src/moods/moods.service.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Injectable, Inject, NotFoundException } from '@nestjs/common'; -import { eq, and } from 'drizzle-orm'; -import { DATABASE_CONNECTION } from '../db/database.module'; -import { type Database } from '../db/connection'; -import { moods, type Mood, type NewMood } from '../db/schema/moods.schema'; -import { CreateMoodDto, UpdateMoodDto } from './dto'; - -@Injectable() -export class MoodsService { - constructor(@Inject(DATABASE_CONNECTION) private db: Database) {} - - async findAllByUser(userId: string): Promise { - return this.db.select().from(moods).where(eq(moods.userId, userId)); - } - - async findOne(id: string, userId: string): Promise { - const [mood] = await this.db - .select() - .from(moods) - .where(and(eq(moods.id, id), eq(moods.userId, userId))); - - if (!mood) { - throw new NotFoundException(`Mood with ID ${id} not found`); - } - - return mood; - } - - async create(userId: string, dto: CreateMoodDto): Promise { - const newMood: NewMood = { - userId, - name: dto.name, - colors: dto.colors, - animation: dto.animation, - isDefault: dto.isDefault ?? false, - }; - - const [mood] = await this.db.insert(moods).values(newMood).returning(); - return mood; - } - - async update(id: string, userId: string, dto: UpdateMoodDto): Promise { - // Verify the mood exists and belongs to the user - await this.findOne(id, userId); - - const [updated] = await this.db - .update(moods) - .set({ - ...dto, - updatedAt: new Date(), - }) - .where(and(eq(moods.id, id), eq(moods.userId, userId))) - .returning(); - - return updated; - } - - async delete(id: string, userId: string): Promise { - // Verify the mood exists and belongs to the user - await this.findOne(id, userId); - - await this.db.delete(moods).where(and(eq(moods.id, id), eq(moods.userId, userId))); - } -} diff --git a/apps-archived/moodlit/apps/backend/src/sequences/dto/index.ts b/apps-archived/moodlit/apps/backend/src/sequences/dto/index.ts deleted file mode 100644 index f97a818a4..000000000 --- a/apps-archived/moodlit/apps/backend/src/sequences/dto/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IsString, IsArray, IsNumber, IsOptional } from 'class-validator'; - -export class CreateSequenceDto { - @IsString() - name: string; - - @IsArray() - @IsString({ each: true }) - moodIds: string[]; - - @IsNumber() - @IsOptional() - duration?: number; -} - -export class UpdateSequenceDto { - @IsString() - @IsOptional() - name?: string; - - @IsArray() - @IsString({ each: true }) - @IsOptional() - moodIds?: string[]; - - @IsNumber() - @IsOptional() - duration?: number; -} diff --git a/apps-archived/moodlit/apps/backend/src/sequences/sequences.controller.ts b/apps-archived/moodlit/apps/backend/src/sequences/sequences.controller.ts deleted file mode 100644 index b646af262..000000000 --- a/apps-archived/moodlit/apps/backend/src/sequences/sequences.controller.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards } from '@nestjs/common'; -import { JwtAuthGuard, CurrentUser, CurrentUserData } from '@manacore/shared-nestjs-auth'; -import { SequencesService } from './sequences.service'; -import { CreateSequenceDto, UpdateSequenceDto } from './dto'; - -@Controller('sequences') -@UseGuards(JwtAuthGuard) -export class SequencesController { - constructor(private readonly sequencesService: SequencesService) {} - - @Get() - async findAll(@CurrentUser() user: CurrentUserData) { - return this.sequencesService.findAllByUser(user.userId); - } - - @Get(':id') - async findOne(@Param('id') id: string, @CurrentUser() user: CurrentUserData) { - return this.sequencesService.findOne(id, user.userId); - } - - @Post() - async create(@Body() dto: CreateSequenceDto, @CurrentUser() user: CurrentUserData) { - return this.sequencesService.create(user.userId, dto); - } - - @Put(':id') - async update( - @Param('id') id: string, - @Body() dto: UpdateSequenceDto, - @CurrentUser() user: CurrentUserData - ) { - return this.sequencesService.update(id, user.userId, dto); - } - - @Delete(':id') - async delete(@Param('id') id: string, @CurrentUser() user: CurrentUserData) { - await this.sequencesService.delete(id, user.userId); - return { success: true }; - } -} diff --git a/apps-archived/moodlit/apps/backend/src/sequences/sequences.module.ts b/apps-archived/moodlit/apps/backend/src/sequences/sequences.module.ts deleted file mode 100644 index 37e5cfcb7..000000000 --- a/apps-archived/moodlit/apps/backend/src/sequences/sequences.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { SequencesController } from './sequences.controller'; -import { SequencesService } from './sequences.service'; - -@Module({ - controllers: [SequencesController], - providers: [SequencesService], - exports: [SequencesService], -}) -export class SequencesModule {} diff --git a/apps-archived/moodlit/apps/backend/src/sequences/sequences.service.ts b/apps-archived/moodlit/apps/backend/src/sequences/sequences.service.ts deleted file mode 100644 index 1506028fc..000000000 --- a/apps-archived/moodlit/apps/backend/src/sequences/sequences.service.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Injectable, Inject, NotFoundException } from '@nestjs/common'; -import { eq, and } from 'drizzle-orm'; -import { DATABASE_CONNECTION } from '../db/database.module'; -import { type Database } from '../db/connection'; -import { sequences, type Sequence, type NewSequence } from '../db/schema/sequences.schema'; -import { CreateSequenceDto, UpdateSequenceDto } from './dto'; - -@Injectable() -export class SequencesService { - constructor(@Inject(DATABASE_CONNECTION) private db: Database) {} - - async findAllByUser(userId: string): Promise { - return this.db.select().from(sequences).where(eq(sequences.userId, userId)); - } - - async findOne(id: string, userId: string): Promise { - const [sequence] = await this.db - .select() - .from(sequences) - .where(and(eq(sequences.id, id), eq(sequences.userId, userId))); - - if (!sequence) { - throw new NotFoundException(`Sequence with ID ${id} not found`); - } - - return sequence; - } - - async create(userId: string, dto: CreateSequenceDto): Promise { - const newSequence: NewSequence = { - userId, - name: dto.name, - moodIds: dto.moodIds, - duration: dto.duration ?? 30, - }; - - const [sequence] = await this.db.insert(sequences).values(newSequence).returning(); - return sequence; - } - - async update(id: string, userId: string, dto: UpdateSequenceDto): Promise { - // Verify the sequence exists and belongs to the user - await this.findOne(id, userId); - - const [updated] = await this.db - .update(sequences) - .set({ - ...dto, - updatedAt: new Date(), - }) - .where(and(eq(sequences.id, id), eq(sequences.userId, userId))) - .returning(); - - return updated; - } - - async delete(id: string, userId: string): Promise { - // Verify the sequence exists and belongs to the user - await this.findOne(id, userId); - - await this.db.delete(sequences).where(and(eq(sequences.id, id), eq(sequences.userId, userId))); - } -} diff --git a/apps-archived/moodlit/apps/backend/tsconfig.json b/apps-archived/moodlit/apps/backend/tsconfig.json deleted file mode 100644 index 44b209041..000000000 --- a/apps-archived/moodlit/apps/backend/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "declaration": true, - "removeComments": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "allowSyntheticDefaultImports": true, - "target": "ES2021", - "sourceMap": true, - "outDir": "./dist", - "baseUrl": "./", - "incremental": true, - "skipLibCheck": true, - "strictNullChecks": true, - "noImplicitAny": false, - "strictBindCallApply": false, - "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false, - "moduleResolution": "node", - "resolveJsonModule": true, - "esModuleInterop": true - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/apps-archived/moodlit/apps/mobile/.gitignore b/apps-archived/moodlit/apps/mobile/.gitignore deleted file mode 100644 index 1861e0868..000000000 --- a/apps-archived/moodlit/apps/mobile/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -node_modules/ -.expo/ -dist/ -npm-debug.* -*.jks -*.p8 -*.p12 -*.key -*.mobileprovision -*.orig.* -web-build/ -# expo router -expo-env.d.ts - -# firebase/supabase/vexo -.env - -ios -android - -# macOS -.DS_Store - -# Temporary files created by Metro to check the health of the file watcher -.metro-health-check* \ No newline at end of file diff --git a/apps-archived/moodlit/apps/mobile/CLAUDE.md b/apps-archived/moodlit/apps/mobile/CLAUDE.md deleted file mode 100644 index bf2917d95..000000000 --- a/apps-archived/moodlit/apps/mobile/CLAUDE.md +++ /dev/null @@ -1,95 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -**Moodlit** is a React Native mobile application built with Expo Router, targeting iOS and Android platforms. The app creates ambient lighting effects using the device's screen and flashlight with customizable color gradients and animations. It uses NativeWind (TailwindCSS for React Native) for styling and Zustand for state management. - -### Key Features -- **Mood Library**: Pre-configured lighting moods (Fire, Breath, Northern Lights, Thunder, etc.) with different color gradients and animation types -- **Custom Moods**: Create custom lighting effects with personalized colors and animations -- **Sequences**: Chain multiple moods together with configurable durations and transitions -- **Dual Output**: Toggle between screen-based lighting and device flashlight -- **Settings**: Adjustable animation speed, haptic feedback, brightness, and auto-timer functionality - -## Development Commands - -### Starting the Development Server -```bash -npm start # Start Expo dev server with dev client -npm run ios # Build and run on iOS simulator -npm run android # Build and run on Android emulator -npm run web # Run web version -``` - -### Building -```bash -npm run prebuild # Generate native directories for iOS/Android -npm run build:dev # Build development build via EAS -npm run build:preview # Build preview version via EAS -npm run build:prod # Build production version via EAS -``` - -### Code Quality -```bash -npm run lint # Run ESLint and Prettier check -npm run format # Auto-fix with ESLint and format with Prettier -``` - -## Architecture - -### Routing -- **Expo Router** (file-based routing): Routes are defined by file structure in the `app/` directory - - `app/_layout.tsx`: Root layout component that wraps all screens - - `app/index.tsx`: Home screen - - `app/details.tsx`: Details screen - - Route navigation uses `expo-router` Link component with typed routes enabled - -### State Management -- **Zustand**: Global state management in `store/store.ts` - - Store definitions follow a pattern of state + action methods - - Example store structure includes state interface and create function - -### Backend Integration -- **Supabase Client**: Configured in `utils/supabase.ts` - - Uses AsyncStorage for session persistence - - Environment variables required: - - `EXPO_PUBLIC_SUPABASE_URL` - - `EXPO_PUBLIC_SUPABASE_ANON_KEY` - - Auto-refresh tokens and persistent sessions enabled - -### Styling System -- **NativeWind**: TailwindCSS for React Native - - Global styles imported via `global.css` in root layout - - Tailwind config includes `app/**` and `components/**` content paths - - Styles defined as string literals with `className` prop (not `style`) - - Example: `className="flex flex-1 bg-white"` - -### Path Aliases -- TypeScript configured with `@/*` path alias mapping to root directory -- Import components/utils with `@/components/...` or `@/utils/...` - -### Components Structure -- Reusable components in `components/` directory: - - `Button.tsx`: Touchable button component - - `Container.tsx`: Layout wrapper - - `ScreenContent.tsx`: Screen template with title and separator - - `EditScreenInfo.tsx`: Info display component - -## Key Configuration Files - -- `app.json`: Expo configuration with typed routes and tsconfigPaths experiments enabled -- `tsconfig.json`: TypeScript with strict mode and path aliases -- `tailwind.config.js`: NativeWind preset with custom content paths -- `babel.config.js`: Babel configuration for Expo -- `metro.config.js`: Metro bundler configuration -- `.env`: Environment variables (not committed, contains Supabase credentials) - -## Development Notes - -- This project uses React 19.1.0 and React Native 0.81.5 -- Expo SDK version 54 -- TypeScript strict mode is enabled -- The app requires Expo Dev Client (not Expo Go) due to custom native dependencies -- Web support is available via Metro bundler with static output diff --git a/apps-archived/moodlit/apps/mobile/app.json b/apps-archived/moodlit/apps/mobile/app.json deleted file mode 100644 index ea43e7168..000000000 --- a/apps-archived/moodlit/apps/mobile/app.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "expo": { - "name": "Moodlit", - "slug": "moods", - "version": "1.0.0", - "scheme": "moods", - "platforms": ["ios", "android"], - "web": { - "bundler": "metro", - "output": "static", - "favicon": "./assets/favicon.png" - }, - "plugins": [ - "expo-router", - [ - "expo-camera", - { - "cameraPermission": "Erlaubt $(PRODUCT_NAME) die Kamera für die Taschenlampen-Funktion zu nutzen." - } - ], - [ - "expo-splash-screen", - { - "backgroundColor": "#000000", - "image": "./assets/splash.png", - "imageWidth": 200 - } - ] - ], - "experiments": { - "typedRoutes": true, - "tsconfigPaths": true - }, - "orientation": "default", - "icon": "./assets/mood-light-logo.png", - "userInterfaceStyle": "dark", - "assetBundlePatterns": ["**/*"], - "ios": { - "supportsTablet": true, - "requireFullScreen": false, - "bundleIdentifier": "com.tilljs.moodlight", - "icon": "./assets/mood-light.icon", - "infoPlist": { - "ITSAppUsesNonExemptEncryption": false, - "UIRequiresFullScreen": false, - "UIUserInterfaceStyle": "Dark", - "UISupportedInterfaceOrientations": [ - "UIInterfaceOrientationPortrait", - "UIInterfaceOrientationLandscapeLeft", - "UIInterfaceOrientationLandscapeRight" - ], - "UISupportedInterfaceOrientations~ipad": [ - "UIInterfaceOrientationPortrait", - "UIInterfaceOrientationPortraitUpsideDown", - "UIInterfaceOrientationLandscapeLeft", - "UIInterfaceOrientationLandscapeRight" - ] - } - }, - "android": { - "adaptiveIcon": { - "foregroundImage": "./assets/mood-light-logo.png", - "backgroundColor": "#000000" - }, - "package": "com.tilljs.moodlight", - "permissions": [ - "CAMERA", - "FLASHLIGHT", - "android.permission.CAMERA", - "android.permission.RECORD_AUDIO" - ] - }, - "extra": { - "router": {}, - "eas": { - "projectId": "faec0f17-97e2-4be5-9a85-d281b5635e7a" - } - }, - "owner": "memoro" - } -} diff --git a/apps-archived/moodlit/apps/mobile/app/+html.tsx b/apps-archived/moodlit/apps/mobile/app/+html.tsx deleted file mode 100644 index 447d6a0a5..000000000 --- a/apps-archived/moodlit/apps/mobile/app/+html.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { ScrollViewStyleReset } from 'expo-router/html'; - -// This file is web-only and used to configure the root HTML for every -// web page during static rendering. -// The contents of this function only run in Node.js environments and -// do not have access to the DOM or browser APIs. -export default function Root({ children }: { children: React.ReactNode }) { - return ( - - - - - - {/* - This viewport disables scaling which makes the mobile website act more like a native app. - However this does reduce built-in accessibility. If you want to enable scaling, use this instead: - - */} - - {/* - Disable body scrolling on web. This makes ScrollView components work closer to how they do on native. - However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line. - */} - - - {/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */} -