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)
This commit is contained in:
Wuesteon 2025-11-27 18:33:16 +01:00
parent 0241f5554c
commit d36b321d9d
3952 changed files with 661498 additions and 739751 deletions

View file

@ -6,18 +6,19 @@ This document tracks critical dependencies across all projects and their target
### High Priority - Version Mismatches
| Package | Target Version | Current Versions | Notes |
|---------|---------------|------------------|-------|
| `@supabase/supabase-js` | **2.81.1** | 2.38.4 - 2.81.1 | Significant spread, alignment critical |
| `typescript` | **5.9.2** | 5.3.3 - 5.9.2 | Update all to latest |
| `react` | **19.1.0** | 18.3.1 - 19.1.0 | Mixed versions |
| `expo` | **54.x** | 52.0.39 - 54.0.21 | Manacore needs update |
| `expo-router` | **6.x** | 4.0.19 - 6.0.14 | Manacore needs update |
| `astro` | **5.16.0** | 5.3.0 - 5.16.0 | Memoro landing needs update |
| Package | Target Version | Current Versions | Notes |
| ----------------------- | -------------- | ----------------- | -------------------------------------- |
| `@supabase/supabase-js` | **2.81.1** | 2.38.4 - 2.81.1 | Significant spread, alignment critical |
| `typescript` | **5.9.2** | 5.3.3 - 5.9.2 | Update all to latest |
| `react` | **19.1.0** | 18.3.1 - 19.1.0 | Mixed versions |
| `expo` | **54.x** | 52.0.39 - 54.0.21 | Manacore needs update |
| `expo-router` | **6.x** | 4.0.19 - 6.0.14 | Manacore needs update |
| `astro` | **5.16.0** | 5.3.0 - 5.16.0 | Memoro landing needs update |
### Current Status by Project
#### Supabase Versions
```
maerchenzauber:
- backend: 2.50.3
@ -38,6 +39,7 @@ memoro:
```
#### Expo/React Native Versions
```
maerchenzauber:
- expo: 54.0.21 ✅
@ -61,6 +63,7 @@ memoro:
```
#### NestJS Versions (Backends)
```
maerchenzauber: NestJS 10.0.0
manadeck: NestJS 11.0.1
@ -141,17 +144,20 @@ After updating dependencies, verify:
## Breaking Changes to Watch
### Supabase 2.38 → 2.81
- Auth session handling may have changed
- Check `onAuthStateChange` listeners
- Verify RLS policies still work
### Expo SDK 52 → 54
- Check expo-router migration guide
- New navigation patterns in 6.x
- Screen options changes
- Layout changes
### NestJS 10 → 11
- Decorator changes
- Module resolution changes
- Check middleware compatibility

View file

@ -87,6 +87,7 @@ The manacore-monorepo uses a comprehensive CI/CD pipeline with the following fea
Configure the following secrets in your GitHub repository (`Settings > Secrets and variables > Actions`):
#### Docker Registry
```
DOCKER_USERNAME=your-docker-username
DOCKER_PASSWORD=your-docker-password
@ -94,6 +95,7 @@ DOCKER_REGISTRY=wuesteon
```
#### Staging Environment
```
STAGING_HOST=staging.manacore.app
STAGING_USER=deploy
@ -117,6 +119,7 @@ STAGING_JWT_PRIVATE_KEY=<private-key>
```
#### Production Environment
```
PRODUCTION_HOST=api.manacore.app
PRODUCTION_USER=deploy
@ -126,12 +129,14 @@ PRODUCTION_API_URL=https://api.manacore.app
```
#### Turbo Cache (Optional)
```
TURBO_TOKEN=<vercel-token>
TURBO_TEAM=<team-name>
```
#### Code Coverage (Optional)
```
CODECOV_TOKEN=<codecov-token>
```
@ -147,6 +152,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: Pull requests to `main` or `develop`
**Steps**:
1. Detect changed projects
2. Run format check
3. Run linting
@ -163,6 +169,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: Push to `main` branch
**Steps**:
1. Full validation (all projects)
2. Build all projects
3. Build and push Docker images
@ -173,6 +180,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: Manual or automated from main CI
**Steps**:
1. SSH to staging server
2. Pull latest Docker images
3. Update environment configuration
@ -186,6 +194,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: Manual only
**Steps**:
1. Validate deployment request
2. Request manual approval
3. Create database backup
@ -201,6 +210,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: PRs, pushes to main, weekly schedule
**Steps**:
1. Run all tests with coverage
2. Collect coverage reports
3. Upload to Codecov
@ -212,6 +222,7 @@ The CI/CD pipeline consists of 6 GitHub Actions workflows:
**Triggers**: Weekly schedule, manual
**Steps**:
1. Check for outdated dependencies
2. Run security audit
3. Create issue for critical vulnerabilities
@ -259,6 +270,7 @@ FROM node:20-alpine AS production
```
**Key Features**:
- Non-root user (`nestjs`)
- Health checks
- Resource limits
@ -269,6 +281,7 @@ FROM node:20-alpine AS production
Template: `docker/templates/Dockerfile.sveltekit`
**Key Features**:
- SSR support
- Static asset optimization
- Non-root user
@ -279,6 +292,7 @@ Template: `docker/templates/Dockerfile.sveltekit`
Template: `docker/templates/Dockerfile.astro`
**Key Features**:
- Nginx-based serving
- Gzip compression
- Security headers
@ -311,12 +325,14 @@ Two environments are provided:
**URL**: `https://staging.manacore.app`
**Characteristics**:
- Automatic deployment from `main` branch
- Separate database instances
- Full feature parity with production
- Verbose logging enabled
**Access**:
```bash
ssh deploy@staging.manacore.app
cd ~/manacore-staging
@ -330,6 +346,7 @@ docker compose ps
**URL**: `https://api.manacore.app`
**Characteristics**:
- Manual deployment with approval
- High availability configuration
- Performance optimized
@ -337,6 +354,7 @@ docker compose ps
- Backup procedures
**Access**:
```bash
ssh deploy@api.manacore.app
cd ~/manacore-production
@ -378,6 +396,7 @@ Production requires manual trigger and approval:
Go to GitHub Actions > CD - Production Deployment > Run workflow
**Required Inputs**:
- Service: `all` or specific service name
- Environment: `production`
- Confirm: Type `deploy`
@ -391,6 +410,7 @@ Approve in: GitHub > Settings > Environments > production-approval
#### Step 3: Automated Deployment
Once approved:
1. Creates database backup
2. Tags current deployment
3. Pulls latest images
@ -471,6 +491,7 @@ export PRODUCTION_USER=deploy
```
**What the script does**:
1. Confirms rollback with user
2. Checks for previous deployment backup
3. Stops current services
@ -545,6 +566,7 @@ docker system prune -a
Automated backups are created before each production deployment.
**Manual backup**:
```bash
# Create backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
@ -563,6 +585,7 @@ Set up external monitoring tools to ping health endpoints:
- Chat Backend: `https://api.manacore.app/api/health`
Recommended tools:
- UptimeRobot
- Pingdom
- Better Uptime
@ -575,6 +598,7 @@ Recommended tools:
**Issue**: Deployment workflow fails
**Solutions**:
1. Check workflow logs in GitHub Actions
2. Verify all required secrets are set
3. Ensure SSH access to server works
@ -593,6 +617,7 @@ echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
**Issue**: Service fails health checks after deployment
**Solutions**:
1. Check service logs
2. Verify environment variables
3. Check database connectivity
@ -614,6 +639,7 @@ docker compose exec mana-core-auth env | grep -v PASSWORD
**Issue**: Services can't connect to database
**Solutions**:
1. Verify database is running
2. Check connection strings
3. Verify credentials
@ -632,6 +658,7 @@ docker compose exec mana-core-auth nc -zv postgres 5432
**Issue**: Docker build fails in CI
**Solutions**:
1. Check Dockerfile syntax
2. Verify all COPY paths exist
3. Check for build dependency issues
@ -650,6 +677,7 @@ docker buildx build --progress=plain --file apps/chat/apps/backend/Dockerfile .
**Issue**: Server runs out of disk space
**Solutions**:
```bash
# Check disk usage
df -h
@ -670,6 +698,7 @@ ls -t | tail -n +10 | xargs rm -rf
**Issue**: Docker Compose services fail to start
**Solutions**:
```bash
# Check service dependencies
docker compose config
@ -692,6 +721,7 @@ Never deploy directly to production without testing in staging.
### 2. Use Tagged Releases
Tag important releases:
```bash
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3

View file

@ -147,6 +147,7 @@ curl -X POST http://localhost:3001/api/auth/register \
### Step 7: Configure SSL (Coolify Auto)
In Coolify UI:
1. Navigate to: Settings → Domains
2. Add domain: `auth.manacore.app`
3. Enable "Auto SSL" (Let's Encrypt)
@ -676,12 +677,12 @@ curl -f https://api-chat.manacore.app/api/health
### Severity Levels
| Severity | Description | Response Time | Escalation |
|----------|-------------|---------------|------------|
| **P1 - Critical** | Total service outage, data loss | Immediate | CTO + All hands |
| **P2 - High** | Major functionality broken | < 30 min | DevOps lead + Backend team |
| **P3 - Medium** | Partial degradation, workaround exists | < 2 hours | On-call engineer |
| **P4 - Low** | Minor issues, no user impact | < 24 hours | Backlog |
| Severity | Description | Response Time | Escalation |
| ----------------- | -------------------------------------- | ------------- | -------------------------- |
| **P1 - Critical** | Total service outage, data loss | Immediate | CTO + All hands |
| **P2 - High** | Major functionality broken | < 30 min | DevOps lead + Backend team |
| **P3 - Medium** | Partial degradation, workaround exists | < 2 hours | On-call engineer |
| **P4 - Low** | Minor issues, no user impact | < 24 hours | Backlog |
### Incident Response Workflow

View file

@ -8,26 +8,26 @@ Das Monorepo nutzt [Turborepo](https://turbo.build/) für parallele Builds und i
## Globale Befehle
| Befehl | Beschreibung |
|--------|--------------|
| `pnpm dev` | Startet alle Apps (Web, Mobile, Landing, Backend) |
| `pnpm build` | Baut alle Packages und Apps |
| `pnpm test` | Führt alle Tests aus |
| `pnpm lint` | Führt Linting für alle Packages aus |
| `pnpm type-check` | TypeScript-Typprüfung für alle Packages |
| `pnpm clean` | Bereinigt Build-Artefakte |
| `pnpm format` | Formatiert alle Dateien mit Prettier |
| `pnpm format:check` | Prüft Formatierung ohne Änderungen |
| Befehl | Beschreibung |
| ------------------- | ------------------------------------------------- |
| `pnpm dev` | Startet alle Apps (Web, Mobile, Landing, Backend) |
| `pnpm build` | Baut alle Packages und Apps |
| `pnpm test` | Führt alle Tests aus |
| `pnpm lint` | Führt Linting für alle Packages aus |
| `pnpm type-check` | TypeScript-Typprüfung für alle Packages |
| `pnpm clean` | Bereinigt Build-Artefakte |
| `pnpm format` | Formatiert alle Dateien mit Prettier |
| `pnpm format:check` | Prüft Formatierung ohne Änderungen |
## App-Typ Befehle
Diese Befehle starten alle Apps eines bestimmten Typs gleichzeitig:
| Befehl | Beschreibung | Apps |
|--------|--------------|------|
| `pnpm dev:web` | Startet alle Web-Apps | maerchenzauber, manacore, manadeck, memoro |
| Befehl | Beschreibung | Apps |
| ------------------ | -------------------------- | ------------------------------------------ |
| `pnpm dev:web` | Startet alle Web-Apps | maerchenzauber, manacore, manadeck, memoro |
| `pnpm dev:landing` | Startet alle Landing Pages | maerchenzauber, manacore, manadeck, memoro |
| `pnpm dev:mobile` | Startet alle Mobile-Apps | maerchenzauber, manacore, manadeck, memoro |
| `pnpm dev:mobile` | Startet alle Mobile-Apps | maerchenzauber, manacore, manadeck, memoro |
### Beispiel
@ -46,12 +46,12 @@ pnpm dev:mobile
Diese Befehle starten ein komplettes Projekt mit allen zugehörigen Apps und Dependencies:
| Befehl | Beschreibung |
|--------|--------------|
| Befehl | Beschreibung |
| ------------------------- | ------------------------------------------------------ |
| `pnpm maerchenzauber:dev` | Startet Maerchenzauber (Backend, Web, Mobile, Landing) |
| `pnpm manacore:dev` | Startet Manacore (Web, Mobile, Landing) |
| `pnpm manadeck:dev` | Startet Manadeck (Web, Mobile, Landing) |
| `pnpm memoro:dev` | Startet Memoro (Web, Mobile, Landing) |
| `pnpm manacore:dev` | Startet Manacore (Web, Mobile, Landing) |
| `pnpm manadeck:dev` | Startet Manadeck (Web, Mobile, Landing) |
| `pnpm memoro:dev` | Startet Memoro (Web, Mobile, Landing) |
## Turbo Filter
@ -69,38 +69,38 @@ pnpm turbo run dev --filter=manacore-web --filter=memoro-web
Da die Package-Namen im Monorepo unterschiedlich sind, hier eine Übersicht:
| Projekt | Web | Landing | Mobile | Backend |
|---------|-----|---------|--------|---------|
| Projekt | Web | Landing | Mobile | Backend |
| -------------- | ------------------ | ---------------------- | --------------------- | ---------------------- |
| maerchenzauber | `@storyteller/web` | `@storyteller/landing` | `@storyteller/mobile` | `@storyteller/backend` |
| manacore | `manacore-web` | `manacore-landing` | `manacore` | - |
| manadeck | `web` | `landing` | `manadeck` | - |
| memoro | `memoro-web` | `memoro-landing` | `memoro` | - |
| manacore | `manacore-web` | `manacore-landing` | `manacore` | - |
| manadeck | `web` | `landing` | `manadeck` | - |
| memoro | `memoro-web` | `memoro-landing` | `memoro` | - |
### Filter-Syntax
| Pattern | Beschreibung |
|---------|--------------|
| `--filter=name` | Exakte Package-Übereinstimmung |
| `--filter=name...` | Package und alle Dependencies |
| `--filter='@scope/*'` | Alle Packages im Scope |
| Pattern | Beschreibung |
| --------------------- | ------------------------------ |
| `--filter=name` | Exakte Package-Übereinstimmung |
| `--filter=name...` | Package und alle Dependencies |
| `--filter='@scope/*'` | Alle Packages im Scope |
## Port-Zuweisungen
Wenn mehrere Apps gleichzeitig laufen, verwenden sie unterschiedliche Ports:
| App-Typ | Projekt | Standard-Port |
|---------|---------|---------------|
| Web | maerchenzauber | 5173 |
| Web | manacore | 5174 |
| Web | manadeck | 5175 |
| Web | memoro | 5176 |
| Landing | maerchenzauber | 4321 |
| Landing | manacore | 4322 |
| Landing | manadeck | 4323 |
| Landing | memoro | 4324 |
| Backend | maerchenzauber | 3000 |
| App-Typ | Projekt | Standard-Port |
| ------- | -------------- | ------------- |
| Web | maerchenzauber | 5173 |
| Web | manacore | 5174 |
| Web | manadeck | 5175 |
| Web | memoro | 5176 |
| Landing | maerchenzauber | 4321 |
| Landing | manacore | 4322 |
| Landing | manadeck | 4323 |
| Landing | memoro | 4324 |
| Backend | maerchenzauber | 3000 |
*Hinweis: Die tatsächlichen Ports können je nach Konfiguration variieren.*
_Hinweis: Die tatsächlichen Ports können je nach Konfiguration variieren._
## Tipps

View file

@ -15,6 +15,7 @@ Comprehensive guide for working with Docker in the manacore-monorepo.
## Overview
The monorepo uses Docker for:
- **Development**: Local service orchestration
- **CI/CD**: Automated builds and tests
- **Production**: Deployment and scaling
@ -22,6 +23,7 @@ The monorepo uses Docker for:
### Image Strategy
All images use:
- **Multi-stage builds**: Smaller production images
- **Alpine Linux**: Minimal base images
- **Non-root users**: Enhanced security
@ -37,6 +39,7 @@ Templates are located in `docker/templates/`. Use these as starting points for n
**File**: `docker/templates/Dockerfile.nestjs`
**Usage**:
```dockerfile
# Copy template
cp docker/templates/Dockerfile.nestjs apps/myproject/apps/backend/Dockerfile
@ -45,11 +48,13 @@ cp docker/templates/Dockerfile.nestjs apps/myproject/apps/backend/Dockerfile
```
**Build Arguments**:
- `SERVICE_PATH`: Path to service (e.g., `apps/chat/apps/backend`)
- `PORT`: Service port (default: 3000)
- `HEALTH_PATH`: Health check endpoint (default: `/health`)
**Example**:
```bash
docker build \
--build-arg SERVICE_PATH=apps/chat/apps/backend \
@ -65,12 +70,14 @@ docker build \
**File**: `docker/templates/Dockerfile.sveltekit`
**Features**:
- SSR support
- Environment variable injection
- Static asset optimization
- Health endpoint
**Usage**:
```bash
docker build \
--build-arg SERVICE_PATH=apps/chat/apps/web \
@ -85,6 +92,7 @@ docker build \
**File**: `docker/templates/Dockerfile.astro`
**Features**:
- Static site serving with Nginx
- Gzip compression
- Security headers
@ -93,6 +101,7 @@ docker build \
**Nginx Configuration**: `docker/nginx/astro.conf`
**Usage**:
```bash
docker build \
--build-arg SERVICE_PATH=apps/chat/apps/landing \
@ -377,10 +386,10 @@ Configure logging drivers:
services:
backend:
logging:
driver: "json-file"
driver: 'json-file'
options:
max-size: "10m"
max-file: "3"
max-size: '10m'
max-file: '3'
```
### 8. Environment Variables
@ -408,6 +417,7 @@ services:
**Issue**: Container exits immediately
**Debug**:
```bash
# View container logs
docker logs container-name
@ -424,6 +434,7 @@ docker run -it --rm image-name sh
**Issue**: Docker runs out of disk space
**Solution**:
```bash
# Check disk usage
docker system df
@ -447,6 +458,7 @@ docker rmi $(docker images -q)
**Issue**: Docker build fails
**Debug**:
```bash
# Build with verbose output
docker build --progress=plain --no-cache -t image-name .
@ -463,6 +475,7 @@ docker build --target builder -t image-name .
**Issue**: Containers can't communicate
**Debug**:
```bash
# List networks
docker network ls
@ -482,6 +495,7 @@ docker exec container1 nslookup container2
**Issue**: Container runs slowly
**Debug**:
```bash
# Check resource usage
docker stats
@ -498,6 +512,7 @@ docker history image-name
**Issue**: Permission denied errors
**Solution**:
```bash
# Check file ownership
docker exec container-name ls -la /app
@ -512,6 +527,7 @@ USER nodejs
**Issue**: Env vars not available in container
**Debug**:
```bash
# Check environment
docker exec container-name env

