# InnungsApp Digitale Plattform fuer Innungen mit Admin-Dashboard (Next.js) und Mobile App (Expo). ## Stack | Layer | Technology | |---|---| | Monorepo | pnpm Workspaces + Turborepo | | Admin Dashboard | Next.js 15 (App Router) | | Mobile App | Expo + React Native | | API | tRPC v11 | | Auth | better-auth (magic links + credential login) | | Database | PostgreSQL + Prisma ORM (`jsonb` fuer Landing-Page-Felder) | | Styling | Tailwind CSS (admin), NativeWind (mobile) | ## Projektstruktur ```text innungsapp/ |-- apps/ | |-- admin/ | `-- mobile/ |-- packages/ | `-- shared/ | `-- prisma/ |-- docker-compose.yml `-- README.md ``` ## Local Setup Port-Hinweis: - Ohne Docker (lokales `pnpm dev`): App typischerweise auf `http://localhost:3000` - Mit Docker Compose: App auf `http://localhost:3010` (Container-intern weiter `3000`) ### Voraussetzungen - Node.js >= 20 - pnpm >= 9 - SMTP-Zugang (fuer Einladungen und Magic Links) ### 1. Abhaengigkeiten installieren ```bash pnpm install ``` ### 2. Umgebungsvariablen setzen (Admin lokal) ```bash cp .env.example .env ``` Danach `.env` anpassen (mindestens `DATABASE_URL`, `BETTER_AUTH_SECRET`, SMTP-Werte). ### 3. DB vorbereiten (lokal) Lokale PostgreSQL-DB starten (nur falls noch nicht aktiv): ```bash docker compose up -d postgres ``` Prisma vorbereiten: ```bash pnpm db:generate pnpm db:push ``` Optional Demo-Daten: ```bash pnpm db:seed pnpm db:seed-superadmin ``` ### 4. Entwicklung starten ```bash pnpm --filter @innungsapp/admin dev pnpm --filter @innungsapp/mobile dev ``` Oder parallel: ```bash pnpm dev ``` ## Production Deployment (Docker, Admin) Dieser Abschnitt ist der verbindliche Weg fuer den Productive-Server. ### Voraussetzungen - Linux Server mit Docker + Docker Compose - DNS-Eintrag auf den Server - SMTP-Zugangsdaten - Reverse Proxy (z. B. Nginx) fuer HTTPS ### 1. Repository klonen ```bash git clone cd innungsapp ``` ### 2. Production-Env anlegen ```bash cp .env.production.example .env ``` Pflichtwerte in `.env`: - `DATABASE_URL` (PostgreSQL DSN, z. B. `postgresql://innungsapp:...@postgres:5432/innungsapp?schema=public`) - `POSTGRES_DB` - `POSTGRES_USER` - `POSTGRES_PASSWORD` - `BETTER_AUTH_SECRET` (mindestens 32 Zeichen) - `BETTER_AUTH_URL` (z. B. `https://app.deine-innung.de`) - `NEXT_PUBLIC_APP_URL` (gleich wie `BETTER_AUTH_URL`) - `EMAIL_FROM` - `SMTP_HOST` - `SMTP_PORT` - `SMTP_SECURE` - `SMTP_USER` - `SMTP_PASS` - `SUPERADMIN_EMAIL` - `SUPERADMIN_PASSWORD` ### 3. Container bauen und starten ```bash docker compose up -d --build ``` Hinweis zum DB-Start: - Wenn Prisma-Migrationen vorhanden sind, wird `prisma migrate deploy` ausgefuehrt. - Wenn keine Migrationen vorhanden sind, wird einmalig `prisma db push` ausgefuehrt. ### 4. Healthcheck und Logs pruefen ```bash docker compose logs -f admin curl -fsS http://localhost:3010/api/health ``` Erwartet: JSON mit `"status":"ok"`, z. B. ```json {"status":"ok","timestamp":"2026-03-04T12:34:56.789Z"} ``` ### 5. Superadmin anlegen (nur beim ersten Start) ```bash docker compose exec -w /app admin node packages/shared/prisma/seed-superadmin.js ``` Login-Daten kommen aus `.env`: - E-Mail: `SUPERADMIN_EMAIL` - Passwort: `SUPERADMIN_PASSWORD` Hinweis: - In `NODE_ENV=production` bricht der Seed ab, wenn `SUPERADMIN_PASSWORD` fehlt. - In Entwicklung wird ohne `SUPERADMIN_PASSWORD` als Fallback `demo1234` genutzt. - Der Seed ist idempotent (`upsert`) und kann bei Bedarf erneut ausgefuehrt werden. ### 6. HTTPS (Reverse Proxy) Nginx sollte auf `localhost:3010` weiterleiten und TLS terminieren. Beispiel: ```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; location / { proxy_pass http://localhost:3010; proxy_http_version 1.1; 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; } } ``` ### 7. Updates einspielen ```bash git pull docker compose up -d --build docker compose logs -f admin ``` ### 8. Backup und Restore (Docker Volumes) Vorher die exakten Volumenamen pruefen: ```bash docker volume ls | grep pg_data docker volume ls | grep uploads_data ``` Backup: ```bash mkdir -p backups docker run --rm \ -v innungsapp_pg_data:/volume \ -v "$(pwd)/backups:/backup" \ alpine sh -c "tar czf /backup/pg_data_$(date +%F_%H%M).tar.gz -C /volume ." ``` Restore (nur bei gestoppter App): ```bash docker compose down docker run --rm \ -v innungsapp_pg_data:/volume \ -v "$(pwd)/backups:/backup" \ alpine sh -c "rm -rf /volume/* && tar xzf /backup/.tar.gz -C /volume" docker compose up -d ``` ### 9. Verifizierte Kommandos (Stand 4. Maerz 2026) Die folgenden Befehle wurden in dieser Umgebung erfolgreich ausgefuehrt: ```bash # 1) Postgres starten (falls noch nicht aktiv) docker compose up -d postgres # 2) Prisma Client generieren (cd packages/shared && npx prisma generate) # 3) Initiale PostgreSQL-Migration erstellen (einmalig) (cd packages/shared && \ DATABASE_URL="postgresql://innungsapp:innungsapp@localhost:5432/innungsapp?schema=public" \ npx prisma migrate dev --name init_postgres --schema=prisma/schema.prisma --create-only) # 4) Migration anwenden (cd packages/shared && \ DATABASE_URL="postgresql://innungsapp:innungsapp@localhost:5432/innungsapp?schema=public" \ npx prisma migrate deploy --schema=prisma/schema.prisma) # 5) Gesamtes Setup bauen und starten docker compose up -d --build # 6) Superadmin seeden (mit ENV-Werten) docker compose exec -e SUPERADMIN_EMAIL=superadmin@innungsapp.de \ -e SUPERADMIN_PASSWORD='demo1234' \ -w /app admin node packages/shared/prisma/seed-superadmin.js # 7) Laufzeitstatus pruefen docker compose ps docker compose logs --tail 80 admin curl -fsS http://localhost:3010/api/health ``` Optionale SQL-Verifikation (wurde ebenfalls erfolgreich getestet): ```bash # JSONB-Spalten pruefen docker compose exec -T postgres psql -U innungsapp -d innungsapp -c \ "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'organizations' AND column_name IN ('landing_page_features','landing_page_footer') ORDER BY column_name;" # Seeded Superadmin pruefen docker compose exec -T postgres psql -U innungsapp -d innungsapp -c \ "SELECT u.email, u.role, u.email_verified, a.provider_id, (a.password IS NOT NULL) AS has_password FROM \"user\" u LEFT JOIN account a ON a.user_id = u.id AND a.provider_id = 'credential' WHERE u.email = 'superadmin@innungsapp.de';" ``` ## Mobile Release (EAS) ```bash cd apps/mobile eas build --platform all --profile production eas submit --platform all ``` Wichtig: - In `apps/mobile/eas.json` sind Submit-Placeholders vorhanden und muessen ersetzt werden. - Fuer Production darf keine API-URL auf `localhost` zeigen. ## Troubleshooting ### `migrate deploy` oder `db push` fehlschlaegt - `DATABASE_URL` pruefen - `postgres` Container Healthcheck pruefen (`docker compose ps`) - Logs: `docker compose logs -f admin` ### Healthcheck liefert Fehler - Containerstatus: `docker compose ps` - App-Logs lesen - Reverse Proxy testweise umgehen und direkt `http://localhost:3010/api/health` pruefen ### Login funktioniert nicht nach Seed - Seed-Command erneut ausfuehren - In DB pruefen, ob `user` und `account` Eintraege fuer `superadmin@innungsapp.de` existieren ## Weiterfuehrende Doku - Produkt-Roadmap: `../ROADMAP.md` - Architektur: `../ARCHITECTURE.md` - API Design: `../API_DESIGN.md`