# gaurangrshah/plura architecture

> Architecture diagram of the GitHub repository gaurangrshah/plura, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/gaurangrshah/plura
- Repository: https://github.com/gaurangrshah/plura

## Overview

1. **Overall shape**
   - This is a **Next.js 14 App Router** monorepo-style application organized around three user-facing surfaces: a **public marketing site**, a **multi-tenant authenticated dashboard**, and **public domain-based pages** for funnels/content.
   - The app is heavily componentized, with most business features implemented in route-local components under `app/` and shared UI/forms under `components/`.

2. **Route partitioning is the top-level boundary**
   - `app/site` contains the **public marketing site**.
   - `app/(main)` contains the **authenticated product UI**.
   - `app/[domain]/[path]` is a **runtime-resolved public route** for tenant-owned pages, likely used for funnel pages or branded content on custom domains/subdomains.
   - This route split is important for architecture diagrams because it separates **public web traffic**, **logged-in dashboard traffic**, and **tenant-hosted public pages**.

3. **Multi-tenant domain model**
   - The dashboard is split into two major tenant scopes:
     - `app/(main)/agency/[agencyId]` for **agency-level administration**
     - `app/(main)/subaccount/[subaccountId]` for **client/sub-account operations**
   - The agency layer manages higher-order concerns like team, billing, subaccounts, launchpad, and settings.
   - The subaccount layer manages operational features like contacts, pipelines, funnels, media, workflows, and settings.
   - This is the core business boundary: **agency owns and administers multiple subaccounts**.

4. **Authentication and access control**
   - The repo uses **Clerk** for auth, with routes for sign-in/sign-up under `app/(main)/agency/(auth)`.
   - `middleware.ts` indicates request-time protection and route gating, which is a key runtime boundary.
   - There is a dedicated unauthorized screen at `app/(main)/agency/unauthorized` and a shared unauthorized component in `components/unauthorized`.
   - For a diagram, auth should be shown as an **edge/request gate** in front of protected dashboard routes.

5. **Data layer and persistence**
   - Data access is centered in `lib/db.ts`, `lib/queries.ts`, `lib/constants.ts`, and `lib/types.ts`.
   - Persistence uses **Prisma** with `prisma/schema.prisma`, and the README states the backend uses **SQLite locally** and **Turso/libsql in production**.
   - This means the architecture has a single database boundary serving all core product domains: agencies, subaccounts, funnels, workflows, pipelines, contacts, billing metadata, and media records.

6. **Payments and billing subsystem**
   - Billing is isolated under `app/(main)/agency/[agencyId]/billing`.
   - Stripe integration is split between:
     - client/server helpers in `lib/stripe/*`
     - API routes in `app/api/stripe/*`
     - billing UI components such as `pricing-card.tsx` and `subscription-helper.tsx`
   - Data flow here is: **billing UI → Stripe action/API route → Stripe service → webhook → database update**.
   - This is a distinct external-service boundary and should be shown separately from the main app database flow.

7. **File uploads and media subsystem**
   - UploadThing is exposed through `app/api/uploadthing/*` and configured in `lib/uploadthing.ts`.
   - The user-facing media area lives at `app/(main)/subaccount/[subaccountId]/media`, with shared media components in `components/media`.
   - This is another external boundary: **dashboard UI → UploadThing API → stored assets → media library UI**.

8. **Funnel builder is a major product subsystem**
   - Funnel management lives under `app/(main)/subaccount/[subaccountId]/funnels`.
   - The funnel editor is nested deeply under `funnels/[funnelId]/editor/[funnelPageId]` and is composed of:
     - a central editor canvas
     - a sidebar with tabs for components/layers/media/settings
     - recursive render components for page elements
   - The funnel editor supports element types like container, two-column layout, text, link, video, checkout, and contact form, indicating a **block-based page builder**.
   - This subsystem should be diagrammed as a **structured content editor** backed by the database.