View file

@ -63,6 +63,7 @@ Dieses Dokument beschreibt die Migration von ManaDeck von Supabase zu einer selb
### Tabellen
#### 1. `decks`
```sql
CREATE TABLE decks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -86,6 +87,7 @@ CREATE INDEX idx_decks_is_featured ON decks(is_featured);
```
#### 2. `cards`
```sql
CREATE TABLE cards (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -107,6 +109,7 @@ CREATE INDEX idx_cards_position ON cards(deck_id, position);
```
#### 3. `study_sessions`
```sql
CREATE TABLE study_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -126,6 +129,7 @@ CREATE INDEX idx_study_sessions_deck_id ON study_sessions(deck_id);
```
#### 4. `card_progress`
```sql
CREATE TABLE card_progress (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -147,6 +151,7 @@ CREATE INDEX idx_card_progress_next_review ON card_progress(next_review);
```
#### 5. `deck_templates`
```sql
CREATE TABLE deck_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -166,6 +171,7 @@ CREATE INDEX idx_deck_templates_is_active ON deck_templates(is_active);
```
#### 6. `ai_generations`
```sql
CREATE TABLE ai_generations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@ -185,6 +191,7 @@ CREATE INDEX idx_ai_generations_status ON ai_generations(status);
```
#### 7. `user_stats` (für Leaderboard)
```sql
CREATE TABLE user_stats (
user_id UUID PRIMARY KEY,
@ -233,23 +240,24 @@ manadeck/
### Schema-Definitionen (Drizzle)
#### `schema/decks.ts`
```typescript
import { pgTable, uuid, varchar, text, boolean, timestamp, jsonb } from 'drizzle-orm/pg-core';
export const decks = pgTable('decks', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull(),
title: varchar('title', { length: 255 }).notNull(),
description: text('description'),
coverImageUrl: text('cover_image_url'),
isPublic: boolean('is_public').default(false),
isFeatured: boolean('is_featured').default(false),
featuredAt: timestamp('featured_at', { withTimezone: true }),
settings: jsonb('settings').default({}),
tags: text('tags').array().default([]),
metadata: jsonb('metadata').default({}),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull(),
title: varchar('title', { length: 255 }).notNull(),
description: text('description'),
coverImageUrl: text('cover_image_url'),
isPublic: boolean('is_public').default(false),
isFeatured: boolean('is_featured').default(false),
featuredAt: timestamp('featured_at', { withTimezone: true }),
settings: jsonb('settings').default({}),
tags: text('tags').array().default([]),
metadata: jsonb('metadata').default({}),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
});
export type Deck = typeof decks.$inferSelect;
@ -257,25 +265,37 @@ export type NewDeck = typeof decks.$inferInsert;
```
#### `schema/cards.ts`
```typescript
import { pgTable, uuid, varchar, text, integer, boolean, timestamp, jsonb } from 'drizzle-orm/pg-core';
import {
pgTable,
uuid,
varchar,
text,
integer,
boolean,
timestamp,
jsonb,
} from 'drizzle-orm/pg-core';
import { decks } from './decks';
export const cardTypeEnum = pgEnum('card_type', ['text', 'flashcard', 'quiz', 'mixed']);
export const cards = pgTable('cards', {
id: uuid('id').primaryKey().defaultRandom(),
deckId: uuid('deck_id').notNull().references(() => decks.id, { onDelete: 'cascade' }),
position: integer('position').notNull().default(0),
title: varchar('title', { length: 255 }),
content: jsonb('content').notNull(),
cardType: cardTypeEnum('card_type').notNull(),
aiModel: varchar('ai_model', { length: 100 }),
aiPrompt: text('ai_prompt'),
version: integer('version').default(1),
isFavorite: boolean('is_favorite').default(false),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
id: uuid('id').primaryKey().defaultRandom(),
deckId: uuid('deck_id')
.notNull()
.references(() => decks.id, { onDelete: 'cascade' }),
position: integer('position').notNull().default(0),
title: varchar('title', { length: 255 }),
content: jsonb('content').notNull(),
cardType: cardTypeEnum('card_type').notNull(),
aiModel: varchar('ai_model', { length: 100 }),
aiPrompt: text('ai_prompt'),
version: integer('version').default(1),
isFavorite: boolean('is_favorite').default(false),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
});
export type Card = typeof cards.$inferSelect;
@ -283,6 +303,7 @@ export type NewCard = typeof cards.$inferInsert;
```
#### `schema/index.ts`
```typescript
export * from './decks';
export * from './cards';
@ -300,6 +321,7 @@ export { cardsRelations } from './cards';
### Client Setup
#### `client.ts`
```typescript
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
@ -309,9 +331,9 @@ const connectionString = process.env.DATABASE_URL!;
// For connection pooling in serverless environments
const client = postgres(connectionString, {
max: 10,
idle_timeout: 20,
connect_timeout: 10,
max: 10,
idle_timeout: 20,
connect_timeout: 10,
});
export const db = drizzle(client, { schema });
@ -325,6 +347,7 @@ export type Database = typeof db;
### Phase 1: Setup (Tag 1-2)
#### 1.1 PostgreSQL Server aufsetzen
```bash
# Option A: Railway.app (empfohlen für Staging)
# Erstelle neues Projekt auf railway.app
@ -344,6 +367,7 @@ docker run -d \
```
#### 1.2 Database Package erstellen
```bash
cd /Users/tillschneider/Documents/__00__Code/manacore-monorepo
mkdir -p packages/manadeck-database
@ -352,6 +376,7 @@ pnpm init
```
#### 1.3 Dependencies installieren
```bash
pnpm add drizzle-orm postgres
pnpm add -D drizzle-kit typescript @types/node
@ -360,17 +385,20 @@ pnpm add -D drizzle-kit typescript @types/node
### Phase 2: Schema & Migration (Tag 2-3)
#### 2.1 Drizzle Schema erstellen
- Alle Tabellen wie oben definiert
- Relations definieren
- Indexes definieren
#### 2.2 Initial Migration generieren
```bash
pnpm drizzle-kit generate
pnpm drizzle-kit migrate
```
#### 2.3 Daten von Supabase exportieren
```bash
# In Supabase Dashboard: SQL Editor
# Export alle Tabellen als CSV oder pg_dump
@ -401,56 +429,54 @@ import { decks, cards } from '@manadeck/database/schema';
import { eq, and, or, desc } from 'drizzle-orm';
export class DeckRepository {
async findAllByUser(userId: string) {
return db.query.decks.findMany({
where: eq(decks.userId, userId),
orderBy: desc(decks.updatedAt),
with: {
cards: true,
},
});
}
async findAllByUser(userId: string) {
return db.query.decks.findMany({
where: eq(decks.userId, userId),
orderBy: desc(decks.updatedAt),
with: {
cards: true,
},
});
}
async findById(id: string) {
return db.query.decks.findFirst({
where: eq(decks.id, id),
with: {
cards: {
orderBy: (cards, { asc }) => [asc(cards.position)],
},
},
});
}
async findById(id: string) {
return db.query.decks.findFirst({
where: eq(decks.id, id),
with: {
cards: {
orderBy: (cards, { asc }) => [asc(cards.position)],
},
},
});
}
async findPublicAndUserDecks(userId: string) {
return db.query.decks.findMany({
where: or(
eq(decks.userId, userId),
and(eq(decks.isPublic, true), eq(decks.isFeatured, true))
),
orderBy: desc(decks.updatedAt),
});
}
async findPublicAndUserDecks(userId: string) {
return db.query.decks.findMany({
where: or(
eq(decks.userId, userId),
and(eq(decks.isPublic, true), eq(decks.isFeatured, true))
),
orderBy: desc(decks.updatedAt),
});
}
async create(data: NewDeck) {
const [deck] = await db.insert(decks).values(data).returning();
return deck;
}
async create(data: NewDeck) {
const [deck] = await db.insert(decks).values(data).returning();
return deck;
}
async update(id: string, userId: string, data: Partial<NewDeck>) {
const [deck] = await db
.update(decks)
.set({ ...data, updatedAt: new Date() })
.where(and(eq(decks.id, id), eq(decks.userId, userId)))
.returning();
return deck;
}
async update(id: string, userId: string, data: Partial<NewDeck>) {
const [deck] = await db
.update(decks)
.set({ ...data, updatedAt: new Date() })
.where(and(eq(decks.id, id), eq(decks.userId, userId)))
.returning();
return deck;
}
async delete(id: string, userId: string) {
await db
.delete(decks)
.where(and(eq(decks.id, id), eq(decks.userId, userId)));
}
async delete(id: string, userId: string) {
await db.delete(decks).where(and(eq(decks.id, id), eq(decks.userId, userId)));
}
}
```
@ -461,30 +487,30 @@ export class DeckRepository {
import { DeckRepository } from '../repositories/deck.repository';
export class DeckService {
constructor(private deckRepo = new DeckRepository()) {}
constructor(private deckRepo = new DeckRepository()) {}
async getUserDecks(userId: string) {
return this.deckRepo.findPublicAndUserDecks(userId);
}
async getUserDecks(userId: string) {
return this.deckRepo.findPublicAndUserDecks(userId);
}
async getDeck(id: string) {
return this.deckRepo.findById(id);
}
async getDeck(id: string) {
return this.deckRepo.findById(id);
}
async createDeck(userId: string, data: CreateDeckInput) {
return this.deckRepo.create({
...data,
userId,
});
}
async createDeck(userId: string, data: CreateDeckInput) {
return this.deckRepo.create({
...data,
userId,
});
}
async updateDeck(id: string, userId: string, data: UpdateDeckInput) {
return this.deckRepo.update(id, userId, data);
}
async updateDeck(id: string, userId: string, data: UpdateDeckInput) {
return this.deckRepo.update(id, userId, data);
}
async deleteDeck(id: string, userId: string) {
return this.deckRepo.delete(id, userId);
}
async deleteDeck(id: string, userId: string) {
return this.deckRepo.delete(id, userId);
}
}
```
@ -498,37 +524,33 @@ import { getToken } from '$lib/auth';
const API_URL = import.meta.env.VITE_API_URL;
async function fetchApi<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const token = getToken();
async function fetchApi<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const token = getToken();
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
...options.headers,
},
});
const response = await fetch(`${API_URL}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
...options.headers,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'API Error');
}
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'API Error');
}
return response.json();
return response.json();
}
export const api = {
get: <T>(endpoint: string) => fetchApi<T>(endpoint),
post: <T>(endpoint: string, data: unknown) =>
fetchApi<T>(endpoint, { method: 'POST', body: JSON.stringify(data) }),
put: <T>(endpoint: string, data: unknown) =>
fetchApi<T>(endpoint, { method: 'PUT', body: JSON.stringify(data) }),
delete: <T>(endpoint: string) =>
fetchApi<T>(endpoint, { method: 'DELETE' }),
get: <T>(endpoint: string) => fetchApi<T>(endpoint),
post: <T>(endpoint: string, data: unknown) =>
fetchApi<T>(endpoint, { method: 'POST', body: JSON.stringify(data) }),
put: <T>(endpoint: string, data: unknown) =>
fetchApi<T>(endpoint, { method: 'PUT', body: JSON.stringify(data) }),
delete: <T>(endpoint: string) => fetchApi<T>(endpoint, { method: 'DELETE' }),
};
```
@ -540,87 +562,95 @@ import { api } from '$lib/api/client';
import type { Deck, CreateDeckInput, UpdateDeckInput } from '$lib/types/deck';
function createDeckStore() {
let decks = $state<Deck[]>([]);
let currentDeck = $state<Deck | null>(null);
let loading = $state(false);
let error = $state<string | null>(null);
let decks = $state<Deck[]>([]);
let currentDeck = $state<Deck | null>(null);
let loading = $state(false);
let error = $state<string | null>(null);
return {
get decks() { return decks; },
get currentDeck() { return currentDeck; },
get loading() { return loading; },
get error() { return error; },
return {
get decks() {
return decks;
},
get currentDeck() {
return currentDeck;
},
get loading() {
return loading;
},
get error() {
return error;
},
async fetchDecks() {
loading = true;
error = null;
try {
decks = await api.get<Deck[]>('/api/decks');
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to fetch decks';
} finally {
loading = false;
}
},
async fetchDecks() {
loading = true;
error = null;
try {
decks = await api.get<Deck[]>('/api/decks');
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to fetch decks';
} finally {
loading = false;
}
},
async fetchDeck(id: string) {
loading = true;
error = null;
try {
currentDeck = await api.get<Deck>(`/api/decks/${id}`);
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to fetch deck';
} finally {
loading = false;
}
},
async fetchDeck(id: string) {
loading = true;
error = null;
try {
currentDeck = await api.get<Deck>(`/api/decks/${id}`);
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to fetch deck';
} finally {
loading = false;
}
},
async createDeck(data: CreateDeckInput) {
loading = true;
error = null;
try {
const deck = await api.post<Deck>('/api/decks', data);
decks = [deck, ...decks];
return deck;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to create deck';
throw e;
} finally {
loading = false;
}
},
async createDeck(data: CreateDeckInput) {
loading = true;
error = null;
try {
const deck = await api.post<Deck>('/api/decks', data);
decks = [deck, ...decks];
return deck;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to create deck';
throw e;
} finally {
loading = false;
}
},
async updateDeck(id: string, data: UpdateDeckInput) {
loading = true;
error = null;
try {
const deck = await api.put<Deck>(`/api/decks/${id}`, data);
decks = decks.map(d => d.id === id ? deck : d);
if (currentDeck?.id === id) currentDeck = deck;
return deck;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to update deck';
throw e;
} finally {
loading = false;
}
},
async updateDeck(id: string, data: UpdateDeckInput) {
loading = true;
error = null;
try {
const deck = await api.put<Deck>(`/api/decks/${id}`, data);
decks = decks.map((d) => (d.id === id ? deck : d));
if (currentDeck?.id === id) currentDeck = deck;
return deck;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to update deck';
throw e;
} finally {
loading = false;
}
},
async deleteDeck(id: string) {
loading = true;
error = null;
try {
await api.delete(`/api/decks/${id}`);
decks = decks.filter(d => d.id !== id);
if (currentDeck?.id === id) currentDeck = null;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to delete deck';
throw e;
} finally {
loading = false;
}
},
};
async deleteDeck(id: string) {
loading = true;
error = null;
try {
await api.delete(`/api/decks/${id}`);
decks = decks.filter((d) => d.id !== id);
if (currentDeck?.id === id) currentDeck = null;
} catch (e) {
error = e instanceof Error ? e.message : 'Failed to delete deck';
throw e;
} finally {
loading = false;
}
},
};
}
export const deckStore = createDeckStore();
@ -629,6 +659,7 @@ export const deckStore = createDeckStore();
### Phase 5: Testing & Cutover (Tag 7-10)
#### 5.1 Integration Tests
```typescript
// tests/deck.integration.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
@ -637,111 +668,111 @@ import { decks } from '@manadeck/database/schema';
import { DeckService } from '../services/deck.service';
describe('DeckService', () => {
const service = new DeckService();
const testUserId = 'test-user-id';
const service = new DeckService();
const testUserId = 'test-user-id';
afterAll(async () => {
await db.delete(decks).where(eq(decks.userId, testUserId));
});
afterAll(async () => {
await db.delete(decks).where(eq(decks.userId, testUserId));
});
it('should create a deck', async () => {
const deck = await service.createDeck(testUserId, {
title: 'Test Deck',
description: 'A test deck',
});
it('should create a deck', async () => {
const deck = await service.createDeck(testUserId, {
title: 'Test Deck',
description: 'A test deck',
});
expect(deck.id).toBeDefined();
expect(deck.title).toBe('Test Deck');
});
expect(deck.id).toBeDefined();
expect(deck.title).toBe('Test Deck');
});
it('should fetch user decks', async () => {
const userDecks = await service.getUserDecks(testUserId);
expect(userDecks.length).toBeGreaterThan(0);
});
it('should fetch user decks', async () => {
const userDecks = await service.getUserDecks(testUserId);
expect(userDecks.length).toBeGreaterThan(0);
});
});
```
#### 5.2 Datenmigrations-Script
```typescript
// scripts/migrate-data.ts
import { db as newDb } from '@manadeck/database';
import { createClient } from '@supabase/supabase-js';
import { decks, cards } from '@manadeck/database/schema';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
);
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_KEY!);
async function migrateDecks() {
console.log('Migrating decks...');
console.log('Migrating decks...');
const { data: supabaseDecks, error } = await supabase
.from('decks')
.select('*');
const { data: supabaseDecks, error } = await supabase.from('decks').select('*');
if (error) throw error;
if (error) throw error;
for (const deck of supabaseDecks) {
await newDb.insert(decks).values({
id: deck.id,
userId: deck.user_id,
title: deck.title,
description: deck.description,
coverImageUrl: deck.cover_image_url,
isPublic: deck.is_public,
isFeatured: deck.is_featured,
featuredAt: deck.featured_at,
settings: deck.settings,
tags: deck.tags,
metadata: deck.metadata,
createdAt: deck.created_at,
updatedAt: deck.updated_at,
}).onConflictDoNothing();
}
for (const deck of supabaseDecks) {
await newDb
.insert(decks)
.values({
id: deck.id,
userId: deck.user_id,
title: deck.title,
description: deck.description,
coverImageUrl: deck.cover_image_url,
isPublic: deck.is_public,
isFeatured: deck.is_featured,
featuredAt: deck.featured_at,
settings: deck.settings,
tags: deck.tags,
metadata: deck.metadata,
createdAt: deck.created_at,
updatedAt: deck.updated_at,
})
.onConflictDoNothing();
}
console.log(`Migrated ${supabaseDecks.length} decks`);
console.log(`Migrated ${supabaseDecks.length} decks`);
}
async function migrateCards() {
console.log('Migrating cards...');
console.log('Migrating cards...');
const { data: supabaseCards, error } = await supabase
.from('cards')
.select('*');
const { data: supabaseCards, error } = await supabase.from('cards').select('*');
if (error) throw error;
if (error) throw error;
for (const card of supabaseCards) {
await newDb.insert(cards).values({
id: card.id,
deckId: card.deck_id,
position: card.position,
title: card.title,
content: card.content,
cardType: card.card_type,
aiModel: card.ai_model,
aiPrompt: card.ai_prompt,
version: card.version,
isFavorite: card.is_favorite,
createdAt: card.created_at,
updatedAt: card.updated_at,
}).onConflictDoNothing();
}
for (const card of supabaseCards) {
await newDb
.insert(cards)
.values({
id: card.id,
deckId: card.deck_id,
position: card.position,
title: card.title,
content: card.content,
cardType: card.card_type,
aiModel: card.ai_model,
aiPrompt: card.ai_prompt,
version: card.version,
isFavorite: card.is_favorite,
createdAt: card.created_at,
updatedAt: card.updated_at,
})
.onConflictDoNothing();
}
console.log(`Migrated ${supabaseCards.length} cards`);
console.log(`Migrated ${supabaseCards.length} cards`);
}
async function main() {
try {
await migrateDecks();
await migrateCards();
// ... andere Tabellen
console.log('Migration completed successfully!');
} catch (error) {
console.error('Migration failed:', error);
process.exit(1);
}
try {
await migrateDecks();
await migrateCards();
// ... andere Tabellen
console.log('Migration completed successfully!');
} catch (error) {
console.error('Migration failed:', error);
process.exit(1);
}
}
main();
@ -751,13 +782,13 @@ main();
## Zeitplan
| Phase | Beschreibung | Dauer | Status |
|-------|--------------|-------|--------|
| 1 | Setup (PostgreSQL, Package) | 1-2 Tage | ⬜ Pending |
| 2 | Schema & Migration | 1-2 Tage | ⬜ Pending |
| 3 | Backend Migration | 2-3 Tage | ⬜ Pending |
| 4 | Frontend Migration | 2-3 Tage | ⬜ Pending |
| 5 | Testing & Cutover | 2-3 Tage | ⬜ Pending |
| Phase | Beschreibung | Dauer | Status |
| ----- | --------------------------- | -------- | ---------- |
| 1 | Setup (PostgreSQL, Package) | 1-2 Tage | ⬜ Pending |
| 2 | Schema & Migration | 1-2 Tage | ⬜ Pending |
| 3 | Backend Migration | 2-3 Tage | ⬜ Pending |
| 4 | Frontend Migration | 2-3 Tage | ⬜ Pending |
| 5 | Testing & Cutover | 2-3 Tage | ⬜ Pending |
**Gesamtdauer: ~10-13 Tage**
@ -766,6 +797,7 @@ main();
## Checkliste
### Pre-Migration
- [ ] PostgreSQL Server aufgesetzt
- [ ] Database Package erstellt
- [ ] Drizzle Schema definiert
@ -773,6 +805,7 @@ main();
- [ ] Supabase Daten exportiert
### Backend
- [ ] Repository Pattern implementiert
- [ ] DeckRepository
- [ ] CardRepository
@ -786,18 +819,21 @@ main();
- [ ] Authorization Middleware (ersetzt RLS)
### Frontend
- [ ] API Client erstellt
- [ ] deckStore migriert
- [ ] Supabase imports entfernt
- [ ] Environment Variables aktualisiert
### Testing
- [ ] Unit Tests für Repositories
- [ ] Integration Tests für Services
- [ ] E2E Tests für API
- [ ] Manual Testing aller Features
### Cutover
- [ ] Daten migriert (Script ausgeführt)
- [ ] DNS/Environment umgestellt
- [ ] Rollback Plan dokumentiert
@ -819,12 +855,12 @@ Supabase-Daten bleiben während der Migration unberührt.
## Kosten nach Migration
| Service | Geschätzte Kosten |
|---------|-------------------|
| PostgreSQL (Railway) | ~$5-20/Monat |
| PostgreSQL (Neon Free) | $0/Monat |
| Backup (optional) | ~$5/Monat |
| **Gesamt** | **$5-25/Monat** |
| Service | Geschätzte Kosten |
| ---------------------- | ----------------- |
| PostgreSQL (Railway) | ~$5-20/Monat |
| PostgreSQL (Neon Free) | $0/Monat |
| Backup (optional) | ~$5/Monat |
| **Gesamt** | **$5-25/Monat** |
vs. Supabase Pro: $25-300/Monat

