managarten/docs/archive/BACKEND_ARCHITECTURE.md
Wuesteon ad495b2044 📝 docs: restructure CLAUDE.md and documentation (74% reduction)
Optimize CLAUDE.md based on industry best practices from HN and HumanLayer:

Changes:
- Trim CLAUDE.md from 678 to 176 lines (74% reduction, 5.7KB)
- Add "Critical Gotchas" section for common AI mistakes
- Add verification signature (🏗️ ManaCore Monorepo)
- Create docs/README.md navigation hub with "I want to..." index
- Delete 5 outdated audit files (ENV_AUDIT_*, DEPENDENCY_ALIGNMENT)
- Archive 7 analysis/historical docs to docs/archive/
- Keep authentication docs separate per request (.claude/guidelines/)

Benefits:
- Better AI instruction adherence (within ~150-200 line budget)
- Progressive disclosure via signposting to detailed docs
- Cleaner navigation with topic-based organization
- Reduced maintenance burden (stale docs archived)

Backup: CLAUDE.md.backup preserves original 678-line version
Change log: docs/archive/RESTRUCTURE_2025-12-16.md
2025-12-16 17:37:19 +01:00

25 KiB

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:

// 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

// 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:

// drizzle.config.ts
export default {
  schema: './src/schema/*',
  out: './migrations',
  driver: 'pg',
  dbCredentials: {
    connectionString: process.env.DATABASE_URL
  }
};

Authentifizierung

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:

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

# 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

// 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:

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:

// 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

// 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

// 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)

# Migration generieren
pnpm --filter @manacore/manadeck-database drizzle-kit generate

# Migration ausführen
pnpm --filter @manacore/manadeck-database drizzle-kit push

Maerchenzauber (Supabase)

# Supabase CLI
supabase migration new <name>
supabase db push

Umgebungsvariablen

Maerchenzauber Backend

# 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

# 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

# Database
DATABASE_URL=postgresql://...

# Redis
REDIS_URL=redis://localhost:6379

# PocketBase
POCKETBASE_URL=

Lokale Entwicklung

Maerchenzauber Backend

cd maerchenzauber/apps/backend
pnpm install
pnpm run start:dev
# Läuft auf Port 3002

Manadeck Backend

# 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

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)

// 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

// packages/shared-supabase/src/client.ts
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.

// 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:
// Einheitliches Error-Format für alle Backends
interface ApiError {
  statusCode: number;
  error: string;
  message: string;
  timestamp: string;
  path: string;
}
  1. Einheitliche Logging-Struktur:
// 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)  │
                └─────────────────────┘