Client Site
Public-facing agent website with listings, areas, and contact functionality
Client Site
The client site is the public-facing website for each agent, displaying their listings and brand.
Overview
Each workspace gets a client site that includes:
- Homepage with hero, featured listing, and service areas
- Listings page with faceted search and filtering
- Area pages for geographic neighborhoods
- Listing detail pages with photo gallery and property info
- Contact page for lead capture
Route Structure
/
├── / # Homepage
├── /listings # Listings search
├── /listings/[id] # Listing detail
├── /areas # Service areas index
├── /areas/[slug] # Area detail + listings
├── /about # Agent bio
└── /contact # Contact formWorkspace Resolution
The client site determines which workspace to display using:
- Host header — Custom domain lookup in
workspace_domains - Query parameter —
?workspace=slugfor development/preview
async function getWorkspaceFromHost(): Promise<Workspace | null> {
const host = headers().get('host');
// Check workspace_domains table
const { data } = await supabase
.from('workspace_domains')
.select('workspace:workspaces(*)')
.eq('domain', host)
.single();
return data?.workspace ?? null;
}Homepage Sections
Hero Section
Full-width hero with:
- Background image (customizable in settings)
- Workspace name / agent tagline
- Call-to-action buttons
Configuration in workspace.settings.site.hero:
interface HeroConfig {
imageUrl?: string; // Custom hero image
tagline?: string; // Hero subtitle text
}Featured Listing Section
Showcase a specific listing with:
- Ken Burns animation on photos
- Property details overlay
- Link to full listing
Configuration in workspace.settings.site.featuredListing:
interface FeaturedListingConfig {
enabled: boolean;
listingId?: string; // UUID of selected listing
}Service Areas Section
Grid of neighborhood cards showing:
- Area hero image
- Name and tagline
- Listing count
- Starting price
Links to /areas/[slug] for each area.
Listings Page
Search & Filtering
The listings page provides:
- Text search — Address, city, subdivision
- Faceted filters — Property type, beds, baths, price range
- Sort options — Newest, price low/high, beds
- Listing source toggle — "My Listings" vs "All Listings"
Listing Source Filtering
By default, the listings page shows agent-affiliated listings:
import_category: personal— Agent's own listingsimport_category: office— Brokerage listings
The "Show All Listings" toggle (if enabled) expands to include:
import_category: search— Service area imports
Configuration: workspace.settings.showAllListingsLink
Pagination
Server-side pagination with:
- 24 listings per page
- Page number in URL
- Total count display
Area Pages
Areas Index (/areas)
Grid of all service areas showing:
- Hero image or gradient
- Area name
- Tagline
- Listing count
- "From $X" pricing
Area Detail (/areas/[slug])
Dedicated page for each service area:
- Hero section with area image
- Description text (SEO)
- Stats (count, price floor)
- Filtered listing grid
- Pagination
- Contact CTA
Area pages always show all listings (including search imports) since users are browsing by location.
Listing Detail Page
Photo Gallery
- Primary photo as hero
- Thumbnail navigation
- Lightbox for full-screen
- Photo priority: uploads > MLS > placeholder
Property Information
Sections include:
- Overview — Price, beds, baths, sqft
- Location — Address, map (if enabled)
- Description — Public remarks
- Features & Amenities — From MLS data
- Property Details — Year built, lot size, etc.
Contact Form
Inline contact form or CTA to contact page.
MLS Compliance
- Attribution text from
compliance_profiles - Disclaimer (if configured)
- MLS number display
Site Header
Responsive header with:
- Logo/workspace name
- Navigation links
- Mobile hamburger menu
Navigation items:
- Home
- Listings
- Areas (if service areas exist)
- About
- Contact
Site Footer
Footer includes:
- Brokerage information
- Social media links
- MLS attribution
- Legal disclaimer
- Copyright
Theming
Workspaces can customize appearance via settings.theme:
Theme Presets
Built-in presets:
luxury— Dark, sophisticatedmodern— Clean, minimalcoastal— Light, airyclassic— Traditional
Color Overrides
Custom colors for light/dark mode:
interface WorkspaceTheme {
preset: ThemePresetId;
colorOverrides?: {
light?: Partial<ThemeColors>;
dark?: Partial<ThemeColors>;
};
}CSS Variables
Theme colors are applied via CSS variables:
:root {
--primary: hsl(var(--theme-primary));
--background: hsl(var(--theme-background));
/* ... */
}Agent & Brokerage Info
Agent Profile
Displayed on About page and footer:
interface AgentInfo {
name: string;
title?: string;
email?: string;
phone?: string;
photoUrl?: string;
licenseNumber?: string;
bio?: string; // Markdown supported
}Brokerage
Displayed in footer:
interface BrokerageInfo {
name: string;
logoUrl?: string;
address?: string;
phone?: string;
website?: string;
}Social Links
interface SocialLinks {
instagram?: string;
facebook?: string;
linkedin?: string;
twitter?: string;
youtube?: string;
tiktok?: string;
}SEO Configuration
Workspace-level SEO settings:
interface SeoConfig {
title?: string; // Default page title
description?: string; // Meta description
ogImage?: string; // Social share image
keywords?: string[];
googleAnalyticsId?: string;
facebookPixelId?: string;
}Feature Flags
Toggle features per workspace:
interface WorkspaceFeatures {
favorites: boolean; // Saved listings
savedSearches: boolean; // Search alerts
virtualTours: boolean; // Virtual tour links
mapView: boolean; // Map toggle
socialSharing: boolean; // Share buttons
mortgageCalculator: boolean;
neighborhoodData: boolean;
}Development
Local Development
Run the client site locally:
pnpm --filter web devUse query parameter for workspace:
http://localhost:3000?workspace=lainey-levinPreview Domains
For staging/preview without custom domain setup, use the query parameter approach or configure preview subdomains.