Skip to content

Repository files navigation

BuildersCabal

BuildersCabal is a startup directory and community platform for the African startup ecosystem. It connects founders, operators, investors, and advisors — giving founders tools to list their startups, track engagement, share pitch decks and demos, and generate investor leads, while giving the broader community a searchable, curated directory of African startups.

What the App Does

For Founders & Operators

  • Submit a startup listing (name, tagline, description, logo, display image, social links)
  • Upload a pitch deck (PDF) — optionally password-protected — and track every person who views it
  • Upload a demo video — same protection and tracking capabilities
  • Log monthly traction metrics (revenue growth rate, retention rate, customers acquired, active users)
  • View analytics: upvotes, profile views, website click-throughs, and deck/demo viewer history (leads)

For Investors & Advisors

  • Browse and search the startup directory, filtered by sector, category, or industry
  • Upvote startups to surface quality listings
  • Access pitch decks and demos with gated viewing (lead capture gate collects name, email, role)

For Everyone

  • Multi-role onboarding that personalises the experience based on occupation (Founder, Operator, Investor, Advisor)
  • Partner offers/discounts from ecosystem tools
  • Community resources (documents, videos)
  • Subscription plans: Launch (free, limited listing) and Accelerate (paid, full feature set)

Tech Stack

Layer Tool
Framework Next.js 14 (App Router)
Database & Backend Convex (real-time reactive database + serverless functions)
Authentication Clerk
Payments Paystack (NGN + USD)
Email/CRM Brevo (contact sync + transactional email)
UI Components shadcn/ui + Radix UI primitives
Styling Tailwind CSS
Animation Framer Motion
State Jotai
Form handling React Hook Form + Zod
File storage Convex Storage (via @xixixao/uploadstuff)
Charts Recharts
Deployment Vercel

Architecture Overview

The app runs as a single Next.js codebase with subdomain routing handled in middleware. Three distinct portals share one deployment:

www.builderscabal.com       → Main app  (app/(root)/...)
admin.builderscabal.com     → Admin portal (app/(sub-domains)/admin/...)
volunteers.builderscabal.com → Volunteer portal (app/(sub-domains)/volunteers/...)

middleware.ts detects the host header and rewrites paths so each subdomain serves the correct route group, all behind Clerk auth.

Convex acts as both the database and the backend. All mutations, queries, and actions live in convex/. The frontend talks directly to Convex via useQuery / useMutation — no separate API server needed. HTTP endpoints in convex/http.ts handle Clerk webhooks (user sync) and CORS-gated cross-domain queries for the subdomains.

Auth flows through Clerk, which is bridged into Convex via ConvexProviderWithClerk (see providers/ConvexClerkProvider.tsx). When a user is created or updated in Clerk, a webhook fires to /clerk on the Convex HTTP router, which syncs the user into the users table.

Repository Structure

├── app/
│   ├── (auth)/                  # Sign-in / sign-up pages
│   ├── (root)/                  # Main site
│   │   ├── page.tsx             # Homepage — startup directory
│   │   ├── [name]/              # Public startup profile page
│   │   ├── startups/            # Full startup listing browse page
│   │   ├── pricing/             # Subscription pricing page
│   │   ├── dashboard/           # Authenticated user dashboard
│   │   │   ├── page.tsx         # Dashboard home + onboarding flow
│   │   │   ├── submit/          # Submit a new startup listing
│   │   │   ├── startup/[id]/    # Edit startup listing
│   │   │   ├── startup/traction/[id]/  # Metrics / traction tracking
│   │   │   ├── startup/preview/ # Preview a listing before publishing
│   │   │   ├── decks/           # Manage pitch decks
│   │   │   ├── demos/           # Manage demo videos
│   │   │   ├── leads/           # View deck/demo viewer leads
│   │   │   ├── offers/          # Partner offers & discounts
│   │   │   ├── resources/       # Community resources
│   │   │   ├── billing/         # Subscription & billing
│   │   │   └── settings/        # Profile, password, notifications
│   │   └── transaction/callback/ # Paystack payment callback
│   └── (sub-domains)/
│       ├── admin/               # Admin portal (approve listings, manage content)
│       └── volunteers/          # Volunteer portal (onboarding, guidelines, roles)
├── convex/                      # All backend logic
│   ├── schema.ts                # Database schema (all tables defined here)
│   ├── startups.ts              # Startup CRUD, metrics, deck/demo management
│   ├── users.ts                 # User CRUD, subscription recording
│   ├── paystack.ts              # Payment initialization & verification
│   ├── brevo.ts                 # Brevo contact sync
│   ├── sendEmail.ts             # Email notifications (nodemailer)
│   ├── http.ts                  # Webhook handler + HTTP API endpoints
│   ├── auth.config.ts           # Clerk JWT config for Convex
│   ├── plans.ts                 # Subscription plan queries
│   ├── transactions.ts          # Transaction records
│   ├── partners.ts              # Partner listings
│   ├── resources.ts             # Community resources
│   ├── volunteers.ts            # Volunteer records
│   └── sectors|categories|industries.ts  # Taxonomy tables
├── components/                  # Shared React components
│   ├── ui/                      # shadcn/ui primitives
│   ├── dashboard/               # Dashboard-specific components
│   ├── website-ui/              # Main site header/footer
│   ├── volunteer-ui/            # Volunteer portal UI
│   └── cabal-ui/                # Custom branded components
├── providers/
│   └── ConvexClerkProvider.tsx  # Auth bridge (Clerk + Convex)
├── middleware.ts                # Subdomain routing + auth protection
├── constants/
│   ├── index.ts                 # App-wide constants
│   └── schema.ts                # Zod validation schemas
└── types/index.ts               # Shared TypeScript types

