Skip to content

System Overview

Three Core Principles

  1. Modular #-architecture — the system grows through bounded contexts. Alpha A = 15 active contexts. Vision (v2.0) = 25+ contexts. No cross-context *.service imports — integration flows through the EventBus only.

  2. Federation-readiness without premature investment — URI-based actor identifiers (acct:[email protected], Webfinger-style), event-sourcing of critical domains. ActivityPub bridge arrives in v2.0.

  3. Cost trajectory $30 → $500/month at 50 k MAU — Supabase + Expo + Cloudflare R2 + Centrifugo. No Convex / Firebase / Clerk without an architectural ADR.

System Diagram

mermaid
graph TB
    subgraph Mobile["apps/mobile (Expo SDK 54 + RN 0.81)"]
        MobileApp[React Native App]
    end

    subgraph Admin["apps/admin (Next.js 15 + shadcn/ui)"]
        AdminPanel[Admin Panel]
    end

    subgraph API["apps/api (NestJS + Fastify)"]
        direction TB
        Identity[identity]
        Interests[interests]
        Reputation[reputation]
        Social[social]
        Posts[posts]
        AI[ai-assistant]
        Economy[economy]
        Notifications[notifications]
        Messaging[messaging]
        Wiki[wiki]
        Contribution[contribution]
        Discovery[discovery]
        Access[access-matrix]
        InviteTree[invite-tree]
        Shared[shared/]
    end

    subgraph Data["Data Layer"]
        PG[(Supabase Postgres)]
        R2[(Cloudflare R2)]
        Centrifugo[Centrifugo WS]
    end

    subgraph AI_Ext["External AI"]
        Anthropic[Anthropic Claude Sonnet 4.6]
    end

    Mobile -->|REST + JWT| API
    Admin -->|REST + JWT| API
    API -->|Prisma| PG
    API -->|Presigned URLs| R2
    API -->|Publish| Centrifugo
    Mobile -->|Subscribe| Centrifugo
    AI -->|Vercel AI SDK| Anthropic

Tech Stack

LayerTechnologyWhy
MobileExpo SDK 54 + RN 0.81 + New ArchitectureOne codebase, EAS OTA updates
Mobile UITamagui v2.0.0-rc.0+Compiler-driven, design tokens first-class
BackendNestJS + FastifyModules = bounded contexts
DatabaseSupabase Postgres + pgvector + RLS50 k MAU free tier, AI embeddings ready
AuthSupabase Auth + custom invite flowRLS integration
Real-timeCentrifugo (self-hosted)Scalable, federation-friendly
AIVercel AI SDK + Anthropic Claude Sonnet 4.6Streaming, provider-agnostic
StorageCloudflare R2 + Supabase StorageZero egress cost for video
Web AdminNext.js 15 + shadcn/ui + Ant DesignOwned code + CRUD factory
MonorepoTurborepo + pnpmSimplicity, remote cache
StateTanStack Query + Zustand + MMKVStandard, offline-first
PushExpo Push600 notif/sec, zero infra
ObservabilityPostHog + SentryFree tiers cover Alpha
HostingFly.io (API + Centrifugo) + Vercel (admin)$5/month start

Monorepo Structure

regulus/
├── apps/
│   ├── api/          NestJS modular monolith
│   │   ├── prisma/   Schema + migrations (49 migrations)
│   │   └── src/
│   │       ├── modules/    One folder = one bounded context
│   │       └── shared/     Guards, EventBus, Prisma, etc.
│   ├── mobile/       Expo SDK 54 (iOS + Android)
│   │   └── src/
│   │       ├── screens/    Full-screen views
│   │       ├── components/ Local UI components
│   │       └── lib/        API client, auth, storage
│   ├── admin/        Next.js 15 admin panel
│   │   └── src/
│   │       ├── pages/      One file = one admin resource
│   │       ├── components/ Admin-specific components
│   │       └── lib/        Queries, auth, API client
│   └── docs/         VitePress documentation (this site)
├── packages/
│   ├── domain/       Shared types, Zod schemas, domain events
│   ├── ui/           Shared React Native components
│   ├── design-tokens/ Tamagui theme tokens
│   └── ai-prompts/   Anthropic prompt templates
└── docs/
    ├── architecture/ ADRs + bounded context map
    ├── adr/          Architecture Decision Records
    └── setup/        Human setup guides

Cross-Cutting Concerns

Reputation, Moderation, Governance, and Economy must integrate through events, not direct service calls:

typescript
// WRONG — cross-context service import
@Injectable()
class ProfileService {
  constructor(private readonly reputationService: ReputationService) {}
}

// CORRECT — event-driven integration
@Injectable()
class ProfileService {
  constructor(private readonly eventBus: EventBus) {}

  async updateProfile(userId: string, data: UpdateProfileDto) {
    await this.eventBus.publish(new ProfileUpdatedEvent({ userId, changes: data }));
  }
}

// Reputation module listens
@OnEvent('profile.updated')
async handleProfileUpdated(event: ProfileUpdatedEvent) { /* ... */ }

Regulus — invite-only social-knowledge platform