← All Projects
BriefDrop

BriefDrop

Multitenant client portal for freelancers & agencies — files, messages, and projects in one private, professional space

next.js
supabase
typescript
tailwind
react
stripe
google-gemini
resend
saas
authentication
rbac
i18n
file-upload
email
multitenant
real-time
analytics
data-viz
app-hero

Problem

Freelancers and agencies had no professional way to share project briefs and status updates with clients. They were stuck emailing PDFs or using generic tools that didn't reflect their brand, had no access controls, and gave no signal about whether clients had actually read the material.

Stack Decisions

Next.js for shareable brief URLs

Server-side rendering made shared brief pages indexable and gave each public link its own Open Graph metadata — critical for a tool where the brief URL is the deliverable sent to a client.

Supabase RLS for multi-tenancy

Row Level Security enforced org isolation at the database layer without a dedicated auth server. Three roles (owner, member, client) map directly to Postgres policies, keeping authorization close to the data.

Stripe Checkout + webhook

Stripe handled the entire billing lifecycle — checkout sessions, subscription upgrades, and cancellations — so the app needed zero payment logic beyond webhook event handling and a customer portal redirect.

Gemini with Server-Sent Events

Streaming the AI output through a Next.js API route via SSE let the UI show text appearing in real time without polling, giving the brief generation a ChatGPT-like feel without a WebSocket server.

Challenges

01

Cross-org data isolation

Designing RLS policies that let clients see only their assigned projects — never other orgs or other clients in the same org — required careful policy layering. A single policy gap would expose client data across tenants.

02

Flash-free theme switching

React hydration runs after the browser paints, so reading theme preference from localStorage in a useEffect caused a visible flash. The fix was an inline <script> injected in the document <head> that sets a data-theme attribute before React loads.

03

Brief engagement analytics

Tracking scroll depth and time-on-page for unauthenticated visitors on shared brief links meant building a lightweight event pipeline that worked without a session or user ID, then aggregating it per brief for the owner dashboard.

Outcome

Shipped as a production SaaS with 3-tier Stripe billing, real-time client presence tracking, AI brief and status report generation, and PDF export — fully deployed on Vercel with no backend servers. The shareable brief URL with OG metadata became the core value prop: a link that looks professional and tells the freelancer when the client opened it.