mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:21:09 +02:00
chore: remove all NestJS backend references, replace with Hono/Bun
- Delete nestjs-backend.md guideline (replaced by hono-server.md) - Delete Dockerfile.nestjs-base and Dockerfile.nestjs templates - Delete stale BACKEND_ARCHITECTURE.md doc (NestJS-era, obsolete) - Update CLAUDE.md, GUIDELINES.md, authentication.md to Hono/Bun first - Update all app CLAUDE.md files: backend/ → server/, NestJS → Hono+Bun - Update all app package.json files: @*/backend → @*/server - Update docs: LOCAL_DEVELOPMENT, PORT_SCHEMA, ENVIRONMENT_VARIABLES, DATABASE_MIGRATIONS, MAC_MINI_SERVER, PROJECT_OVERVIEW - Update scripts: generate-env.mjs, setup-databases.sh, build-app.sh - Update CI/CD: cd-macmini.yml backend → server paths - Update Astro docs site: @chat/backend → @chat/server Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
708299b35e
commit
ab387b9b3d
43 changed files with 598 additions and 2398 deletions
|
|
@ -1,945 +0,0 @@
|
|||
# Backend-Architektur im Manacore Monorepo
|
||||
|
||||
Diese Dokumentation beschreibt die Backend-Implementierungen aller Projekte im Manacore Monorepo.
|
||||
|
||||
## Übersicht
|
||||
|
||||
Das Monorepo enthält 6 Hauptprojekte mit unterschiedlichen Backend-Architekturen:
|
||||
|
||||
| Projekt | Backend-Typ | Datenbank | Status |
|
||||
|---------|-------------|-----------|--------|
|
||||
| **Maerchenzauber** | NestJS v10 | Supabase (PostgreSQL) | Aktiv |
|
||||
| **Manadeck** | NestJS v11 | PostgreSQL + Drizzle ORM | Aktiv |
|
||||
| **Uload** | NestJS v11 | PostgreSQL + Drizzle ORM | Aktiv |
|
||||
| **Picture** | Kein Backend | - | Frontend-only |
|
||||
| **Memoro** | Kein Backend | - | Frontend-only |
|
||||
| **Manacore** | Kein Backend (extern) | - | Externes Backend |
|
||||
|
||||
---
|
||||
|
||||
## 1. Maerchenzauber
|
||||
|
||||
**Pfad:** `/maerchenzauber/apps/backend`
|
||||
|
||||
**Zweck:** KI-gestützte Kindergeschichten-Generierung mit benutzerdefinierten Charakteren.
|
||||
|
||||
### Technologie-Stack
|
||||
|
||||
- **Framework:** NestJS 10.0.0
|
||||
- **Datenbank:** Supabase (PostgreSQL)
|
||||
- **ORM:** `@supabase/supabase-js` v2.81.1
|
||||
- **AI-Services:** Azure OpenAI, Google Gemini, Replicate
|
||||
|
||||
### Architektur
|
||||
|
||||
```
|
||||
apps/backend/
|
||||
├── src/
|
||||
│ ├── character/ # Charakter-Modul
|
||||
│ │ ├── character.controller.ts
|
||||
│ │ ├── character.service.ts
|
||||
│ │ └── character.repository.ts
|
||||
│ ├── story/ # Story-Modul
|
||||
│ │ ├── story.controller.ts
|
||||
│ │ ├── story.service.ts
|
||||
│ │ └── pipelines/ # Story-Generierung-Pipelines
|
||||
│ ├── core/ # Kern-Services
|
||||
│ │ └── services/
|
||||
│ │ └── prompting.service.ts
|
||||
│ ├── settings/ # Benutzereinstellungen
|
||||
│ ├── health/ # Health-Checks
|
||||
│ └── feedback/ # Feedback-Modul
|
||||
```
|
||||
|
||||
### Datenbank-Schema
|
||||
|
||||
**Tabellen:**
|
||||
- `characters` - Benutzercharaktere
|
||||
- `stories` - Generierte Geschichten
|
||||
- `story_collections` - Sammlungen von Geschichten
|
||||
- `user_settings` - Benutzereinstellungen
|
||||
|
||||
**Sicherheit:** Row-Level Security (RLS) für Datenzugriffskontrolle
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
Mana Core Integration via `@mana-core/nestjs-integration`:
|
||||
|
||||
```typescript
|
||||
// Beispiel: Geschützter Endpoint
|
||||
@UseGuards(AuthGuard)
|
||||
@Get('characters')
|
||||
async getCharacters(@CurrentUser() user: User) {
|
||||
return this.characterService.findByUser(user.id);
|
||||
}
|
||||
```
|
||||
|
||||
**Auth-Endpoint:** `https://mana-core-middleware-111768794939.europe-west3.run.app`
|
||||
|
||||
### AI-Services
|
||||
|
||||
| Service | Verwendung | API |
|
||||
|---------|------------|-----|
|
||||
| Azure OpenAI (GPT-4) | Story-Generierung | `MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT` |
|
||||
| Google Gemini | Charakter-Generierung | `GOOGLE_GEMINI_API_KEY` |
|
||||
| Replicate (Flux) | Bildgenerierung | `REPLICATE_API_TOKEN` |
|
||||
|
||||
### File Storage
|
||||
|
||||
- **Provider:** Supabase Storage
|
||||
- **Bucket:** `maerchenzauber`
|
||||
- **Verwendung:** Charakter- und Story-Bilder
|
||||
|
||||
### Deployment
|
||||
|
||||
- **Plattform:** Google Cloud Run
|
||||
- **Region:** europe-west3
|
||||
- **URL:** `https://storyteller-backend-111768794939.europe-west3.run.app`
|
||||
- **Port:** 3002 (Development)
|
||||
|
||||
---
|
||||
|
||||
## 2. Manadeck
|
||||
|
||||
**Pfad:** `/manadeck/apps/backend`
|
||||
|
||||
**Zweck:** KI-gestützte Lernkarten-Generierung (Flashcards, Quizzes, Mixed).
|
||||
|
||||
### Technologie-Stack
|
||||
|
||||
- **Framework:** NestJS 11.0.1
|
||||
- **Datenbank:** PostgreSQL 16
|
||||
- **ORM:** Drizzle ORM
|
||||
- **AI-Service:** Google Gemini API
|
||||
|
||||
### Architektur
|
||||
|
||||
```
|
||||
apps/backend/
|
||||
├── src/
|
||||
│ ├── api.controller.ts # Haupt-API-Endpoints
|
||||
│ ├── public.controller.ts # Öffentliche Endpoints
|
||||
│ ├── health.controller.ts # Health-Checks
|
||||
│ ├── ai.service.ts # AI-Generierung
|
||||
│ └── repositories/
|
||||
│ ├── deck.repository.ts
|
||||
│ ├── card.repository.ts
|
||||
│ ├── user-stats.repository.ts
|
||||
│ └── deck-template.repository.ts
|
||||
```
|
||||
|
||||
### Datenbank-Package
|
||||
|
||||
Das Datenbank-Schema ist in einem separaten Package ausgelagert:
|
||||
|
||||
**Pfad:** `/packages/manadeck-database`
|
||||
|
||||
```typescript
|
||||
// Verwendung im Backend
|
||||
import { db, schema } from '@manacore/manadeck-database';
|
||||
|
||||
const decks = await db.query.decks.findMany({
|
||||
where: eq(schema.decks.userId, userId)
|
||||
});
|
||||
```
|
||||
|
||||
**Drizzle-Konfiguration:**
|
||||
```typescript
|
||||
// drizzle.config.ts
|
||||
export default {
|
||||
schema: './src/schema/*',
|
||||
out: './migrations',
|
||||
driver: 'pg',
|
||||
dbCredentials: {
|
||||
connectionString: process.env.DATABASE_URL
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
```typescript
|
||||
import { AuthGuard, CurrentUser } from '@mana-core/nestjs-integration';
|
||||
|
||||
@Controller('api')
|
||||
@UseGuards(AuthGuard)
|
||||
export class ApiController {
|
||||
@Post('decks')
|
||||
async createDeck(@CurrentUser() user: User, @Body() dto: CreateDeckDto) {
|
||||
// Credit-Prüfung und Deck-Erstellung
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Credit-System
|
||||
|
||||
Integration mit Mana Core Credit Service:
|
||||
|
||||
```typescript
|
||||
import { CreditClientService } from '@mana-core/nestjs-integration';
|
||||
|
||||
@Injectable()
|
||||
export class AiService {
|
||||
constructor(private creditClient: CreditClientService) {}
|
||||
|
||||
async generateDeck(userId: string, input: GenerateInput) {
|
||||
// 1. Credit-Balance prüfen
|
||||
const hasCredits = await this.creditClient.checkBalance(userId, 'DECK_CREATION');
|
||||
|
||||
// 2. Deck generieren
|
||||
const deck = await this.generateWithGemini(input);
|
||||
|
||||
// 3. Credits abziehen
|
||||
await this.creditClient.deduct(userId, 'DECK_CREATION');
|
||||
|
||||
return deck;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AI-Generierung
|
||||
|
||||
**Unterstützte Kartentypen:**
|
||||
- `text` - Textbasierte Karten
|
||||
- `flashcard` - Klassische Lernkarten
|
||||
- `quiz` - Multiple-Choice Quiz
|
||||
- `mixed` - Gemischte Inhalte
|
||||
|
||||
**Schwierigkeitsgrade:**
|
||||
- `beginner`
|
||||
- `intermediate`
|
||||
- `advanced`
|
||||
|
||||
### Docker-Setup
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml (Lokale Entwicklung)
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
ports:
|
||||
- "5433:5432"
|
||||
environment:
|
||||
POSTGRES_DB: manadeck
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4
|
||||
ports:
|
||||
- "5050:80"
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
- **Docker Image:** Multi-stage Build (Node 18-alpine)
|
||||
- **Port:** 8080
|
||||
- **Health-Check:** `/health`
|
||||
|
||||
---
|
||||
|
||||
## 3. Uload
|
||||
|
||||
**Pfad:** `/uload/apps/backend`
|
||||
|
||||
**Zweck:** URL-Shortener mit Link-Analytics.
|
||||
|
||||
### Technologie-Stack
|
||||
|
||||
- **Framework:** NestJS 11.0.1
|
||||
- **Datenbank:** PostgreSQL 16
|
||||
- **ORM:** Drizzle ORM
|
||||
- **Cache:** Redis (optional)
|
||||
|
||||
### Architektur
|
||||
|
||||
```
|
||||
uload/apps/backend/
|
||||
├── src/
|
||||
│ ├── main.ts
|
||||
│ ├── app.module.ts
|
||||
│ ├── config/
|
||||
│ │ └── validation.schema.ts
|
||||
│ ├── controllers/
|
||||
│ │ ├── redirect.controller.ts # GET /:code (public redirect)
|
||||
│ │ ├── links.controller.ts # CRUD /api/links
|
||||
│ │ ├── analytics.controller.ts # GET /api/analytics
|
||||
│ │ └── health.controller.ts
|
||||
│ ├── services/
|
||||
│ │ ├── links.service.ts
|
||||
│ │ ├── redirect.service.ts
|
||||
│ │ └── analytics.service.ts
|
||||
│ └── database/
|
||||
│ ├── database.module.ts
|
||||
│ └── repositories/
|
||||
│ ├── link.repository.ts
|
||||
│ └── click.repository.ts
|
||||
├── Dockerfile
|
||||
└── package.json
|
||||
```
|
||||
|
||||
### Datenbank-Package
|
||||
|
||||
**Pfad:** `/packages/uload-database`
|
||||
|
||||
```typescript
|
||||
// Verwendung im Backend
|
||||
import { db, links, clicks, eq, desc } from '@manacore/uload-database';
|
||||
|
||||
const userLinks = await db.query.links.findMany({
|
||||
where: eq(links.userId, userId),
|
||||
orderBy: desc(links.createdAt)
|
||||
});
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
| Endpoint | Method | Auth | Beschreibung |
|
||||
|----------|--------|------|--------------|
|
||||
| `/:code` | GET | Public | Redirect zu Original-URL |
|
||||
| `/api/links` | GET | Protected | Liste aller Links |
|
||||
| `/api/links` | POST | Protected | Link erstellen |
|
||||
| `/api/links/:id` | GET | Protected | Link Details |
|
||||
| `/api/links/:id` | PATCH | Protected | Link aktualisieren |
|
||||
| `/api/links/:id` | DELETE | Protected | Link löschen |
|
||||
| `/api/analytics/:linkId` | GET | Protected | Link-Statistiken |
|
||||
| `/health` | GET | Public | Health Check |
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
Mana Core Integration via `@mana-core/nestjs-integration`:
|
||||
|
||||
```typescript
|
||||
import { AuthGuard, CurrentUser } from '@mana-core/nestjs-integration';
|
||||
|
||||
@Controller('api/links')
|
||||
@UseGuards(AuthGuard)
|
||||
export class LinksController {
|
||||
@Get()
|
||||
async getLinks(@CurrentUser() user: any) {
|
||||
return this.linksService.getLinks(user.sub);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
- **Docker Image:** Multi-stage Build (Node 20-alpine)
|
||||
- **Port:** 3003
|
||||
- **Health-Check:** `/health`
|
||||
|
||||
---
|
||||
|
||||
## 4. Picture
|
||||
|
||||
**Pfad:** `/picture`
|
||||
|
||||
**Zweck:** Bild- und Medienverwaltung.
|
||||
|
||||
### Architektur
|
||||
|
||||
**Kein dediziertes Backend.** Picture verwendet:
|
||||
|
||||
- SvelteKit Server-Routes für Backend-Logik
|
||||
- Mana Core für Authentifizierung
|
||||
- Shared Packages aus `/packages`
|
||||
|
||||
```
|
||||
picture/
|
||||
├── apps/
|
||||
│ ├── mobile/ # React Native Expo
|
||||
│ ├── web/ # SvelteKit
|
||||
│ └── landing/ # Astro
|
||||
└── packages/
|
||||
├── design-tokens/ # Design System
|
||||
├── mobile-ui/ # Mobile UI Components
|
||||
└── shared/ # Utilities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Memoro
|
||||
|
||||
**Pfad:** `/memoro`
|
||||
|
||||
**Zweck:** Legacy-Content und Memory-Preservation.
|
||||
|
||||
### Architektur
|
||||
|
||||
**Kein dediziertes Backend.** Memoro verwendet:
|
||||
|
||||
- SvelteKit Server-Routes
|
||||
- Mana Core für Authentifizierung
|
||||
- Supabase (Legacy-Konfiguration vorhanden)
|
||||
|
||||
```
|
||||
memoro/
|
||||
├── apps/
|
||||
│ ├── mobile/
|
||||
│ ├── web/
|
||||
│ └── landing/
|
||||
└── supabase/ # Legacy Supabase Config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Manacore
|
||||
|
||||
**Pfad:** `/manacore`
|
||||
|
||||
**Zweck:** Core-Authentifizierung und Credit-System.
|
||||
|
||||
### Architektur
|
||||
|
||||
Das Manacore-Backend ist **extern gehostet** und nicht Teil des Monorepos:
|
||||
|
||||
- **URL:** `https://mana-core-middleware-111768794939.europe-west3.run.app`
|
||||
- **Integration:** Via `@mana-core/nestjs-integration` Package
|
||||
|
||||
```
|
||||
manacore/
|
||||
├── apps/
|
||||
│ ├── mobile/ # Auth-Flow UI
|
||||
│ ├── web/ # Dashboard
|
||||
│ └── landing/ # Marketing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shared Packages für Backend
|
||||
|
||||
### @manacore/manadeck-database
|
||||
|
||||
PostgreSQL-Datenbankschema für Manadeck.
|
||||
|
||||
```
|
||||
packages/manadeck-database/
|
||||
├── src/
|
||||
│ ├── schema/ # Drizzle Schema
|
||||
│ ├── client.ts # DB Client
|
||||
│ └── index.ts # Exports
|
||||
├── drizzle.config.ts
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
### @manacore/uload-database
|
||||
|
||||
PostgreSQL-Datenbankschema für Uload URL-Shortener.
|
||||
|
||||
```
|
||||
packages/uload-database/
|
||||
├── src/
|
||||
│ ├── schema/
|
||||
│ │ ├── users.ts
|
||||
│ │ ├── links.ts
|
||||
│ │ ├── clicks.ts
|
||||
│ │ ├── tags.ts
|
||||
│ │ ├── workspaces.ts
|
||||
│ │ ├── accounts.ts
|
||||
│ │ └── relations.ts
|
||||
│ ├── client.ts # DB Client
|
||||
│ └── index.ts # Exports
|
||||
├── drizzle.config.ts
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
### @mana-core/nestjs-integration
|
||||
|
||||
Externe Dependency für Backend-Integration:
|
||||
|
||||
```typescript
|
||||
// Installation via git
|
||||
"@mana-core/nestjs-integration": "git+https://github.com/mana-core/nestjs-integration.git"
|
||||
```
|
||||
|
||||
**Bereitgestellte Features:**
|
||||
- `AuthGuard` - JWT-Authentifizierung
|
||||
- `@CurrentUser()` - User-Context Decorator
|
||||
- `CreditClientService` - Credit-Operationen
|
||||
- Konfigurationsmodule
|
||||
|
||||
---
|
||||
|
||||
## Authentifizierungs-Pattern
|
||||
|
||||
Alle Projekte nutzen zentrale **Mana Core Authentifizierung**:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Frontend │────▶│ Project Backend │────▶│ Mana Core │
|
||||
│ (Web/Mobile) │ │ (NestJS/etc.) │ │ Middleware │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
shared-auth AuthGuard JWT Validation
|
||||
shared-auth-ui @CurrentUser Credit Service
|
||||
shared-auth-stores CreditClient User Management
|
||||
```
|
||||
|
||||
### Frontend-Integration
|
||||
|
||||
```typescript
|
||||
// Shared Auth Store (Svelte)
|
||||
import { authStore } from '@manacore/shared-auth-stores';
|
||||
|
||||
// Login
|
||||
await authStore.login(email, password);
|
||||
|
||||
// Token für API-Requests
|
||||
const token = authStore.getAccessToken();
|
||||
```
|
||||
|
||||
### Backend-Integration
|
||||
|
||||
```typescript
|
||||
// NestJS Module Setup
|
||||
@Module({
|
||||
imports: [
|
||||
ManaCoreModule.forRoot({
|
||||
serviceKey: process.env.MANA_CORE_SERVICE_KEY,
|
||||
baseUrl: process.env.MANA_CORE_URL,
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Datenbank-Migrationen
|
||||
|
||||
### Manadeck (Drizzle)
|
||||
|
||||
```bash
|
||||
# Migration generieren
|
||||
pnpm --filter @manacore/manadeck-database drizzle-kit generate
|
||||
|
||||
# Migration ausführen
|
||||
pnpm --filter @manacore/manadeck-database drizzle-kit push
|
||||
```
|
||||
|
||||
### Maerchenzauber (Supabase)
|
||||
|
||||
```bash
|
||||
# Supabase CLI
|
||||
supabase migration new <name>
|
||||
supabase db push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Umgebungsvariablen
|
||||
|
||||
### Maerchenzauber Backend
|
||||
|
||||
```env
|
||||
# Supabase
|
||||
SUPABASE_URL=
|
||||
SUPABASE_SERVICE_ROLE_KEY=
|
||||
|
||||
# Mana Core
|
||||
MANA_CORE_URL=https://mana-core-middleware-111768794939.europe-west3.run.app
|
||||
MANA_CORE_SERVICE_KEY=
|
||||
|
||||
# AI Services
|
||||
MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT=
|
||||
AZURE_OPENAI_API_KEY=
|
||||
GOOGLE_GEMINI_API_KEY=
|
||||
REPLICATE_API_TOKEN=
|
||||
```
|
||||
|
||||
### Manadeck Backend
|
||||
|
||||
```env
|
||||
# Database
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/manadeck
|
||||
|
||||
# Mana Core
|
||||
MANA_CORE_URL=
|
||||
MANA_CORE_SERVICE_KEY=
|
||||
|
||||
# AI
|
||||
GOOGLE_GEMINI_API_KEY=
|
||||
|
||||
# Server
|
||||
PORT=8080
|
||||
```
|
||||
|
||||
### Uload
|
||||
|
||||
```env
|
||||
# Database
|
||||
DATABASE_URL=postgresql://...
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# PocketBase
|
||||
POCKETBASE_URL=
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Lokale Entwicklung
|
||||
|
||||
### Maerchenzauber Backend
|
||||
|
||||
```bash
|
||||
cd maerchenzauber/apps/backend
|
||||
pnpm install
|
||||
pnpm run start:dev
|
||||
# Läuft auf Port 3002
|
||||
```
|
||||
|
||||
### Manadeck Backend
|
||||
|
||||
```bash
|
||||
# 1. Datenbank starten
|
||||
cd packages/manadeck-database
|
||||
docker-compose up -d
|
||||
|
||||
# 2. Backend starten
|
||||
cd manadeck/apps/backend
|
||||
pnpm install
|
||||
pnpm run start:dev
|
||||
# Läuft auf Port 8080
|
||||
```
|
||||
|
||||
### Uload
|
||||
|
||||
```bash
|
||||
cd uload
|
||||
docker-compose up -d # PostgreSQL + Redis
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
Das Manacore Monorepo verwendet verschiedene Backend-Strategien:
|
||||
|
||||
1. **Full Backend (NestJS):** Maerchenzauber, Manadeck - Für komplexe Geschäftslogik und AI-Integration
|
||||
2. **Embedded Database (PocketBase):** Uload - Für einfache CRUD-Operationen
|
||||
3. **Frontend-only:** Picture, Memoro - Server-Routes in SvelteKit
|
||||
4. **External Backend:** Manacore - Zentrale Auth/Credit-Services
|
||||
|
||||
Alle Projekte teilen sich:
|
||||
- Gemeinsame Authentifizierung via Mana Core
|
||||
- Shared Packages für UI, Auth, Types
|
||||
- Einheitliches Deployment-Pattern (Docker + Cloud Run)
|
||||
|
||||
---
|
||||
|
||||
## Vereinheitlichungs-Roadmap
|
||||
|
||||
### Aktuelle Fragmentierung
|
||||
|
||||
| Aspekt | Maerchenzauber | Manadeck | Uload |
|
||||
|--------|----------------|----------|-------|
|
||||
| Framework | NestJS v10 | NestJS v11 | PocketBase |
|
||||
| Datenbank | Supabase | PostgreSQL | PocketBase + PG |
|
||||
| ORM | @supabase/js | Drizzle | Drizzle |
|
||||
| Auth | Mana Core | Mana Core | PocketBase + Mana Core |
|
||||
|
||||
---
|
||||
|
||||
### Strategie 1: Shared NestJS Backend Package
|
||||
|
||||
**Ziel:** Ein gemeinsames `@manacore/shared-backend` Package mit wiederverwendbaren Modulen.
|
||||
|
||||
```
|
||||
packages/shared-backend/
|
||||
├── src/
|
||||
│ ├── auth/
|
||||
│ │ ├── auth.module.ts
|
||||
│ │ ├── auth.guard.ts
|
||||
│ │ └── current-user.decorator.ts
|
||||
│ ├── database/
|
||||
│ │ ├── database.module.ts
|
||||
│ │ ├── drizzle.provider.ts
|
||||
│ │ └── base.repository.ts
|
||||
│ ├── health/
|
||||
│ │ └── health.module.ts
|
||||
│ ├── credits/
|
||||
│ │ └── credits.module.ts
|
||||
│ └── common/
|
||||
│ ├── filters/
|
||||
│ ├── interceptors/
|
||||
│ └── pipes/
|
||||
```
|
||||
|
||||
**Vorteile:**
|
||||
- Einheitliche Auth-Integration
|
||||
- Wiederverwendbare Module
|
||||
- Konsistente Error-Handling
|
||||
|
||||
**Aufwand:** Mittel
|
||||
|
||||
---
|
||||
|
||||
### Strategie 2: Einheitliche Datenbank-Strategie
|
||||
|
||||
#### Option A: Alles auf Drizzle + PostgreSQL (Empfohlen)
|
||||
|
||||
```typescript
|
||||
// packages/shared-database/src/base-schema.ts
|
||||
export const baseColumns = {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
updatedAt: timestamp('updated_at').defaultNow(),
|
||||
userId: text('user_id').notNull(),
|
||||
};
|
||||
|
||||
// Projekt-spezifische Erweiterung
|
||||
// maerchenzauber/database/schema/characters.ts
|
||||
import { baseColumns } from '@manacore/shared-database';
|
||||
|
||||
export const characters = pgTable('characters', {
|
||||
...baseColumns,
|
||||
name: text('name').notNull(),
|
||||
traits: jsonb('traits'),
|
||||
});
|
||||
```
|
||||
|
||||
**Migration von Supabase:**
|
||||
- Supabase ist PostgreSQL → Schema kann übernommen werden
|
||||
- RLS-Policies in Application-Layer verschieben
|
||||
- Storage → S3/Cloudflare R2
|
||||
|
||||
#### Option B: Alles auf Supabase
|
||||
|
||||
```typescript
|
||||
export const createProjectClient = (project: 'maerchenzauber' | 'manadeck' | 'uload') => {
|
||||
return createClient(
|
||||
process.env[`${project.toUpperCase()}_SUPABASE_URL`],
|
||||
process.env[`${project.toUpperCase()}_SUPABASE_KEY`]
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
**Vorteile Supabase:**
|
||||
- Eingebaute Auth (optional nutzbar)
|
||||
- Storage inklusive
|
||||
- Realtime-Subscriptions
|
||||
- Edge Functions möglich
|
||||
|
||||
**Nachteile Supabase:**
|
||||
- Vendor Lock-in
|
||||
- Weniger Kontrolle über Schema
|
||||
|
||||
**Empfehlung:** Drizzle + PostgreSQL wegen Type-Safety, moderner API und keinem Vendor Lock-in.
|
||||
|
||||
---
|
||||
|
||||
### Strategie 3: Einheitliche Monorepo Backend Struktur
|
||||
|
||||
**Ziel-Architektur:**
|
||||
|
||||
```
|
||||
packages/
|
||||
├── shared-backend/ # Gemeinsame NestJS Module
|
||||
│ ├── auth/
|
||||
│ ├── database/
|
||||
│ ├── health/
|
||||
│ └── credits/
|
||||
├── shared-database/ # Drizzle Basis-Schema
|
||||
│ ├── base-schema.ts
|
||||
│ ├── migrations/
|
||||
│ └── client.ts
|
||||
├── maerchenzauber-database/ # Projekt-Schema
|
||||
├── manadeck-database/ # ✓ Existiert bereits
|
||||
└── uload-database/ # Neu
|
||||
|
||||
apps/
|
||||
├── maerchenzauber-backend/ # Nutzt shared-backend
|
||||
├── manadeck-backend/ # Nutzt shared-backend
|
||||
└── uload-backend/ # Neues NestJS Backend (ersetzt PocketBase)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Strategie 4: Shared Backend als Service-Layer
|
||||
|
||||
**Ziel:** Gemeinsamer Service-Layer, projekt-spezifische Controller.
|
||||
|
||||
```typescript
|
||||
// packages/shared-backend/src/services/ai.service.ts
|
||||
@Injectable()
|
||||
export class BaseAiService {
|
||||
constructor(
|
||||
private gemini: GeminiClient,
|
||||
private credits: CreditService,
|
||||
) {}
|
||||
|
||||
protected async generateWithCredits<T>(
|
||||
userId: string,
|
||||
operation: string,
|
||||
generator: () => Promise<T>
|
||||
): Promise<T> {
|
||||
await this.credits.check(userId, operation);
|
||||
const result = await generator();
|
||||
await this.credits.deduct(userId, operation);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// maerchenzauber/backend/src/story/story.service.ts
|
||||
@Injectable()
|
||||
export class StoryService extends BaseAiService {
|
||||
async generateStory(userId: string, input: StoryInput) {
|
||||
return this.generateWithCredits(userId, 'STORY_GENERATION', async () => {
|
||||
// Projekt-spezifische Logik
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Strategie 5: API-Gateway Pattern (Optional)
|
||||
|
||||
**Ziel:** Ein zentrales Gateway vor allen Backends.
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ API Gateway │
|
||||
│ (Kong/Traefik) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────────────────┼────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||
│ Maerchenzauber│ │ Manadeck │ │ Uload │
|
||||
│ Backend │ │ Backend │ │ Backend │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
```
|
||||
|
||||
**Vorteile:**
|
||||
- Zentrale Auth-Validierung
|
||||
- Rate Limiting
|
||||
- Request Logging
|
||||
- Einheitliche API-Struktur
|
||||
|
||||
**Aufwand:** Hoch - Empfohlen erst bei Skalierungsbedarf
|
||||
|
||||
---
|
||||
|
||||
### Empfohlene Implementierungsreihenfolge
|
||||
|
||||
#### Phase 1: Shared Backend Package
|
||||
|
||||
**Priorität:** Hoch
|
||||
**Aufwand:** 2-3 Wochen
|
||||
|
||||
Neues Package `packages/shared-backend/` mit:
|
||||
- Auth Module (wraps @mana-core/nestjs-integration)
|
||||
- Health Module
|
||||
- Credits Module
|
||||
- Base Repository Pattern
|
||||
- Common Decorators, Guards, Filters
|
||||
|
||||
#### Phase 2: Datenbank-Vereinheitlichung
|
||||
|
||||
**Priorität:** Hoch
|
||||
**Aufwand:** 3-4 Wochen
|
||||
|
||||
1. `packages/shared-database/` mit Drizzle Basis-Schema erstellen
|
||||
2. Maerchenzauber von Supabase auf Drizzle migrieren
|
||||
3. Uload PocketBase durch PostgreSQL + Drizzle ersetzen
|
||||
|
||||
#### Phase 3: Uload Backend Neubau (Optional)
|
||||
|
||||
**Priorität:** Mittel
|
||||
**Aufwand:** 2-3 Wochen
|
||||
|
||||
PocketBase → NestJS Migration:
|
||||
- Konsistenz mit anderen Projekten
|
||||
- Bessere Integration mit Mana Core
|
||||
- Einheitliches Deployment
|
||||
|
||||
---
|
||||
|
||||
### Optionen-Vergleich
|
||||
|
||||
| Option | Aufwand | Benefit | Empfehlung |
|
||||
|--------|---------|---------|------------|
|
||||
| Shared Backend Package | Mittel | Hoch | ✅ Priorität 1 |
|
||||
| Drizzle überall | Mittel-Hoch | Hoch | ✅ Priorität 2 |
|
||||
| Uload auf NestJS | Hoch | Mittel | ⚡ Optional |
|
||||
| API Gateway | Sehr Hoch | Mittel | ⏳ Später |
|
||||
|
||||
---
|
||||
|
||||
### Quick Wins (sofort umsetzbar)
|
||||
|
||||
1. **NestJS Version angleichen** → Alle auf v11
|
||||
2. **Einheitliche Health-Endpoints** → `/health`, `/health/ready`
|
||||
3. **Gemeinsame ESLint/Prettier Config** → `@manacore/eslint-config-backend`
|
||||
4. **Einheitliche Error-Response-Struktur:**
|
||||
|
||||
```typescript
|
||||
// Einheitliches Error-Format für alle Backends
|
||||
interface ApiError {
|
||||
statusCode: number;
|
||||
error: string;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
path: string;
|
||||
}
|
||||
```
|
||||
|
||||
5. **Einheitliche Logging-Struktur:**
|
||||
|
||||
```typescript
|
||||
// packages/shared-backend/src/logging/logger.service.ts
|
||||
@Injectable()
|
||||
export class AppLogger {
|
||||
log(context: string, message: string, meta?: Record<string, any>) {
|
||||
console.log(JSON.stringify({
|
||||
level: 'info',
|
||||
context,
|
||||
message,
|
||||
timestamp: new Date().toISOString(),
|
||||
...meta,
|
||||
}));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Ziel-Architektur nach Vereinheitlichung
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Shared Packages │
|
||||
├─────────────────┬─────────────────┬─────────────────────────┤
|
||||
│ shared-backend │ shared-database │ shared-types │
|
||||
│ - AuthModule │ - baseColumns │ - ApiError │
|
||||
│ - HealthModule │ - drizzleClient │ - User │
|
||||
│ - CreditsModule │ - migrations │ - CreditOperation │
|
||||
│ - BaseRepo │ │ │
|
||||
└────────┬────────┴────────┬────────┴────────┬────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Maerchenzauber │ │ Manadeck │ │ Uload │
|
||||
│ Backend │ │ Backend │ │ Backend │
|
||||
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
|
||||
│ NestJS v11 │ │ NestJS v11 │ │ NestJS v11 │
|
||||
│ PostgreSQL │ │ PostgreSQL │ │ PostgreSQL │
|
||||
│ Drizzle ORM │ │ Drizzle ORM │ │ Drizzle ORM │
|
||||
│ Port: 3002 │ │ Port: 8080 │ │ Port: 3003 │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
└─────────────────┼─────────────────┘
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Mana Core │
|
||||
│ (Auth + Credits) │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
|
@ -246,8 +246,8 @@ pnpm --filter mana-core-auth db:generate
|
|||
pnpm --filter mana-core-auth db:migrate
|
||||
|
||||
# chat-backend
|
||||
pnpm --filter @chat/backend db:push
|
||||
pnpm --filter @chat/backend db:migrate
|
||||
pnpm --filter @chat/server db:push
|
||||
pnpm --filter @chat/server db:migrate
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ The generator reads `.env.development` and creates app-specific `.env` files wit
|
|||
|----------|--------|---------|
|
||||
| Expo (mobile) | `EXPO_PUBLIC_` | `EXPO_PUBLIC_SUPABASE_URL` |
|
||||
| SvelteKit (web) | `PUBLIC_` | `PUBLIC_SUPABASE_URL` |
|
||||
| NestJS (backend) | None | `SUPABASE_URL` |
|
||||
| Hono/Bun (server) | None | `DATABASE_URL` |
|
||||
|
||||
## File Locations
|
||||
|
||||
|
|
@ -40,19 +40,17 @@ The generator reads `.env.development` and creates app-specific `.env` files wit
|
|||
- **`.env.development`** - Single source of truth, committed to git
|
||||
|
||||
### Generated Files (gitignored)
|
||||
- `services/mana-core-auth/.env`
|
||||
- `apps/chat/apps/backend/.env`
|
||||
- `services/mana-auth/.env`
|
||||
- `apps/chat/apps/server/.env`
|
||||
- `apps/chat/apps/mobile/.env`
|
||||
- `apps/chat/apps/web/.env`
|
||||
- `apps/maerchenzauber/apps/backend/.env`
|
||||
- `apps/maerchenzauber/apps/mobile/.env`
|
||||
- `apps/maerchenzauber/apps/web/.env`
|
||||
- `apps/manacore/apps/mobile/.env`
|
||||
- `apps/manacore/apps/web/.env`
|
||||
- `apps/memoro/apps/mobile/.env`
|
||||
- `apps/memoro/apps/web/.env`
|
||||
- `apps/manadeck/apps/backend/.env`
|
||||
- `apps/manadeck/apps/server/.env`
|
||||
- `apps/manadeck/apps/web/.env`
|
||||
- `apps/*/apps/server/.env` (all apps with compute servers)
|
||||
- `apps/*/apps/web/.env` (all web apps)
|
||||
- `apps/*/apps/mobile/.env` (all mobile apps)
|
||||
|
||||
## Variable Reference
|
||||
|
||||
|
|
@ -98,28 +96,6 @@ The generator reads `.env.development` and creates app-specific `.env` files wit
|
|||
| `CHAT_SUPABASE_URL` | Supabase project URL | - |
|
||||
| `CHAT_SUPABASE_ANON_KEY` | Supabase anonymous key | - |
|
||||
|
||||
### Maerchenzauber Project
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `MAERCHENZAUBER_BACKEND_PORT` | Backend service port | `3003` |
|
||||
| `MAERCHENZAUBER_APP_ID` | Mana Core app ID | - |
|
||||
| `MAERCHENZAUBER_SUPABASE_URL` | Supabase project URL | - |
|
||||
| `MAERCHENZAUBER_SUPABASE_ANON_KEY` | Supabase anonymous key | - |
|
||||
| `MAERCHENZAUBER_JWT_SECRET` | JWT secret for Supabase | - |
|
||||
| `MAERCHENZAUBER_AZURE_OPENAI_KEY` | Azure OpenAI key | - |
|
||||
| `MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint | - |
|
||||
| `MAERCHENZAUBER_REPLICATE_API_KEY` | Replicate API key (images) | - |
|
||||
|
||||
### Memoro Project
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `MEMORO_SUPABASE_URL` | Supabase project URL |
|
||||
| `MEMORO_SUPABASE_ANON_KEY` | Supabase anonymous key |
|
||||
| `MEMORO_MIDDLEWARE_API_URL` | Middleware API URL |
|
||||
| `MEMORO_APPID` | Mana Core app ID |
|
||||
|
||||
### Manacore Project
|
||||
|
||||
| Variable | Description |
|
||||
|
|
@ -168,9 +144,9 @@ Edit `scripts/generate-env.mjs` and add your app config:
|
|||
},
|
||||
},
|
||||
{
|
||||
path: 'apps/my-project/apps/backend/.env',
|
||||
path: 'apps/my-project/apps/server/.env',
|
||||
vars: {
|
||||
// For NestJS, no prefix needed
|
||||
// For Hono/Bun servers, no prefix needed
|
||||
API_KEY: (env) => env.MY_NEW_PROJECT_API_KEY,
|
||||
API_URL: (env) => env.MY_NEW_PROJECT_URL,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,35 +1,94 @@
|
|||
# Local Development Guide
|
||||
|
||||
This guide explains how to set up and run applications locally with automatic database setup.
|
||||
This guide explains how to set up and run applications locally. All apps use a **local-first architecture** with IndexedDB (Dexie.js) for reads/writes and mana-sync for background synchronization. Server-side compute (AI, file operations, RRULE expansion, etc.) is handled by lightweight **Hono/Bun servers**.
|
||||
|
||||
## Quick Start
|
||||
|
||||
For any project with a backend, use the `dev:*:full` command:
|
||||
### Fastest: `dev:*:local` (recommended for daily development)
|
||||
|
||||
No auth service needed. Starts mana-sync + server (if any) + web:
|
||||
|
||||
```bash
|
||||
pnpm dev:chat:full # Start chat with auth + database setup
|
||||
pnpm dev:zitare:full # Start zitare with auth + database setup
|
||||
pnpm dev:contacts:full # Start contacts with auth + database setup
|
||||
# ... etc
|
||||
pnpm dev:todo:local # sync + server + web
|
||||
pnpm dev:chat:local # sync + server + web
|
||||
pnpm dev:zitare:local # sync + web (no server needed)
|
||||
pnpm dev:clock:local # sync + web (no server needed)
|
||||
```
|
||||
|
||||
Guest mode works out of the box -- data lives in IndexedDB, no login required.
|
||||
|
||||
### Full stack: `dev:*:full` (with auth + database setup)
|
||||
|
||||
Use this when you need authentication, cross-device sync, or to test the full production flow:
|
||||
|
||||
```bash
|
||||
pnpm dev:todo:full # DB setup + auth + sync + server + web
|
||||
pnpm dev:chat:full # DB setup + auth + sync + server + web
|
||||
pnpm dev:zitare:full # auth + sync + web
|
||||
pnpm dev:calendar:full # DB setup + auth + sync + server + web
|
||||
```
|
||||
|
||||
These commands automatically:
|
||||
1. Create the database if it doesn't exist
|
||||
2. Push the latest schema (Drizzle `db:push`)
|
||||
3. Start the auth service (mana-core-auth)
|
||||
4. Start the backend and web app with colored output
|
||||
1. Create the database if it doesn't exist (for apps with Drizzle schemas)
|
||||
2. Push the latest schema (`drizzle-kit push --force`)
|
||||
3. Start the auth service (mana-auth)
|
||||
4. Start mana-sync (Go WebSocket server)
|
||||
5. Start the Hono/Bun server (if the app has one)
|
||||
6. Start the web app with colored output
|
||||
|
||||
## Available Full Dev Commands
|
||||
## Available Dev Commands
|
||||
|
||||
| Command | Database | Backend Port | Web Port |
|
||||
|---------|----------|--------------|----------|
|
||||
| `pnpm dev:chat:full` | chat | 3002 | 5173 |
|
||||
| `pnpm dev:zitare:full` | zitare | 3007 | 5177 |
|
||||
| `pnpm dev:contacts:full` | contacts | 3015 | 5184 |
|
||||
| `pnpm dev:calendar:full` | calendar | 3014 | 5179 |
|
||||
| `pnpm dev:clock:full` | clock | 3017 | 5187 |
|
||||
| `pnpm dev:todo:full` | todo | 3018 | 5188 |
|
||||
| `pnpm dev:picture:full` | picture | 3006 | 5175 |
|
||||
### Apps with Hono/Bun Servers
|
||||
|
||||
These apps have server-side compute and support both `local` and `full` modes:
|
||||
|
||||
| App | Server Port | Web Port | `local` | `full` |
|
||||
|-----|-------------|----------|---------|--------|
|
||||
| Todo | 3019 | 5188 | Yes | Yes |
|
||||
| Chat | 3002 | 5174 | Yes | Yes |
|
||||
| Calendar | 3003 | 5179 | Yes | Yes |
|
||||
| Contacts | 3004 | 5184 | Yes | Yes |
|
||||
| Picture | 3006 | 5175 | Yes | Yes |
|
||||
| ManaDeck | 3009 | 5176 | Yes | Yes |
|
||||
| Mukke | 3010 | 5180 | Yes | Yes |
|
||||
| Questions | 3011 | 5111 | Yes | Yes |
|
||||
| Storage | 3016 | 5185 | Yes | Yes |
|
||||
| Context | 3020 | 5192 | Yes | Yes |
|
||||
| Planta | 3022 | 5191 | Yes | Yes |
|
||||
| NutriPhi | 3023 | 5180 | Yes | Yes |
|
||||
| Traces | 3026 | mobile | Yes | Yes |
|
||||
| Presi | 3008 | 5178 | Yes | Yes |
|
||||
| uLoad | 3070 | 5173 | Yes | Yes |
|
||||
| News | 3071 | 5173 | Yes | Yes |
|
||||
| WiseKeep | 3072 | 5173 | Yes | Yes |
|
||||
| Moodlit | 3073 | 5173 | Yes | Yes |
|
||||
|
||||
### Apps without Servers (sync + web only)
|
||||
|
||||
These apps use only IndexedDB + mana-sync, no server-side compute:
|
||||
|
||||
| App | Web Port | `local` | `full` |
|
||||
|-----|----------|---------|--------|
|
||||
| Zitare | 5107 | Yes | Yes |
|
||||
| Clock | 5187 | Yes | Yes |
|
||||
| SkilltTree | 5195 | Yes | Yes |
|
||||
| Photos | 5189 | Yes | Yes |
|
||||
| CityCorners | 5196 | Yes | Yes |
|
||||
| Inventar | 5190 | Yes | Yes |
|
||||
| Times | 5197 | Yes | Yes |
|
||||
| Calc | 5198 | Yes | Yes |
|
||||
| ManaVoxel | 5028 | Yes | Yes |
|
||||
|
||||
### Infrastructure Ports
|
||||
|
||||
| Service | Port | Description |
|
||||
|---------|------|-------------|
|
||||
| mana-auth | 3001 | Central auth (Better Auth + EdDSA JWT) |
|
||||
| mana-sync | 3050 | Data sync (Go, WebSocket, field-level LWW) |
|
||||
| PostgreSQL | 5432 | Database |
|
||||
| Redis | 6379 | Cache |
|
||||
| MinIO API | 9000 | S3-compatible storage |
|
||||
| MinIO Console | 9001 | Storage web UI |
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -39,41 +98,65 @@ Before running any `dev:*:full` command:
|
|||
# 1. Start Docker infrastructure (PostgreSQL, Redis, MinIO)
|
||||
pnpm docker:up
|
||||
|
||||
# 2. Generate environment files (runs automatically on pnpm install)
|
||||
# 2. Build mana-sync (first time only, or after Go changes)
|
||||
pnpm dev:sync:build
|
||||
|
||||
# 3. Generate environment files (runs automatically on pnpm install)
|
||||
pnpm setup:env
|
||||
```
|
||||
|
||||
For `dev:*:local`, only mana-sync needs to be built. No Docker required unless your server uses a database.
|
||||
|
||||
## Database Setup Commands
|
||||
|
||||
### Individual Service Setup
|
||||
|
||||
```bash
|
||||
pnpm setup:db:auth # Setup mana-core-auth database + schema
|
||||
pnpm setup:db:chat # Setup chat database + schema
|
||||
pnpm setup:db:zitare # Setup zitare database + schema
|
||||
pnpm setup:db:contacts # Setup contacts database + schema
|
||||
pnpm setup:db:calendar # Setup calendar database + schema
|
||||
pnpm setup:db:clock # Setup clock database + schema
|
||||
pnpm setup:db:todo # Setup todo database + schema
|
||||
pnpm setup:db:picture # Setup picture database + schema
|
||||
pnpm setup:db:auth # Setup mana-auth database + schema
|
||||
pnpm setup:db:chat # Setup chat database + schema
|
||||
pnpm setup:db:todo # Setup todo database + schema
|
||||
pnpm setup:db:contacts # Setup contacts database + schema
|
||||
pnpm setup:db:calendar # Setup calendar database + schema
|
||||
pnpm setup:db:picture # Setup picture database + schema
|
||||
pnpm setup:db:uload # Setup uload database + schema
|
||||
pnpm setup:db:context # Setup context database + schema
|
||||
pnpm setup:db:storage # Setup storage database + schema
|
||||
pnpm setup:db:mukke # Setup mukke database + schema
|
||||
pnpm setup:db:planta # Setup planta database + schema
|
||||
pnpm setup:db:nutriphi # Setup nutriphi database + schema
|
||||
pnpm setup:db:questions # Setup questions database + schema
|
||||
pnpm setup:db:traces # Setup traces database + schema
|
||||
```
|
||||
|
||||
### Setup All Databases
|
||||
|
||||
```bash
|
||||
pnpm setup:db # Creates ALL databases and pushes ALL schemas
|
||||
pnpm setup:db # Creates ALL databases and pushes ALL schemas
|
||||
```
|
||||
|
||||
This is useful when setting up a fresh environment or after pulling new schema changes.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
Guest: App -> IndexedDB (Dexie.js) -> UI (no sync)
|
||||
Logged in: App -> IndexedDB -> UI -> SyncEngine -> mana-sync (Go) -> PostgreSQL
|
||||
<- WebSocket push <-
|
||||
```
|
||||
|
||||
**mana-sync** (Go, port 3050) handles WebSocket-based sync with field-level last-write-wins conflict resolution. All CRUD goes through IndexedDB first, making the UI instant regardless of network.
|
||||
|
||||
**Hono/Bun servers** handle operations that cannot run client-side:
|
||||
- AI/LLM calls (chat, questions, picture generation)
|
||||
- File operations (storage, media processing)
|
||||
- RRULE expansion and reminder scheduling (todo, calendar)
|
||||
- Server-side data processing (news extraction, transcription)
|
||||
|
||||
### Docker Init Script
|
||||
|
||||
On first `pnpm docker:up`, the PostgreSQL container runs `docker/init-db/01-create-databases.sql` which creates all databases:
|
||||
|
||||
- manacore, chat, zitare, contacts, calendar, clock, todo, manadeck
|
||||
- storage, mail, moodlit, finance, inventory, techbase, voxel_lava, figgos
|
||||
On first `pnpm docker:up`, the PostgreSQL container runs `docker/init-db/01-create-databases.sql` which creates all databases.
|
||||
|
||||
### Setup Script
|
||||
|
||||
|
|
@ -84,6 +167,16 @@ The `scripts/setup-databases.sh` script:
|
|||
|
||||
The `--force` flag auto-approves schema changes without interactive prompts.
|
||||
|
||||
### What each command starts
|
||||
|
||||
| Command pattern | What it runs |
|
||||
|-----------------|-------------|
|
||||
| `dev:*:local` | mana-sync + server (if any) + web |
|
||||
| `dev:*:full` | DB setup + mana-auth + mana-sync + server (if any) + web |
|
||||
| `dev:*:server` | Just the Hono/Bun server (`bun run --watch src/index.ts`) |
|
||||
| `dev:*:web` | Just the SvelteKit web app |
|
||||
| `dev:*:app` | Server + web (no sync, no auth) |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Database doesn't exist
|
||||
|
|
@ -103,17 +196,26 @@ PGPASSWORD=devpassword psql -h localhost -U manacore -d postgres -c "CREATE DATA
|
|||
If you see errors about missing tables/columns:
|
||||
|
||||
```bash
|
||||
# Push the latest schema
|
||||
pnpm --filter @chat/backend db:push --force
|
||||
# Push the latest schema from the server package
|
||||
pnpm --filter @chat/server db:push --force
|
||||
```
|
||||
|
||||
### mana-sync not built
|
||||
|
||||
If you see `./server: No such file or directory`:
|
||||
|
||||
```bash
|
||||
pnpm dev:sync:build
|
||||
```
|
||||
|
||||
### Port already in use
|
||||
|
||||
If auth (port 3001) is already running:
|
||||
If auth (port 3001) or sync (port 3050) is already running:
|
||||
|
||||
```bash
|
||||
# Check what's using the port
|
||||
lsof -i :3001
|
||||
lsof -i :3050
|
||||
|
||||
# Kill the process if needed
|
||||
kill <PID>
|
||||
|
|
@ -134,23 +236,6 @@ pnpm docker:up
|
|||
pnpm setup:db
|
||||
```
|
||||
|
||||
## Apps Without Full Commands
|
||||
|
||||
Some apps don't have backends or don't use Drizzle:
|
||||
|
||||
| App | Reason |
|
||||
|-----|--------|
|
||||
| manacore | No backend (uses other services) |
|
||||
| manadeck | Backend exists but no db:push |
|
||||
| bauntown, context, maerchenzauber, memoro, news, nutriphi, presi, quote, reader, storage, wisekeep | No backends |
|
||||
|
||||
For these, use the regular dev commands:
|
||||
|
||||
```bash
|
||||
pnpm dev:manacore:web
|
||||
pnpm dev:manadeck:app
|
||||
```
|
||||
|
||||
## Adding a New Application
|
||||
|
||||
### Step 1: Create Project Structure
|
||||
|
|
@ -160,7 +245,7 @@ Create the standard project structure under `apps/`:
|
|||
```
|
||||
apps/newproject/
|
||||
├── apps/
|
||||
│ ├── backend/ # NestJS API (if needed)
|
||||
│ ├── server/ # Hono/Bun server (if needed for compute)
|
||||
│ ├── mobile/ # Expo React Native app
|
||||
│ ├── web/ # SvelteKit web app
|
||||
│ └── landing/ # Astro marketing page
|
||||
|
|
@ -170,9 +255,24 @@ apps/newproject/
|
|||
└── CLAUDE.md # Project documentation
|
||||
```
|
||||
|
||||
### Step 2: Configure Backend Database (if applicable)
|
||||
### Step 2: Set Up Local-First Data Layer
|
||||
|
||||
If your backend uses Drizzle ORM:
|
||||
1. Create `apps/newproject/apps/web/src/lib/data/local-store.ts` with `createLocalStore()`
|
||||
2. Create `apps/newproject/apps/web/src/lib/data/guest-seed.ts` for onboarding data
|
||||
3. Use `collection.getAll()` / `collection.insert()` in stores (not API calls)
|
||||
4. In layout: `await store.initialize()`, `store.startSync()` on login
|
||||
|
||||
### Step 3: Create Hono/Bun Server (if needed)
|
||||
|
||||
Only needed if your app requires server-side compute (AI, file ops, etc.).
|
||||
|
||||
Create `apps/newproject/apps/server/` with:
|
||||
- `src/index.ts` -- Hono app entry point
|
||||
- `src/config.ts` -- Port and env config
|
||||
- `src/routes/health.ts` -- Health check endpoint
|
||||
- `package.json` with `"name": "@newproject/server"`
|
||||
|
||||
### Step 4: Configure Database (if the server uses Drizzle)
|
||||
|
||||
1. **Add database to Docker init** (`docker/init-db/01-create-databases.sql`):
|
||||
```sql
|
||||
|
|
@ -181,84 +281,59 @@ If your backend uses Drizzle ORM:
|
|||
```
|
||||
|
||||
2. **Add to setup script** (`scripts/setup-databases.sh`):
|
||||
|
||||
In the `setup_service()` function, add a new case:
|
||||
```bash
|
||||
newproject)
|
||||
create_db_if_not_exists "newproject"
|
||||
push_schema "@newproject/backend" "newproject"
|
||||
push_schema "@newproject/server" "newproject"
|
||||
;;
|
||||
```
|
||||
|
||||
Also add to the `ALL_DATABASES` array:
|
||||
```bash
|
||||
ALL_DATABASES=(
|
||||
...
|
||||
"newproject"
|
||||
)
|
||||
```
|
||||
|
||||
And to the services loop at the bottom:
|
||||
```bash
|
||||
for service in auth chat ... newproject; do
|
||||
```
|
||||
|
||||
3. **Add DATABASE_URL to `.env.development`**:
|
||||
```env
|
||||
NEWPROJECT_DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/newproject
|
||||
```
|
||||
|
||||
4. **Update `scripts/generate-env.mjs`** to generate the backend `.env` file.
|
||||
4. **Update `scripts/generate-env.mjs`** to generate the server `.env` file.
|
||||
|
||||
### Step 3: Add Package.json Scripts
|
||||
### Step 5: Add Package.json Scripts
|
||||
|
||||
Add to root `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
// Project-level dev (all apps)
|
||||
"newproject:dev": "turbo run dev --filter=newproject...",
|
||||
|
||||
// Individual app commands
|
||||
"dev:newproject:web": "pnpm --filter @newproject/web dev",
|
||||
"dev:newproject:mobile": "pnpm --filter @newproject/mobile dev",
|
||||
"dev:newproject:backend": "pnpm --filter @newproject/backend dev",
|
||||
"dev:newproject:landing": "pnpm --filter @newproject/landing dev",
|
||||
"dev:newproject:app": "turbo run dev --filter=@newproject/web --filter=@newproject/backend",
|
||||
|
||||
// Full dev with auto database setup
|
||||
"dev:newproject:full": "./scripts/setup-databases.sh newproject && ./scripts/setup-databases.sh auth && concurrently -n auth,backend,web -c blue,green,cyan \"pnpm dev:auth\" \"pnpm dev:newproject:backend\" \"pnpm dev:newproject:web\"",
|
||||
|
||||
// Database shortcuts
|
||||
"newproject:db:push": "pnpm --filter @newproject/backend db:push",
|
||||
"newproject:db:studio": "pnpm --filter @newproject/backend db:studio",
|
||||
|
||||
// Setup shortcut
|
||||
"dev:newproject:server": "cd apps/newproject/apps/server && bun run --watch src/index.ts",
|
||||
"dev:newproject:local": "concurrently -n sync,server,web -c magenta,yellow,cyan \"pnpm dev:sync\" \"pnpm dev:newproject:server\" \"pnpm dev:newproject:web\"",
|
||||
"dev:newproject:full": "./scripts/setup-databases.sh newproject && ./scripts/setup-databases.sh auth && concurrently -n auth,sync,server,web -c blue,magenta,yellow,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:newproject:server\" \"pnpm dev:newproject:web\"",
|
||||
"setup:db:newproject": "./scripts/setup-databases.sh newproject"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Create Project CLAUDE.md
|
||||
For apps **without** a server (sync + web only):
|
||||
|
||||
Create `apps/newproject/CLAUDE.md` with:
|
||||
- Project overview
|
||||
- Structure diagram
|
||||
- Available commands
|
||||
- API endpoints (if backend)
|
||||
- Environment variables
|
||||
- Tech stack details
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev:newproject:web": "pnpm --filter @newproject/web dev",
|
||||
"dev:newproject:local": "concurrently -n sync,web -c magenta,cyan \"pnpm dev:sync\" \"pnpm dev:newproject:web\"",
|
||||
"dev:newproject:full": "concurrently -n auth,sync,web -c blue,magenta,cyan \"pnpm dev:auth\" \"pnpm dev:sync\" \"pnpm dev:newproject:web\""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See existing projects like `apps/chat/CLAUDE.md` for reference.
|
||||
### Step 6: Create Project CLAUDE.md
|
||||
|
||||
### Step 5: Test the Setup
|
||||
Create `apps/newproject/CLAUDE.md` with project overview, structure, commands, and API endpoints.
|
||||
|
||||
### Step 7: Test the Setup
|
||||
|
||||
```bash
|
||||
# Create database and push schema
|
||||
pnpm setup:db:newproject
|
||||
# Quick start (no auth needed)
|
||||
pnpm dev:newproject:local
|
||||
|
||||
# Start with full dev command
|
||||
# Full stack (with auth + DB setup)
|
||||
pnpm dev:newproject:full
|
||||
```
|
||||
|
||||
|
|
@ -266,10 +341,13 @@ pnpm dev:newproject:full
|
|||
|
||||
- [ ] Create project structure under `apps/newproject/`
|
||||
- [ ] Add `pnpm-workspace.yaml` in project root
|
||||
- [ ] Add database to `docker/init-db/01-create-databases.sql`
|
||||
- [ ] Add service to `scripts/setup-databases.sh`
|
||||
- [ ] Add DATABASE_URL to `.env.development`
|
||||
- [ ] Set up local-store with Dexie.js collections
|
||||
- [ ] Create guest seed data
|
||||
- [ ] Add Hono/Bun server (if compute needed)
|
||||
- [ ] Add database to `docker/init-db/01-create-databases.sql` (if using Drizzle)
|
||||
- [ ] Add service to `scripts/setup-databases.sh` (if using Drizzle)
|
||||
- [ ] Add DATABASE_URL to `.env.development` (if using Drizzle)
|
||||
- [ ] Update `scripts/generate-env.mjs` for env generation
|
||||
- [ ] Add scripts to root `package.json`
|
||||
- [ ] Create `CLAUDE.md` with project documentation
|
||||
- [ ] Test with `pnpm dev:newproject:full`
|
||||
- [ ] Test with `pnpm dev:newproject:local`
|
||||
|
|
|
|||
|
|
@ -454,16 +454,15 @@ git pull
|
|||
|
||||
### Docker Base Images
|
||||
|
||||
Alle Apps werden auf vorgebauten Base Images aufgebaut, um Build-Zeit und Memory-Verbrauch zu reduzieren:
|
||||
Alle Web-Apps werden auf einem vorgebauten Base Image aufgebaut, um Build-Zeit und Memory-Verbrauch zu reduzieren. Backend-Server verwenden `docker/Dockerfile.hono-server` (Hono + Bun) direkt.
|
||||
|
||||
| Base Image | Dockerfile | Verwendet von |
|
||||
|------------|-----------|---------------|
|
||||
| `sveltekit-base:local` | `docker/Dockerfile.sveltekit-base` | Alle SvelteKit Web-Apps |
|
||||
| `nestjs-base:local` | `docker/Dockerfile.nestjs-base` | Alle NestJS Backends |
|
||||
|
||||
Die Base Images enthalten alle Shared Packages (`packages/`) vorinstalliert und vorgebaut. App-Dockerfiles müssen nur noch ihren app-spezifischen Code kopieren.
|
||||
Das Base Image enthaelt alle Shared Packages (`packages/`) vorinstalliert und vorgebaut. App-Dockerfiles muessen nur noch ihren app-spezifischen Code kopieren.
|
||||
|
||||
**Base Images neu bauen** wenn sich Shared Packages ändern:
|
||||
**Base Image neu bauen** wenn sich Shared Packages aendern:
|
||||
|
||||
```bash
|
||||
./scripts/mac-mini/build-app.sh --base
|
||||
|
|
|
|||
|
|
@ -46,23 +46,23 @@ Canonical port assignments for all ManaCore services. This is the single source
|
|||
| 3024 | mana-voice-bot | Python | Voice-to-voice assistant |
|
||||
| 3025-3029 | *(reserved)* | | |
|
||||
|
||||
## 3030-3059: App Backends
|
||||
## 3030-3059: App Compute Servers
|
||||
|
||||
Only apps that need server-side compute (AI, external APIs, file operations).
|
||||
Pure CRUD apps use mana-sync directly.
|
||||
|
||||
| Port | Service | Runtime | Description |
|
||||
|------|---------|---------|-------------|
|
||||
| 3030 | chat-backend | NestJS | AI chat, streaming, spaces |
|
||||
| 3030 | chat-server | Hono/Bun | AI chat, streaming, spaces |
|
||||
| 3031 | todo-server | Hono/Bun | RRULE expansion, reminders |
|
||||
| 3032 | calendar-backend | NestJS | CalDAV sync, Google Calendar, notifications |
|
||||
| 3033 | contacts-backend | NestJS | Google Contacts, vCard import/export |
|
||||
| 3034 | storage-backend | NestJS | S3 file ops, versioning, shares |
|
||||
| 3035 | picture-backend | NestJS | Replicate AI, generation orchestration |
|
||||
| 3036 | manadeck-backend | NestJS | AI card generation |
|
||||
| 3037 | mukke-backend | NestJS | Audio processing, BPM, ID3 tags |
|
||||
| 3038 | nutriphi-backend | NestJS | Gemini meal analysis |
|
||||
| 3039 | planta-backend | NestJS | Gemini plant analysis |
|
||||
| 3032 | calendar-server | Hono/Bun | CalDAV sync, Google Calendar, notifications |
|
||||
| 3033 | contacts-server | Hono/Bun | Google Contacts, vCard import/export |
|
||||
| 3034 | storage-server | Hono/Bun | S3 file ops, versioning, shares |
|
||||
| 3035 | picture-server | Hono/Bun | Replicate AI, generation orchestration |
|
||||
| 3036 | manadeck-server | Hono/Bun | AI card generation |
|
||||
| 3037 | mukke-server | Hono/Bun | Audio processing, BPM, ID3 tags |
|
||||
| 3038 | nutriphi-server | Hono/Bun | Gemini meal analysis |
|
||||
| 3039 | planta-server | Hono/Bun | Gemini plant analysis |
|
||||
| 3040 | presi-server | Hono/Bun | Share links |
|
||||
| 3041-3059 | *(reserved)* | | |
|
||||
|
||||
|
|
@ -78,28 +78,28 @@ Pure CRUD apps use mana-sync directly.
|
|||
|
||||
## 5000-5059: Web Frontends (SvelteKit)
|
||||
|
||||
| Port | Service | Corresponds to Backend |
|
||||
| Port | Service | Corresponds to Server |
|
||||
|------|---------|----------------------|
|
||||
| 5000 | mana-web | Hub/Dashboard |
|
||||
| 5010 | chat-web | 3030 chat-backend |
|
||||
| 5010 | chat-web | 3030 chat-server |
|
||||
| 5011 | todo-web | 3031 todo-server |
|
||||
| 5012 | calendar-web | 3032 calendar-backend |
|
||||
| 5012 | calendar-web | 3032 calendar-server |
|
||||
| 5013 | clock-web | *(local-first only)* |
|
||||
| 5014 | contacts-web | 3033 contacts-backend |
|
||||
| 5015 | storage-web | 3034 storage-backend |
|
||||
| 5014 | contacts-web | 3033 contacts-server |
|
||||
| 5015 | storage-web | 3034 storage-server |
|
||||
| 5016 | presi-web | 3040 presi-server |
|
||||
| 5017 | nutriphi-web | 3038 nutriphi-backend |
|
||||
| 5017 | nutriphi-web | 3038 nutriphi-server |
|
||||
| 5018 | zitare-web | *(local-first only)* |
|
||||
| 5019 | photos-web | *(local-first + mana-media)* |
|
||||
| 5020 | skilltree-web | *(local-first only)* |
|
||||
| 5021 | picture-web | 3035 picture-backend |
|
||||
| 5021 | picture-web | 3035 picture-server |
|
||||
| 5022 | citycorners-web | *(local-first only)* |
|
||||
| 5023 | manadeck-web | 3036 manadeck-backend |
|
||||
| 5024 | mukke-web | 3037 mukke-backend |
|
||||
| 5023 | manadeck-web | 3036 manadeck-server |
|
||||
| 5024 | mukke-web | 3037 mukke-server |
|
||||
| 5025 | inventar-web | *(local-first only)* |
|
||||
| 5026 | context-web | *(local-first only)* |
|
||||
| 5027 | questions-web | *(local-first only)* |
|
||||
| 5028 | planta-web | 3039 planta-backend |
|
||||
| 5028 | planta-web | 3039 planta-server |
|
||||
| 5029 | moodlit-web | *(future)* |
|
||||
| 5030-5049 | *(reserved)* | |
|
||||
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ nutriphi/
|
|||
│ ├── mobile/ # Expo React Native App (@nutriphi/mobile)
|
||||
│ ├── web/ # SvelteKit Web App (@nutriphi/web)
|
||||
│ └── landing/ # Astro Landing Page (@nutriphi/landing)
|
||||
├── backend/ # NestJS API Server (@nutriphi/backend)
|
||||
├── server/ # Hono/Bun server (@nutriphi/server)
|
||||
```
|
||||
|
||||
#### API Endpoints
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue