Skip to content

Rwb3n/callsheet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CALLSHEET

An autonomous commercial entity operating as a B2B discovery platform for UK broadcast, film, and TV production services.


What Is This?

CALLSHEET is not a product in the traditional sense. It is an autonomous commercial entity β€” a cognitive system instantiated within a legal shell, designed to perceive its environment, make decisions, and procure human or machine resources when it cannot act alone.

The platform (directory, search, matching, subscriptions) is what the entity does. The entity itself is the system that operates the platform.

Domain: UK broadcast/film/TV production services. 7 sectors, 64 service areas, 269 specialisations.

Model: Unified accounts (every user is both buyer and provider). Quality earned, visibility bought. Β£199/Β£399/Β£699 annual tiers.


How It Works β€” The Simple Version

What users see

flowchart LR
    classDef person fill:#e8daef,stroke:#6c3483,color:#1a1a1a
    classDef action fill:#d4efdf,stroke:#1e8449,color:#1a1a1a
    classDef result fill:#d4e6f1,stroke:#2471a3,color:#1a1a1a

    BUYER(["🎬 Production Company<br/><i>needs a camera crew</i>"]):::person

    SEARCH["Search<br/><i>'camera operator London'</i>"]:::action
    RESULTS["See ranked results<br/><i>quality + relevance</i>"]:::action
    PROFILE["View provider profile<br/><i>credits, reviews, trust badge</i>"]:::action
    ENQUIRY["Send enquiry"]:::action
    RESPONSE(["Provider responds<br/><i>connection made βœ“</i>"]):::result

    BUYER --> SEARCH --> RESULTS --> PROFILE --> ENQUIRY --> RESPONSE
Loading
flowchart LR
    classDef person fill:#fef9e7,stroke:#b7950b,color:#1a1a1a
    classDef action fill:#d4efdf,stroke:#1e8449,color:#1a1a1a
    classDef result fill:#d4e6f1,stroke:#2471a3,color:#1a1a1a

    PROVIDER(["πŸŽ₯ Camera Operator<br/><i>wants to be found</i>"]):::person

    CLAIM["Claim or create<br/>their listing"]:::action
    FILL["Add profile, credits,<br/>photos, services"]:::action
    VERIFY["Get verified<br/><i>Companies House check</i>"]:::action
    UPGRADE["Optionally upgrade<br/><i>more photos, priority, analytics</i>"]:::action
    FOUND(["Found by buyers<br/><i>enquiries arrive βœ“</i>"]):::result

    PROVIDER --> CLAIM --> FILL --> VERIFY --> UPGRADE --> FOUND
Loading

How the business works

flowchart TD
    classDef money fill:#d5f5e3,stroke:#1e8449,color:#1a1a1a
    classDef free fill:#d4e6f1,stroke:#2471a3,color:#1a1a1a
    classDef value fill:#fef9e7,stroke:#b7950b,color:#1a1a1a

    subgraph FREE ["Free Tier β€” Everyone gets this"]
        F1["Listed in directory"]
        F2["Appear in search results"]
        F3["Receive enquiries"]
        F4["Basic profile"]
    end
    class FREE free

    subgraph PAID ["Paid Tiers β€” Β£199 / Β£399 / Β£699 per year"]
        P1["More photos & media"]
        P2["Visibility boost in search"]
        P3["Analytics dashboard"]
        P4["Priority placement"]
        P5["Competitor benchmarking"]
    end
    class PAID money

    subgraph ENGINE ["What the system does automatically"]
        E1["Scores quality (0-100) based on<br/>completeness, freshness, accuracy"]:::value
        E2["Detects stale data and<br/>nudges providers to update"]:::value
        E3["Spots churn risk and<br/>intervenes before cancellation"]:::value
        E4["Monitors its own health<br/>and generates reports"]:::value
    end

    FREE -- "conversion nudges<br/>(you got 12 views!)" --> PAID
    PAID -- "revenue funds<br/>the platform" --> ENGINE
    ENGINE -- "better data = better<br/>search = more buyers" --> FREE
Loading

What makes it different from a normal directory

Most directories are databases with a search box. CALLSHEET is designed to run itself.