9. **Workflow automation subsystem**
   - Workflows live under `app/(main)/subaccount/[subaccountId]/workflows`.
   - The editor uses provider-based state and dedicated UI pieces:
     - canvas
     - sidebar
     - toolbar
     - node settings
     - workflow nodes
   - There is a small action layer in `workflows/_actions/workflow-actions.ts`, suggesting server-side mutations for workflow creation/update.
   - This is a separate builder from funnels: funnels are for page composition, workflows are for automation logic.

10. **Pipeline / CRM subsystem**
   - Pipelines are implemented under `app/(main)/subaccount/[subaccountId]/pipelines`.
   - The feature uses lane/ticket/view/settings components, which implies a **kanban-style deal or lead pipeline**.
   - Contacts live separately under `contacts`, and there are forms for tickets and contacts, so the likely flow is **contacts and leads feed pipeline tickets**.
   - In a diagram, pipelines should be shown as the operational CRM layer connected to subaccount data.

11. **Agency administration features**
   - Agency-level pages cover `team`, `billing`, `all-subaccounts`, `launchpad`, and `settings`.
   - Shared forms such as invitation, agency details, subaccount details, and subscription forms support these admin flows.
   - This layer is where an agency manages tenants, users, and paid plan state rather than end-customer operations.

12. **Shared UI and composition model**
   - `components/ui` is a large shadcn/ui-style base layer used across the app.
   - Feature-specific shared components live in `components/forms`, `components/global`, `components/sidebar`, `components/media`, and `components/site`.
   - The repo uses reusable provider wrappers in `providers/` for theme, modals, workflow editor state, and editor actions.
   - This indicates a design where route pages are thin shells and most interactive behavior is delegated to shared component systems.

13. **Runtime and deployment concerns**
   - The app runs on **Next.js/Vercel**, with `vercel.json` controlling the build command and Sentry configs present for client/edge/server error reporting.
   - `instrumentation.ts` suggests app-level runtime instrumentation is enabled.
   - Because auth middleware and public-domain routing are part of the request path, edge/runtime behavior matters to the system architecture.

14. **What to show in an architecture diagram**
   - The most important boxes are:
     - public site
     - auth gate/middleware
     - agency dashboard
     - subaccount dashboard
     - public domain page renderer
     - Prisma/Turso database
     - Stripe
     - UploadThing
     - funnel editor
     - workflow editor
     - pipeline/contacts CRM
   - The key arrows are:
     - browser/request → middleware → route group
     - route group → server components/actions/queries → database
     - billing UI → Stripe → webhook → database
     - media UI → UploadThing → stored assets
     - editors → provider state + database-backed persistence

