0%
Vibe44 Logo

Architecture

System design, data flows, component boundaries, and integration topology for this codebase.

️ Technology Stack

LayerTechnologyPurpose
FrameworkNext.js 16 (App Router)RSC, Server Actions, edge middleware
LanguageTypeScript 6 (Strict)Zero any, compile-time safety
DatabasePostgreSQL 15 (Supabase)32 tables, RLS on every table
ORMDrizzle ORMType-safe SQL, schema-driven
AuthSupabase AuthPKCE, OAuth, MFA, passkeys
PaymentsUniversal Adapter (5 providers)Strategy pattern, env var swap
AIUniversal Adapter (4 providers)Validated Gemini, OpenAI, Anthropic, DeepSeek factories
Embeddingsgemini-embedding-2 + pgvector3072-dim, cosine similarity RAG
VoiceUniversal Adapter (2 providers)ElevenLabs/Murf TTS; STT requires ElevenLabs
EmailUniversal Adapter (4 providers)Validated SendGrid, Resend, Postmark, Brevo adapters
AnalyticsUniversal Adapter (9 providers)Consent-gated scripts/events with CSP allowlisting
Rate LimitingUpstash RedisEdge middleware, circuit breaker
BackgroundUniversal Adapter (QStash / Trigger.dev)Strategy pattern, swappable background jobs
Knowledge GraphGraphifyAST parsed, 71.5x token reduction for AI Agents
StylingTailwind CSS v4 + shadcn/ui (57)OKLCH, Glassmorphism 2.0
Motionmotion/react (LazyMotion)Spring physics, ~15KB vs ~100KB
i18nnext-intl3 languages, 14 sub-modules
TestingVitest + Playwright900 tests across 84 unit test files + E2E coverage
APIoRPC + OpenAPI 3.0.3 + ScalarType-safe RPC, interactive docs
Error TrackingSentryPII and replay opt-in, GDPR-safe default

Request Lifecycle

Every request passes through this pipeline:

Browser Request
    ↓
proxy.ts (Edge Middleware)
    ├── Route classification (public / auth / protected / super-admin / API)
    ├── Rate limiting (Upstash Redis, per-tier from lib/config/pricing.ts)
    ├── Circuit breaker (auto IP ban after 5 violations)
    ├── CSP nonce generation (per-request, strict-dynamic)
    ├── CSRF validation (HMAC-bound double-submit cookie + user binding)
    ├── Auth session refresh (Supabase token rotation)
    ├── MFA enforcement (AAL2 check via getAuthenticatorAssuranceLevel(), fail-closed)
    ├── Feature flag redirects (disabled modules → /dashboard)
    ├── Header injection (x-pathname, x-org-id, x-nonce, x-impersonating-*)
    ├── Signed impersonation context propagation (1hr auto-expiry + read-time profile revalidation)
    ├── Waitlist Gating: unapproved users deleted via super-admin client
    ├── Waitlist Metadata Sync: fullName → profile (first login)
    └── CSRF cookie seeding/refresh for authenticated page requests
    ↓
Next.js App Router
    ├── Root layout (fonts, ThemeProvider, MotionProvider, NextIntlClientProvider, CSRFProvider)
    ├── Server Component (data fetching via Server Actions)
    └── Client Component (interactive UI, motion animations)
    ↓
Server Actions (app/actions/)
    ├── 1. Auth check → requireUser() / verifyAdmin()
    ├── 2. Zod validation → schema.safeParse(input)
    ├── 3. Drizzle operation → db.select/insert/update/delete
    └── 4. Cache invalidation → revalidatePath() + revalidateTag(..., "max")
    ↓
PostgreSQL (Supabase)
    ├── RLS policies enforce data isolation at query level
    ├── Drizzle ORM parameterizes all queries (SQL injection prevention)
    └── Indexes optimized for RLS super-admin checks + common patterns

Performance Contracts

