Local Business Directory
Run the boilerplate as a local business directory — the localBusiness vertical adds business fields, a Types facet, and auto-enables claims, quotes, local SEO and maps from a single config flag.
Why this matters
Directory, store and jobs were all built for the web. The local business vertical is built for businesses that exist on a street — HVAC pros, dentists, gyms, tradespeople. Turn it on and the whole platform reshapes around them: listings carry phone, opening hours, business type and USPs; visitors search by service × type × city; every listing plots on a map; owners claim their profiles; and visitors send quote requests that become leads.
The point of the vertical is that you don't wire those pieces together yourself. Selecting it flips on the entire local stack at once.
Setting vertical: 'localBusiness' auto-enables claims, quotes, localSeo and map, and force-disables SaaS-only modules. You don't toggle each feature by hand — the vertical implies them.
Turn it on
1. Select the vertical in config/platform.config.ts:
export const platformConfig = {
vertical: 'localBusiness', // 'directory' | 'store' | 'jobs' | 'localBusiness'
};2. Confirm the flag in config/features.config.ts — localBusiness: true ships on by default. The vertical also relies on claims, quotes, localSeo and map, which it enables implicitly at runtime.
3. Run the migrations. The local business data model spans migrations 0009–0012. The simplest path is the bundled file:
# Supabase SQL Editor — runs 0009 → 0012 in order
supabase/migrations/APPLY_LOCAL_BUSINESS.sqlOr apply them individually: 0009_add_local_business_fields.sql, 0010_add_lead_subscriptions.sql, 0011_add_email_campaigns.sql, 0012_normalize_locations.sql. See Supabase Setup.
4. Add a Mapbox token so the map renders — NEXT_PUBLIC_MAPBOX_TOKEN in your env. Without it the map degrades to a placeholder and everything else still works. See Maps & Location.
What the vertical adds
| Piece | What it does |
|---|---|
| Business fields | phone, business_type, opening hours, usps, google_place_id on each listing, surfaced in a contact-forward business card and detail panel. |
| Types facet | A second filter dimension alongside categories — visitors narrow by business type end-to-end (/api/business-types, catalogue filter, submit/edit forms). |
| Hero search | A home-page search across service × type × city, plus a browse-by-category tile section. |
| Owner claims | Business owners claim and verify their own listing — see Listing Claims. |
| Quote leads | Visitors request quotes that fan out to matching pros — see Quotes & Leads. |
| Local SEO pages | Programmatic "service-in-city" landing pages and a /locations browser — see Local SEO Pages. |
Business listing fields
New columns on apps (migration 0009):
phone— public contact number.business_type— the value behind the Types facet.hours— opening hours (structured JSON).usps— a short list of selling points (also generated by AI enrichment).google_place_id— reference to the Google Places entry.
These appear as fields in the submit/edit forms and persist through the /api/projects POST/PUT mapping — no code changes needed to collect them.
Import a CSV of businesses and mark the rows unclaimed so real owners can take them over later, then run AI CSV enrichment to scrape each site into a description and USPs. You can seed hundreds of listings in an afternoon.
Switching away
The vertical is a single config value. The shared core — auth, admin, categories, search, SEO, theming — is identical across formats, so switching back to directory doesn't rebuild anything. The local-only tables stay in place, harmlessly unused.
Related
- Features Config — the flag table and how verticals interact.
- Listing Claims
- Quotes & Leads
- Local SEO Pages
- Maps & Location