stadtwerke/innungsapp/CLAUDE.md

4.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

InnungsApp is a multi-tenant SaaS platform for German trade guilds (Innungen). It consists of:

  • Admin Dashboard: Next.js 15 web app for guild administrators
  • Mobile App: Expo React Native app for guild members (iOS + Android)
  • Shared Package: Prisma ORM schema, types, and utilities

Commands

All commands run from innungsapp/ root unless noted.

# Development
pnpm install          # Install all workspace dependencies
pnpm dev              # Start all apps in parallel (Turborepo)

# Per-app dev
pnpm --filter admin dev           # Admin only (Next.js on :3000)
pnpm --filter mobile dev          # Mobile only (Expo)
cd apps/mobile && npx expo run:android
cd apps/mobile && npx expo run:ios

# Type checking & linting
pnpm type-check       # tsc --noEmit across all apps
pnpm lint             # ESLint across all apps

# Database (Prisma via shared package)
pnpm db:generate      # Regenerate Prisma client after schema changes
pnpm db:migrate       # Run migrations (dev)
pnpm db:push          # Push schema without migration (prototype)
pnpm db:studio        # Open Prisma Studio
pnpm db:seed          # Seed with test data
pnpm db:reset         # Drop + re-migrate + re-seed

# Deployment
vercel --cwd apps/admin                        # Deploy admin to Vercel
cd apps/mobile && eas build --platform all --profile production
cd apps/mobile && eas submit --platform all

Architecture

Monorepo Structure

  • pnpm Workspaces + Turborepoapps/admin, apps/mobile, packages/shared
  • packages/shared exports Prisma client, schema types, and shared utilities
  • Both apps import from @innungsapp/shared

Data Flow

Mobile App (Expo)
      │
      ▼ HTTP (tRPC)
Admin App (Next.js API Routes)
      │
      ▼ Prisma ORM
PostgreSQL Database

The mobile app calls the admin app's tRPC API (/api/trpc). There is no separate backend — the Next.js app serves both the admin UI and the API.

tRPC Procedure Hierarchy

Three protection levels in apps/admin/server/trpc.ts:

  • publicProcedure — No auth
  • protectedProcedure — Session required
  • memberProcedure — Session + valid org membership (injects orgId and role)

Routers are in apps/admin/server/routers/: members, news, termine, stellen, organizations.

Multi-Tenancy

Every resource (member, news, event, job listing) is scoped to an Organization. The memberProcedure extracts orgId from the session and all queries filter by it. Org plan types: pilot, standard, pro, verband.

Authentication

  • better-auth with magic links (email-based, passwordless)
  • Admin creates a member → email invitation sent via SMTP → member sets up account
  • Session stored in DB; mobile app persists session token in AsyncStorage
  • Auth handler: apps/admin/app/api/auth/[...all]/route.ts

Mobile Routing (Expo Router)

File-based routing with two route groups:

  • (auth)/ — Login, check-email (unauthenticated)
  • (app)/ — Tab navigation: home, members, news, stellen, termine, profil (requires session)

Zustand (store/auth.store.ts) holds auth state; React Query handles server state via tRPC.

Admin Routing (Next.js App Router)

  • /login — Magic link login
  • /dashboard — Protected layout with sidebar
  • /dashboard/mitglieder — Member CRUD
  • /dashboard/news — News management
  • /dashboard/termine — Event management
  • /dashboard/stellen — Job listings
  • /dashboard/einstellungen — Org settings (AVV acceptance)

File uploads are stored locally in apps/admin/uploads/ and served via /api/uploads/[...path].

Environment Variables

Required in apps/admin/.env (see .env.example):

  • DATABASE_URL — PostgreSQL connection
  • BETTER_AUTH_SECRET / BETTER_AUTH_URL — Auth config
  • SMTP_* — Email for magic links
  • NEXT_PUBLIC_APP_URL — Admin public URL
  • EXPO_PUBLIC_API_URL — Mobile points to admin API
  • UPLOAD_DIR / UPLOAD_MAX_SIZE_MB — File storage

Key Conventions

  • Styling: Tailwind CSS in admin; NativeWind v4 (Tailwind syntax) in mobile
  • Validation: Zod schemas defined inline with tRPC procedures
  • Dates: date-fns for formatting
  • Icons: lucide-react (admin), @expo/vector-icons (mobile)
  • Schema changes: Always run pnpm db:generate after editing packages/shared/prisma/schema.prisma
  • tRPC client (mobile): configured in apps/mobile/lib/trpc.ts, uses superjson transformer