The current performance hardening uses stable production primitives, not experimental framework flags:

  • Next.js config strips unstable keys after plugin composition; production builds must not depend on experimental.
  • Pricing auth/billing reads execute in parallel and commit one derived billing-context state update.
  • Drizzle reads use explicit projections to reduce payload size and avoid accidental over-fetching.
  • Super-Admin webhook log reads clamp requested limits to 100 rows and project only fields needed by retry/list/detail views.
  • Fixed-aspect next/image assets include style={{ width: "auto", height: "auto" }} to prevent ratio warnings and layout shifts.
  • Heavy client libraries remain behind dynamic import or provider-level lazy loading: Recharts via chart wrappers, support chat widget via next/dynamic, and motion via LazyMotion + domAnimation.

Directory Structure

app/
├── (marketing)/          # Public: landing, pricing, blog, contact, system, docs, API ref
├── (auth)/               # Login, signup, forgot/reset password, invite, verified
├── (protected)/          # Dashboard, billing, settings, super-admin, onboarding
│   ├── dashboard/
│   │   ├── analytics/    # Usage analytics (Recharts)
│   │   ├── billing/      # Subscriptions, invoices
│   │   ├── organizations/# Multi-tenant teams
│   │   ├── projects/     # Project CRUD
│   │   └── settings/     # Profile, security (MFA/passkeys), notifications, activity
│   └── super-admin/      # 17 super-admin module routes
└── api/
    ├── auth/callback/    # OAuth, magic link, password-reset code exchange
    ├── health/           # Minimal public liveness endpoint
    ├── rpc/[...path]/    # oRPC handler (type-safe API)
    └── webhooks/         # Payment webhooks (stripe, polar, lemon-squeezy, dodo, creem)

components/
├── auth/                 # Split-screen auth, MFA challenge, passkeys
├── dashboard/            # Sidebar, nav, charts, settings, org switcher
├── global/               # Header, footer, chat widget, theme toggle
├── marketing/            # Hero, features, pricing, testimonials
├── super-admin/          # 17 super-admin modules (Glassmorphism 2.0 logic)
├── support/              # Tickets, chat widget
└── ui/                   # 57 shadcn/ui primitives (you own the code)

lib/
├── ai/                   # Universal AI Adapter, providers/, RAG, intent, embeddings
├── rpc/                  # oRPC routers, procedures, middleware
├── auth/                 # Supabase client factory (server, client, super-admin), RBAC
├── config/               # App config, pricing, feature flags (single source of truth)
├── db/                   # Drizzle client + schema/ (14 domain files)
├── email/                # Universal Email Adapter, templates, i18n content
├── invoices/             # PDF Invoice generation service
├── payments/             # Universal Payment Adapter (5 providers), types, utils
├── jobs/                 # Universal Background Jobs (shared business logic)
├── qstash/               # QStash transport adapter for background jobs
├── trigger/              # Trigger.dev transport adapter for background jobs
├── realtime/             # Supabase Realtime broadcasting utilities
├── security/             # SSRF (ssrf.ts), crypto (crypto.ts), security alerts
├── seo/                  # Metadata generators, JSON-LD schemas
├── validations/          # Shared Zod schemas
└── voice/                # Universal Voice Adapter (ElevenLabs, Murf AI)

locales/
├── frontend/             # UI: en.ts, es.ts, fr.ts (14 sub-modules each)
└── emails/               # Email content: en.ts, es.ts, fr.ts

.agents/
├── skills/               # 4 SKILL.md (backend, frontend, graphify, i18n)
└── workflows/            # 18 step-by-step playbooks

graphify-out/             # 🧠 Auto-generated AST knowledge graph for AI

Integration Architecture

Universal Payment Adapter

lib/payments/
├── types.ts              # PaymentProvider interface contract
├── index.ts              # Factory: getPaymentProvider() reads PAYMENT_PROVIDER env var
├── readiness.ts          # Selected-provider env and paid-tier product readiness
├── utils.ts              # mapProductNameToTier(), shared helpers
└── providers/
    ├── stripe.ts
    ├── polar.ts
    ├── lemon-squeezy.ts
    ├── dodo.ts
    └── creem.ts

Pattern: Strategy. All providers implement PaymentProvider. App code calls getPaymentProvider() — never a specific provider. Switching = one env var change, zero code mods. getPaymentProviderReadiness() validates the selected provider's API key/access token, webhook secret, and active paid-tier price/product IDs for super-admin health without exposing secret values.

