A VC-focused startup intelligence SaaS platform built with React, TypeScript, and Supabase.
- Frontend: React 18, TypeScript, Vite, Tailwind CSS
- UI Components: shadcn/ui, Radix UI primitives
- Backend: Supabase (PostgreSQL, Edge Functions, Auth)
- Payments: Stripe (subscriptions, one-time purchases)
- Data Pipeline: Zyte API (web scraping), Google Gemini AI (enrichment)
src/
├── components/
│ ├── billing/ # Upgrade modals, CSV export CTA
│ ├── dashboard/ # Startup grid, cards, filters, hero
│ ├── layout/ # Header, navigation
│ └── ui/ # shadcn/ui components
├── hooks/
│ ├── useAuth.tsx # Authentication context
│ ├── useBilling.tsx # Subscription management
│ ├── useCredits.tsx # Credit deduction logic
│ ├── useProfile.tsx # User profile context
│ └── useStartups.tsx # Startup data fetching
├── pages/
│ ├── Index.tsx # Main dashboard
│ ├── Auth.tsx # Login/signup with invite codes
│ └── Billing.tsx # Subscription management
├── integrations/
│ └── supabase/ # Supabase client & types
└── config/
└── billing.ts # Plan definitions, credit costs
supabase/
├── functions/
│ ├── scrape-startups/ # 2x daily data scraping
│ ├── enrich-startup/ # AI-powered data enrichment
│ ├── create-checkout/ # Stripe checkout sessions
│ ├── stripe-webhook/ # Payment event handling
│ ├── deduct-credits/ # Server-side credit deduction
│ └── ... # Other edge functions
└── config.toml # Supabase configuration
- Invite code required for signup (no public registration)
- Email confirmation flow with resend functionality
- Protected profile fields (credits, subscription tier)
- 1 credit per startup detail view
- 5 credits for CSV export
- Server-side deduction via
deduct_user_creditsRPC - Low credit warnings at ≤50 and ≤10 credits
- Pagination: 20 startups per page with "Load More"
- Blurred overlay for unauthenticated users (after 4th startup)
- Three card tabs: Market (default), Predictive AI, Team
- Bootstrapped startups exempt from date-based filtering
- Geography (country, city)
- Business Model (B2B/B2C, target customer)
- Team & Signal (founder type, FAANG alumni, prior exits)
- Capital Efficiency (funding bands, runway, burn multiple)
- Sectors (AI/ML, Fintech, Healthcare, etc.)
- Funding Type (Bootstrapped listed first)
profiles- User data with credits and subscription tierstartups- Company data with VC intelligence fieldsfunding_rounds- Funding history per startupfavorites- User bookmarks with notesinvite_codes- Single-use signup codescredit_transactions- Usage logging
- RLS policies on all tables
secure_profile_updatetrigger protects billing fieldsadmin_update_profileRPC for server-side updates- Service role required for credit operations
SUPABASE_URL
SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET
ZYTE_API_KEY
GEMINI_API_KEY # Get free at https://aistudio.google.com/app/apikey
The startup enrichment uses Google Gemini API which offers a generous free tier:
- Free: 15 requests/minute, 1 million tokens/day
- Fast: Gemini 1.5 Flash is optimized for speed
- Reliable: Google's infrastructure
Get your free API key at: https://aistudio.google.com/app/apikey
- Node.js 18+
- npm or bun
# Install dependencies
npm install
# Start development server
npm run devEdge functions are deployed automatically when code is pushed. Functions are located in supabase/functions/.
scrape-startupsfunction runs via cron- Sources: TechCrunch, SEC Filings, StarterStory, ProductHunt, VentureBeat, Startups.gallery, etc.
- Uses Zyte API for automatic data extraction
- Detects new startups and funding round updates
enrich-startupfunction processes new/updated startups- Uses Google Gemini 1.5 Flash for VC intelligence analysis (free tier available)
- Generates: team scores, unicorn probability, PMF score
- Populates: founder background, traction, unit economics
| Plan | Monthly Credits | Price |
|---|---|---|
| Starter | 500 | $249/mo |
| Growth | 1,000 | $499/mo |
| Scale | Unlimited | $899/mo |
checkout.session.completed- New subscriptioncustomer.subscription.updated- Plan changescustomer.subscription.deleted- Cancellationinvoice.payment_succeeded- Credit pack purchases
The enforce_secure_profile_update trigger prevents direct modification of credits_remaining and subscription_tier. All billing operations must use:
SELECT admin_update_profile(user_id, new_credits, new_tier);const { success, creditsRemaining } = await deductCredits('view_startup', {
description: 'Viewed startup details',
resourceId: startupId
});// Get fresh session to avoid stale tokens
const { data: { session } } = await supabase.auth.getSession();
const userId = session?.user?.id;
// Use service role for admin operations
const serviceClient = createClient(supabaseUrl, serviceRoleKey);
await serviceClient.rpc('admin_update_profile', { ... });Uses HSL color tokens defined in src/index.css:
--primary/--primary-foreground--secondary/--secondary-foreground--muted/--muted-foreground--accent/--accent-foreground
Typography: Libre Baskerville for headers, Geist Sans for body.
- Frontend: Vercel (
vercel.jsonhandles SPA routing) - Backend: Supabase Edge Functions (auto-deploys)
Proprietary - All rights reserved.
