Documentation
Authentication

Client Mode

What the client sees, and what they can and cannot do.

Who is a client

A user whose profiles.role = 'client' with profiles.client_id set to a specific client. The owner or stakeholder at the brand we serve — the person who reads updates, approves deliverables, submits requests, books calls and reviews KPIs.

URL pattern

  • Production base: https://clients.flooringpros-marketing.com/
  • Each client's portal is at clients.flooringpros-marketing.com/[client-slug] (slug-friendly route maps to the underlying /dashboard/clients/[id]).
  • The URL itself is the access control: visiting it without a session redirects to /login.
Bookmarkable
Clients are encouraged to bookmark their portal URL. It does not change after onboarding — the same URL is used for the whole engagement.

Entry point

Client users authenticate via a magic link generated by the Invite Client flow (run by Chesney or Dan). After login they are redirected straight to their client's page (/dashboard/clients/[id]) — they never see the client list at /dashboard.

Default tab

Client users land on the Client Hub → Home. The greeting in the hero pulls the first name from info_primary_contact_name (set by admins on the Client Info hub) and falls back to the company's first word if no contact is configured yet.

Hubs visible to clients

HubDefault sub-tabNotes
Client HubHomeFull sub-tab set — Home, Onboarding, Scorecard, Game Plan, Deliverables, Wins, Content & Authority, Meeting Notes, Resources & Docs, Billing.
ReportingHidden from clients today. Roadmap: surface a curated subset (Pipeline + Reporting Home only) once Phase 3 ships.
Client InfoRead-only bento grid. Client sees the same fields admin filled in. Useful for catching mistakes (wrong domain expiry, stale phone number).
No sidebar for clients
On /dashboard/clients/[id] the sidebar is hidden completely for client users. They get full-bleed and only ever see their own portal. Admins keep the dark sidebar so they can move between clients.

Sub-tabs inside the Client Hub

Every sub-tab is visible to clients (read-only):

Sub-tabContentEditable by client
SummaryBusiness KPIs, Lead Pipeline, Leads Broken Down, Leads/Appointments by Source.No (read-only).
Historical RevenueRFMS sheet integration — historical revenue trend.No.
Snapshot & GoalsWhere the client is now vs. where they want to be.No (admin edits, client views).
Pipeline OverviewDetailed pipeline metrics — rates, costs, attribution, stage breakdown.No (read-only).
ScorecardHealth-check style ratings across marketing pillars.No.
90-Day Game PlanTactical roadmap for the next quarter.No.
Journey & DeliverablesOnboarding milestones and deliverable timeline.No.
KPI ReportingMonthly KPI table tracked over time.No.
Content & WebsiteTracker of content shipped and website improvements.No.
DocumentsFiles and links shared with the client.No (admin uploads).

What clients can do

The portal is mostly read-only, but a client can:

  • Submit Request — open the modal, send a request to the FPM team. This lands in our internal queue and currently surfaces in Slack.
  • Approve deliverables — when the Approvals UI ships, mark a deliverable as approved or request changes.
  • Book a call — calendar embed in the right rail (planned).
  • Download monthly PDF — same export as admin.
Read-only by design
Everything else is curated by the FPM team. The portal is meant to be the single source of truth for the client's engagement, not a tool the client edits.

Data isolation

A client must never see another client's data. Two layers protect this:

  • Route-level. The dashboard layout reads profiles.client_id server-side and forces the URL to that client. Navigating to a different /dashboard/clients/[other-id] serves a 403 / redirect.
  • Row-level. Supabase RLS policies on clients, integrations, portal_data, and external_metrics require the row's client_id to match profiles.client_id for the requesting user, unless the user has the admin role.
Adding a new table?
Any table that contains per-client data needs an RLS policy mirroring the existing ones. Without it, RLS defaults to deny and the client will see nothing — or worse, RLS could be off and they will see everything. Always ALTER TABLE ... ENABLE ROW LEVEL SECURITY and write a policy.

UX differences from admin

  • No edit pencils on portal sub-tabs.
  • No Connect / Disconnect buttons on the integrations panel.
  • No Sidebar client list — instead, the sidebar shows account info and a logout button.
  • No Edit Client link.
  • No internal-only top-level tabs (Paid Marketing, Social Media, etc.).
  • The PDF download button is still visible — clients can export their own monthly report.
  • The Submit Request button is the primary call-to-action in the right rail.

Logout

Same as admin — Supabase signOut clears cookies and the next request redirects to /login.