Paid product-name fallback: Providers that cannot resolve a tier from metadata or price/product IDs call mapProductNameToTier() in lib/payments/utils.ts. The helper matches configured paid tier IDs and display names first, maps config-driven highIntentAliases (e.g., business, agency, enterprise) to the correct paid tier, and falls back to the lowest paid tier for unknown paid provider names so completed one-time purchases are never downgraded to the default free tier. Each call emits a [mapProductNameToTier] warning so teams can replace string-based matching with metadata or configured IDs.

Webhook flow:

Provider sends webhook
    ↓
app/api/webhooks/[provider]/route.ts
    ↓
Read raw body + signature header(s)
    ↓
provider.handleWebhook(payload, signature) — HMAC-SHA256
    ↓
webhook_logs claim(provider, event_id) — success skip, active-processing skip, failed/stale retry
    ↓
syncSubscriptionToDb() / savePurchase() — provider-resource upsert/dedup + profiles.subscription_tier + subscriptions/purchases

Features:

  • Token-Based Fulfillment: Secure, signed, short-lived download links for digital products.
  • Same-Origin Redirects: Checkout success/cancel and portal return URLs are built with lib/security/redirects.ts from config.app.url plus allowlisted paths. External redirect targets are rejected before provider session creation.
  • Provider Resource Idempotency: subscriptions(provider, provider_subscription_id) and purchases(provider, provider_payment_id) are unique when provider IDs are present, preventing duplicate entitlements after webhook retries or concurrent deliveries.
  • Billing Identity Parity: REST checkout, portal, cancel, and subscription routes use getEffectiveUserId() so impersonated super-admin flows target the same account as Server Actions.
  • Fail-Closed Paid Deletion: Account deletion stops before local profile/auth/storage removal if immediate provider subscription cancellation, configured-bucket storage cleanup, or Auth deletion fails.
  • Dynamic Usage Limits: Renders tier constraints (projects, team members, API requests, storage) directly from central pricing configs without hardcoded fallbacks.
  • Upgrade Guard Hardening: Intelligently hides "Upgrade Plan" buttons exclusively for users already on the most expensive plan.

AI & RAG Pipeline

User message (text or voice)
    ↓
Language detection (getAIProvider().classifyIntent() — 100+ languages)
    ↓
Generate embedding (getEmbeddingProvider().generateEmbedding(), 3072 dims)
    ↓
pgvector cosine similarity → knowledge_base
    ↓
Top-K context injected into AI provider prompt
    ↓
getAIProvider().streamChat() responds (in detected language)
    ↓
[Optional] Voice Provider (ElevenLabs / Murf) TTS → speech; STT only when ElevenLabs is configured
    ↓
Response → chat widget (Web Audio API)

Key properties:

  • Lazy conversation creation — DB record on first message, not widget open
  • Guest access — no auth required
  • Message dedup — client-side + event IDs
  • Provider gates — invalid AI_PROVIDER / EMBEDDING_PROVIDER values fail closed before SDK construction

Email Adapter

lib/email/
├── index.ts              # sendEmail() — validates EMAIL_PROVIDER and configured-key fallback
├── types.ts              # EmailTemplateType (13 template names)
├── providers/
│   ├── sendgrid.ts       # Native batch up to 1000
│   ├── resend.ts         # Auto-chunks at 100
│   ├── postmark.ts       # Official postmark SDK, auto-chunks at 500
│   └── brevo.ts          # Sequential Promise.allSettled
└── templates/            # 13 i18n-ready templates

Analytics Adapter

lib/analytics/
├── consent.ts            # localStorage/cookie consent contract + app-local change event
├── index.ts              # getAnalyticsAdapter() — SSR/feature/consent guard
├── types.ts              # AnalyticsProvider (10 event helpers)
└── providers/            # 9 implementations

PII protection: trackSignup() excludes email. Client scripts mount through components/providers/analytics-provider.tsx only after explicit analytics consent. proxy.ts allowlists analytics connect-src endpoints for the configured providers; DataFast requires both NEXT_PUBLIC_DATAFAST_WEBSITE_ID and NEXT_PUBLIC_DATAFAST_DOMAIN.