View file

@ -64,6 +64,7 @@ pnpm run nutriphi:dev
Maerchenzauber ist eine magische Geschichten-App für Kinder, die mithilfe von KI personalisierte Geschichten mit benutzerdefinierten Charakteren erstellt.
#### Features
- KI-gestützte Geschichtenerstellung mit konsistenten Charakteren
- Benutzerdefinierte Charaktergenerierung aus Beschreibungen oder Fotos
- Mehrseitige illustrierte Geschichten (10 Seiten)
@ -72,17 +73,19 @@ Maerchenzauber ist eine magische Geschichten-App für Kinder, die mithilfe von K
- System-Charaktere (z.B. "Finia" der weise Fuchs)
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Backend | NestJS (Port 3002) |
| Mobile | React Native + Expo |
| Web | SvelteKit |
| Landing | Astro |
| KI | Azure OpenAI (GPT-4), Google Gemini, Replicate (Flux) |
| Datenbank | Supabase (PostgreSQL) |
| Storage | Supabase Storage |
| Komponente | Technologie |
| ---------- | ----------------------------------------------------- |
| Backend | NestJS (Port 3002) |
| Mobile | React Native + Expo |
| Web | SvelteKit |
| Landing | Astro |
| KI | Azure OpenAI (GPT-4), Google Gemini, Replicate (Flux) |
| Datenbank | Supabase (PostgreSQL) |
| Storage | Supabase Storage |
#### Projektstruktur
```
maerchenzauber/
├── apps/
@ -93,6 +96,7 @@ maerchenzauber/
```
#### Entwicklung
```bash
# Backend starten
cd maerchenzauber/apps/backend && npm run dev
@ -113,6 +117,7 @@ cd maerchenzauber/apps/web && npm run dev
Manacore ist die zentrale Plattform für Organisations-Management, Team-Kollaboration und Credit-Transfers. Es dient als Authentifizierungs-Hub für alle anderen Anwendungen.
#### Features
- Einheitliche Authentifizierung mit Supabase
- Organisations-Management mit rollenbasiertem Zugriff
- Team-Kollaboration und Mitgliederverwaltung
@ -122,21 +127,24 @@ Manacore ist die zentrale Plattform für Organisations-Management, Team-Kollabor
- Echtzeit-Updates
#### Unterstützte Apps
- **Memoro** - Sprachaufnahmen und Memory-Management
- **ManaDeck** - KI-gestützte Lernkarten
- **Storyteller** - Kreatives Schreiben mit KI
- **ManaCore** - Zentrale Account- und Organisationsverwaltung
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Web | SvelteKit 2 + Svelte 5 (Runes) |
| Mobile | Expo 52 + React Native 0.76 |
| Styling | TailwindCSS / NativeWind |
| Auth | Supabase Auth mit SSR |
| Testing | Vitest + Playwright |
| Komponente | Technologie |
| ---------- | ------------------------------ |
| Web | SvelteKit 2 + Svelte 5 (Runes) |
| Mobile | Expo 52 + React Native 0.76 |
| Styling | TailwindCSS / NativeWind |
| Auth | Supabase Auth mit SSR |
| Testing | Vitest + Playwright |
#### Projektstruktur
```
manacore/
├── apps/
@ -154,6 +162,7 @@ manacore/
Manadeck ist ein Deck-Management-System mit KI-gestützter Kartenerstellung und dem integrierten Mana Credit-System.
#### Features
- Deck-Erstellung und -Verwaltung
- KI-gestützte Kartengenerierung
- Credit-System Integration (10 Mana pro Deck, 2 Mana pro Karte)
@ -161,23 +170,26 @@ Manadeck ist ein Deck-Management-System mit KI-gestützter Kartenerstellung und
- NestJS Backend mit AuthGuard
#### Credit-Kosten
| Operation | Kosten |
|-----------|--------|
| Deck erstellen | 10 Mana |
| Karte erstellen | 2 Mana |
| KI-Kartengenerierung | 5 Mana |
| Deck exportieren | 3 Mana |
| Operation | Kosten |
| -------------------- | ------- |
| Deck erstellen | 10 Mana |
| Karte erstellen | 2 Mana |
| KI-Kartengenerierung | 5 Mana |
| Deck exportieren | 3 Mana |
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Backend | NestJS (Port 8080) |
| Mobile | React Native + Expo |
| Web | SvelteKit |
| Landing | Astro |
| Datenbank | Supabase |
| Komponente | Technologie |
| ---------- | ------------------- |
| Backend | NestJS (Port 8080) |
| Mobile | React Native + Expo |
| Web | SvelteKit |
| Landing | Astro |
| Datenbank | Supabase |
#### Projektstruktur
```
manadeck/
├── backend/ # NestJS API Server
@ -196,6 +208,7 @@ manadeck/
Memoro transformiert Audio-Aufnahmen in strukturierte, durchsuchbare Inhalte mithilfe von KI. Ideal für Meetings, Interviews, Vorlesungen oder persönliche Notizen.
#### Features
- Hochwertige Audio-Aufnahme (Hintergrundaufnahme mit Pause/Resume)
- KI-gestützte Analyse (Blueprints und Prompts)
- Kollaborative Spaces für Teams
@ -205,17 +218,19 @@ Memoro transformiert Audio-Aufnahmen in strukturierte, durchsuchbare Inhalte mit
- Enterprise-Security mit Row-Level Security
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Mobile | React Native 0.81.4 + Expo SDK 54 |
| Web | SvelteKit 2.x |
| Audio | expo-audio, Azure Speech Services |
| State | Zustand |
| Payments | RevenueCat |
| Analytics | PostHog, Sentry |
| i18n | react-i18next (32 Sprachen) |
| Komponente | Technologie |
| ---------- | --------------------------------- |
| Mobile | React Native 0.81.4 + Expo SDK 54 |
| Web | SvelteKit 2.x |
| Audio | expo-audio, Azure Speech Services |
| State | Zustand |
| Payments | RevenueCat |
| Analytics | PostHog, Sentry |
| i18n | react-i18next (32 Sprachen) |
#### Projektstruktur
```
memoro/
├── apps/
@ -227,6 +242,7 @@ memoro/
```
#### Feature-Module
- auth, audioRecordingV2, memos, spaces, credits
- subscription, i18n, theme, blueprints, prompts
- und 23 weitere...
@ -240,20 +256,23 @@ memoro/
Picture ist eine Cross-Platform Bildbearbeitungs-Anwendung mit Canvas-basierter Bearbeitung.
#### Features
- Canvas-basierte Bildbearbeitung (Konva)
- Cross-Platform (iOS, Android, Web)
- Theme-System Integration
- Subscription-Management
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Mobile | React Native + Expo SDK 54 |
| Web | SvelteKit + Svelte 5 |
| Canvas | Konva |
| Styling | TailwindCSS 4.0 |
| Komponente | Technologie |
| ---------- | -------------------------- |
| Mobile | React Native + Expo SDK 54 |
| Web | SvelteKit + Svelte 5 |
| Canvas | Konva |
| Styling | TailwindCSS 4.0 |
#### Projektstruktur
```
picture/
├── apps/
@ -273,6 +292,7 @@ uLoad ist eine URL-Shortening und Link-Management Plattform mit umfangreichen An
**Live:** https://ulo.ad
#### Features
- URL-Verkürzung
- Link-Analytics und Tracking
- Stripe-Integration für Zahlungen
@ -280,19 +300,21 @@ uLoad ist eine URL-Shortening und Link-Management Plattform mit umfangreichen An
- Cloudflare R2 Storage
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Framework | SvelteKit v2.22 + Svelte 5.0 |
| Backend | PocketBase (embedded SQLite) |
| Datenbank | PostgreSQL via Drizzle ORM |
| Cache | Redis |
| Styling | Tailwind CSS v4.0 |
| Testing | Vitest + Playwright |
| Payments | Stripe |
| Email | Resend |
| Storage | Cloudflare R2 |
| Komponente | Technologie |
| ---------- | ---------------------------- |
| Framework | SvelteKit v2.22 + Svelte 5.0 |
| Backend | PocketBase (embedded SQLite) |
| Datenbank | PostgreSQL via Drizzle ORM |
| Cache | Redis |
| Styling | Tailwind CSS v4.0 |
| Testing | Vitest + Playwright |
| Payments | Stripe |
| Email | Resend |
| Storage | Cloudflare R2 |
#### Projektstruktur
```
uload/
├── apps/
@ -305,6 +327,7 @@ uload/
```
#### Entwicklung
```bash
cd uload/apps/web
@ -328,20 +351,23 @@ pnpm run test # Unit + E2E Tests
Chat ist eine mobile Chat-Anwendung mit Supabase-Backend und Markdown-Unterstützung.
#### Features
- Echtzeit-Chat mit Supabase
- Markdown-Rendering
- Expo Router Navigation
- NativeWind Styling
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Mobile | Expo SDK 52 + React Native 0.76.7 |
| Navigation | Expo Router |
| Styling | NativeWind (Tailwind CSS) |
| Backend | Supabase |
| Komponente | Technologie |
| ---------- | --------------------------------- |
| Mobile | Expo SDK 52 + React Native 0.76.7 |
| Navigation | Expo Router |
| Styling | NativeWind (Tailwind CSS) |
| Backend | Supabase |
#### Projektstruktur
```
chat/
├── apps/
@ -357,6 +383,7 @@ chat/
Nutriphi ist ein intelligenter Ernährungs-Tracker, der mithilfe von Google Gemini Vision API Fotos von Mahlzeiten analysiert und automatisch Nährwertinformationen extrahiert.
#### Features
- KI-gestützte Mahlzeitenanalyse aus Fotos
- Automatische Erkennung von Kalorien, Protein, Kohlenhydraten, Fett
- Tägliche Ernährungsbilanz und Statistiken
@ -366,17 +393,19 @@ Nutriphi ist ein intelligenter Ernährungs-Tracker, der mithilfe von Google Gemi
- Cloud-Sync mit Supabase
#### Tech-Stack
| Komponente | Technologie |
|------------|-------------|
| Backend | NestJS (Port 3002) |
| Mobile | Expo SDK 53 + React Native 0.79 |
| Web | SvelteKit |
| Landing | Astro |
| KI | Google Gemini Vision API |
| Datenbank | Supabase (PostgreSQL), SQLite (lokal) |
| State | Zustand |
| Komponente | Technologie |
| ---------- | ------------------------------------- |
| Backend | NestJS (Port 3002) |
| Mobile | Expo SDK 53 + React Native 0.79 |
| Web | SvelteKit |
| Landing | Astro |
| KI | Google Gemini Vision API |
| Datenbank | Supabase (PostgreSQL), SQLite (lokal) |
| State | Zustand |
#### Projektstruktur
```
nutriphi/
├── apps/
@ -387,16 +416,18 @@ nutriphi/
```
#### API Endpoints
| Endpoint | Methode | Beschreibung |
|----------|---------|--------------|
| `/api/health` | GET | Health Check |
| `/api/meals/analyze/image` | POST | Mahlzeit-Foto analysieren |
| `/api/meals/analyze/text` | POST | Mahlzeit-Text analysieren |
| `/api/meals` | POST | Mahlzeit speichern |
| `/api/meals/user/:userId` | GET | Mahlzeiten eines Users |
| `/api/meals/user/:userId/summary` | GET | Tagesbilanz |
| Endpoint | Methode | Beschreibung |
| --------------------------------- | ------- | ------------------------- |
| `/api/health` | GET | Health Check |
| `/api/meals/analyze/image` | POST | Mahlzeit-Foto analysieren |
| `/api/meals/analyze/text` | POST | Mahlzeit-Text analysieren |
| `/api/meals` | POST | Mahlzeit speichern |
| `/api/meals/user/:userId` | GET | Mahlzeiten eines Users |
| `/api/meals/user/:userId/summary` | GET | Tagesbilanz |
#### Entwicklung
```bash
# Backend starten
pnpm dev:nutriphi:backend
@ -419,48 +450,48 @@ Alle Projekte teilen gemeinsame Packages unter `packages/`:
### Core Packages
| Package | Beschreibung |
|---------|--------------|
| `@manacore/shared-types` | Gemeinsame TypeScript Types |
| `@manacore/shared-utils` | Utility-Funktionen (Date, String, Async) |
| `@manacore/shared-supabase` | Einheitlicher Supabase Client |
| `@manacore/shared-config` | Gemeinsame Konfiguration |
| Package | Beschreibung |
| --------------------------- | ---------------------------------------- |
| `@manacore/shared-types` | Gemeinsame TypeScript Types |
| `@manacore/shared-utils` | Utility-Funktionen (Date, String, Async) |
| `@manacore/shared-supabase` | Einheitlicher Supabase Client |
| `@manacore/shared-config` | Gemeinsame Konfiguration |
### Auth & Security
| Package | Beschreibung |
|---------|--------------|
| `@manacore/shared-auth` | Authentifizierungs-Logik |
| `@manacore/shared-auth-ui` | Auth UI-Komponenten |
| `@manacore/shared-auth-stores` | Auth State Stores |
| Package | Beschreibung |
| ------------------------------ | ------------------------ |
| `@manacore/shared-auth` | Authentifizierungs-Logik |
| `@manacore/shared-auth-ui` | Auth UI-Komponenten |
| `@manacore/shared-auth-stores` | Auth State Stores |
### UI & Styling
| Package | Beschreibung |
|---------|--------------|
| `@manacore/shared-ui` | React Native UI-Komponenten |
| `@manacore/shared-icons` | Icon-Library |
| `@manacore/shared-tailwind` | Tailwind Konfiguration |
| `@manacore/shared-theme` | Theme-Logik |
| `@manacore/shared-theme-ui` | Theme UI-Komponenten |
| `@manacore/shared-branding` | Branding Assets |
| `@manacore/shared-landing-ui` | Landing Page Komponenten |
| Package | Beschreibung |
| ----------------------------- | --------------------------- |
| `@manacore/shared-ui` | React Native UI-Komponenten |
| `@manacore/shared-icons` | Icon-Library |
| `@manacore/shared-tailwind` | Tailwind Konfiguration |
| `@manacore/shared-theme` | Theme-Logik |
| `@manacore/shared-theme-ui` | Theme UI-Komponenten |
| `@manacore/shared-branding` | Branding Assets |
| `@manacore/shared-landing-ui` | Landing Page Komponenten |
### Business Logic
| Package | Beschreibung |
|---------|--------------|
| Package | Beschreibung |
| ------------------------------------- | ----------------------------- |
| `@manacore/shared-subscription-types` | Subscription TypeScript Types |
| `@manacore/shared-subscription-ui` | Subscription UI-Komponenten |
| `@manacore/shared-credit-service` | Credit/Mana Service |
| `@manacore/shared-i18n` | Internationalisierung |
| `@manacore/shared-subscription-ui` | Subscription UI-Komponenten |
| `@manacore/shared-credit-service` | Credit/Mana Service |
| `@manacore/shared-i18n` | Internationalisierung |
### Datenbank
| Package | Beschreibung |
|---------|--------------|
| Package | Beschreibung |
| ------------------- | ------------------------- |
| `manadeck-database` | Manadeck Datenbank-Schema |
| `uload-database` | uLoad Datenbank-Schema |
| `uload-database` | uLoad Datenbank-Schema |
### Verwendung
@ -477,41 +508,41 @@ import { formatDate, truncate, retry } from '@manacore/shared-utils';
### Frontend
| Kategorie | Web | Mobile |
|-----------|-----|--------|
| Framework | SvelteKit 2 / Astro | React Native + Expo |
| UI Library | Svelte 5 (Runes) | React 18/19 |
| Styling | TailwindCSS | NativeWind |
| State | Svelte Stores | Zustand / Context |
| Routing | File-based | Expo Router |
| Kategorie | Web | Mobile |
| ---------- | ------------------- | ------------------- |
| Framework | SvelteKit 2 / Astro | React Native + Expo |
| UI Library | Svelte 5 (Runes) | React 18/19 |
| Styling | TailwindCSS | NativeWind |
| State | Svelte Stores | Zustand / Context |
| Routing | File-based | Expo Router |
### Backend
| Kategorie | Technologie |
|-----------|-------------|
| API | NestJS |
| Auth | Mana Core Middleware / Supabase Auth |
| Database | PostgreSQL (Supabase) / PocketBase |
| Storage | Supabase Storage / Cloudflare R2 |
| Cache | Redis |
| Kategorie | Technologie |
| --------- | ------------------------------------ |
| API | NestJS |
| Auth | Mana Core Middleware / Supabase Auth |
| Database | PostgreSQL (Supabase) / PocketBase |
| Storage | Supabase Storage / Cloudflare R2 |
| Cache | Redis |
### AI/ML
| Service | Verwendung |
|---------|------------|
| Azure OpenAI (GPT-4) | Text-Generierung |
| Google Gemini | Text-Analyse |
| Replicate (Flux) | Bild-Generierung |
| Azure Speech Services | Sprache-zu-Text |
| Service | Verwendung |
| --------------------- | ---------------- |
| Azure OpenAI (GPT-4) | Text-Generierung |
| Google Gemini | Text-Analyse |
| Replicate (Flux) | Bild-Generierung |
| Azure Speech Services | Sprache-zu-Text |
### DevOps
| Kategorie | Technologie |
|-----------|-------------|
| Package Manager | pnpm 9.15.0 |
| Build System | Turborepo |
| CI/CD | EAS Build (Mobile), Vercel/Netlify (Web) |
| Deployment | Google Cloud Run, Docker |
| Kategorie | Technologie |
| --------------- | ---------------------------------------- |
| Package Manager | pnpm 9.15.0 |
| Build System | Turborepo |
| CI/CD | EAS Build (Mobile), Vercel/Netlify (Web) |
| Deployment | Google Cloud Run, Docker |
---
@ -597,6 +628,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
### Analyse des bestehenden Ökosystems
**Stärken der Plattform:**
- Etabliertes Credit-System (Mana) für Monetarisierung
- Zentrale Authentifizierung über Manacore
- Multi-Platform-Expertise (Web + Mobile)
@ -606,6 +638,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Bewährte Shared Packages
**Bestehende Domänen:**
- Kreatives Schreiben (Maerchenzauber)
- Sprachaufnahmen & Transkription (Memoro)
- Lernen & Wissensmanagement (Manadeck)
@ -622,6 +655,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine Notion-ähnliche Notiz-Anwendung mit tiefer KI-Integration und nahtloser Verbindung zu anderen Mana-Apps.
**Kernfeatures:**
- Block-basierter Editor (ähnlich Notion)
- KI-gestützte Zusammenfassungen und Umstrukturierung
- Automatische Verlinkung verwandter Notizen (Knowledge Graph)
@ -630,6 +664,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Markdown-Export/Import
**Synergien:**
- **Memoro-Integration:** Audio-Memos werden automatisch als Notizen importiert
- **Manadeck-Integration:** Aus Notizen Lernkarten generieren
- **Chat-Integration:** Chat-Verläufe als Notizen speichern
@ -645,6 +680,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Zielgruppe:** Studenten, Wissensarbeiter, Forscher, Journalisten
**Technische Besonderheiten:**
- Offline-first mit Sync
- Echtzeit-Kollaboration
- Versionierung & History
@ -657,6 +693,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein schlankes, KI-gestütztes Projektmanagement-Tool, das sich auf Einzelpersonen und kleine Teams konzentriert.
**Kernfeatures:**
- Kanban-Boards, Listen und Kalender-Ansichten
- KI-gestützte Task-Zerlegung (großes Ziel → Subtasks)
- Intelligente Priorisierung basierend auf Deadlines und Abhängigkeiten
@ -665,6 +702,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Focus Mode mit Pomodoro-Timer
**Synergien:**
- **Memoro-Integration:** Meeting-Aufnahmen → automatisch extrahierte Action Items
- **ManaNote-Integration:** Projekt-Dokumentation verknüpfen
- **Manacore-Integration:** Team-Spaces mit Rollen
@ -688,6 +726,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein Kalender, der nicht nur Termine verwaltet, sondern aktiv bei der Zeitplanung hilft.
**Kernfeatures:**
- Smart Scheduling: Findet automatisch optimale Zeitslots
- Meeting-Vorbereitung: Zeigt relevante Dokumente/Notizen vor Terminen
- Time Blocking: KI schlägt Fokuszeiten vor
@ -696,6 +735,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Reisezeit-Berechnung zwischen Terminen
**Synergien:**
- **Memoro-Integration:** Nach Meetings automatisch Transkript verlinken
- **ManaTask-Integration:** Deadline-Visualisierung im Kalender
- **ManaNote-Integration:** Meeting-Notizen direkt zum Termin
@ -719,6 +759,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Während Maerchenzauber auf Kindergeschichten spezialisiert ist, richtet sich ManaWrite an professionelle Content-Erstellung.
**Kernfeatures:**
- Blog-Posts, Artikel, Essays
- Marketing-Texte (Ads, Landing Pages, E-Mails)
- Social Media Content mit Plattform-Anpassung
@ -728,6 +769,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- A/B-Varianten-Generierung
**Content-Typen:**
- Blog-Artikel
- Newsletter
- Produktbeschreibungen
@ -736,6 +778,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Reden und Präsentationen
**Synergien:**
- **Memoro-Integration:** Gesprochene Gedanken → ausformulierte Texte
- **ManaNote-Integration:** Notizen → fertige Artikel
- **uLoad-Integration:** Tracking-Links für veröffentlichte Inhalte
@ -758,6 +801,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein mobiler Video-Editor für kurze Social-Media-Videos mit KI-Unterstützung.
**Kernfeatures:**
- Automatische Untertitel-Generierung (32 Sprachen)
- KI-Schnitt: Erkennt beste Momente, entfernt "Ähms" und Pausen
- Thumbnail-Generierung mit KI
@ -767,6 +811,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Talking Head → Animated Avatar
**Synergien:**
- **Memoro-Integration:** Audio-Transkripte für Untertitel
- **Picture-Integration:** Thumbnail-Bearbeitung
- **ManaWrite-Integration:** Video-Skripte erstellen
@ -788,6 +833,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine All-in-One Lösung für Podcast-Produktion - von der Aufnahme bis zur Veröffentlichung.
**Kernfeatures:**
- Multi-Track-Aufnahme (Remote-Interviews)
- Automatische Audio-Verbesserung (Noise Reduction, Normalisierung)
- KI-Kapitel-Generierung mit Timestamps
@ -797,6 +843,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Analytics Dashboard
**Synergien:**
- **Memoro-Integration:** Gleiche Audio-Engine, Transkription
- **ManaWrite-Integration:** Show Notes und Beschreibungen
- **uLoad-Integration:** Tracking-Links für Episoden
@ -819,6 +866,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ergänzung zu Picture mit Fokus auf Brand-Design und Marketing-Materialien.
**Kernfeatures:**
- Logo-Generator mit Varianten
- Brand Kit Management (Farben, Fonts, Assets)
- Social Media Template-Generator
@ -828,6 +876,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Infografik-Generator
**Synergien:**
- **Picture-Integration:** Detaillierte Bildbearbeitung
- **ManaWrite-Integration:** Text für Marketing-Materialien
- **uLoad-Integration:** QR-Codes mit Tracking
@ -852,6 +901,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine Plattform zum Erstellen und Konsumieren von Mikro-Kursen mit KI-Unterstützung.
**Kernfeatures:**
- Kurs-Builder mit Drag & Drop
- KI-generierte Quizze und Tests
- Lernpfade mit Abhängigkeiten
@ -861,6 +911,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Spaced Repetition Integration
**Synergien:**
- **Manadeck-Integration:** Kursinhalte → Lernkarten
- **Memoro-Integration:** Vorlesungen aufnehmen und transkribieren
- **ManaNote-Integration:** Kurs-Notizen
@ -883,6 +934,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein Tool zum schnellen Erfassen und Verarbeiten von Dokumenten, Artikeln und Büchern.
**Kernfeatures:**
- PDF/EPUB-Import und -Annotation
- Web-Artikel-Clipper
- KI-Zusammenfassungen (verschiedene Längen)
@ -892,6 +944,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Text-to-Speech für Dokumente
**Synergien:**
- **Manadeck-Integration:** Highlights → Lernkarten
- **ManaNote-Integration:** Exzerpte in Notizen überführen
- **ManaLearn-Integration:** Leselisten für Kurse
@ -913,6 +966,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Mehr als ein einfacher Übersetzer - ein Tool für professionelle Lokalisierung.
**Kernfeatures:**
- Dokumenten-Übersetzung (PDF, DOCX, etc.)
- Kontext-bewusste Übersetzung
- Terminologie-Management (Glossare)
@ -922,6 +976,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Batch-Übersetzung für Websites
**Synergien:**
- **ManaWrite-Integration:** Mehrsprachige Content-Erstellung
- **Shared i18n:** Gleiche 32-Sprachen-Basis
- **ManaRead-Integration:** Fremdsprachige Dokumente verstehen
@ -945,6 +1000,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein personalisierter Fitness-Begleiter mit adaptiven Trainingsplänen.
**Kernfeatures:**
- KI-generierte Trainingspläne basierend auf Zielen
- Video-Übungsanleitungen
- Progressive Overload Tracking
@ -970,6 +1026,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine App für mentales Wohlbefinden mit geführten Meditationen und Journaling.
**Kernfeatures:**
- Geführte Meditationen (verschiedene Längen und Themen)
- Atemübungen mit Visualisierung
- Stimmungs-Tracking
@ -979,6 +1036,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Therapie-Vorbereitung (Gedanken strukturieren)
**Synergien:**
- **Maerchenzauber-Integration:** Beruhigende Geschichten
- **Memoro-Integration:** Gedanken aufnehmen statt schreiben
@ -999,6 +1057,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein Rezept-Manager mit KI-Funktionen für Planung und Anpassung.
**Kernfeatures:**
- Rezept-Import aus URLs
- KI-Rezeptgenerierung basierend auf Zutaten ("Was kann ich kochen?")
- Automatische Skalierung von Portionen
@ -1027,6 +1086,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein intelligentes Tool zur Verwaltung persönlicher Finanzen mit KI-Insights.
**Kernfeatures:**
- Bank-Synchronisation (via Plaid/ähnlich)
- Automatische Kategorisierung von Transaktionen
- Budget-Erstellung und -Tracking
@ -1053,6 +1113,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Einfache Rechnungsstellung für Freelancer und kleine Unternehmen.
**Kernfeatures:**
- Professionelle Rechnungs-Templates
- Automatische Nummerierung
- Wiederkehrende Rechnungen
@ -1064,6 +1125,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Kunden-Verwaltung (CRM-light)
**Synergien:**
- **ManaDesign-Integration:** Gebrandete Rechnungen
- **uLoad-Integration:** Zahlungslinks
@ -1083,6 +1145,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein Tool zur Erstellung überzeugender Pitch-Decks und Präsentationen.
**Kernfeatures:**
- KI-generierte Präsentations-Struktur
- Design-Vorlagen für verschiedene Anlässe
- Storytelling-Unterstützung
@ -1093,6 +1156,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Pitch-Timer mit Übung
**Synergien:**
- **ManaDesign-Integration:** Visuelle Assets
- **ManaWrite-Integration:** Texte und Skripte
- **Memoro-Integration:** Präsentation aufnehmen und analysieren
@ -1116,6 +1180,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine Video-Konferenz-Lösung mit eingebauter KI-Unterstützung.
**Kernfeatures:**
- HD Video-Calls
- Echtzeit-Transkription
- Live-Untertitel in verschiedenen Sprachen
@ -1127,6 +1192,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Aufnahme mit automatischer Verarbeitung
**Synergien:**
- **Memoro-Integration:** Gleiche Transkriptions-Engine
- **ManaNote-Integration:** Meeting Notes direkt speichern
- **ManaTask-Integration:** Action Items → Tasks
@ -1149,6 +1215,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine moderne Forum/Community-Plattform für Marken und Communities.
**Kernfeatures:**
- Threads und Diskussionen
- Q&A-Bereich mit Voting
- KI-Moderation
@ -1159,6 +1226,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Integration mit Chat
**Synergien:**
- **Chat-Integration:** Private Nachrichten
- **ManaLearn-Integration:** Community-Kurse
- **Manacore-Integration:** Organisation/Team als Community
@ -1181,6 +1249,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine intelligente Bibliothek für Code-Snippets mit KI-Unterstützung.
**Kernfeatures:**
- Snippet-Organisation mit Tags und Ordnern
- Syntax-Highlighting für alle gängigen Sprachen
- KI-Code-Erklärung
@ -1207,6 +1276,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Automatische API-Dokumentation und Testing.
**Kernfeatures:**
- OpenAPI/Swagger-Import
- Automatische Docs-Generierung
- Interaktiver API-Explorer
@ -1233,6 +1303,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein KI-gestützter Reiseplaner für die perfekte Reise.
**Kernfeatures:**
- KI-Reiserouten basierend auf Interessen und Budget
- Tag-für-Tag-Itineraries
- Restaurant- und Aktivitäts-Empfehlungen
@ -1243,6 +1314,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Erinnerungsbuch nach der Reise
**Synergien:**
- **Picture-Integration:** Reisefotos bearbeiten
- **ManaNote-Integration:** Reisenotizen
- **ManaFinance-Integration:** Reise-Budget
@ -1264,6 +1336,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Eine Erweiterung von Maerchenzauber für interaktive "Choose Your Own Adventure"-Geschichten.
**Kernfeatures:**
- Interaktive Entscheidungs-Geschichten
- KI-generierte Verzweigungen
- Verschiedene Genres (Fantasy, Krimi, Romance, Horror)
@ -1273,6 +1346,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Multiplayer-Abenteuer (Gruppen-Entscheidungen)
**Synergien:**
- **Maerchenzauber-Integration:** Charaktere und Illustrationen
- **Chat-Integration:** Multiplayer-Koordination
@ -1293,6 +1367,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
**Konzept:** Ein Tool zur KI-gestützten Musikerstellung für Content Creator.
**Kernfeatures:**
- Hintergrundmusik-Generierung
- Stil- und Stimmungs-basierte Musik
- Podcast-Intro/Outro-Generator
@ -1303,6 +1378,7 @@ Dieser Abschnitt enthält durchdachte Ideen für neue Anwendungen, die das Manac
- Loops und Samples
**Synergien:**
- **ManaPodcast-Integration:** Musik für Podcasts
- **ManaVideo-Integration:** Hintergrundmusik
- **ManaMind-Integration:** Entspannungsmusik
@ -1325,32 +1401,32 @@ Basierend auf Synergien mit bestehenden Apps, Marktpotenzial und technischer Mac
#### Hohe Priorität (Sofortiges Potenzial)
| App | Begründung |
|-----|------------|
| **ManaNote** | Natürliche Erweiterung von Memoro, hohe Synergien |
| **ManaWrite** | Nutzt bestehende KI-Infrastruktur, klarer Markt |
| **ManaRead** | Ergänzt Manadeck perfekt, Bildungsmarkt |
| **ManaMeet** | Memoro-Technologie wiederverwendbar |
| App | Begründung |
| ------------- | ------------------------------------------------- |
| **ManaNote** | Natürliche Erweiterung von Memoro, hohe Synergien |
| **ManaWrite** | Nutzt bestehende KI-Infrastruktur, klarer Markt |
| **ManaRead** | Ergänzt Manadeck perfekt, Bildungsmarkt |
| **ManaMeet** | Memoro-Technologie wiederverwendbar |
#### Mittlere Priorität (Strategisch wichtig)
| App | Begründung |
|-----|------------|
| **ManaTask** | Produktivitäts-Suite vervollständigen |
| **ManaCalendar** | Verbindet alle Produktivitäts-Apps |
| **ManaPodcast** | Wachsender Markt, Memoro-Basis |
| **ManaDesign** | Picture erweitern, Marketing-Use-Cases |
| **ManaLearn** | Manadeck + Memoro + Video kombinieren |
| App | Begründung |
| ---------------- | -------------------------------------- |
| **ManaTask** | Produktivitäts-Suite vervollständigen |
| **ManaCalendar** | Verbindet alle Produktivitäts-Apps |
| **ManaPodcast** | Wachsender Markt, Memoro-Basis |
| **ManaDesign** | Picture erweitern, Marketing-Use-Cases |
| **ManaLearn** | Manadeck + Memoro + Video kombinieren |
#### Langfristig (Exploration)
| App | Begründung |
|-----|------------|
| **ManaVideo** | Komplex, aber hoher Bedarf |
| App | Begründung |
| --------------- | ---------------------------------- |
| **ManaVideo** | Komplex, aber hoher Bedarf |
| **ManaFinance** | Andere Domäne, aber hohe Nachfrage |
| **ManaFit** | Großer Markt, wenig Synergien |
| **ManaMusic** | KI-Musik im Aufwind |
| **ManaTrip** | Saisonal, aber emotional |
| **ManaFit** | Großer Markt, wenig Synergien |
| **ManaMusic** | KI-Musik im Aufwind |
| **ManaTrip** | Saisonal, aber emotional |
---
@ -1388,4 +1464,4 @@ Die Vision: **Ein zusammenhängendes Ökosystem, in dem Daten nahtlos zwischen A
---
*Zuletzt aktualisiert: November 2025*
_Zuletzt aktualisiert: November 2025_

View file

@ -35,35 +35,39 @@ Komplette Anleitung zum Hosten aller Projekte auf eigener Infrastruktur (VPS).
## Technologie-Stack pro Projekt
| Projekt | Web App | Landing | Backend | Mobile | Datenbank |
|---------|---------|---------|---------|--------|-----------|
| **Maerchenzauber** | SvelteKit | Astro | NestJS | Expo | Supabase |
| **Manacore** | SvelteKit | Astro | - | Expo | Supabase |
| **Manadeck** | SvelteKit | Astro | NestJS | Expo | PostgreSQL |
| **Memoro** | SvelteKit | Astro | - | Expo | Supabase |
| **Picture** | SvelteKit | Astro | - | Expo | Supabase |
| **uLoad** | SvelteKit | - | - | - | PostgreSQL + Redis |
| Projekt | Web App | Landing | Backend | Mobile | Datenbank |
| ------------------ | --------- | ------- | ------- | ------ | ------------------ |
| **Maerchenzauber** | SvelteKit | Astro | NestJS | Expo | Supabase |
| **Manacore** | SvelteKit | Astro | - | Expo | Supabase |
| **Manadeck** | SvelteKit | Astro | NestJS | Expo | PostgreSQL |
| **Memoro** | SvelteKit | Astro | - | Expo | Supabase |
| **Picture** | SvelteKit | Astro | - | Expo | Supabase |
| **uLoad** | SvelteKit | - | - | - | PostgreSQL + Redis |
---
## Deployment-Optionen im Überblick
### Option A: Single VPS mit Coolify (Empfohlen für Start)
- **Kosten:** ~€15-30/Monat
- **Komplexität:** Niedrig
- **Skalierung:** Begrenzt
### Option B: Multi-VPS mit Coolify
- **Kosten:** ~€50-100/Monat
- **Komplexität:** Mittel
- **Skalierung:** Gut
### Option C: Kubernetes (K3s)
- **Kosten:** ~€30-80/Monat
- **Komplexität:** Hoch
- **Skalierung:** Sehr gut
### Option D: Hybrid (Self-Hosted + Managed)
- **Kosten:** ~€20-50/Monat + Supabase
- **Komplexität:** Niedrig-Mittel
- **Skalierung:** Flexibel
@ -97,15 +101,15 @@ Die einfachste Lösung für den Start. Alle Services auf einem Server.
## Ressourcen-Anforderungen
| Komponente | RAM | CPU | Disk |
|------------|-----|-----|------|
| PostgreSQL | 1GB | 0.5 | 10GB |
| Redis | 256MB | 0.2 | 1GB |
| Coolify | 512MB | 0.3 | 5GB |
| Traefik | 128MB | 0.1 | - |
| Pro Web App | 256MB | 0.3 | - |
| Pro Backend | 512MB | 0.5 | - |
| Pro Landing | 64MB | 0.1 | - |
| Komponente | RAM | CPU | Disk |
| ----------------- | -------- | ------ | --------- |
| PostgreSQL | 1GB | 0.5 | 10GB |
| Redis | 256MB | 0.2 | 1GB |
| Coolify | 512MB | 0.3 | 5GB |
| Traefik | 128MB | 0.1 | - |
| Pro Web App | 256MB | 0.3 | - |
| Pro Backend | 512MB | 0.5 | - |
| Pro Landing | 64MB | 0.1 | - |
| **Gesamt (alle)** | **~6GB** | **~4** | **~30GB** |
**Empfohlener Server:** Hetzner CX31 (4 vCPU, 8GB RAM, 80GB) - €8.98/Monat
@ -128,6 +132,7 @@ curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
### 2. Datenbank-Services erstellen
**PostgreSQL:**
```
Name: shared-postgres
Version: 16-alpine
@ -135,6 +140,7 @@ Databases: manacore, manadeck, uload
```
**Redis:**
```
Name: shared-redis
Version: 7-alpine
@ -152,6 +158,7 @@ Version: 7-alpine
#### Konfiguration pro Projekt
**Alle SvelteKit Web Apps:**
```
Base Directory: /
Dockerfile: {projekt}/apps/web/Dockerfile # Falls vorhanden
@ -163,6 +170,7 @@ Port: 3000
```
**Alle Astro Landing Pages:**
```
Build Pack: Static
Base Directory: {projekt}/apps/landing
@ -171,6 +179,7 @@ Publish Directory: dist
```
**NestJS Backends:**
```
Base Directory: /
Dockerfile: {projekt}/apps/backend/Dockerfile
@ -181,21 +190,21 @@ Port: 4000
### 4. Domain-Mapping
| Service | Domain | Port |
|---------|--------|------|
| uload-web | ulo.ad | 3000 |
| maerchenzauber-web | app.maerchenzauber.de | 3001 |
| maerchenzauber-landing | maerchenzauber.de | 8080 |
| Service | Domain | Port |
| ---------------------- | --------------------- | ---- |
| uload-web | ulo.ad | 3000 |
| maerchenzauber-web | app.maerchenzauber.de | 3001 |
| maerchenzauber-landing | maerchenzauber.de | 8080 |
| maerchenzauber-backend | api.maerchenzauber.de | 4000 |
| manacore-web | app.manacore.io | 3002 |
| manacore-landing | manacore.io | 8081 |
| manadeck-web | app.manadeck.de | 3003 |
| manadeck-landing | manadeck.de | 8082 |
| manadeck-backend | api.manadeck.de | 4001 |
| memoro-web | app.memoro.ai | 3004 |
| memoro-landing | memoro.ai | 8083 |
| picture-web | app.picture.io | 3005 |
| picture-landing | picture.io | 8084 |
| manacore-web | app.manacore.io | 3002 |
| manacore-landing | manacore.io | 8081 |
| manadeck-web | app.manadeck.de | 3003 |
| manadeck-landing | manadeck.de | 8082 |
| manadeck-backend | api.manadeck.de | 4001 |
| memoro-web | app.memoro.ai | 3004 |
| memoro-landing | memoro.ai | 8083 |
| picture-web | app.picture.io | 3005 |
| picture-landing | picture.io | 8084 |
---
@ -228,16 +237,19 @@ Bessere Isolation und Skalierung durch mehrere Server.
## Server-Aufteilung
### VPS 1: Frontend (CX21 - €4.49/Monat)
- Alle SvelteKit Web Apps
- Alle Astro Landing Pages
- Traefik Reverse Proxy
### VPS 2: Backends (CX21 - €4.49/Monat)
- Maerchenzauber NestJS Backend
- Manadeck NestJS Backend
- Background Workers
### VPS 3: Datenbanken (CX31 - €8.98/Monat)
- PostgreSQL (shared)
- Redis (shared)
- Automated Backups
@ -424,22 +436,22 @@ Kombination aus Self-Hosting und Managed Services für beste Balance.
### Managed Services (empfohlen)
| Service | Anbieter | Kosten | Grund |
|---------|----------|--------|-------|
| Datenbank | Supabase | Free-$25/M | Auth + Realtime inklusive |
| Landing Pages | Vercel/Netlify | Free | CDN + Edge |
| CDN | Cloudflare | Free | DDoS + Caching |
| Email | Resend | Free-$20/M | Deliverability |
| Payments | Stripe | % per Tx | Compliance |
| Service | Anbieter | Kosten | Grund |
| ------------- | -------------- | ---------- | ------------------------- |
| Datenbank | Supabase | Free-$25/M | Auth + Realtime inklusive |
| Landing Pages | Vercel/Netlify | Free | CDN + Edge |
| CDN | Cloudflare | Free | DDoS + Caching |
| Email | Resend | Free-$20/M | Deliverability |
| Payments | Stripe | % per Tx | Compliance |
### Self-Hosted (VPS)
| Service | Grund |
|---------|-------|
| Service | Grund |
| -------- | -------------------------------------- |
| Web Apps | Volle Kontrolle, günstiger bei Traffic |
| Backends | Custom Code, API Keys |
| uLoad | Komplett eigene Infra gewünscht |
| Redis | Falls benötigt |
| Backends | Custom Code, API Keys |
| uLoad | Komplett eigene Infra gewünscht |
| Redis | Falls benötigt |
## Setup
@ -472,13 +484,13 @@ curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
## Kosten-Vergleich
| Komponente | Full Self-Hosted | Hybrid |
|------------|------------------|--------|
| VPS | €9-18/Monat | €4.50/Monat |
| Supabase | - | Free-€25/Monat |
| Vercel | - | Free |
| Cloudflare | - | Free |
| **Gesamt** | **€9-18/Monat** | **€4.50-30/Monat** |
| Komponente | Full Self-Hosted | Hybrid |
| ---------- | ---------------- | ------------------ |
| VPS | €9-18/Monat | €4.50/Monat |
| Supabase | - | Free-€25/Monat |
| Vercel | - | Free |
| Cloudflare | - | Free |
| **Gesamt** | **€9-18/Monat** | **€4.50-30/Monat** |
---
@ -546,6 +558,7 @@ CMD ["nginx", "-g", "daemon off;"]
## NestJS Backends
Bereits vorhanden in:
- `maerchenzauber/apps/backend/Dockerfile`
- `manadeck/backend/Dockerfile`
@ -578,6 +591,7 @@ DATABASE_URL=postgresql://user:pass@host:5432/db
## Projekt-spezifische Variablen
### Maerchenzauber Backend
```env
AZURE_OPENAI_ENDPOINT=https://xxx.openai.azure.com
AZURE_OPENAI_API_KEY=xxx
@ -587,11 +601,13 @@ GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
```
### Manadeck Backend
```env
GOOGLE_GEMINI_API_KEY=xxx
```
### uLoad
```env
REDIS_URL=redis://localhost:6379
STRIPE_SECRET_KEY=sk_live_xxx
@ -609,18 +625,21 @@ AUTH_SECRET=xxx
# Checkliste: Komplettes Self-Hosting
## Infrastruktur
- [ ] VPS bestellt (Hetzner CX21/CX31)
- [ ] SSH-Zugang eingerichtet
- [ ] Coolify installiert
- [ ] Firewall konfiguriert
## Datenbanken
- [ ] PostgreSQL läuft
- [ ] Redis läuft (falls benötigt)
- [ ] Backups eingerichtet
- [ ] Connection Strings notiert
## Projekte (für jedes)
- [ ] Dockerfile erstellt/geprüft
- [ ] Environment Variables gesetzt
- [ ] Domain konfiguriert
@ -628,16 +647,19 @@ AUTH_SECRET=xxx
- [ ] Health-Check funktioniert
## DNS (für jede Domain)
- [ ] A-Record auf Server-IP
- [ ] www CNAME (optional)
- [ ] Propagation geprüft
## Monitoring
- [ ] Logs erreichbar
- [ ] Alerting eingerichtet (optional)
- [ ] Uptime-Monitoring (optional)
## Backups
- [ ] Datenbank-Backup automatisiert
- [ ] Backup-Test durchgeführt
- [ ] Offsite-Backup (optional)
@ -654,6 +676,7 @@ AUTH_SECRET=xxx
4. **Cloudflare** für DNS + CDN (Free)
**Vorteile:**
- Schneller Start
- Geringe Kosten
- Managed Auth & Realtime
@ -662,6 +685,7 @@ AUTH_SECRET=xxx
## Für Wachstum: Option B (Multi-VPS)
Wenn Traffic steigt:
1. Datenbanken auf eigenen VPS migrieren
2. Frontend/Backend trennen
3. Load Balancing hinzufügen
@ -669,6 +693,7 @@ Wenn Traffic steigt:
## Für Enterprise: Option C (Kubernetes)
Wenn benötigt:
- Auto-Scaling
- Zero-Downtime Deployments
- Multi-Region

