Client Portal Builder
White-label client portal for freelancers and small agencies. Instant setup, custom domains, Stripe payments. Priced under HoneyBook. Weekend MVP guide + prompts.
Freelancers and small agencies invest serious money in front-of-house brand: a clean site, polished proposals, tight case studies. Then the client signs and the experience immediately collapses into Google Drive shared links, a Slack channel, a Loom inbox, and a Notion page. Five tools, four logins, zero cohesion. The perception of professionalism ends the second onboarding starts. The workarounds are worse than they look. Clients forward files to the wrong email. The designer sends a Figma link to a client who does not have Figma. Invoice status lives in Stripe, project timeline lives in a spreadsheet, and revision comments live in whoever's DMs were loudest that week. Every missed file is a billable hour of "where is this?" Every confused client is a reference that does not happen.
Built for Developers, Solo Founders, Freelancers.
Suggested stack: Next.js 14 App Router, Supabase, Vercel Custom Domains API, Stripe Connect (Standard), Resend + custom domain, Tailwind + CSS variables. Weekend scope: about 12 hours.
The Problem
Freelancers and small agencies invest serious money in front-of-house brand: a clean site, polished proposals, tight case studies. Then the client signs and the experience…
The Solution
A white-label, multi-tenant client portal where the setup is 60 seconds and every pixel is brandable. Freelancer signs up, picks a service-type template (design, consulting…
Market Research
57M US freelancers (Upwork 2024), 60%+ earning from 2+ clients. Every one of them needs a delivery surface that is not a shared Google Drive.
Competitive Landscape
HoneyBook — Category leader for creative freelancers. Strong mobile, polished templates, acquired by private equity in 2024. Setup is template-heavy; onboarding measured in hours…
Business Model
Free ($0) — 1 client portal, 1 GB storage, subdomain only (yourname.portal.app), “Powered by” footer
Recommended Tech Stack
Next.js 14 App Router — Middleware inspects the `Host` header and rewrites to `/[tenantSlug]/`. Agency admin at `app.product.com`; client portals at custom domain or…
AI Prompts to Build This
Copy these build prompts into Claude, Cursor, or your AI coding tool. Create a free account to unlock the full research behind them.
1. Multi-Tenant Scaffold
Create a Next.js 14 App Router multi-tenant SaaS for a client portal builder. Supabase backend, Tailwind, TypeScript. Architecture: - Admin app at app.product.com (agency owner dashboard) - Client portals at *.portal.product.com AND on custom agency domains - Next.js middleware inspects Host header. If host is app.product.com -> render admin routes. If host matches a tenant subdomain or custom domain -> rewrite to /[tenantSlug]/portal/... Schema (Supabase Postgres): - tenants(id, slug, custom_domain, brand_logo_url, brand_primary_hex, service_template_type, stripe_account_id, plan, created_at) - memberships(id, tenant_id, user_id, role: 'owner' | 'member' | 'client', created_at) - projects(id, tenant_id, client_membership_id, title, status, created_at) - milestones(id, project_id, title, due_date, status, position) - files(id, project_id, path, size, uploaded_by, created_at) - messages(id, project_id, sender_membership_id, body, created_at) - invoices(id, project_id, stripe_invoice_id, amount_cents, status) RLS: every row scoped by tenant_id AND membership. Owners see everything in their tenant. Clients see only projects they are a member of. Auth: Supabase magic links, no passwords. Client invite email contains a signed URL that auto-joins the client to the project's membership row on click.
2. Custom Domains via Vercel API
Implement custom-domain support end-to-end using the Vercel Domains API. Flow: 1. In /admin/settings/domain the agency owner types their domain (projects.agency.com). 2. Server action calls POST https://api.vercel.com/v10/projects/{PROJECT_ID}/domains with { name: "projects.agency.com" } using VERCEL_API_TOKEN. 3. Vercel returns verification records. Display them to the user: "Add these DNS records to your domain:" - CNAME projects -> cname.vercel-dns.com 4. Poll Vercel's GET /v6/domains/:name/config every 30s; when verified=true, update tenants.custom_domain. 5. Vercel auto-provisions Let's Encrypt SSL within ~60s of verification. In middleware.ts: - For every request, look up tenants WHERE custom_domain = host OR slug = host.split('.')[0] - If found, rewrite URL to /[tenantSlug]/portal/rest - If not found and host !== app.product.com, render a friendly "portal not found" page Do NOT store DNS records in your own DB; always re-fetch from Vercel to avoid drift. Test with a throwaway domain on Cloudflare or Namecheap before shipping.3. Stripe Connect + Service Templates
Two features, one prompt. A) Stripe Connect (Standard accounts): - In /admin/settings/billing, add a "Connect Stripe" button - Redirect to https://connect.stripe.com/oauth/authorize?response_type=code&client_id=CA_xxx&scope=read_write&state= - On callback, exchange code for access_token via POST https://connect.stripe.com/oauth/token; store the account_id in tenants.stripe_account_id - To create an invoice, call Stripe API with Stripe-Account: {account_id} header. The money flows to the agency's Stripe, not yours. - Your platform billing (Solo/Agency $29/$99) is separate: standard Stripe Billing on your own account. B) Service templates (the product's core UX): - When an agency signs up, ask one question: "What do you deliver?" - Options: design, consulting, marketing, coaching, development - Based on the choice, seed the first project with: - design: milestones = [Brief approved, First round, Revisions, Final delivery] - consulting: milestones = [Kickoff, Discovery, Recommendations, Implementation] - marketing: milestones = [Audit, Strategy approved, Campaign live, Reporting] - coaching: milestones = [Intake, Session 1, Mid-point check-in, Session N, Wrap] - development: milestones = [Scope, Spike, Sprint 1, Sprint 2, Launch] - Seed a starter message thread with a welcome message using the agency's logo. - Defaults are the product. Let power users edit them; never force them to build from blank.