# InnungsApp — Technische Architektur > **Version:** 1.0 | **Stand:** Februar 2026 --- ## 1. Überblick InnungsApp besteht aus drei Hauptkomponenten: ``` ┌─────────────────────────────────────────────────────────────┐ │ CLIENTS │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Mobile App │ │ Admin Web App │ │ │ │ (React Native) │ │ (Next.js) │ │ │ │ iOS + Android │ │ Browser │ │ │ └────────┬────────┘ └────────┬────────┘ │ └───────────┼────────────────────┼──────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────┐ │ SUPABASE │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │ │ Auth │ │ Postgres │ │ Storage │ │ Realtime │ │ │ │ Magic │ │ + RLS │ │ PDFs │ │ Push + │ │ │ │ Link │ │ Database │ │ Images │ │ Events │ │ │ └──────────┘ └──────────┘ └──────────┘ └───────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ EXTERNE DIENSTE │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │ │ Expo │ │ Resend │ │ PostHog │ │ Mux │ │ │ │ Push │ │ E-Mail │ │ Analytics│ │ Video │ │ │ │ (FCM/APNs│ │ Transact.│ │ │ │ (Q2) │ │ │ └──────────┘ └──────────┘ └──────────┘ └───────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 2. Mobile App (React Native + Expo) ### Tech Stack | Schicht | Technologie | Begründung | |---|---|---| | Framework | React Native 0.74 + Expo SDK 51 | Eine Codebasis iOS + Android | | Navigation | Expo Router v3 (file-based) | Typ-sicher, einfach wartbar | | State Management | Zustand | Leichtgewichtig, kein Redux-Overhead | | Data Fetching | TanStack Query v5 | Caching, Background Refetch, Optimistic Updates | | UI-Komponenten | Custom + NativeWind (Tailwind on Native) | Konsistentes Design, schnelle Entwicklung | | Push Notifications | Expo Notifications + FCM/APNs | Out-of-the-box mit Expo | | Auth | Supabase Auth Client | Magic Link Flow | | Type Safety | TypeScript (strict mode) | Pflicht für Produktionscode | ### Ordnerstruktur ``` apps/mobile/ ├── app/ # Expo Router — File-based Navigation │ ├── (auth)/ │ │ ├── login.tsx # Magic Link Login Screen │ │ └── verify.tsx # Token Verification │ ├── (tabs)/ │ │ ├── _layout.tsx # Tab Bar Layout │ │ ├── index.tsx # Dashboard / Home Feed │ │ ├── members.tsx # Mitgliederverzeichnis │ │ ├── news.tsx # Mitteilungen Feed │ │ ├── termine.tsx # Terminkalender │ │ └── stellen.tsx # Lehrlingsbörse │ ├── member/[id].tsx # Mitglied Detailansicht │ ├── news/[id].tsx # Beitrag Detailansicht │ ├── termin/[id].tsx # Termin Detailansicht │ └── _layout.tsx # Root Layout (Auth Guard) ├── components/ │ ├── ui/ # Atomare UI-Komponenten │ │ ├── Button.tsx │ │ ├── Card.tsx │ │ ├── Badge.tsx │ │ ├── Avatar.tsx │ │ └── Input.tsx │ ├── members/ # Feature-spezifische Komponenten │ ├── news/ │ ├── termine/ │ └── stellen/ ├── hooks/ │ ├── useAuth.ts │ ├── useMembers.ts │ ├── useNews.ts │ └── usePushNotifications.ts ├── lib/ │ ├── supabase.ts # Supabase Client Singleton │ ├── queryClient.ts # TanStack Query Client │ └── notifications.ts # Push Token Registration ├── store/ │ └── auth.ts # Zustand Auth Store ├── types/ │ └── database.ts # Generierte Supabase Types └── constants/ ├── colors.ts # Design Tokens └── config.ts # Env-Variablen ``` --- ## 3. Admin Web App (Next.js) ### Tech Stack | Schicht | Technologie | |---|---| | Framework | Next.js 14 (App Router) | | Styling | Tailwind CSS + shadcn/ui | | Auth | Supabase Auth (SSR) | | Data Fetching | Server Components + TanStack Query (Client) | | Tables | TanStack Table v8 | | Forms | React Hook Form + Zod | | Charts | Recharts | | Deployment | Vercel | ### Ordnerstruktur ``` apps/admin/ ├── app/ │ ├── (auth)/ │ │ └── login/page.tsx │ ├── (dashboard)/ │ │ ├── layout.tsx # Sidebar Layout │ │ ├── page.tsx # Overview Dashboard │ │ ├── members/ │ │ │ ├── page.tsx # Mitgliederliste │ │ │ ├── new/page.tsx # Mitglied anlegen │ │ │ └── [id]/page.tsx # Mitglied bearbeiten │ │ ├── news/ │ │ │ ├── page.tsx │ │ │ └── new/page.tsx │ │ ├── termine/ │ │ ├── stellen/ │ │ └── settings/ │ └── layout.tsx ├── components/ │ ├── ui/ # shadcn/ui Komponenten │ ├── data-table/ │ └── forms/ └── lib/ ├── supabase-server.ts # Supabase SSR Client └── actions.ts # Server Actions ``` --- ## 4. Backend: Supabase ### Warum Supabase? - **Kein eigener API-Server** nötig für MVP → spart 4–6 Wochen Entwicklung - **PostgreSQL** mit vollem SQL-Zugriff → keine NoSQL-Kompromisse - **Row Level Security** → Multi-Tenancy ohne eigene Middleware - **Realtime** → Live-Updates ohne WebSocket-Implementierung - **Storage** → S3-kompatibel, CDN included - **Auth** → Magic Link, Sessions, JWT out-of-the-box - **EU-Region Frankfurt** → DSGVO-konform ### Supabase Services genutzt | Service | Verwendung | |---|---| | Auth | Magic Link Login, Session-Management, JWT | | Database | PostgreSQL, alle Tabellen | | Row Level Security | Multi-Tenancy, Datenisolation | | Storage | PDF-Anhänge, Profilbilder, Logos | | Realtime | Live-Updates (News Feed, Teilnehmerlisten) | | Edge Functions | Komplexe Businesslogik (Einladungs-E-Mails) | --- ## 5. Multi-Tenancy Konzept ### Datenisolation via Row Level Security (RLS) Jede Innung ist eine `organization`. Alle Tabellen haben eine `org_id` Spalte. ```sql -- Beispiel RLS Policy für die members-Tabelle CREATE POLICY "members_isolation" ON members FOR ALL USING (org_id = ( SELECT org_id FROM user_roles WHERE user_id = auth.uid() )); ``` **Prinzip:** - Kein Nutzer sieht Daten außerhalb seiner `org_id` - Policy wird für jede Operation (SELECT, INSERT, UPDATE, DELETE) durchgesetzt - Supabase prüft dies auf Datenbankebene — kein Bypass möglich ### Tenancy Identifikation - **MVP:** `org_id` wird beim Login aus `user_roles` geladen und in allen Queries mitgegeben - **Post-MVP:** Subdomain-Routing (`innung-elektro-stuttgart.innungsapp.de`) mit Middleware-Lookup --- ## 6. Authentifizierung ### Login Flow ``` Nutzer gibt E-Mail ein │ ▼ Supabase sendet Magic Link │ ▼ Nutzer klickt Link im E-Mail │ ▼ App/Browser öffnet sich, Token wird verarbeitet │ ▼ Supabase Auth gibt Session zurück (JWT) │ ▼ App lädt user_roles → bestimmt org_id und Rolle │ ▼ Redirect zu korrekter Startseite ``` ### Rollen-System ```sql CREATE TYPE user_role AS ENUM ('admin', 'member', 'public'); CREATE TABLE user_roles ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid REFERENCES auth.users NOT NULL, org_id uuid REFERENCES organizations NOT NULL, role user_role NOT NULL DEFAULT 'member', created_at timestamptz DEFAULT now(), UNIQUE(user_id, org_id) ); ``` --- ## 7. Push Notifications ### Architektur ``` Admin erstellt Beitrag │ ▼ Supabase Edge Function wird getriggert (via Database Webhook) │ ▼ Edge Function fetcht alle Push Tokens der org_id │ ▼ Expo Push Notification Service (EPNS) │ ┌──┴──┐ ▼ ▼ APNs FCM (iOS) (Android) ``` ### Push Token Registrierung (Mobile) ```typescript // hooks/usePushNotifications.ts async function registerPushToken() { const { status } = await Notifications.requestPermissionsAsync(); if (status !== 'granted') return; const token = await Notifications.getExpoPushTokenAsync({ projectId: Constants.expoConfig.extra.eas.projectId, }); await supabase .from('push_tokens') .upsert({ user_id: user.id, token: token.data }); } ``` --- ## 8. Infrastruktur & Kosten ### Monatliche Kosten (MVP, bis 100 Innungen) | Service | Plan | Kosten/Monat | |---|---|---| | Supabase | Pro | 25 € | | Vercel | Pro | 20 € | | Resend (E-Mail) | Starter | 0 € (bis 3.000 Mails) | | Expo EAS Build | Production | 29 € | | PostHog | Cloud | 0 € (bis 1 Mio. Events) | | Apple Developer | (jährlich) | 8 € | | **Gesamt** | | **~82 €/Monat** | ### Skalierung (ab 500 Innungen) | Service | Plan | Kosten/Monat | |---|---|---| | Supabase | Team | 599 € | | Vercel | Enterprise | ~400 € | | Resend | Business | 89 € | | **Gesamt** | | **~1.100 €/Monat** | Break-even bei 6 zahlenden Innungen à 200 €. --- ## 9. Deployment & CI/CD ### Pipeline ``` git push → GitHub/Gitea │ ├── Mobile: Expo EAS Build (iOS + Android) │ └── App Store / Play Store (manual submit) │ └── Web Admin: Vercel Deploy (automatisch) └── Preview URL für jeden Branch ``` ### Environments | Environment | Supabase | Vercel | Verwendung | |---|---|---|---| | `development` | Lokal (Docker) | localhost:3000 | Entwicklung | | `staging` | Staging-Projekt | staging.innungsapp.de | Pilot-Tests | | `production` | Pro-Projekt | app.innungsapp.de | Live |