294 lines
6.8 KiB
Markdown
294 lines
6.8 KiB
Markdown
# InnungsApp
|
||
|
||
Die digitale Plattform für Innungen — News, Mitgliederverzeichnis, Termine und Lehrlingsbörse.
|
||
|
||
## Stack
|
||
|
||
| Schicht | Technologie |
|
||
|---|---|
|
||
| **Monorepo** | pnpm Workspaces + Turborepo |
|
||
| **Mobile App** | Expo (React Native) + Expo Router |
|
||
| **Admin Dashboard** | Next.js 15 (App Router) |
|
||
| **API** | tRPC v11 |
|
||
| **Auth** | better-auth (Magic Links) |
|
||
| **Datenbank** | PostgreSQL + Prisma ORM |
|
||
| **Styling Mobile** | NativeWind v4 (Tailwind CSS) |
|
||
| **Styling Admin** | Tailwind CSS |
|
||
| **State Management** | Zustand (Mobile) + React Query (beide Apps) |
|
||
|
||
## Projekt-Struktur
|
||
|
||
```
|
||
innungsapp/
|
||
├── apps/
|
||
│ ├── mobile/ # Expo React Native App (iOS + Android)
|
||
│ └── admin/ # Next.js Admin Dashboard
|
||
├── packages/
|
||
│ └── shared/ # TypeScript-Typen + Prisma Client
|
||
└── ...
|
||
```
|
||
|
||
## Setup
|
||
|
||
### Voraussetzungen
|
||
|
||
- Node.js >= 20
|
||
- pnpm >= 9
|
||
- PostgreSQL-Datenbank
|
||
- SMTP-Server (für Magic Links)
|
||
|
||
### 1. Abhängigkeiten installieren
|
||
|
||
```bash
|
||
pnpm install
|
||
```
|
||
|
||
### 2. Umgebungsvariablen
|
||
|
||
```bash
|
||
cp .env.example apps/admin/.env.local
|
||
# .env.local befüllen (DATABASE_URL, BETTER_AUTH_SECRET, SMTP_*)
|
||
```
|
||
|
||
### 3. Datenbank einrichten
|
||
|
||
```bash
|
||
# Prisma Client generieren
|
||
pnpm db:generate
|
||
|
||
# Migrationen anwenden
|
||
pnpm db:migrate
|
||
|
||
# Demo-Daten einspielen (optional)
|
||
pnpm db:seed
|
||
```
|
||
|
||
### 4. Entwicklung starten
|
||
|
||
```bash
|
||
# Admin Dashboard (http://localhost:3000)
|
||
pnpm --filter @innungsapp/admin dev
|
||
|
||
# Mobile App (Expo DevTools)
|
||
pnpm --filter @innungsapp/mobile dev
|
||
```
|
||
|
||
Oder alles parallel:
|
||
```bash
|
||
pnpm dev
|
||
```
|
||
|
||
## Datenbank-Schema
|
||
|
||
Das Schema befindet sich in `packages/shared/prisma/schema.prisma`.
|
||
|
||
Wichtige Tabellen:
|
||
- `organizations` — Innungen (Multi-Tenancy)
|
||
- `members` — Mitglieder (verknüpft mit Auth-User nach Einladung)
|
||
- `user_roles` — Berechtigungen (admin | member)
|
||
- `news`, `news_reads`, `news_attachments` — News-System
|
||
- `termine`, `termin_anmeldungen` — Terminverwaltung
|
||
- `stellen` — Lehrlingsbörse (öffentlich lesbar)
|
||
|
||
## Auth-Flow
|
||
|
||
1. **Admin einrichten:** Seed-Daten oder manuell in der DB
|
||
2. **Mitglied einladen:** Admin erstellt Mitglied → "Einladung senden" → Magic Link per E-Mail
|
||
3. **Mitglied loggt ein:** Magic Link → Session → App-Zugang
|
||
|
||
## API (tRPC)
|
||
|
||
Alle API-Endpunkte sind typsicher über tRPC definiert:
|
||
|
||
- `organizations.*` — Org-Einstellungen, Stats, AVV
|
||
- `members.*` — CRUD, Einladungen
|
||
- `news.*` — CRUD, Lesestatus, Push-Benachrichtigungen
|
||
- `termine.*` — CRUD, Anmeldungen
|
||
- `stellen.*` — Public + Auth-geschützte Endpunkte
|
||
|
||
## Deployment
|
||
|
||
### Admin — Docker (empfohlen für Self-Hosting)
|
||
|
||
**Voraussetzungen:** Docker + Docker Compose auf dem Server installiert.
|
||
|
||
#### Schritt 1: Repository klonen
|
||
|
||
```bash
|
||
git clone <repo-url>
|
||
cd innungsapp
|
||
```
|
||
|
||
#### Schritt 2: Umgebungsvariablen anlegen
|
||
|
||
```bash
|
||
cp .env.production.example .env
|
||
```
|
||
|
||
Dann `.env` öffnen und **alle Werte** befüllen:
|
||
|
||
| Variable | Beschreibung |
|
||
|---|---|
|
||
| `BETTER_AUTH_SECRET` | Zufälliger String (min. 32 Zeichen) — z.B. `openssl rand -hex 32` |
|
||
| `BETTER_AUTH_URL` | Öffentliche URL der App, z.B. `https://app.deine-innung.de` |
|
||
| `NEXT_PUBLIC_APP_URL` | Gleicher Wert wie `BETTER_AUTH_URL` |
|
||
| `EMAIL_FROM` | Absender-Adresse für Magic Links |
|
||
| `SMTP_HOST` | SMTP-Server-Adresse |
|
||
| `SMTP_PORT` | Meistens `587` (STARTTLS) oder `465` (SSL) |
|
||
| `SMTP_USER` | SMTP-Benutzername |
|
||
| `SMTP_PASS` | SMTP-Passwort |
|
||
|
||
#### Schritt 3: Container bauen und starten
|
||
|
||
```bash
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Der Build dauert beim ersten Mal ~2–3 Minuten. Danach läuft die App auf **Port 3000**.
|
||
|
||
Logs prüfen:
|
||
```bash
|
||
docker compose logs -f admin
|
||
```
|
||
|
||
#### Schritt 4: Superadmin anlegen (nur beim ersten Start)
|
||
|
||
```bash
|
||
docker compose exec admin node -e "
|
||
const { PrismaClient } = require('@prisma/client');
|
||
const { scryptSync, randomBytes } = require('crypto');
|
||
const prisma = new PrismaClient();
|
||
// Superadmin wird via seed-superadmin.ts angelegt
|
||
"
|
||
```
|
||
|
||
Einfacher: Den Seed direkt ausführen:
|
||
|
||
```bash
|
||
docker compose exec -w /app admin \
|
||
node packages/shared/prisma/seed-superadmin.js
|
||
```
|
||
|
||
> Standard-Login nach Seed: `superadmin@innungsapp.de` / `demo1234`
|
||
> **Passwort sofort in den Einstellungen ändern!**
|
||
|
||
#### Schritt 5: Reverse Proxy (HTTPS)
|
||
|
||
Nginx-Beispielkonfiguration für `app.deine-innung.de`:
|
||
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name app.deine-innung.de;
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl;
|
||
server_name app.deine-innung.de;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/app.deine-innung.de/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/app.deine-innung.de/privkey.pem;
|
||
|
||
client_max_body_size 20M;
|
||
|
||
location / {
|
||
proxy_pass http://localhost:3000;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection 'upgrade';
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_cache_bypass $http_upgrade;
|
||
}
|
||
}
|
||
```
|
||
|
||
SSL-Zertifikat mit Certbot:
|
||
```bash
|
||
certbot --nginx -d app.deine-innung.de
|
||
```
|
||
|
||
#### Updates einspielen
|
||
|
||
```bash
|
||
git pull
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Datenbank und Uploads bleiben dabei erhalten (Docker Volumes).
|
||
|
||
#### Häufige Befehle
|
||
|
||
```bash
|
||
# Status prüfen
|
||
docker compose ps
|
||
|
||
# Logs ansehen
|
||
docker compose logs -f admin
|
||
|
||
# Container neustarten
|
||
docker compose restart admin
|
||
|
||
# In Container einloggen
|
||
docker compose exec admin sh
|
||
|
||
# App stoppen
|
||
docker compose down
|
||
|
||
# App stoppen + Daten löschen (Vorsicht!)
|
||
docker compose down -v
|
||
```
|
||
|
||
---
|
||
|
||
### Admin — Vercel (Alternative)
|
||
|
||
```bash
|
||
# Umgebungsvariablen in Vercel setzen:
|
||
# DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, SMTP_*
|
||
|
||
vercel --cwd apps/admin
|
||
```
|
||
|
||
### Mobile (EAS Build)
|
||
|
||
```bash
|
||
cd apps/mobile
|
||
eas build --platform all --profile production
|
||
eas submit --platform all
|
||
```
|
||
|
||
## DSGVO / AVV
|
||
|
||
- AVV-Akzeptanz in Admin → Einstellungen (Pflichtfeld vor Go-Live)
|
||
- Alle personenbezogenen Daten in EU-Region (Datenbankserver in Deutschland empfohlen)
|
||
- Keine Daten an Dritte außer Expo Push API (anonymisierte Token)
|
||
|
||
## Roadmap
|
||
|
||
Siehe `innung-app-mvp.md` für die vollständige Roadmap.
|
||
|
||
## Apps starten (Schnellstart)
|
||
|
||
Um die Anwendungen lokal zu starten, öffne ein Terminal im Hauptverzeichnis (`innungsapp/`) und nutze folgende Befehle:
|
||
|
||
**Admin Dashboard starten:**
|
||
```bash
|
||
pnpm --filter @innungsapp/admin dev
|
||
```
|
||
Das Dashboard ist im Browser unter [http://localhost:3000](http://localhost:3000) erreichbar.
|
||
|
||
**Mobile App starten:**
|
||
```bash
|
||
pnpm --filter @innungsapp/mobile dev
|
||
```
|
||
Dies startet den Expo-Server. Scanne den QR-Code mit der **Expo Go App** auf deinem Smartphone oder drücke `a` (für den Android Emulator) bzw. `i` (für den iOS Simulator) im Terminal.
|
||
|
||
**Beides gleichzeitig starten:**
|
||
```bash
|
||
pnpm dev
|
||
```
|