flowchart LR
    classDef normal fill:#fadbd8,stroke:#922b21,color:#1a1a1a
    classDef cs fill:#d4efdf,stroke:#1e8449,color:#1a1a1a

    subgraph NORMAL ["Typical Directory"]
        N1["Human updates listings"]:::normal
        N2["Human monitors quality"]:::normal
        N3["Human chases renewals"]:::normal
        N4["Human handles support"]:::normal
    end

    subgraph CALLSHEET ["CALLSHEET"]
        C1["System detects stale data<br/>and triggers updates"]:::cs
        C2["System scores quality<br/>across 5 dimensions"]:::cs
        C3["System detects churn risk<br/>and sends win-back offers"]:::cs
        C4["System triages support<br/>and escalates when stuck"]:::cs
    end

    NORMAL -- "replace manual<br/>work with" --> CALLSHEET
Loading

TL;DR: It's a production services directory that watches its own data quality, nudges providers to keep profiles fresh, automatically handles billing/compliance/churn, and only calls a human when it encounters something it can't resolve on its own.


Architecture β€” Under the Hood

The four departments, explained simply

Think of CALLSHEET as a company with four departments. Each department does its own job and talks to the others through a shared noticeboard. Nobody reaches into another department's filing cabinet.

Department Job Example
Data & Listings Owns all the directory records. Scores quality, checks freshness, verifies identities. "This listing hasn't been updated in 6 months β€” flag it."
Operations Processes payments, handles compliance, creates support tickets. "Paddle says this card failed β€” start the grace period."
Platform & Product The website. Search, profiles, dashboards, onboarding, emails. "Someone searched 'camera operator London' β€” show the best matches."
Commercial & Revenue Grows the business. Conversion nudges, churn prevention, pricing. "This free user got 12 enquiries β€” suggest upgrading."

Four autonomous sub-entities coordinate through typed events and query interfaces. No shared mutable state. Each sub-entity is a black box with defined contracts.

graph TB
    classDef domain fill:#d4e6f1,stroke:#2471a3,color:#1a1a1a
    classDef bus fill:#f9e79f,stroke:#b7950b,color:#333
    classDef infra fill:#d5f5e3,stroke:#1e8449,color:#1a1a1a
    classDef external fill:#e8d5b7,stroke:#8b6914,color:#333

    PADDLE["Paddle<br/><i>Billing & Taxes</i>"]:::external
    RESEND["Resend<br/><i>Transactional Email</i>"]:::external
    R2["Cloudflare R2<br/><i>Media Storage</i>"]:::external
    CH["Companies House<br/><i>Verification API</i>"]:::external

    subgraph DL ["Data & Listings"]
        direction TB
        DL1["Listing CRUD & Integrity"]
        DL2["Quality Scoring (5-dim, 0-100)"]
        DL3["Decay Detection & Enrichment"]
        DL4["Verification (4-tier)"]
    end
    class DL domain

    subgraph OPS ["Operations"]
        direction TB
        OPS1["Paddle Webhook Processing"]
        OPS2["Support Triage & Tickets"]
        OPS3["Compliance & GDPR"]
        OPS4["Billing Reconciliation"]
    end
    class OPS domain

    subgraph PP ["Platform & Product"]
        direction TB
        PP1["Search (FTS + Trigram)"]
        PP2["Onboarding & Claim Flows"]
        PP3["Dashboard & Admin Panel"]
        PP4["Email Pipeline"]
    end
    class PP domain

    subgraph CR ["Commercial & Revenue"]
        direction TB
        CR1["Feature Gating & Pricing"]
        CR2["Conversion Triggers (6 types)"]
        CR3["Churn Intervention & Win-back"]
        CR4["Revenue Perception"]
    end
    class CR domain

    EB(["Event Bus β€” 25 Typed Events / ~50 Consumers"]):::bus
    INFRA["Shared Infrastructure<br/><i>Event Bus Β· Scheduler (35 actions) Β· Flow Engine<br/>Decision Logger Β· Email Transport Β· Storage</i>"]:::infra

    DL <-..-> EB
    OPS <-..-> EB
    PP <-..-> EB
    CR <-..-> EB

    PADDLE --> OPS
    PP --> RESEND
    PP --> R2
    DL --> CH
    DL & OPS & PP & CR --> INFRA
Loading
Sub-entity contract summary
Sub-Entity Events Emitted Events Consumed Queries Exposed Autonomous Decisions
Data & Listings 9 4 2 Quality scoring, claim evaluation, decay response, enrichment cadence
Operations 3 10 5 Support triage, task routing, billing reconciliation, compliance scheduling
Platform & Product 9 12 1 Search ranking, onboarding flow, account closure orchestration
Commercial & Revenue 4 8 0 Conversion triggers, churn intervention, win-back eligibility

