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.
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)
| 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 |
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.
├── 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
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 |
Startup Submission
- Authenticated user fills
dashboard/submitform - Logo and display image uploaded to Convex Storage, URLs stored
createStartupmutation runs —approved: false,status: "draft"by default- Email sent to admin notifying of new listing
- Admin approves via admin subdomain →
approved: true,status: "published" - 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/demoHistoryon the startup record — visible as leads indashboard/leads
Payment (Paystack)
- User selects a plan on
/pricing initializePaymentaction creates a pending transaction and returns a Paystack authorization URL- User is redirected to Paystack checkout
- On success, Paystack redirects back to
/transaction/callback verifyPaymentaction confirms the transaction with Paystack, marks transactioncompleted, and updates the user's subscription fields
Onboarding Flow (first login)
- Select occupation (Founder / Operator / Investor / Advisor)
- Role-specific questions (e.g. investment sectors for investors, roles worked for operators)
- "How did you hear about us?"
- Join community confirmation
- Dashboard unlocked
- Node.js 18+
- A Convex account
- A Clerk account
- A Paystack account (for payments)
- A Brevo account (for email/CRM)
npm installnpx convex devThis starts the Convex development server, creates a project, and generates convex/_generated/. Keep this running alongside the Next.js dev server.
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 toIn your Clerk dashboard:
- Set the JWT issuer to match your Convex deployment domain — this is what
convex/auth.config.tsreferences. - Create a webhook pointing to
https://<your-convex-http-url>/clerkand enable these events:user.createduser.updateduser.deleted
- 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.
npm run devThe 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).
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.
The app is deployed on Vercel. The vercel.json includes a redirect from the apex domain (builderscabal.com) to www.builderscabal.com.
For production:
- Add all environment variables from
.env.localto your Vercel project settings - Run
npx convex deployto push the Convex backend to production - Ensure Clerk is configured with production keys and the production webhook URL
- Update
convex/auth.config.tswith the production Clerk domain if it differs from development
| 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.
npm run dev # Start Next.js dev server
npm run build # Production build
npm run start # Start production server
npm run lint # Run ESLintRun alongside Convex:
npx convex dev # Start Convex dev server (required for local development)
npx convex deploy # Deploy Convex backend to production