Clock Project Guide
Übersicht
Clock ist eine vollständige Uhren-App mit Weltzeituhr, Wecker, Timer, Stoppuhr und Pomodoro. Die App synchronisiert Wecker und Timer zwischen Geräten über ein Backend.
Project Structure
apps/clock/
├── apps/
│ ├── backend/ # NestJS API server (@clock/backend)
│ │ └── src/
│ │ ├── main.ts
│ │ ├── app.module.ts
│ │ ├── db/
│ │ │ ├── database.module.ts
│ │ │ ├── connection.ts
│ │ │ ├── schema/
│ │ │ │ ├── alarms.schema.ts
│ │ │ │ ├── timers.schema.ts
│ │ │ │ ├── world-clocks.schema.ts
│ │ │ │ └── presets.schema.ts
│ │ │ └── seed.ts
│ │ ├── alarm/
│ │ ├── timer/
│ │ ├── world-clock/
│ │ ├── preset/
│ │ └── health/
│ │
│ ├── web/ # SvelteKit web app (@clock/web)
│ │ └── src/
│ │ ├── lib/
│ │ │ ├── api/
│ │ │ ├── stores/
│ │ │ ├── components/
│ │ │ └── i18n/
│ │ └── routes/
│ │ ├── +layout.svelte
│ │ ├── +page.svelte # Dashboard
│ │ ├── alarms/
│ │ ├── timers/
│ │ ├── stopwatch/
│ │ ├── pomodoro/
│ │ ├── world-clock/
│ │ ├── settings/
│ │ ├── feedback/
│ │ └── (auth)/
│ │
│ └── landing/ # Astro landing page (@clock/landing)
│
├── packages/
│ └── shared/ # Shared types & constants (@clock/shared)
│
├── package.json
└── CLAUDE.md
Commands
Root Level (from monorepo root)
# Alle Apps starten
pnpm clock:dev # Run all clock apps
# Einzelne Apps starten
pnpm dev:clock:backend # Start backend server (port 3017)
pnpm dev:clock:web # Start web app (port 5187)
pnpm dev:clock:landing # Start landing page (port 4323)
pnpm dev:clock:app # Start web + backend together
# Datenbank
pnpm clock:db:push # Push schema to database
pnpm clock:db:studio # Open Drizzle Studio
pnpm clock:db:seed # Seed initial data
# Deploy
pnpm deploy:landing:clock # Deploy landing to Cloudflare Pages
Backend (apps/clock/apps/backend)
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
pnpm db:seed # Seed initial data
Web App (apps/clock/apps/web)
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
Landing Page (apps/clock/apps/landing)
pnpm dev # Start dev server (port 4323)
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 |
| Landing |
Astro 5.x, Tailwind CSS |
| Auth |
Mana Core Auth (JWT) |
| i18n |
svelte-i18n (DE, EN, FR, ES, IT) |
Features
1. Weltzeituhr
- Zeitzonen-Übersicht mit mehreren Städten
- Zeitdifferenz zum lokalen Standort
- Tag/Nacht-Indikator
- Drag & Drop Sortierung
2. Wecker
- Erstelle/Bearbeite/Lösche Wecker
- Wiederholende Wecker (Wochentage wählen)
- Snooze-Funktion (konfigurierbar)
- Verschiedene Alarm-Sounds
- Cross-Device Sync
3. Timer
- Multiple Timer gleichzeitig
- Timer-Presets (Quick Select)
- Cross-Device Sync für aktive Timer
- Start/Pause/Reset Kontrollen
4. Stoppuhr
- Präzise Zeitmessung
- Rundenzeiten mit Best/Worst Markierung
- Lokal-only (kein Sync nötig)
5. Pomodoro
- Arbeit/Pause Zyklen
- Anpassbare Intervalle
- Preset-Auswahl (Klassisch, Kurzer Fokus, Tiefe Arbeit)
- Push-Benachrichtigungen
API Endpoints
Health
GET /api/v1/health # Health check
Alarms
GET /api/v1/alarms # List all alarms
POST /api/v1/alarms # Create alarm
GET /api/v1/alarms/:id # Get alarm
PUT /api/v1/alarms/:id # Update alarm
DELETE /api/v1/alarms/:id # Delete alarm
PATCH /api/v1/alarms/:id/toggle # Toggle enabled
Timers
GET /api/v1/timers # List all timers
POST /api/v1/timers # Create timer
GET /api/v1/timers/:id # Get timer
PUT /api/v1/timers/:id # Update timer
DELETE /api/v1/timers/:id # Delete timer
POST /api/v1/timers/:id/start # Start timer
POST /api/v1/timers/:id/pause # Pause timer
POST /api/v1/timers/:id/reset # Reset timer
World Clocks
GET /api/v1/world-clocks # List world clocks
POST /api/v1/world-clocks # Add city
DELETE /api/v1/world-clocks/:id # Remove city
PUT /api/v1/world-clocks/reorder # Reorder cities
GET /api/v1/timezones/search # Search timezones
Presets
GET /api/v1/presets # List presets
POST /api/v1/presets # Create preset
PUT /api/v1/presets/:id # Update preset
DELETE /api/v1/presets/:id # Delete preset
Database Schema
alarms
| Column |
Type |
Description |
id |
UUID |
Primary key |
user_id |
UUID |
Owner |
label |
VARCHAR(255) |
Alarm name |
time |
TIME |
Alarm time (HH:MM:SS) |
enabled |
BOOLEAN |
Active flag |
repeat_days |
INT[] |
[0-6] für Wochentage |
snooze_minutes |
INTEGER |
Snooze duration |
sound |
VARCHAR(100) |
Sound identifier |
vibrate |
BOOLEAN |
Vibration enabled |
timers
| Column |
Type |
Description |
id |
UUID |
Primary key |
user_id |
UUID |
Owner |
label |
VARCHAR(255) |
Timer name |
duration_seconds |
INTEGER |
Total duration |
remaining_seconds |
INTEGER |
Time left |
status |
VARCHAR(20) |
idle/running/paused/finished |
sound |
VARCHAR(100) |
Sound identifier |
world_clocks
| Column |
Type |
Description |
id |
UUID |
Primary key |
user_id |
UUID |
Owner |
timezone |
VARCHAR(100) |
IANA timezone |
city_name |
VARCHAR(255) |
Display name |
sort_order |
INTEGER |
Display order |
presets
| Column |
Type |
Description |
id |
UUID |
Primary key |
user_id |
UUID |
Owner |
type |
VARCHAR(20) |
timer/pomodoro |
name |
VARCHAR(255) |
Preset name |
duration_seconds |
INTEGER |
Duration |
settings |
JSONB |
Type-specific settings |
Environment Variables
Backend (.env)
NODE_ENV=development
PORT=3017
DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/clock
MANA_CORE_AUTH_URL=http://localhost:3001
CORS_ORIGINS=http://localhost:5173,http://localhost:5186,http://localhost:8081
DEV_BYPASS_AUTH=true
DEV_USER_ID=your-test-user-id
Web (.env)
PUBLIC_BACKEND_URL=http://localhost:3017
PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001
Web App Stores (Svelte 5 Runes)
// auth.svelte.ts - Authentication
authStore.isAuthenticated
authStore.user
authStore.signIn(email, password)
authStore.signOut()
authStore.getAccessToken()
// alarms.svelte.ts - Alarms
alarmsStore.alarms
alarmsStore.nextAlarm
alarmsStore.fetchAlarms()
alarmsStore.createAlarm(input)
alarmsStore.toggleAlarm(id)
// timers.svelte.ts - Timers
timersStore.timers
timersStore.activeTimers
timersStore.startTimer(id)
timersStore.pauseTimer(id)
timersStore.resetTimer(id)
// stopwatch.svelte.ts - Stopwatch (local only)
stopwatchStore.isRunning
stopwatchStore.elapsedTime
stopwatchStore.laps
stopwatchStore.start()
stopwatchStore.lap()
stopwatchStore.reset()
// pomodoro.svelte.ts - Pomodoro (local only)
pomodoroStore.phase
pomodoroStore.remainingTime
pomodoroStore.completedSessions
pomodoroStore.start()
pomodoroStore.skip()
pomodoroStore.loadPreset(preset)
// world-clocks.svelte.ts - World Clocks
worldClocksStore.worldClocks
worldClocksStore.addWorldClock(input)
worldClocksStore.removeWorldClock(id)
worldClocksStore.reorderWorldClocks(ids)
Quick Start
1. Datenbank erstellen
# 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 clock;"
# Schema pushen
pnpm clock:db:push
2. Apps starten
# Backend + Web zusammen
pnpm dev:clock:app
# Oder einzeln:
pnpm dev:clock:backend # Terminal 1
pnpm dev:clock:web # Terminal 2
pnpm dev:clock:landing # Terminal 3 (optional)
3. URLs öffnen
Testing API (mit curl)
# Health Check
curl http://localhost:3017/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')
# Wecker abrufen
curl http://localhost:3017/api/v1/alarms \
-H "Authorization: Bearer $TOKEN"
# Neuen Wecker erstellen
curl -X POST http://localhost:3017/api/v1/alarms \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"time": "07:00:00", "label": "Aufwachen"}'
# Timer erstellen und starten
TIMER_ID=$(curl -s -X POST http://localhost:3017/api/v1/timers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"durationSeconds": 300, "label": "5 Minuten"}' | jq -r '.id')
curl -X POST http://localhost:3017/api/v1/timers/$TIMER_ID/start \
-H "Authorization: Bearer $TOKEN"
Important Notes
- Authentication: Nutzt Mana Core Auth (JWT im Authorization Header)
- Database: PostgreSQL mit Drizzle ORM (Port 5432)
- Port: Backend läuft auf Port 3017, Web auf 5187, Landing auf 4323
- i18n: 5 Sprachen unterstützt (DE, EN, FR, ES, IT)
- Theme: Amber/Orange (#f59e0b) als Primärfarbe
- Local Features: Stoppuhr und Pomodoro laufen lokal ohne Backend-Sync