Architecture
SUDIGITAL runs on a single backend monorepo — sudi.engine — that serves all three products through one API, one database, and one authentication system.
System Overview
┌───────────────────────────────────────────────────────────────────┐
│ FRONTENDS │
│ │
│ sudigital.com (unified shell) neptu.sudigital.com pasar.sudigital.com
│ apps/web — unified dashboard apps/neptu apps/pasar │
│ (React/Vite) (React/Vite) (React/Vite) │
│ │
└──────────────┬────────────────┬──────────────────┬────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ sudi.engine API │
│ (Elysia) │
│ │
│ /v1 - one prefix, product sub-namespaces: │
│ /v1/missions /v1/nft/* /v1/chat │
│ /v1/ai/* /v1/blockchain /v1/notifications │
│ /v1/wallet /v1/pricing /v1/payments │
│ /v1/neptu/* calendar, checks, people, share, token │
│ /v1/pasar/* markets, prediction-market, strategies │
│ core: auth, users, plans, airdrops, admin/*, webhooks/* │
│ │
├─────────────────────────────────────────────────────────────────┤
│ SERVICES │
│ │
│ Privy Auth Drizzle ORM OpenAI/Vertex ccxt/Jupiter │
│ (JWT) (PostgreSQL) (LLM) (Exchange) │
│ │
└──────────┬────────────────────────────────────┬─────────────────┘
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ PostgreSQL │ │ Worker │
│ (single DB) │ │ (background jobs) │
│ │ │ (cron tasks) │
│ users │ └──────────────────────┘
│ member_* tables │
│ neptu_* tables │ ┌──────────────────────┐
│ pasar_* tables │ │ Telegram Bot │
│ shared tables │ │ (raw Bot API) │
│ │ └──────────────────────┘
└──────────────────────┘Monorepo Structure
sudi.engine/
├── apps/
│ ├── api/ — Elysia REST API
│ ├── web/ — Unified member dashboard + main site
│ ├── neptu/ — Neptu frontend
│ ├── pasar/ — ThePasar frontend
│ ├── worker/ — Background jobs & cron
│ └── cli/ — Terminal dashboard
│
├── packages/
│ ├── shared/ — Types, constants, configs, errors
│ ├── contracts/ — Blockchain config, chain/token constants
│ ├── db/ — Drizzle ORM (PostgreSQL, 40+ schemas)
│ ├── ai/ — AI providers (OpenAI, Google Vertex; DeepSeek opt-in)
│ ├── auth/ — Privy auth (hooks, context, cross-subdomain SSO)
│ ├── solana/ — Solana client (programs, token, signing)
│ ├── evm/ — EVM chain client (contracts, ABIs, signing)
│ ├── nft/ — NFT, claim, tokenomics constants
│ ├── missions/ — Mission & chat constants
│ ├── integrations/ — Telegram bot + integration catalog
│ ├── logger/ — Pino structured logging
│ ├── ui/ — Shared UI components (React + TailwindCSS v4)
│ ├── neptu/ — Balinese calendar engine
│ ├── pasar/ — Pasar trading shared code
│ ├── graphify/ — Knowledge graph (graphology)
│ ├── miro-fish/ — Multi-agent prediction engine
│ ├── decision/ — System One (Laya) decision client
│ └── sanity/ — Sanity CMS client
│
└── docs/ — This documentation siteDependency Order
shared -> logger -> db -> ai -> neptu -> graphify -> miro-fish -> appsAuthentication
All products share one auth system via Privy on a single root domain:
- Users authenticate with wallet (Phantom, MetaMask) or social login
- Privy issues ES256/EdDSA JWTs; sudi.engine validates them on every request
- Privy stores its session in a first-party HttpOnly cookie scoped to
.sudigital.com, so the session is shared across every product subdomain - One user account works across all products — no separate registration per product
neptu.dayandthepasar.comare legacy aliases that redirect to their*.sudigital.comsubdomains, so the shared cookie always applies- The frontend never mirrors the JWT into a JS-readable cookie
Database Design
Single PostgreSQL database with domain-organized schemas:
Core (cross-cutting):
users— Unified user table (Privy auth, wallet address)audit_log— System-wide audit trailjob_queue— Worker job queuemarket_data— Shared market data
Missions, NFTs & engagement tables:
nft_collections,nft_traits,nft_metadatas,holder_shares— NFT system and revenue sharesmissions,mission_participants— Mission systemchat_sessions,chat_messages— Chatxp_accounts,xp_transactions,stake_accounts— XP and stakingclaim_conditions,claim_proofs— Airdrop claims
Billing and platform tables (shared, not Neptu-only):
pricing_plans,plan_prices— the pricing catalog; one price per plan per currencysubscriptions,payments— billing, for every productreferrals— referral systemai_usage,ai_usage_events— AI quota and meteringapi_keys,api_subscriptions,api_usage,api_invoices— the developer API product
Neptu tables:
people,person_categories— public figures and private people for astrology analysisai_insight_cache— cached readings
ThePasar tables — a prediction market, not an exchange:
prediction_markets— user-created binary markets (question, category, close and expiry times)prediction_orders— the cents-denominated order book (CLOB)prediction_positions— matched positionsprediction_escrows— per-user escrow rows backing open ordersprediction_settlements,prediction_payouts— settlement record and payouts, written together
The exchange-strategy module the product was originally planned around still ships in the same database (strategies, bots, alerts, alert_history, integrations, integration_logs) and is reachable at /v1/pasar/strategies and /v1/pasar/automation. It is not the public product.
API Design
Every route lives under /v1; the product sub-namespaces nest inside it:
GET /v1/health — System health (public)
GET /v1/auth/me — Current user (shared)
GET /v1/pricing/plans — The pricing catalog (public)
GET /v1/missions — List missions
GET /v1/nft/collections — List NFT collections
GET /v1/wallet/balance/:address — Wallet balance
GET /v1/ai/daily/:birthDate — Daily AI insight
GET /v1/neptu/calendar/reading — Balinese calendar reading
GET /v1/neptu/people — Public figures
GET /v1/pasar/prediction-markets — Prediction markets, orders, positions
GET /v1/pasar/market — Exchange market data
GET /v1/pasar/strategies — Exchange strategies (legacy module)There is no /hub namespace: an earlier draft of this page invented one, and it never existed.
Unified Member Dashboard
Authenticated member dashboards are unified in the web app (apps/web) behind a single shell. Members navigate the whole ecosystem without being redirected to a product subdomain; subdomains remain the home for public landing pages and deep product features.
Navigation model
The shell follows the standard Web2/Web3 split of two independent controls:
| Control | Scope | Source |
|---|---|---|
| Product switcher | Ecosystem context (Neptu / Pasar / platform) | Sanity siteSettings.products |
| Workspace switcher | Section scope (Dashboard / Admin / Developer) | App teams + role gating |
Terminology: an app switcher ("waffle") launches between distinct apps and leaves the shell (Google Workspace, Microsoft 365); a product switcher swaps product context inside a persistent shell (Notion, Linear, Vercel); a workspace/org switcher changes the data/tenant scope. sudi.engine uses the in-shell product switcher plus a separate workspace switcher — never two competing controls.
Routing
- The shared shell lives in
packages/ui(AppSidebar,TeamSwitcher,lib/workspace.ts,lib/workspace-preference.ts) and is prop-driven. - Product dashboard entry points render in-app at
/neptuand/pasarinapps/web, backed by the shared cross-product API client. productRoutesmaps a product id to its in-app route, so selecting a product stays on the web origin. When no in-app route exists the switcher falls back to the product's external URL.apps/websupplies routes for Neptu and Pasar and derives the active ecosystem from the first path segment viadetectEcosystem(packages/ui/src/lib/workspace.ts).- The last-selected workspace is persisted (
sudi:last-workspace) and resumed on root visits. - Each product subdomain's
/dashboardredirects to the unified dashboard whenVITE_WEB_URLis set; landing and deep routes stay on the subdomain until they are migrated.
Content Authoring & Delivery
Public page content is served from the Sanity Content API at runtime — the app fetches with a public CDN client, so publishing a document updates the site without a rebuild. The build only writes SEO shells (title/description) for crawlers.
Three layers, one owner each:
| Layer | Owner | Where |
|---|---|---|
| Page structure | code | Sanity schema + scripts/seed page builders |
| Prose | Sanity Studio | one page document per locale |
| Numbers | code | @sudi/nft → packages/nft/src/facts.ts |
Facts (supply, allocation, mission split, NFT revenue split, APY band, burn share) are derived from the constants and rendered per locale (4억, 400.000.000, 400,000,000). They are never typed into prose or into a translation, which is what made the 105% allocation possible.
The seed is bootstrap-only by default (createIfNotExists), so Studio edits survive every run. --refresh deliberately replaces documents and clears their drafts; --publish publishes pending drafts in one bulk request. Full contract: scripts/seed/README.md.
Next Steps
- Products — detailed look at each product
- Tokenomics — how $SUDIGITAL connects the ecosystem