Database Schema

All tables are defined in convex/schema.ts.

Table Purpose
users All accounts. Stores role (founder, operator, investor, advisor), onboarding state, notification preferences, and Paystack subscription details
startups Startup listings. Tracks views, upvotes, website clicks, pitch deck, demo, traction metrics, and viewer history (leads)
transactions Paystack payment records — linked to a user and plan
plans Available subscription plans with Paystack plan codes
partners Ecosystem partners with discount codes and links
volunteers Volunteer records linked to user accounts
resources Community resources (files, videos) with view tracking
sectors Taxonomy: e.g. Fintech, Healthtech
categories Taxonomy: e.g. B2B, B2C
industries Taxonomy: e.g. Agriculture, Education

Key Flows

Startup Submission

  1. Authenticated user fills dashboard/submit form
  2. Logo and display image uploaded to Convex Storage, URLs stored
  3. createStartup mutation runs — approved: false, status: "draft" by default
  4. Email sent to admin notifying of new listing
  5. Admin approves via admin subdomain → approved: true, status: "published"
  6. Listing appears in public directory

Pitch Deck / Demo Gating

  • Founder uploads file or pastes embed URL
  • Can toggle visibility (showDeck / showDemo) and enable password protection
  • Public viewers who attempt to access are prompted for contact details
  • Details saved as deckHistory / demoHistory on the startup record — visible as leads in dashboard/leads

Payment (Paystack)

  1. User selects a plan on /pricing
  2. initializePayment action creates a pending transaction and returns a Paystack authorization URL
  3. User is redirected to Paystack checkout
  4. On success, Paystack redirects back to /transaction/callback
  5. verifyPayment action confirms the transaction with Paystack, marks transaction completed, and updates the user's subscription fields

Onboarding Flow (first login)

  1. Select occupation (Founder / Operator / Investor / Advisor)
  2. Role-specific questions (e.g. investment sectors for investors, roles worked for operators)
  3. "How did you hear about us?"
  4. Join community confirmation
  5. Dashboard unlocked

Local Development Setup

Prerequisites

1. Install dependencies

npm install

2. Set up Convex

npx convex dev

This starts the Convex development server, creates a project, and generates convex/_generated/. Keep this running alongside the Next.js dev server.

3. Configure environment variables

Create a .env.local file at the root. You need the following variables:

# Convex
CONVEX_DEPLOYMENT=          # from `npx convex dev` output
NEXT_PUBLIC_CONVEX_URL=     # e.g. https://<slug>.convex.cloud
NEXT_PUBLIC_CONVEX_HTTP_URL= # e.g. https://<slug>.convex.site

# Origin URLs (used for CORS in Convex HTTP endpoints)
CLIENT_ORIGIN=http://localhost:3000
ADMIN_CLIENT_ORIGIN=http://admin.localhost:3000
VOLUNTEER_CLIENT_ORIGIN=http://volunteers.localhost:3000
NEXT_PUBLIC_CLIENT_ORIGIN=http://localhost:3000

# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=   # from Clerk dashboard
CLERK_SECRET_KEY=                    # from Clerk dashboard
CLERK_WEBHOOK_SECRET=                # from Clerk webhook setup (see below)

NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/dashboard
NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL=/dashboard

# Paystack
PAYSTACK_SECRET_KEY=    # sk_test_... for dev
PAYSTACK_PUBLIC_KEY=    # pk_test_... for dev

# Brevo
BREVO_API_KEY=
BREVO_LIST_ID=          # numeric ID of the contact list to add signups to

4. Configure Clerk

In your Clerk dashboard:

  1. Set the JWT issuer to match your Convex deployment domain — this is what convex/auth.config.ts references.
  2. Create a webhook pointing to https://<your-convex-http-url>/clerk and enable these events:
    • user.created
    • user.updated
    • user.deleted
  3. Copy the webhook signing secret into CLERK_WEBHOOK_SECRET.

For subdomain auth to work locally you'll need to configure allowed origins in Clerk to include localhost:3000 variants.

5. Start the development server

npm run dev

The app runs on http://localhost:3000. The admin and volunteer portals require subdomain routing — for local testing, tools like /etc/hosts aliases or a proxy (e.g. Caddy) are needed to simulate admin.localhost and volunteers.localhost, or you can test those routes directly by prepending the subdomain path (the middleware rewrites them as path prefixes internally).

6. Seed taxonomy data

The directory filters (sectors, categories, industries) need data in their tables. Insert records via the Convex dashboard (https://dashboard.convex.dev) or write a seed script that calls the relevant mutations.

Deployment

The app is deployed on Vercel. The vercel.json includes a redirect from the apex domain (builderscabal.com) to www.builderscabal.com.

For production:

  1. Add all environment variables from .env.local to your Vercel project settings
  2. Run npx convex deploy to push the Convex backend to production
  3. Ensure Clerk is configured with production keys and the production webhook URL
  4. Update convex/auth.config.ts with the production Clerk domain if it differs from development

Subscription Plans

Plan Price Key Features
Launch Free 1 startup listing, basic analytics, limited lead access
Accelerate $47/mo or $32/mo (annual) Up to 3 listings, pitch deck & demo uploads, full lead generation, password protection, engagement reports

Payments are processed via Paystack. The plan codes stored in the plans table must match the plan codes created in your Paystack dashboard.

Scripts

npm run dev      # Start Next.js dev server
npm run build    # Production build
npm run start    # Start production server
npm run lint     # Run ESLint

Run alongside Convex:

npx convex dev   # Start Convex dev server (required for local development)
npx convex deploy  # Deploy Convex backend to production

About

The most impactful community of African builders making products that solve real problems.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages