Table of Contents
Why a portal beats email
Three things change the moment a client lands on a branded portal instead of a Notion page or an email thread.
They stop asking "any updates?" because the answer is on the dashboard. They stop losing files because there's one place. And they stop comparing you to other freelancers, because you look like a software company that also does the work.
The third one is what lets you raise rates. A portal is a brand asset.
The 5 features that matter
Skip portals with 50 features. Five do almost all the work:
1. Project list with status (Discovery / In progress / Review / Shipped).
2. File library, scoped per project (PDFs, mockups, exports).
3. Approval workflow — client clicks Approve on a deliverable, you get notified.
4. Invoices — view, download, pay (Stripe).
5. Notes / messages — one thread per project, not 15 emails.
Anything else is icing. Build the cake first.
Note
If your business has a sixth thing your clients always ask about (e.g. timesheets for hourly work, brand guidelines for design retainers), add it. Otherwise — five.
Step 1 · Scaffold the portal (10 min)
One prompt creates the whole shell. Replace the bracketed bits with your business.
Build a client portal for <my agency, FabricLabs>. Pages: /login, /dashboard (list of projects with status badge), /project/:id (file list, notes thread, approvals list, invoice list). Use the built-in email and password auth. Persist projects, files, notes, invoices to D1. Include a settings page where the agency owner can add new clients and assign projects to them. Brand it dark with violet accents.
Ready to Build?
Start building your full-stack application with Fabricate. Free tier available — no credit card required.
Start Building FreeStep 2 · Per-client auth (20 min)
By default every signed-in user sees everything. You want each client to see only their own projects.
Important
Test the cross-client block before you onboard a real client. Open the portal as Client A, then in another browser as Client B. If you can read each other's files, the filter isn't applied — re-prompt Fabricate to enforce it on every endpoint.
Add a `clientId` column to projects, files, notes, and invoices in D1. On every read endpoint, filter by `clientId === currentUser.clientId`. Add an admin role on the users table that can see everything and assign clientId on user invite. Block non-admins from any cross-client read.
Step 3 · Files + approvals (30 min)
Files go to Cloudflare R2 (Fabricate wires this for you). The approval workflow is one boolean column + a notification.
Add file upload to /project/:id using R2 storage, scoped by clientId + projectId. Show a list of files with download links. Add a `deliverables` table: title, fileId, status (pending | approved | changes_requested), client_comment. On the client side, an Approve button sets status=approved and emails me via Resend. On the agency side, I can see all pending approvals on the dashboard.
Step 4 · White-label it (20 min)
Two changes turn 'a Fabricate app' into 'your portal':
1. Custom domain. In the Fabricate project settings → Custom domain → add `clients.youragency.com` and follow the CNAME instructions. ~10 minutes including DNS propagation.
2. Logo + colour. Drop your logo into the project, then prompt: "Replace the placeholder logo on the sidebar and login page with /assets/logo.svg. Use my brand violet (#6D28D9) as the primary accent."
Tip
Custom domain is a Pro feature. If you're on Free, do steps 1–3 first to make sure the portal works, then upgrade just before onboarding your first client.
Ready to Build?
Start building your full-stack application with Fabricate. Free tier available — no credit card required.
Start Building FreeStep 5 · Migrate your first client (1 hour)
Pick the client most likely to love it — usually the one who emails you the most often. Email them: "I've built a private portal for our work — projects, files, approvals, invoices. Sending you a login now. Same fee, less email."
Copy their existing project status from Notion / spreadsheets / wherever, upload the last three deliverables to the portal, and post one note in the messages thread saying "All your stuff is here from now on." That's the migration.
Repeat for client 2 and 3 over the next week. By client 5 the migration takes 20 minutes.
How to charge for it
You have two pricing moves once the portal is real.
• Bundle it. Add 10–20% to your retainer next renewal cycle, framed as "includes our private client portal." Most clients don't push back if you ship the value first.
• Productise it. Sell the portal access for $49–$99/month on top of project fees, especially to clients who keep asking for status updates. The portal pays for itself across 3 clients in two months.
Tip
Don't charge existing clients separately mid-contract. Roll it into the next renewal — no friction, no negotiation. New clients see the portal as part of the offering from day one and pay the higher rate naturally.
What's next
You shipped the portal. Two natural next moves:
• Add Stripe invoices via the playbook "Add Stripe in 30 Minutes" so clients pay directly from the portal. Reduces invoice-chasing time to zero.
• Productise further — once 3+ clients are on the portal, package the same setup as a sub-SaaS for other freelancers in your niche. We've seen this turn into $1–5K MRR for agency owners within a quarter.
Ready to Build?
Start building your full-stack application with Fabricate. Free tier available — no credit card required.
Start Building Free