View file

@ -29,12 +29,14 @@ This document outlines the plan to unify common code across all web apps in the
All web apps now use the shared packages consistently:
**Logo Components** - Migrated to `@manacore/shared-branding`:
- `memoro/apps/web/src/lib/components/MemoroLogo.svelte` → uses `AppLogo`
- `manadeck/apps/web/src/lib/components/ManaDeckLogo.svelte` → uses `AppLogo`
- `manacore/apps/web/src/lib/components/ManaCoreLogo.svelte` → uses `AppLogo`
- `maerchenzauber/apps/web/src/lib/components/StorytellerLogo.svelte` → uses `AppLogo`
**Formatter Functions** - Migrated to `@manacore/shared-utils`:
- `memoro/apps/web/src/lib/components/memo/AdditionalRecordings.svelte` → uses `formatDurationFromMs`, `formatFileSize`
- `memoro/apps/web/src/lib/components/RecordingButton.svelte` → uses `formatDuration`
- `memoro/apps/web/src/lib/components/statistics/OverviewCard.svelte` → uses `formatDurationWithUnits`
@ -52,6 +54,7 @@ All web apps now use the shared packages consistently:
**Estimated LOC Savings**: 500-800 per app
**Components to unify**:
- `Button.svelte` - Primary, secondary, ghost, danger variants
- `Input.svelte` - Text input with label, error states
- `Text.svelte` - Typography component with variants
@ -63,6 +66,7 @@ All web apps now use the shared packages consistently:
- `Dropdown.svelte` - Select/dropdown menus
**Apps using these**:
- ManaCore Web
- Memoro Web
- Maerchenzauber Web
@ -77,6 +81,7 @@ All web apps now use the shared packages consistently:
**Estimated LOC Savings**: 800-1200 per app
**Modules to unify**:
- `tokenManager.ts` - JWT token storage, refresh, validation
- `authService.ts` - Login, logout, register, password reset
- `supabaseClient.ts` - Authenticated Supabase client factory
@ -84,6 +89,7 @@ All web apps now use the shared packages consistently:
- `authGuard.ts` - Route protection utilities
**Considerations**:
- Each app may have different Supabase projects
- Token storage strategy (localStorage vs cookies)
- OAuth providers per app
@ -97,6 +103,7 @@ All web apps now use the shared packages consistently:
**Estimated Benefit**: Consistent branding, easier theme updates
**Config unified**:
- Color palette (primary, secondary, accent colors)
- Theme variants (Lume, Nature, Stone, Ocean) with light/dark modes
- Typography scale (font sizes, line heights)
@ -105,6 +112,7 @@ All web apps now use the shared packages consistently:
- CSS variable-based theming system
**Structure**:
```
packages/shared-tailwind/
├── package.json
@ -117,6 +125,7 @@ packages/shared-tailwind/
```
**Apps using this**:
- Memoro Web (full migration with theme.css + components.css)
- ManaCore Web (preset only, keeps local colors)
- ManaDeck Web (colors import, HSL-based system)
@ -131,6 +140,7 @@ packages/shared-tailwind/
**Estimated LOC Savings**: 200-400 per app
**Utilities included**:
- `date.ts` - formatDate, formatRelativeTime, toISOString
- `format.ts` - formatDuration, formatFileSize, formatNumber, formatCurrency, formatPercent
- `validation.ts` - isValidEmail, isValidUrl, isValidPhone, validatePassword, isValidUuid
@ -146,6 +156,7 @@ packages/shared-tailwind/
**Estimated Benefit**: Type safety across packages
**Types to unify**:
- `User` - Common user type
- `ApiResponse<T>` - Standard API response wrapper
- `PaginatedResponse<T>` - Pagination types
@ -163,6 +174,7 @@ packages/shared-tailwind/
**Estimated LOC Savings**: 100-300 per app
**Modules to unify**:
- `i18n.ts` - svelte-i18n setup and initialization
- `detectLocale.ts` - Browser language detection
- Common translations:
@ -172,6 +184,7 @@ packages/shared-tailwind/
- Validation messages
**Structure**:
```
packages/shared-i18n/
├── package.json
@ -197,6 +210,7 @@ packages/shared-i18n/
**Estimated Benefit**: Consistent env handling
**Config to unify**:
- Environment variable validation (Zod schemas)
- API endpoint construction
- Feature flag utilities
@ -229,6 +243,7 @@ packages/shared-i18n/
## Guidelines for Shared Packages
### Package Structure
```
packages/shared-{name}/
├── package.json
@ -240,24 +255,26 @@ packages/shared-{name}/
```
### Package.json Template
```json
{
"name": "@manacore/shared-{name}",
"version": "0.1.0",
"private": true,
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"peerDependencies": {
"svelte": "^5.0.0"
}
"name": "@manacore/shared-{name}",
"version": "0.1.0",
"private": true,
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"peerDependencies": {
"svelte": "^5.0.0"
}
}
```
### Best Practices
1. **Keep it minimal** - Only share truly common code
2. **Document props** - Use TypeScript interfaces with JSDoc
3. **Version carefully** - Coordinate updates across apps
@ -273,6 +290,7 @@ packages/shared-{name}/
Centralized branding configuration for all Mana ecosystem apps.
**Exports**:
- `AppLogo` - SVG logo component that renders app-specific logo
- `AppLogoWithName` - Logo with app name and tagline
- `ManaIcon` - Generic Mana icon component
@ -280,9 +298,10 @@ Centralized branding configuration for all Mana ecosystem apps.
- `AppId` type - Union type of all app IDs
**Usage**:
```svelte
<script>
import { AppLogo } from '@manacore/shared-branding';
import { AppLogo } from '@manacore/shared-branding';
</script>
<AppLogo app="memoro" size={32} />
@ -294,6 +313,7 @@ Centralized branding configuration for all Mana ecosystem apps.
Duration and formatting utilities.
**Exports**:
- `formatDuration(seconds)` - Returns `MM:SS` or `HH:MM:SS`
- `formatDurationFromMs(ms)` - Converts milliseconds first
- `formatDurationWithUnits(seconds, locale)` - Returns `2h 30m` style