Data Model

erDiagram
    ACCOUNT ||--o{ LISTING : "0..N manages"
    ACCOUNT ||--o| BUYER_FACET : "always active"
    ACCOUNT ||--o| SUPPRESSION : "comms control"

    LISTING ||--o| VERIFICATION : "4-tier trust"
    LISTING ||--o| QUALITY_SCORE : "5-dim 0-100"
    LISTING ||--o| ENGAGEMENT : "views, searches, enquiries"
    LISTING ||--o{ TAXONOMY_TAG : "sector > area > spec"
    LISTING ||--o{ MEDIA_ITEM : "images, tier-gated"
    LISTING ||--o{ CREDIT : "client endorsements"

    BUYER_FACET ||--o{ SHORTLIST : "max 10"
    BUYER_FACET ||--o{ ENQUIRY : "sent to listings"
    BUYER_FACET ||--o{ SEARCH_HISTORY : "recent + saved"

    ACCOUNT {
        text id "Better Auth (text)"
        string email "verified"
        text_array departments
    }
    LISTING {
        uuid id
        enum entityType "freelancer | company | ..."
        enum claimStatus "unclaimed | claimed | disputed"
        enum subscriptionTier "free | standard | premium | partner"
        enum lifecycleStatus "active | suspended | archived"
    }
    VERIFICATION {
        enum tier "unclaimed > claimed > verified > premium_verified"
        timestamp claimedAt
        int verificationScore
    }
    QUALITY_SCORE {
        int composite "0-100"
        int completeness "0-25"
        int freshness "0-25"
        int accuracy "0-20"
        int richness "0-15"
        int verification "0-15"
    }
Loading
Full schema: 8 schema files, 17 migrations, ~50 tables
src/db/schema/
β”œβ”€β”€ auth.ts              # Better Auth (user, session, verification)
β”œβ”€β”€ accounts.ts          # Account profiles, departments
β”œβ”€β”€ data-and-listings.ts # 25 tables β€” listings, taxonomy, engagement, credits
β”œβ”€β”€ commercial.ts        # commercial_state, churn_analysis_log, sponsored_impressions
β”œβ”€β”€ operations.ts        # support_tickets, task_specs, compliance, billing
β”œβ”€β”€ intelligence.ts      # enrichment_schedules, decay_signals, perception_aggregates
β”œβ”€β”€ correspondence.ts    # correspondence_log, suppressed_emails
└── shared.ts            # domain_events, deferred_actions, orchestrated_flows, decisions

Search & Ranking

PostgreSQL full-text search with synonym expansion, trigram fallback, and a multiplicative ranking formula.

flowchart LR
    classDef input fill:#e8daef,stroke:#6c3483,color:#1a1a1a
    classDef process fill:#d4efdf,stroke:#1e8449,color:#1a1a1a
    classDef formula fill:#fef9e7,stroke:#b7950b,color:#1a1a1a

    Q(["Query"]):::input --> SYN["Synonym<br/>Expansion"]:::process --> FTS["tsvector<br/>@@"]:::process --> RANK:::formula
    FTS -- "0 results" --> TRI["Trigram<br/>Fallback<br/><i>similarity > 0.3</i>"]:::process --> OUT
    RANK --> OUT(["Results"])

    subgraph RANK ["Ranking Formula"]
        F["ts_rank_cd Γ— (1.0 + quality_boost + paid_boost)"]
        QB["quality: composite/100 Γ— 0.5"]
        PB["paid: 0.00 | 0.15 | 0.25"]
    end
Loading

A high-quality free listing beats a low-quality premium listing. Quality is earned, visibility is bought β€” but quality always wins the tiebreak.


Verification & Trust

stateDiagram-v2
    [*] --> Unclaimed : seeded from import
    Unclaimed --> Claimed : owner claims + email verified
    Claimed --> Verified : Companies House match + domain match
    Verified --> PremiumVerified : paid tier + enhanced evidence
    Claimed --> Unclaimed : claim abandoned (90d)

    state Claimed {
        [*] --> AutoApprove : CH active + domain email match
        [*] --> AutoReject : CH dissolved
        [*] --> ManualReview : evidence insufficient
        [*] --> DisputeResolution : competing claim
    }
Loading

Event-Driven Coordination

25 typed domain events connect the four sub-entities. ~50 async consumers react to state changes. No polling, no shared state.

flowchart LR
    classDef dl fill:#d4efdf,stroke:#1e8449,color:#1a1a1a
    classDef ops fill:#d6eaf8,stroke:#2e86c1,color:#1a1a1a
    classDef pp fill:#e8daef,stroke:#6c3483,color:#1a1a1a
    classDef cr fill:#fce4ec,stroke:#c0392b,color:#1a1a1a
    classDef bus fill:#f9e79f,stroke:#b7950b,color:#333

    DL["D&L<br/><i>9 events</i>"]:::dl
    OPS["Ops<br/><i>3 events</i>"]:::ops
    PP["PP<br/><i>9 events</i>"]:::pp
    CR["CR<br/><i>4 events</i>"]:::cr

    EB(["Event Bus"]):::bus

    DL --> EB
    OPS --> EB
    PP --> EB
    CR --> EB

    EB --> DL
    EB --> OPS
    EB --> PP
    EB --> CR
Loading
Key event flows
Trigger Event Key Consumers
User claims listing claim_approved D&L: quality recalc, enrichment upgrade Β· CR: trigger reset, win-back cancel Β· PP: search reindex
Paddle webhook subscription_tier_changed D&L: enrichment cadence adjust Β· PP: feature gates refresh Β· CR: revenue metrics update
Subscription cancelled subscription_ended CR: churn analysis + win-back scheduling Β· PP: downgrade feature access Β· Ops: update records
Quality drops below 40 quality_score_changed CR: low-quality intervention (notification + 30d check)
GDPR erasure erasure_completed PP: purge search indexes Β· CR: anonymise churn logs, cancel win-backs
Listing goes stale decay_signal_detected Ops: create ticket if unreachable Β· Intel: annotate with ticket status

Infrastructure Layer (S0)

Six shared modules that every domain builds on.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Shared Infrastructure                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Event Bus   β”‚  Scheduler   β”‚ Flow Engine  β”‚ Decision Logger β”‚
β”‚  25 events   β”‚  35 actions  β”‚ erasure +    β”‚ typed decisions  β”‚
β”‚  ~50 async   β”‚  self-perp.  β”‚ closure      β”‚ audit trail     β”‚
β”‚  consumers   β”‚  retry logic β”‚ orchestrated β”‚                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚    Email Transport (Resend)  β”‚  Object Storage (R2)          β”‚
β”‚    logging Β· suppression Β·   β”‚  upload Β· download Β· variants  β”‚
β”‚    bounce handling Β· DSAR    β”‚  WebP processing via sharp     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Intelligence Layer (S9)

The entity's perception, learning, and autonomy systems.

flowchart TD
    classDef perception fill:#d4efdf,stroke:#1e8449,color:#1a1a1a
    classDef decision fill:#fef9e7,stroke:#b7950b,color:#1a1a1a
    classDef learning fill:#e8daef,stroke:#6c3483,color:#1a1a1a
    classDef action fill:#d6eaf8,stroke:#2e86c1,color:#1a1a1a

    subgraph PERCEIVE ["Perception"]
        QS["Quality Scoring<br/><i>5 dimensions, 0-100</i>"]:::perception
        DECAY["Decay Detection<br/><i>website, email, CH, social, postcode</i>"]:::perception
        ANALYTICS["Analytics Pipeline<br/><i>search terms, demographics,<br/>competitor bench, enquiry response</i>"]:::perception
    end

    subgraph DECIDE ["Intelligence"]
        L["Learning Hypotheses<br/><i>L1-L7 measurement</i>"]:::decision
        CHURN["Proactive Churn<br/><i>engagement decline + billing signals</i>"]:::decision
        REVENUE["Revenue Health<br/><i>8-metric extended perception</i>"]:::decision
    end

    subgraph ACT ["Action"]
        CEREMONY["12 Ceremony Handlers<br/><i>taxonomy review, data health,<br/>principal briefing, etc.</i>"]:::action
        ENRICH["Enrichment Scheduling<br/><i>tiered cadence by verification</i>"]:::action
        INTERVENE["Interventions<br/><i>churn, quality, conversion</i>"]:::action
    end

    PERCEIVE --> DECIDE --> ACT
    ACT -.-> |"feedback"| PERCEIVE
Loading

Codebase at a Glance

callsheet/
β”‚
β”œβ”€β”€ 0-strategic-frame/           # Entity architecture frame, output style guides
β”œβ”€β”€ 1-investigation/             # 14 research deliverables (LOCKED)
β”œβ”€β”€ 2-concept-design/            # 5 domain specs, 341 stress-test scenarios
β”‚   └── diagrams/                # 38 Mermaid diagrams (technical + plain English)
β”œβ”€β”€ 3-requirements/              # 11 slices (v2), 5 interface specs, 693 AC
β”œβ”€β”€ 4-work-management/           # 82 work items, 93 retros, epochs/arcs/chapters
β”œβ”€β”€ 5-launch-readiness/          # Deployment readiness tracker
β”‚
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                     # Next.js 16 pages (24 routes)
β”‚   β”‚   β”œβ”€β”€ admin/               # 8-page admin panel
β”‚   β”‚   β”œβ”€β”€ dashboard/           # Provider + buyer dashboard
β”‚   β”‚   β”œβ”€β”€ search/              # Full-text search with facets
β”‚   β”‚   β”œβ”€β”€ providers/[slug]/    # SSG + ISR listing profiles
β”‚   β”‚   └── api/                 # tRPC, auth, webhooks
β”‚   β”‚
β”‚   β”œβ”€β”€ server/
β”‚   β”‚   β”œβ”€β”€ routers/             # 31 tRPC routers (20 domain + 10 admin + root)
β”‚   β”‚   └── trpc.ts              # Context, middleware, procedures
β”‚   β”‚
β”‚   β”œβ”€β”€ domains/
β”‚   β”‚   β”œβ”€β”€ data-and-listings/   # Quality, decay, analytics, consumers
β”‚   β”‚   β”œβ”€β”€ commercial/          # Pricing, conversion, churn, win-back
β”‚   β”‚   β”œβ”€β”€ operations/          # Paddle, billing, compliance, support
β”‚   β”‚   β”œβ”€β”€ intelligence/        # Ceremony handlers, perception consumers
β”‚   β”‚   └── platform/            # Buyer UX, dashboard, enquiry, reminders
β”‚   β”‚
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ events/              # Event bus + singleton + types
β”‚   β”‚   β”œβ”€β”€ scheduler/           # 35 deferred action handlers
β”‚   β”‚   β”œβ”€β”€ flows/               # Orchestrated flow engine
β”‚   β”‚   β”œβ”€β”€ email/               # Resend transport + logging
β”‚   β”‚   └── services/            # DI container (AppServices)
β”‚   β”‚
β”‚   └── db/
β”‚       β”œβ”€β”€ schema/              # 8 schema files (~50 tables, 17 migrations)
β”‚       └── seed/                # Taxonomy (7/64/269) + demo data
β”‚
β”œβ”€β”€ drizzle/                     # Migration SQL files
β”œβ”€β”€ e2e/                         # Playwright API-level tests
└── .claude/skills/              # 12 AI agent pipeline skills

Test Suite

703 unit tests        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘  40%
1,013 integration     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘  59%
7 E2E (API-level)     β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘   1%
─────────────────────────────────────────────────────
1,723 total           All passing. 0 type errors.

Integration tests run against a real Postgres instance (Supabase local). No mocked databases.


Build Sequence

The platform was built in 11 vertical slices, each stress-tested with 20+ boundary scenarios before implementation.

S0  Infrastructure    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  52 AC   Event bus, scheduler, flow engine, email, storage
S1  Data Model        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  42 AC   Schema, search, CRUD, integrity, consumers
S2  Onboarding        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  41 AC   Account creation, listing creation, CH lookup
S3  Claim & Verify    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  48 AC   Claim evaluation, approval/rejection, disputes
S4  Subscriptions     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  50 AC   Paddle webhooks, feature gating, downgrade
S5  Provider Exp      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  46 AC   Dashboard, enquiry inbox, profile strength
S6  Buyer Exp         β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  52 AC   Search page, shortlists, buyer dashboard
S7  Operations        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 101 AC   Admin panel, compliance, billing, health
S8  Commercial        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  93 AC   Conversion, churn, win-back, revenue
S9  Entity Intel      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 101 AC   Quality scoring, decay, analytics, learning
S10 Hardening         β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  72 AC   Not yet decomposed
    Presentation      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  35 AC   tRPC wiring, UI components, search page

Tech Stack

Layer Technology Why
Framework Next.js 16 App Router, RSC, ISR, API routes
Language TypeScript 5.9 (strict) Zero any, zero type errors
API tRPC 11 End-to-end type safety, batch requests
Database PostgreSQL via Supabase Full-text search, pg_trgm, JSONB
ORM Drizzle Type-safe schema, migrations, $type<T>() for JSONB
Auth Better Auth Email/password, session management
Payments Paddle Merchant of record, webhook-driven
Email Resend Transactional email with bounce handling
Storage Cloudflare R2 S3-compatible, WebP variant generation
Styling Tailwind v4 + shadcn/ui CSS-first config, Radix primitives
Testing Vitest + Playwright Unit + real-DB integration + API-level E2E
Hosting Vercel Edge-ready, ISR support
Target cost ~Β£36/month Supabase free + Vercel free + R2 free tier + Resend free

Getting Started

# Prerequisites: Node.js 20+, Docker (for Supabase local)

# 1. Clone and install
git clone https://github.com/Rwb3n/callsheet.git
cd callsheet
npm install

# 2. Start local Supabase
npx supabase start

# 3. Set up environment
cp .env.example .env.local
# DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres

# 4. Push schema + seed
drizzle-kit push
npm run db:custom-sql
npm run db:seed
npm run db:seed-demo

# 5. Run
npm run dev          # http://localhost:3000

# 6. Test
npm run test              # 703 unit tests
npm run test:integration  # 1,013 integration tests (needs Supabase running)
npm run typecheck         # 0 errors
Nuclear reset
npm run db:reset    # supabase reset β†’ drizzle push β†’ custom-sql β†’ seed β†’ seed-demo
npm run dev:demo    # db:reset + dev server

Architecture Diagrams

38 Mermaid diagrams in two versions β€” technical and plain English. All render natively on GitHub.

# Technical Plain English
1 Macro Topology The Big Picture
2 Entity Relationships Users and Listings
3 Procurement Engine How the System Hires Humans
4 Paddle Webhooks What Happens When Someone Pays
5 Search & Ranking How Search Works
6 GDPR Erasure Deleting Someone's Data
7 Event Consumer Matrix Department Notifications
8 Verification Escalation How Trust Builds
9 Decay & Enrichment Keeping Data Fresh
10 Scheduler (35 actions) The Task Scheduler
11 Support Triage Support Requests
12 Claim Volume Claim Capacity
13 Onboarding Paths Three Paths to a Listing
14 Conversion Funnel Converting Free to Paid
15 Churn & Win-back When Someone Cancels
16 S0 Infrastructure The Six Shared Tools
17 Comms Pipeline Email End to End
18 Integrity & Taxonomy Listing Quality Checks
19 Search Infrastructure Search Under the Hood

Project Phases

Phase 0 β€” Strategic Frame        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  ACTIVE
Phase 1 β€” Investigation          β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  COMPLETE (LOCKED)
Phase 2 β€” Concept Design         β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  COMPLETE (341 scenarios)
Phase 3 β€” Requirements           β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  COMPLETE (11 slices, 693 AC)
Phase 4 β€” Work Management        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  ACTIVE (82 work items)
Phase 5 β€” Launch Readiness       β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘  PENDING

Key Design Decisions

Decision Choice Rationale
Account model Unified (buyer + provider) Every user is both. Provider is opt-in facet.
Sub-entity boundaries 4 autonomous domains Black-box composability. Typed contracts only.
Search PostgreSQL FTS + pg_trgm Good enough until 10-20K listings. Service layer abstracts.
Ranking Quality Γ— relevance + paid boost Quality earned (0-100 composite), visibility bought (tier multiplier).
Pricing Β£199 / Β£399 / Β£699 annual Standard / Premium / Partner. Freelancer discount considered.
Verification 4-tier (Unclaimed β†’ Premium Verified) Companies House API automated. Progressive trust.
Events In-process TypeScript bus ~50 async consumers via waitUntil(). Migrate at >30% request duration.
Transactions Orchestrated flows + event reactions No distributed transactions. Erasure/closure are stepped flows.

Settled β€” Not Open for Discussion

These decisions are final. The rationale is documented in entity-architecture-frame.md and concept design specs.

  • Modular monolith (extract when bottlenecks demand)
  • Domain events as primary coordination mechanism
  • Application-level in-process event bus
  • TypeScript const exports for schema versioning
  • Sub-entity composability as a hard constraint
  • No shared mutable state across domain boundaries

License

Proprietary. All rights reserved.


Built by an autonomous entity, for autonomous entities.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages