Zum Hauptinhalt springen

Architektur-Übersicht

Roestify ist eine Multi-Tenant SaaS-Plattform für Kaffeeröstereien, gebaut mit Next.js App Router, tRPC und Drizzle ORM auf PostgreSQL.

Tech Stack

SchichtTechnologieVersion
RuntimeNode.js>= 20.9
FrameworkNext.js (App Router, Turbopack)16.1.1
SpracheTypeScript (strict mode)5.x
UIReact + shadcn/ui + Tailwind CSS19 / 3.4
FormsReact Hook Form + Zod4.3.5 (Zod)
APItRPC (primär) + REST (Webhooks, OAuth)11.0.0
Data Fetching@tanstack/react-query via @trpc/react-query5.90
DatenbankPostgreSQL (Sevalla Managed, Frankfurt)-
ORMDrizzle ORM + postgres-js0.45.1 / 3.4.8
AuthAuth.js (NextAuth v5 beta) + @auth/drizzle-adapter5.0.0-beta.30
Rate LimitingIn-Memory (Custom)-
E-MailResend-
PaymentsStripe20.4.0
PDF@react-pdf/renderer + pdf-lib4.3.2 / 1.17.1
StorageS3-kompatibel (AWS SDK v3)-
i18nnext-intl4.8.3
TestsVitest (Unit) + Playwright (E2E)4.0.18 / 1.58.2
HostingSevalla (Nixpacks, Frankfurt)-

Projektstruktur

roestify/
├── roestify-app/ # Next.js Anwendung
│ ├── src/
│ │ ├── app/
│ │ │ ├── (protected)/ # Auth-geschützte Seiten
│ │ │ │ └── dashboard/ # Alle App-Seiten
│ │ │ ├── (public)/ # Login, Register, Landing
│ │ │ └── api/
│ │ │ ├── trpc/ # tRPC Handler
│ │ │ └── v1/ # REST-Routes (OAuth, Webhooks, Cron)
│ │ ├── server/
│ │ │ ├── auth/ # Auth.js Config + Providers
│ │ │ ├── db/
│ │ │ │ ├── index.ts # Drizzle Client + Connection
│ │ │ │ └── schema/ # Drizzle Schema-Definitionen
│ │ │ └── trpc/
│ │ │ ├── init.ts # tRPC Init + Transformer
│ │ │ ├── context.ts # Request Context
│ │ │ ├── middleware.ts # Activity Tracking
│ │ │ ├── router.ts # Root Router
│ │ │ └── routers/ # Domain-Router (production, b2b, ...)
│ │ ├── components/
│ │ │ ├── ui/ # shadcn/ui Primitives
│ │ │ └── [domain]/ # Feature-spezifische Komponenten
│ │ ├── hooks/ # Custom React Hooks
│ │ ├── lib/
│ │ │ ├── validations/ # Zod-Schemas pro Domain
│ │ │ ├── pdf/ # PDF-Generation (@react-pdf/renderer)
│ │ │ ├── rate-limit.ts # In-Memory Rate Limiter
│ │ │ ├── storage.ts # S3-kompatibler Storage Client
│ │ │ └── utils.ts # Shared Utilities
│ │ └── types/ # TypeScript-Typen
│ ├── drizzle/
│ │ └── migrations/ # SQL-Migrationsdateien (Drizzle Kit)
│ └── features/ # Feature-Spezifikationen
├── roestify-docs/ # Docusaurus Dokumentation
│ ├── docs/ # User-Docs (Hilfe-Center)
│ └── dev/ # Developer-Docs
└── .claude/ # Claude Code Regeln

Architektur-Prinzipien

Server-First

React Server Components als Default. 'use client' nur bei Interaktivität, Browser APIs oder Hooks (useState, useEffect).

Multi-Tenancy by Design

Jede Datenbankzeile gehört einem Tenant. Die Isolation wird durch 6 Sicherheitsschichten erzwungen — von RLS über Default-Werte bis zu CASCADE Delete.

3-Ebenen-Validierung

Client (Zod + RHF) → Server (Zod in tRPC) → DB (Constraints + Triggers)

Keine Ebene darf übersprungen werden.

Feature-basierte Organisation

Code ist nach Geschäftsdomäne organisiert, nicht nach technischer Schicht. Jede Domain hat eigene Komponenten, Validierungen und tRPC-Router.

API-Architektur: Hybrid (tRPC + REST)

Roestify verwendet eine hybride API-Architektur:

tRPC (Primär)

Alle CRUD-Operationen und App-Logik laufen über tRPC:

/api/trpc/{router.procedure}

Router-Module:

RouterDomäne
productionLots, Lieferanten, Maschinen, Profile, Tonnen, Röst-Log, Varianten, Abpackung, Wartung
b2bKunden, Bestellungen, Rechnungen, Abos, Preise, Forecasts
analyticsBerichte, Metriken
tenantEinstellungen, Team, Onboarding, Billing
online-storeShopify-Integration
shippingDHL-Versand
billingStripe, Subscriptions
traceabilityRückverfolgung

REST (Speziell)

REST-Endpoints unter /api/v1/ für Fälle, die nicht in tRPC passen:

  • OAuth-Flows — Shopify OAuth (Redirect-basiert)
  • Webhooks — Stripe, Shopify (Signatur-Validierung)
  • Cron-Jobs — DHL-Tracking, Shopify-Sync (Bearer-Auth)
  • Öffentliche APIs — Display-Polling, Bestellformular
  • Admin-Panel — Platform-Admin-Endpunkte
  • File-Uploads — Logo-Upload (Multipart)

Sicherheitsarchitektur

Request → Rate Limit → Auth Check → Permission Check → Zod Validation → RLS Query → Response
SchichttRPCREST
Rate LimitIn-Memory (per IP)In-Memory (per IP)
AuthprotectedProcedure (Session)Session JWT / Bearer Token
PermissionRBAC via Rolle im ContextrequirePermission()
ValidationZod im .input()Zod manuell
Tenant-IsolationtenantId aus SessiontenantId aus Session / RLS

Siehe Auth & RBAC für Details zum Berechtigungsmodell.

Externe Integrationen

ServiceVerwendungAuth
ShopifyProdukt-Sync, Bestellungen, InventarOAuth 2.0 (HMAC-verifiziert)
DHLVersandlabels, TrackingOAuth 2.0 ROPC + pgcrypto
StripeBilling, SubscriptionsWebhook (Signatur-verifiziert)
ResendTransaktions-E-MailsAPI Key
SentryError MonitoringDSN
PostHogAnalytics (EU Cloud)API Key (Cookie-gated)
S3Datei-Storage (Logos, PDFs)Access Key + Secret