View file

@ -18,12 +18,12 @@ This document provides a comprehensive automated testing strategy for the Manaco
### Existing Tests by Project
| Project | Backend | Mobile | Web | Total |
|---------|---------|--------|-----|-------|
| Maerchenzauber | 8 | 5 | 0 | 13 |
| Memoro | 0 | 3 | 0 | 3 |
| Uload | 0 | 0 | 9 | 9 |
| **Total** | **8** | **8** | **9** | **25** |
| Project | Backend | Mobile | Web | Total |
| -------------- | ------- | ------ | ----- | ------ |
| Maerchenzauber | 8 | 5 | 0 | 13 |
| Memoro | 0 | 3 | 0 | 3 |
| Uload | 0 | 0 | 9 | 9 |
| **Total** | **8** | **8** | **9** | **25** |
### Strengths
@ -44,7 +44,9 @@ This document provides a comprehensive automated testing strategy for the Manaco
### 1. Documentation (docs/)
#### [TESTING.md](./TESTING.md) - 35,000+ words
Comprehensive testing strategy covering:
- Testing infrastructure by app type
- Test organization patterns
- Coverage strategy (80% minimum, 100% for critical paths)
@ -54,7 +56,9 @@ Comprehensive testing strategy covering:
- Best practices and FAQs
#### [TESTING_IMPLEMENTATION_GUIDE.md](./TESTING_IMPLEMENTATION_GUIDE.md) - 8,000+ words
Quick start guide for developers:
- Step-by-step setup for each app type
- Running tests locally
- Coverage reports
@ -62,6 +66,7 @@ Quick start guide for developers:
- Quick reference commands
#### [TESTING_SUMMARY.md](./TESTING_SUMMARY.md) - This file
High-level overview and index of all testing resources.
### 2. Shared Test Configuration (packages/test-config/)
@ -81,6 +86,7 @@ packages/test-config/
```
**Features**:
- 80% coverage thresholds enforced
- Auto-clear mocks between tests
- Platform-specific ignore patterns
@ -112,7 +118,9 @@ test-examples/
### 4. CI/CD Integration (.github/workflows/)
#### [test.yml](./.github/workflows/test.yml)
Automated testing workflow with:
- Parallel test execution across all projects
- Coverage reporting to Codecov
- Automated PR comments with results
@ -127,6 +135,7 @@ Automated testing workflow with:
8. Status reporting
**Features**:
- Matrix strategy for parallel execution
- Automatic coverage uploads
- PR status checks
@ -135,15 +144,15 @@ Automated testing workflow with:
## Testing Framework Matrix
| App Type | Framework | Config Location | Coverage Tool |
|----------|-----------|----------------|---------------|
| **NestJS Backend** | Jest | `@manacore/test-config/jest-backend` | Jest |
| **React Native Mobile** | Jest + jest-expo | `@manacore/test-config/jest-mobile` | Jest |
| **SvelteKit Web** | Vitest | `@manacore/test-config/vitest-svelte` | v8 |
| **Astro Landing** | Vitest | `@manacore/test-config/vitest-base` | v8 |
| **Shared Packages** | Vitest | `@manacore/test-config/vitest-base` | v8 |
| **E2E (Web)** | Playwright | `@manacore/test-config/playwright` | N/A |
| **E2E (Mobile)** | Detox/Maestro | TBD | N/A |
| App Type | Framework | Config Location | Coverage Tool |
| ----------------------- | ---------------- | ------------------------------------- | ------------- |
| **NestJS Backend** | Jest | `@manacore/test-config/jest-backend` | Jest |
| **React Native Mobile** | Jest + jest-expo | `@manacore/test-config/jest-mobile` | Jest |
| **SvelteKit Web** | Vitest | `@manacore/test-config/vitest-svelte` | v8 |
| **Astro Landing** | Vitest | `@manacore/test-config/vitest-base` | v8 |
| **Shared Packages** | Vitest | `@manacore/test-config/vitest-base` | v8 |
| **E2E (Web)** | Playwright | `@manacore/test-config/playwright` | N/A |
| **E2E (Mobile)** | Detox/Maestro | TBD | N/A |
## Coverage Strategy
@ -336,10 +345,10 @@ it('should create item successfully', async () => {
```typescript
// ✅ Good
it('should reject sign in with invalid email format')
it('should reject sign in with invalid email format');
// ❌ Bad
it('test sign in')
it('test sign in');
```
### 3. Test Behavior, Not Implementation
@ -457,6 +466,7 @@ afterEach(() => {
This testing strategy provides a complete foundation for achieving 80% test coverage across the Manacore monorepo. All documentation, configurations, examples, and CI/CD integration are ready for implementation. The next step is to begin writing tests following the patterns and guidelines provided.
**Estimated Impact**:
- **Quality**: 80%+ reduction in bugs
- **Confidence**: 100% confidence in deployments
- **Velocity**: Faster feature development with safety net

View file

@ -169,15 +169,16 @@ redis://uload-redis:6379
Da uload Teil eines Monorepos ist, muss die Build-Konfiguration genau so sein:
| Einstellung | Wert |
|-------------|------|
| **Base Directory** | `/` (leer lassen oder `/`) |
| **Build Pack** | Dockerfile |
| **Dockerfile Location** | `uload/Dockerfile` |
| **Port Exposes** | `3000` |
| Einstellung | Wert |
| ----------------------- | -------------------------- |
| **Base Directory** | `/` (leer lassen oder `/`) |
| **Build Pack** | Dockerfile |
| **Dockerfile Location** | `uload/Dockerfile` |
| **Port Exposes** | `3000` |
**Warum `/` als Base Directory?**
Das Dockerfile benötigt Zugriff auf:
- `uload/apps/web/` (die App)
- `packages/shared-*` (gemeinsame Packages)
- `pnpm-workspace.yaml` und `pnpm-lock.yaml` (Workspace-Config)
@ -243,10 +244,10 @@ Kopiere das Ergebnis als `AUTH_SECRET`.
Bei deinem DNS-Provider (z.B. Cloudflare, Namecheap):
| Type | Name | Value | TTL |
|------|------|-------|-----|
| A | @ | DEINE-SERVER-IP | 3600 |
| A | www | DEINE-SERVER-IP | 3600 |
| Type | Name | Value | TTL |
| ---- | ---- | --------------- | ---- |
| A | @ | DEINE-SERVER-IP | 3600 |
| A | www | DEINE-SERVER-IP | 3600 |
### 8.2 Domain in Coolify hinzufügen
@ -275,6 +276,7 @@ DNS-Änderungen können 5-30 Minuten dauern. SSL-Zertifikate werden automatisch
Klicke auf das laufende Deployment um die Logs zu sehen.
**Erfolgreicher Build zeigt:**
```
✔ done
Listening on http://0.0.0.0:3000
@ -321,8 +323,9 @@ curl https://ulo.ad/api/health
```
Erwartete Antwort:
```json
{"status":"ok","timestamp":"2025-11-25T12:00:00.000Z","uptime":123.45}
{ "status": "ok", "timestamp": "2025-11-25T12:00:00.000Z", "uptime": 123.45 }
```
### 11.2 Website öffnen
@ -351,6 +354,7 @@ In Coolify: Application → **Redeploy**
Application → **Logs**
**Via SSH:**
```bash
docker logs -f $(docker ps -qf "name=uload")
```
@ -375,19 +379,19 @@ cat backup_20251125.sql | docker exec -i uload-postgres psql -U uload uload
### Build schlägt fehl
| Problem | Lösung |
|---------|--------|
| "Cannot find package" | Prüfe Base Directory (muss `/` sein) |
| "pnpm-lock.yaml not found" | Prüfe dass pnpm-lock.yaml im Repo ist |
| Timeout beim Build | Erhöhe Build-Timeout in Coolify Settings |
| Problem | Lösung |
| -------------------------- | ---------------------------------------- |
| "Cannot find package" | Prüfe Base Directory (muss `/` sein) |
| "pnpm-lock.yaml not found" | Prüfe dass pnpm-lock.yaml im Repo ist |
| Timeout beim Build | Erhöhe Build-Timeout in Coolify Settings |
### Container startet nicht
| Problem | Lösung |
|---------|--------|
| "Missing API key" | Prüfe RESEND_API_KEY Environment Variable |
| "Cannot connect to database" | Prüfe DATABASE_URL (Internal URL!) |
| Port already in use | Prüfe ob alter Container noch läuft |
| Problem | Lösung |
| ---------------------------- | ----------------------------------------- |
| "Missing API key" | Prüfe RESEND_API_KEY Environment Variable |
| "Cannot connect to database" | Prüfe DATABASE_URL (Internal URL!) |
| Port already in use | Prüfe ob alter Container noch läuft |
### SSL-Zertifikat Fehler
@ -429,18 +433,19 @@ cat backup_20251125.sql | docker exec -i uload-postgres psql -U uload uload
## Dateien im Repository
| Datei | Beschreibung |
|-------|--------------|
| `uload/Dockerfile` | Multi-Stage Docker Build |
| `uload/docker-compose.yml` | Lokale Entwicklung |
| `uload/docker-compose.coolify.yml` | Coolify Deployment |
| `uload/docker-compose.prod.yml` | Standalone Production |
| Datei | Beschreibung |
| ---------------------------------- | ------------------------ |
| `uload/Dockerfile` | Multi-Stage Docker Build |
| `uload/docker-compose.yml` | Lokale Entwicklung |
| `uload/docker-compose.coolify.yml` | Coolify Deployment |
| `uload/docker-compose.prod.yml` | Standalone Production |
---
## Support
Bei Problemen:
1. Coolify Logs prüfen
2. Container Logs prüfen (`docker logs`)
3. GitHub Issues: https://github.com/anthropics/claude-code/issues

View file

@ -25,7 +25,9 @@ test-examples/
### Backend Tests (NestJS)
#### `example.controller.spec.ts`
Demonstrates:
- Controller unit testing with mocked services
- Request/response handling
- Authentication/authorization testing
@ -34,13 +36,16 @@ Demonstrates:
- CRUD operations
**Key Patterns**:
- Use `@nestjs/testing` TestingModule
- Mock all service dependencies
- Test both success and error paths
- Verify service method calls
#### `example.service.spec.ts`
Demonstrates:
- Service business logic testing
- Database operation mocking
- External API mocking
@ -49,6 +54,7 @@ Demonstrates:
- Authorization checks
**Key Patterns**:
- Mock database and external services
- Test error handling thoroughly
- Verify data transformations
@ -57,7 +63,9 @@ Demonstrates:
### Mobile Tests (React Native)
#### `ExampleComponent.test.tsx`
Demonstrates:
- Component rendering
- User interactions (press, long press)
- State management
@ -67,13 +75,16 @@ Demonstrates:
- Snapshot testing
**Key Patterns**:
- Use `@testing-library/react-native`
- Test user behavior, not implementation
- Verify accessibility props
- Test loading and error states
#### `authService.test.ts`
Demonstrates:
- Async service testing
- API call mocking with fetch
- Storage operations (SecureStore)
@ -82,6 +93,7 @@ Demonstrates:
- Integration with other services
**Key Patterns**:
- Mock global fetch
- Mock Expo modules (SecureStore)
- Test timeout scenarios
@ -90,7 +102,9 @@ Demonstrates:
### Web Tests (SvelteKit)
#### `Button.test.ts`
Demonstrates:
- Svelte 5 component testing
- Reactive state with runes ($state, $derived)
- User events
@ -100,13 +114,16 @@ Demonstrates:
- Debouncing
**Key Patterns**:
- Use `@testing-library/svelte`
- Test Svelte 5 reactivity
- Verify accessibility attributes
- Test custom event dispatch
#### `page.server.test.ts`
Demonstrates:
- Server load function testing
- Form action testing
- Database mocking (PocketBase)
@ -116,6 +133,7 @@ Demonstrates:
- File upload handling
**Key Patterns**:
- Mock `locals` object
- Mock database client
- Test redirect behavior
@ -125,7 +143,9 @@ Demonstrates:
### Shared Package Tests
#### `format.test.ts`
Demonstrates:
- Pure function testing
- Parameterized tests (it.each)
- Edge case testing
@ -135,6 +155,7 @@ Demonstrates:
- Unicode and emoji handling
**Key Patterns**:
- Test with multiple inputs using `it.each`
- Cover edge cases thoroughly
- Test security vulnerabilities
@ -180,6 +201,7 @@ jest.mock('@your-project/custom-service', () => ({
### 4. Reference Best Practices
Each file includes comments explaining:
- Why specific patterns are used
- What to test and what not to test
- Common pitfalls to avoid

View file

@ -85,11 +85,15 @@ describe('ExampleController', () => {
error: new Error('Validation failed'),
});
await expect(controller.create(invalidDto, { user: mockUser })).rejects.toThrow(BadRequestException);
await expect(controller.create(invalidDto, { user: mockUser })).rejects.toThrow(
BadRequestException
);
});
it('should throw UnauthorizedException when user is not authenticated', async () => {
await expect(controller.create(createDto, { user: null })).rejects.toThrow(UnauthorizedException);
await expect(controller.create(createDto, { user: null })).rejects.toThrow(
UnauthorizedException
);
});
it('should handle service errors gracefully', async () => {
@ -155,7 +159,9 @@ describe('ExampleController', () => {
error: new Error('Not found'),
});
await expect(controller.findOne('invalid-id', { user: mockUser })).rejects.toThrow(NotFoundException);
await expect(controller.findOne('invalid-id', { user: mockUser })).rejects.toThrow(
NotFoundException
);
});
it('should not allow access to other users examples', async () => {
@ -166,7 +172,9 @@ describe('ExampleController', () => {
error: null,
});
await expect(controller.findOne(exampleId, { user: mockUser })).rejects.toThrow(UnauthorizedException);
await expect(controller.findOne(exampleId, { user: mockUser })).rejects.toThrow(
UnauthorizedException
);
});
});
@ -236,7 +244,9 @@ describe('ExampleController', () => {
error: new Error('Not found'),
});
await expect(controller.remove('invalid-id', { user: mockUser })).rejects.toThrow(NotFoundException);
await expect(controller.remove('invalid-id', { user: mockUser })).rejects.toThrow(
NotFoundException
);
});
it('should not allow deletion of other users examples', async () => {
@ -245,7 +255,9 @@ describe('ExampleController', () => {
error: new Error('Unauthorized'),
});
await expect(controller.remove(exampleId, { user: mockUser })).rejects.toThrow(UnauthorizedException);
await expect(controller.remove(exampleId, { user: mockUser })).rejects.toThrow(
UnauthorizedException
);
});
});
});

View file

@ -36,7 +36,9 @@ describe('ExampleComponent', () => {
});
it('should render with testID for automation', () => {
const { getByTestId } = render(<ExampleComponent {...defaultProps} testID="example-component" />);
const { getByTestId } = render(
<ExampleComponent {...defaultProps} testID="example-component" />
);
expect(getByTestId('example-component')).toBeTruthy();
});
@ -78,7 +80,9 @@ describe('ExampleComponent', () => {
});
it('should call onLongPress when long pressed', () => {
const { getByText } = render(<ExampleComponent {...defaultProps} onLongPress={mockOnLongPress} />);
const { getByText } = render(
<ExampleComponent {...defaultProps} onLongPress={mockOnLongPress} />
);
fireEvent(getByText('Test Title'), 'onLongPress');
@ -242,7 +246,9 @@ describe('ExampleComponent', () => {
});
it('should handle undefined props gracefully', () => {
const { getByText } = render(<ExampleComponent title="Test" onPress={mockOnPress} description={undefined} />);
const { getByText } = render(
<ExampleComponent title="Test" onPress={mockOnPress} description={undefined} />
);
expect(getByText('Test')).toBeTruthy();
});

View file

@ -72,7 +72,10 @@ describe('authService', () => {
// Verify tokens were stored
expect(SecureStore.setItemAsync).toHaveBeenCalledWith('@auth/appToken', mockTokens.appToken);
expect(SecureStore.setItemAsync).toHaveBeenCalledWith('@auth/refreshToken', mockTokens.refreshToken);
expect(SecureStore.setItemAsync).toHaveBeenCalledWith(
'@auth/refreshToken',
mockTokens.refreshToken
);
});
it('should handle invalid credentials error', async () => {