Main entry points: [`app/(main)/subaccount/[subaccountId]/page.tsx`](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/page.tsx) (Subaccount hub), [`lib/queries.ts`](https://github.com/gaurangrshah/plura/blob/main/lib/queries.ts) (Queries), [`app/layout.tsx`](https://github.com/gaurangrshah/plura/blob/main/app/layout.tsx) (App shell), [`app/(main)/agency/[agencyId]/page.tsx`](https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/page.tsx) (Agency hub)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_public["Public web"]
  node_n_site["Marketing site<br/>public pages<br/>[page.tsx]"]
  node_n_domain["Tenant pages<br/>public runtime route<br/>[page.tsx]"]
end

subgraph group_grp_app["Authenticated app"]
  node_n_auth["Sign in<br/>Clerk auth<br/>[page.tsx]"]
  node_n_agency_home["Agency hub<br/>agency dashboard<br/>[page.tsx]"]
  node_n_agency_team["Team<br/>agency admin<br/>[page.tsx]"]
  node_n_agency_billing["Billing<br/>[page.tsx]"]
  node_n_sub_home["Subaccount hub<br/>tenant dashboard<br/>[page.tsx]"]
  node_n_contacts["Contacts<br/>CRM<br/>[page.tsx]"]
  node_n_pipelines["Pipelines<br/>kanban CRM<br/>[page.tsx]"]
  node_n_funnels["Funnels<br/>page builder<br/>[page.tsx]"]
  node_n_funnel_editor["Funnel editor<br/>block editor<br/>[page.tsx]"]
  node_n_workflows["Workflows<br/>automation<br/>[page.tsx]"]
  node_n_media["Media library<br/>asset manager<br/>[page.tsx]"]
end

subgraph group_grp_platform["Platform core"]
  node_n_root["App shell<br/>Next.js root<br/>[layout.tsx]"]
  node_n_middleware{{"Auth gate<br/>request middleware<br/>[middleware.ts]"}}
  node_n_queries["Queries<br/>data access<br/>[queries.ts]"]
  node_n_db[("Database<br/>Prisma + libsql<br/>[schema.prisma]")]
end

subgraph group_grp_integrations["External integrations"]
  node_n_stripe{{"Stripe<br/>billing service<br/>[actions.ts]"}}
  node_n_stripe_webhook["Stripe webhook<br/>api route<br/>[route.ts]"]
  node_n_upload{{"UploadThing<br/>media service<br/>[uploadthing.ts]"}}
  node_n_upload_api["Upload API<br/>api route<br/>[route.ts]"]
end

node_n_root -->|"serves"| node_n_site
node_n_root -->|"wraps"| node_n_auth
node_n_root -->|"wraps"| node_n_agency_home
node_n_root -->|"wraps"| node_n_sub_home
node_n_root -->|"serves"| node_n_domain
node_n_middleware -->|"gates"| node_n_auth
node_n_middleware -->|"gates"| node_n_agency_home
node_n_middleware -->|"gates"| node_n_sub_home
node_n_middleware -->|"allows"| node_n_domain
node_n_auth -->|"enters"| node_n_agency_home
node_n_agency_home -->|"navigates"| node_n_agency_team
node_n_agency_home -->|"navigates"| node_n_agency_billing
node_n_agency_billing -->|"charges"| node_n_stripe
node_n_stripe -->|"syncs"| node_n_stripe_webhook
node_n_stripe_webhook -->|"updates"| node_n_db
node_n_agency_team -->|"reads/writes"| node_n_queries
node_n_queries -->|"persists"| node_n_db
node_n_sub_home -->|"navigates"| node_n_contacts
node_n_sub_home -->|"navigates"| node_n_pipelines
node_n_sub_home -->|"navigates"| node_n_funnels
node_n_sub_home -->|"navigates"| node_n_workflows
node_n_sub_home -->|"navigates"| node_n_media
node_n_contacts -->|"reads/writes"| node_n_queries
node_n_pipelines -->|"reads/writes"| node_n_queries
node_n_funnels -->|"opens"| node_n_funnel_editor
node_n_funnel_editor -->|"reads/writes"| node_n_queries
node_n_funnel_editor -->|"saves"| node_n_db
node_n_workflows -->|"reads/writes"| node_n_queries
node_n_workflows -->|"saves"| node_n_db
node_n_media -->|"uploads"| node_n_upload_api
node_n_upload_api -->|"uses"| node_n_upload
node_n_media -->|"lists"| node_n_db
node_n_domain -->|"renders from"| node_n_queries

click node_n_root "https://github.com/gaurangrshah/plura/blob/main/app/layout.tsx"
click node_n_site "https://github.com/gaurangrshah/plura/blob/main/app/site/page.tsx"
click node_n_domain "https://github.com/gaurangrshah/plura/blob/main/app/[domain]/[path]/page.tsx"
click node_n_middleware "https://github.com/gaurangrshah/plura/blob/main/middleware.ts"
click node_n_auth "https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/(auth)/sign-in/[[...sign-in]]/page.tsx"
click node_n_agency_home "https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/page.tsx"
click node_n_agency_team "https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/team/page.tsx"
click node_n_agency_billing "https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/billing/page.tsx"
click node_n_sub_home "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/page.tsx"
click node_n_contacts "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/contacts/page.tsx"
click node_n_pipelines "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/pipelines/page.tsx"
click node_n_funnels "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/funnels/page.tsx"
click node_n_funnel_editor "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/funnels/[funnelId]/editor/[funnelPageId]/page.tsx"
click node_n_workflows "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/workflows/editor/[workflowId]/page.tsx"
click node_n_media "https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/media/page.tsx"
click node_n_queries "https://github.com/gaurangrshah/plura/blob/main/lib/queries.ts"
click node_n_db "https://github.com/gaurangrshah/plura/blob/main/prisma/schema.prisma"
click node_n_stripe "https://github.com/gaurangrshah/plura/blob/main/lib/stripe/actions.ts"
click node_n_stripe_webhook "https://github.com/gaurangrshah/plura/blob/main/app/api/stripe/webhook/route.ts"
click node_n_upload "https://github.com/gaurangrshah/plura/blob/main/lib/uploadthing.ts"
click node_n_upload_api "https://github.com/gaurangrshah/plura/blob/main/app/api/uploadthing/route.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_n_site,node_n_domain toneBlue
class node_n_auth,node_n_agency_home,node_n_agency_team,node_n_agency_billing,node_n_sub_home,node_n_contacts,node_n_pipelines,node_n_funnels,node_n_funnel_editor,node_n_workflows,node_n_media toneAmber
class node_n_root,node_n_middleware,node_n_queries,node_n_db toneMint
class node_n_stripe,node_n_stripe_webhook,node_n_upload,node_n_upload_api toneRose
```

## Components

### Public web

Marketing site and tenant-facing public pages

- [Marketing site](https://github.com/gaurangrshah/plura/blob/main/app/site/page.tsx): public pages · Public site surface for marketing and acquisition · `app/site/page.tsx`
- [Tenant pages](https://github.com/gaurangrshah/plura/blob/main/app/[domain]/[path]/page.tsx): public runtime route · Runtime-resolved public pages by domain and path · `app/[domain]/[path]/page.tsx`

### Authenticated app

Protected agency and subaccount dashboard surfaces

- [Sign in](https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/(auth)/sign-in/[[...sign-in]]/page.tsx): Clerk auth · Authentication entry for protected dashboard access · `app/(main)/agency/(auth)/sign-in/[[...sign-in]]/page.tsx`
- [Agency hub](https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/page.tsx): agency dashboard · Top-level agency administration landing area · `app/(main)/agency/[agencyId]/page.tsx`
- [Team](https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/team/page.tsx): agency admin · Agency team management and invitations · `app/(main)/agency/[agencyId]/team/page.tsx`
- [Billing](https://github.com/gaurangrshah/plura/blob/main/app/(main)/agency/[agencyId]/billing/page.tsx): agency billing · Agency subscription and plan management · `app/(main)/agency/[agencyId]/billing/page.tsx`
- [Subaccount hub](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/page.tsx): tenant dashboard · Primary subaccount workspace landing area · `app/(main)/subaccount/[subaccountId]/page.tsx`
- [Contacts](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/contacts/page.tsx): CRM · Contact management and lead records · `app/(main)/subaccount/[subaccountId]/contacts/page.tsx`
- [Pipelines](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/pipelines/page.tsx): kanban CRM · Deal and lead pipeline operations · `app/(main)/subaccount/[subaccountId]/pipelines/page.tsx`
- [Funnels](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/funnels/page.tsx): page builder · Funnel management and page composition entry · `app/(main)/subaccount/[subaccountId]/funnels/page.tsx`
- [Funnel editor](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/funnels/[funnelId]/editor/[funnelPageId]/page.tsx): block editor · Structured funnel page editor and canvas · `app/(main)/subaccount/[subaccountId]/funnels/[funnelId]/editor/[funnelPageId]/page.tsx`
- [Workflows](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/workflows/editor/[workflowId]/page.tsx): automation · Workflow automation management and editor entry · `app/(main)/subaccount/[subaccountId]/workflows/editor/[workflowId]/page.tsx`
- [Media library](https://github.com/gaurangrshah/plura/blob/main/app/(main)/subaccount/[subaccountId]/media/page.tsx): asset manager · Subaccount media browsing and uploads · `app/(main)/subaccount/[subaccountId]/media/page.tsx`

### Platform core

Shared data access, auth gating, and runtime infrastructure

- [App shell](https://github.com/gaurangrshah/plura/blob/main/app/layout.tsx): Next.js root · Global app layout and shared shell · `app/layout.tsx`
- [Auth gate](https://github.com/gaurangrshah/plura/blob/main/middleware.ts): request middleware · Request-time protection and route gating · `middleware.ts`
- [Queries](https://github.com/gaurangrshah/plura/blob/main/lib/queries.ts): data access · Shared server-side query and mutation layer · `lib/queries.ts`
- [Database](https://github.com/gaurangrshah/plura/blob/main/prisma/schema.prisma): Prisma + libsql · Primary persistence for agencies, subaccounts, funnels, workflows, CRM, and media metadata · `prisma/schema.prisma`

### External integrations

Payment and media service boundaries

- [Stripe](https://github.com/gaurangrshah/plura/blob/main/lib/stripe/actions.ts): billing service · Billing actions and subscription orchestration · `lib/stripe/actions.ts`
- [Stripe webhook](https://github.com/gaurangrshah/plura/blob/main/app/api/stripe/webhook/route.ts): api route · Stripe event ingestion and persistence updates · `app/api/stripe/webhook/route.ts`
- [UploadThing](https://github.com/gaurangrshah/plura/blob/main/lib/uploadthing.ts): media service · Upload configuration and request handling for assets · `lib/uploadthing.ts`
- [Upload API](https://github.com/gaurangrshah/plura/blob/main/app/api/uploadthing/route.ts): api route · UploadThing API endpoint for media transfers · `app/api/uploadthing/route.ts`

## Connections

- App shell → Marketing site: serves · Root shell renders the public marketing surface
- App shell → Sign in: wraps · App shell hosts the sign-in flow
- App shell → Agency hub: wraps · App shell hosts the protected agency dashboard
- App shell → Subaccount hub: wraps · App shell hosts the protected subaccount workspace
- App shell → Tenant pages: serves · App shell also serves runtime-resolved public pages
- Auth gate → Sign in: gates · Middleware protects access to authenticated routes
- Auth gate → Agency hub: gates · Middleware gates agency areas
- Auth gate → Subaccount hub: gates · Middleware gates subaccount areas
- Auth gate → Tenant pages: allows · Public tenant pages are resolved at request time
- Sign in → Agency hub: enters · Successful auth leads into the agency workspace
- Agency hub → Team: navigates · Agency admin surface links to team management
- Agency hub → Billing: navigates · Agency admin surface links to billing
- Billing → Stripe: charges · Billing UI delegates checkout and subscription actions
- Stripe → Stripe webhook: syncs · Stripe events are received through the webhook route
- Stripe webhook → Database: updates · Webhook state is persisted to the database
- Team → Queries: reads/writes · Team admin uses shared server-side data access
- Queries → Database: persists · Queries layer reads and writes the primary database
- Subaccount hub → Contacts: navigates · Subaccount hub links to CRM contacts
- Subaccount hub → Pipelines: navigates · Subaccount hub links to pipelines
- Subaccount hub → Funnels: navigates · Subaccount hub links to funnel management
- Subaccount hub → Workflows: navigates · Subaccount hub links to workflow automation
- Subaccount hub → Media library: navigates · Subaccount hub links to media library
- Contacts → Queries: reads/writes · Contacts are managed through the shared data layer
- Pipelines → Queries: reads/writes · Pipeline lanes and tickets persist through queries
- Funnels → Funnel editor: opens · Funnel management drills into the page editor
- Funnel editor → Queries: reads/writes · Editor state is backed by server persistence
- Funnel editor → Database: saves · Funnel pages and elements are stored in the database
- Workflows → Queries: reads/writes · Workflow builder uses server actions and queries
- Workflows → Database: saves · Workflow definitions persist in the database
- Media library → Upload API: uploads · Media UI sends files through the upload endpoint
- Upload API → UploadThing: uses · API route is configured by UploadThing helpers
- Media library → Database: lists · Media library reads stored asset metadata
- Tenant pages → Queries: renders from · Public tenant pages are assembled from persisted content
