-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture Overview
ZAO OS is a Next.js 16 application using the App Router with React 19 Server Components and Client Components. Data lives in Supabase PostgreSQL with Row-Level Security. Social features run on the Farcaster protocol via Neynar. Everything is TypeScript.
| Layer | Technology | Purpose |
|---|---|---|
| Framework | Next.js 16, React 19, TypeScript 5 | App shell, routing, SSR/RSC |
| Styling | Tailwind CSS v4 | Utility-first CSS, dark theme |
| Database | Supabase PostgreSQL | Data storage, RLS, real-time |
| Auth | iron-session | Encrypted httpOnly cookies, 7-day TTL |
| Social | Neynar SDK (Farcaster) | Casts, reactions, signers, channels |
| Messaging | XMTP (MLS protocol) | E2E encrypted DMs and groups |
| Web3 (EVM) | Wagmi, Viem, RainbowKit | Wallet connections, contract reads |
| Web3 (Solana) | Solana Web3.js, Wallet Adapter | WaveWarZ integration |
| Voice | 100ms HMS SDK | Live audio rooms |
| Video | Jitsi React SDK | Video calls |
| Streaming | Livepeer SDK | Multistream, recording, clipping |
| Storage | Arweave, ArDrive Turbo | Permanent music storage |
| Analytics | PostHog | Event tracking, user identification |
| Rate Limiting | Upstash Redis | Per-IP API rate limits |
| Validation | Zod | Input validation on all API routes |
| State | React Query (@tanstack) | Server state, caching, mutations |
| Cross-posting | twitter-api-v2, @atproto/api, @hiveio/dhive, discord.js | Multi-platform publishing |
src/
├── app/ # Next.js App Router
│ ├── (auth)/ # Protected routes (requires session)
│ │ ├── home/ # Dashboard
│ │ ├── chat/ # Farcaster channel feed
│ │ ├── music/ # Music player & library
│ │ ├── messages/ # XMTP encrypted DMs
│ │ ├── governance/ # Snapshot polls
│ │ ├── fractals/ # Fractal governance
│ │ ├── respect/ # Respect leaderboard
│ │ ├── library/ # Knowledge base
│ │ ├── directory/ # Member directory
│ │ ├── settings/ # User preferences
│ │ ├── admin/ # Admin dashboard (7 tabs)
│ │ ├── wavewarz/ # Solana prediction market
│ │ ├── ecosystem/ # Partner integrations
│ │ └── ... # notifications, social, calls, etc.
│ ├── api/ # Route handlers
│ │ ├── auth/ # SIWF, SIWE, session, signers
│ │ ├── chat/ # Messages, threads, reactions, search
│ │ ├── music/ # Library, playlists, trending, radio, mint
│ │ ├── members/ # Directory, profiles
│ │ ├── admin/ # Users, allowlist, health, sync
│ │ ├── respect/ # Leaderboard, sync, transfers
│ │ ├── fractals/ # Sessions, proposals, analytics
│ │ ├── publish/ # Cross-platform posting
│ │ ├── platforms/ # OAuth for X, Twitch, YouTube, etc.
│ │ ├── hats/ # Hats Protocol checks
│ │ ├── zounz/ # Nouns Builder proposals
│ │ ├── snapshot/ # Snapshot polls
│ │ ├── 100ms/ # Voice room tokens
│ │ └── ... # search, upload, notifications, etc.
│ ├── spaces/ # Public voice channel pages
│ ├── members/ # Public profile pages
│ └── page.tsx # Landing / login
├── components/ # React components by feature
│ ├── music/ # 30+ components (player, queue, EQ, etc.)
│ ├── chat/ # 16 components (messages, compose, search)
│ ├── admin/ # 12 components (dashboard tabs)
│ ├── governance/ # Snapshot + fractal components
│ ├── spaces/ # Voice room components
│ ├── messages/ # XMTP DM components
│ └── ... # members, settings, hats, zounz, etc.
├── hooks/ # Custom React hooks
│ ├── useAuth.ts # Authentication state
│ ├── useChat.ts # Channel chat operations
│ ├── usePlayerQueue.ts # Music queue management
│ ├── useRadio.ts # Radio mode state
│ ├── useListeningRoom.ts # Listening room state
│ └── ... # 16 total hooks
├── contexts/ # React contexts
│ ├── QueueContext.tsx # Music queue state
│ └── XMTPContext.tsx # XMTP messaging state (500+ lines)
├── providers/ # Provider wrappers
│ └── audio/ # PlayerProvider, HTMLAudioProvider, etc.
├── lib/ # Utilities by domain
│ ├── auth/ # iron-session config
│ ├── db/ # Supabase client setup
│ ├── farcaster/ # Neynar SDK client
│ ├── music/ # Curation, audio filters, Audius, Arweave
│ ├── publish/ # Cross-platform publishing
│ ├── gates/ # Allowlist gating
│ ├── hats/ # Hats Protocol client
│ ├── validation/ # Zod schemas
│ ├── moderation/ # AI content moderation
│ └── ... # ens, bluesky, snapshot, discord, etc.
└── types/ # TypeScript type definitions
community.config.ts # ALL community-specific configuration
Everything community-specific — branding, channels, contracts, admin FIDs, partners, nav structure — lives in community.config.ts. This is the one file forkers need to change to make ZAO OS their own. See Fork Guide: Getting Started.
Pages are React Server Components unless they need interactivity. Client components use "use client" directive and are code-split with next/dynamic when heavy.
Direct Supabase client queries instead of an ORM. Simpler, fewer abstractions, easier to understand what's happening at the database level. RLS handles authorization at the database layer.
Encrypted httpOnly cookies (iron-session) instead of JWTs. Can't be read by JavaScript, can't be stolen from localStorage, 7-day TTL with automatic refresh.
SIWF (Sign In With Farcaster) for social features, SIWE (Sign In With Ethereum) for token holders. Progressive onboarding — start with wallet, add Farcaster for posting, add XMTP for encrypted messaging.
Public messages are Farcaster casts, but we cache them in Supabase for fast loading, search, and filtering. Neynar webhooks keep the cache fresh.
Each music platform has its own provider class. The PlayerProvider orchestrates them — detecting which provider to use based on the URL, managing playback state, and handling transitions (crossfade) between tracks.
All API data flows through @tanstack/react-query — automatic caching, background refetching, optimistic updates. No Redux, no Zustand, no global state libraries.
Per-IP rate limits on all API route families, enforced in src/middleware.ts via Upstash Redis. Protects against abuse without adding complexity to individual routes.
User Action
→ React Component (Client)
→ React Query mutation/query
→ API Route Handler (Server)
→ Zod validation
→ Session check (iron-session)
→ Supabase query (with RLS)
→ Response → React Query cache → UI update
For Farcaster operations:
User posts a cast
→ API Route → Neynar SDK → Farcaster network
→ Neynar webhook fires → API Route → Supabase cache updated
→ React Query invalidation → UI shows new cast
For XMTP messaging:
User sends DM
→ XMTPContext → XMTP SDK → MLS encryption → XMTP network
→ Recipient's XMTP stream receives → XMTPContext → UI update
(Never touches our server — true E2E encryption)
See the Fork Guide: Database & Auth for setup details. Key points:
- RLS on all tables — Supabase Row-Level Security, not application-level auth checks
-
Server-only secrets —
SUPABASE_SERVICE_ROLE_KEY,NEYNAR_API_KEY,SESSION_SECRET,APP_SIGNER_PRIVATE_KEYnever exposed to browser -
Zod on all inputs — every API route validates with
safeParsebefore processing - HMAC webhook verification — Neynar and Alchemy webhooks verified with SHA-512 signatures
-
No
dangerouslySetInnerHTML— ever - CSP headers — Content Security Policy in middleware
- Rate limiting — per-IP on all API routes