Skip to main content

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.

One flag, the whole stack

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.tslocalBusiness: 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 00090012. The simplest path is the bundled file:

# Supabase SQL Editor — runs 0009 → 0012 in order
supabase/migrations/APPLY_LOCAL_BUSINESS.sql

Or 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

PieceWhat it does
Business fieldsphone, business_type, opening hours, usps, google_place_id on each listing, surfaced in a contact-forward business card and detail panel.
Types facetA second filter dimension alongside categories — visitors narrow by business type end-to-end (/api/business-types, catalogue filter, submit/edit forms).
Hero searchA home-page search across service × type × city, plus a browse-by-category tile section.
Owner claimsBusiness owners claim and verify their own listing — see Listing Claims.
Quote leadsVisitors request quotes that fan out to matching pros — see Quotes & Leads.
Local SEO pagesProgrammatic "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.

Seed a directory fast

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.