Skip to content

System Architecture

Last refreshed: 2026-05-21

Topology

Anuva CMS is a Next.js 15 App Router app with Payload CMS 3.65 embedded in the same runtime. React 19 powers the UI. Payload uses Postgres through @payloadcms/db-postgres.

Important entry points:

  • src/app/(frontend)/(public): public pages, auth pages, blog.
  • src/app/(frontend)/app: authenticated app routes and server actions.
  • src/app/(payload): Payload admin shell and generated API handlers.
  • src/app/api: Better Auth, presentation orchestration APIs, worker render APIs, and Zoho webhook routes.
  • src/mastra: Mastra runtime, agents, tools, workflows, memory, and TTS adapter.
  • src/lib: shared app services, Payload helpers, auth, billing, RAG, presentation config, and Anuva contracts.
flowchart TB
  subgraph next["⚛️ Next.js app runtime"]
    public["🌐 Public routes"]
    app["🧑‍💻 App routes"]
    api["🔌 Route handlers"]
    payloadAdmin["📦 Payload admin"]
  end

  app --> actions["🧱 Server actions"]
  api --> services["🧰 Shared services"]
  actions --> services
  services --> payload["📦 Payload Local API"]
  payload --> postgres["🗄️ Postgres"]
  services --> mastra["🤖 Mastra runtime"]
  mastra --> postgres
  services --> storage["🪣 S3-compatible storage"]
  services --> providers["✨ AI, email, and billing providers"]

Runtime Dependencies

  • Database: Postgres via DATABASE_URI.
  • Storage: S3-compatible buckets via S3_*.
  • Email: Resend via RESEND_API_KEY.
  • Auth: Better Auth integrated through payload-auth.
  • AI: OpenAI, Google, and ElevenLabs keys are present in the active environment.
  • Billing: Zoho Billing config and webhook processing.

Request Flow

  1. UI routes call server actions in src/app/(frontend)/app/**/actions.ts.
  2. Server actions call requireAuthContext or handleAction from src/lib/server-actions.ts.
  3. Payload Local API reads and writes workspace-scoped collections.
  4. Generation actions either run legacy action logic or call Mastra workflow/tool paths.
  5. Worker scripts pick up queued RAG and presentation generation jobs, and the external Python render worker talks to /api/worker/v1.
sequenceDiagram
  actor User
  participant UI as App route
  participant Action as Server action
  participant Auth as Auth context
  participant Payload as Payload Local API
  participant Worker as Worker or Mastra

  User->>UI: Submit product action
  UI->>Action: Invoke action
  Action->>Auth: Resolve user and workspace
  Action->>Payload: Read/write scoped docs
  Action->>Worker: Queue or run generation path
  Worker->>Payload: Persist status and artifacts

External Render Worker

Final video rendering now has a dedicated worker-facing API under /api/worker/v1. The Next.js app does not expose Payload collections directly to the Python worker. Instead, shared render-worker services:

  • list or claim video_generation_jobs
  • build a RenderJobPackage from persisted PresentationConfigPublic
  • issue signed asset and upload URLs against S3-compatible storage
  • persist latest worker heartbeat state in render_workers
  • persist append-only failure diagnostics in render_worker_reports
flowchart LR
  queue["video_generation_jobs"] --> api["/api/worker/v1"]
  api --> package["RenderJobPackage"]
  api --> workers["render_workers"]
  api --> reports["render_worker_reports"]
  package --> python["Anuva Python Server"]
  python --> unity["Unity renderer"]
  python --> s3["S3-compatible storage"]

Payload Relationship

Payload owns content and app data. Collections are registered in src/payload.config.ts through:

  • Users.
  • AnuvaxCollections.
  • Blog.
  • PayloadUploads.
  • PrivateUploads.

Payload globals are global-footer, global-terms, and global-privacy.

Mastra Relationship

src/mastra/runtime.ts creates a single Mastra instance with:

  • workflow: presentationVideoWorkflow.
  • agents: intent, knowledge, narrative, visual, presentation analyst/planner, director, edit, and anuvaxTextAgent.
  • TTS: anuvaxElevenLabsTts.
  • storage: PostgresStore using the same DATABASE_URI.

The runtime includes recovery code for missing Mastra storage tables.

Data Flow Summary

Presentation generation moves from product input to contracts, scenes, visuals, slide markup, direction, public config snapshots, audio/image tasks, and render/generation jobs. RAG ingestion moves from uploaded media or web source metadata to rag_sources, rag_chunks, and vector records in the anuvax_rag_chunks_v1 index.