️ Data Model

Entity Relationships

auth.users (Supabase-managed)
    └── profiles (1:1)
            ├── subscriptions (1:many)
            ├── purchases (1:many)
            ├── invoices (1:many)
            ├── projects (1:many)
            ├── activity_logs (1:many)
            ├── ai_conversations (1:many)
            │       └── ai_messages (1:many)
            ├── support_tickets (1:many)
            │       └── ticket_replies (1:many)
            ├── api_keys (1:many)
            │       └── api_usage_logs (1:many)
            ├── passkeys (1:many)
            ├── notification_preferences (1:1)
            └── organizations (owner, 1:many)
                    └── org_members (many:many with profiles)
                    └── org_invitations (1:many)

Standalone:
    ├── posts ← blog_categories (many:1)
    ├── knowledge_base (RAG vectors)
    ├── generated_legal_docs
    ├── contact_submissions
    ├── waitlist
    ├── newsletter_subscribers
    ├── webhook_logs
    ├── webauthn_challenges
    ├── auth_events (append-only)
    ├── affiliates → referrals → affiliate_payouts
    └── user_legal_consents

Key Design Decisions

DecisionRationale
UUID primary keysGlobally unique, no sequential enumeration
timestamptz everywhereTimezone-aware, no UTC bugs
text not varcharPostgreSQL treats identically; avoids arbitrary limits
Hard deletes + CASCADESimpler cleanup; retained deletion facts live in auth_events
JSONB for metadataFlexible extension (goals, product_usage, line_items)
Barrel re-exportsSingle import point; domain files keep schema organized

Security Architecture

                    ┌──────────────────────────────────────┐
                    │           Edge Layer                 │
                    │  Rate Limiting (Upstash Redis)       │
                    │  Circuit Breaker (auto IP ban)       │
                    │  CSP Nonce (per-request)             │
                    │  CSRF (HMAC-bound double-submit)     │
                    └──────────────┬───────────────────────┘
                                   │
                    ┌──────────────▼───────────────────────┐
                    │        Application Layer             │
                    │  Auth Check (supabase.auth.getUser)  │
                    │  MFA Enforcement (AAL2 check)        │
                    │  Zod Input Validation                │
                    │  Ownership Verification              │
                    └──────────────┬───────────────────────┘
                                   │
                    ┌──────────────▼───────────────────────┐
                    │         Database Layer                │
                    │  RLS on all 32 tables                │
                    │  Drizzle parameterized queries       │
                    │  FOR UPDATE row locks (credits)      │
                    │  API Key SHA-256 hashing             │
                    │  Composite indexes (20+)             │
                    │  auth_events append-only logging     │
                    └─────────────────────────────────────┘

Full OWASP Top 10 (2025) compliance. See SECURITY_AUDIT.md · THREAT_MODEL.md · SUPPLY_CHAIN_SECURITY.md.


️ Configuration Architecture

Single source of truth:

lib/config.ts (barrel export)
    ├── lib/config/app.ts        # App name, URL, feature flags, legal
    ├── lib/config/pricing.ts    # PRICING_TIERS: prices, limits, credits, rate limits, provider IDs
    └── lib/config/billing.ts    # Billing model toggles (subs, lifetime, credits, seats, trials)

Feature flags gate UI + server-side logic:

// UI
{isOrganizationsEnabled() && <OrgSwitcher />}

// Server
if (!isOrganizationsEnabled()) return { success: false, error: t("disabled") };

21 helpers: isProjectsEnabled(), isOrganizationsEnabled(), isCreditsEnabled(), isSeatsEnabled(), isSubscriptionsEnabled(), isLifetimePurchasesEnabled(), isDigitalProductsEnabled(), isTrialEnabled(), isBlogEnabled(), isAiChatEnabled(), isVoiceEnabled(), isSTTEnabled(), isWaitlistEnabled(), isI18nEnabled(), isAnalyticsEnabled(), isStorageEnabled(), isEmailEnabled(), isAffiliatesEnabled(), isSupportTicketsEnabled(), isDocsEnabled(), isApiReferenceEnabled().


Copyright © 2026 Vibe44. Built with ❤️ by Scale with Alap.