Client Info Hub
The third hub. A bento grid of everything we know about a client — read-only for clients, fully editable by admins.
Why this exists
The agency was juggling client metadata across notes, Drive folders, WhatsApp threads and the team's memory. The Client Info hub consolidates it: one canonical place for company info, primary contact, domain & hosting expirations, brand assets, social handles, billing, notes. The client sees the same view we do — proves we have it organised, and lets them spot mistakes early.
Bento grid layout
The hub renders one full-bleed page (no sub-tabs). Cards span across a 12-column grid:
| Card | Span | Content |
|---|---|---|
| About the company | 7 | Legal name, industry, founded year, team size, free-text description. |
| Primary contact | 5 | Name, role, email (mailto), phone (tel). The first name drives the Home greeting. |
| Headquarters | 5 | Street, city, state, zip, country. |
| Domain & hosting | 7 | Domain, registrar, hosting provider, plus domain and SSL expiration dates. |
| Brand assets | 6 | Brand colors as live swatches with hex labels + typography description. |
| Social media | 6 | Facebook, Instagram, LinkedIn, YouTube, TikTok URLs (rendered as external links). |
| Billing & legal | 5 | Billing email + tax / business ID. |
| Notes | 7 | Freeform admin notes — sensitivities, scope nuances, internal context. |
Schema
All fields live as dedicated columns on the clients table prefixed with info_. Migration: supabase/add-client-info.sql.
-- Company
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_legal_name text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_industry text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_founded_year int;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_employee_count text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_about text;
-- Primary contact (name drives the greeting on Home)
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_primary_contact_name text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_primary_contact_role text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_primary_contact_email text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_primary_contact_phone text;
-- Address
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_address text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_city text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_state text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_zip text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_country text;
-- Domain & hosting
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_domain text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_domain_registrar text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_domain_expiration date;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_hosting_provider text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_ssl_expiration date;
-- Brand
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_brand_colors text; -- comma-separated hex
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_brand_fonts text;
-- Social
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_social_facebook text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_social_instagram text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_social_linkedin text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_social_youtube text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_social_tiktok text;
-- Billing & legal
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_billing_email text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_tax_id text;
ALTER TABLE clients ADD COLUMN IF NOT EXISTS info_notes text;Editing flow
Admins see two affordances:
- A global Edit info button in the page header opens the editor at the top.
- A pencil icon in every card's top-right opens the editor and scrolls to that section automatically.
The editor is one modal split into 8 sections (Company / Contact / Address / Domain / Brand / Social / Billing / Notes). Save writes directly to the clients table via the Supabase browser client; empty strings are coerced to null. After save the page calls router.refresh() so the bento grid re-reads the latest row.
UPDATE the clients table. The pencil icon is hidden for client users in the UI, but RLS is the actual gate.Primary contact drives the greeting
The Home page used to greet "Good morning, Denver" using the company name. With Client Info shipped, the greeting reads info_primary_contact_name first and falls back to the company name only if the contact field is empty. So once an admin setsinfo_primary_contact_name = 'John Smith', the client sees "Good morning, John."
Component paths
| File | Purpose |
|---|---|
| src/components/portal/sections/ClientInfoSection.tsx | Read-only bento grid + per-card pencil affordance. |
| src/components/portal/editors/ClientInfoEditor.tsx | Modal editor with all sections; saves to clients table. |
| src/lib/types/clientInfo.ts | Shared TS interface mirroring the SQL columns. |
| supabase/add-client-info.sql | Migration that adds the 29 info_* columns. |
Status
live Hub, bento grid, editor, expiration tinting, greeting wiring all shipped in Phase 1.1. Future polish that is intentionally out-of-scope for now: per-section RLS so a sensitive sub-section (e.g. tax ID) can be hidden from client view; audit log of edits; multi-contact support.