Engineering

aleoflow architecture

A modular full-stack SSR marketplace on TanStack Start. Routes, modules, adapters, secrets, and how to extend.

Routes

RoutePurpose
/County-aware discovery home: search, featured pro, categories, newsletter, for-pros CTA.
/categories/$slugSEO category page with filters (city, availability, rating, verified) and provider cards.
/pros/$slugIndexable business profile: hours, services, reviews, FAQs, sticky Request Service CTA.
/request/$proSlugMulti-step guided intake with local progress save and reference number.
/for-prosBusiness value prop + onboarding application form.
/pro/dashboardDemo business portal: Overview, Leads, Profile, Services, Reviews, Analytics, Settings.
/about, /privacy, /termsStatic legal/about pages.
GET /api/v1/businessesFiltered business list (REST).
GET /api/v1/businesses/$slugSingle business (REST).
POST /api/v1/leadsPublic lead submission (REST).
POST /api/v1/chatCustom chat widget start/send (REST).
POST /api/v1/webhooks/lead-statusHMAC-verified lead status webhook (REST).

Modules

FileResponsibility
src/lib/db/types.tsTyped domain models (Market, City, Category, Business, Lead, …).
src/lib/db/seed.tsSeeded local JSON (markets, categories, businesses, leads).
src/lib/db/adapters.tsAdapter interfaces: Database, Email/SMS, CRM, Analytics, Geocoding, ReviewSource.
src/lib/db/demo.tsIn-memory demo repository implementing the Database adapter.
src/lib/db/repo.tsFactory wiring adapters from env; falls back to demo with no credentials.
src/lib/chat.server.tsChat adapter: demo in-memory + live Conversations API (GHL_API_KEY/GHL_LOCATION_ID).
src/lib/chat.functions.tsServer functions for the custom chat widget: startChat, sendChatMessage, getChatMessages.
src/lib/aleo.functions.tsServer functions: search, getBusiness, submitLead, updateLeadStatus, etc.
src/lib/schemas.tsZod schemas shared by server functions and REST routes.
src/lib/rate-limit.tsIn-memory rate-limit adapter + client IP helper.

Adapters

Each external concern is behind an interface. The demo implementation keeps preview working with no credentials.

AdapterDemoReal (with secret)
DatabaseIn-memory storeDATABASE_URL → Postgres
EmailNo-opRESEND_API_KEY → Resend
SMSNo-opTWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN → Twilio
CRMNo-opGHL_API_KEY / GHL_LOCATION_ID → CRM + Conversations API
ChatBranded local echoGHL_API_KEY / GHL_LOCATION_ID → Conversations API
GeocodingStatic MN coordsGOOGLE_MAPS_API_KEY → Google Maps
Review sourceSeed reviews + reputation widgetProvider review API

Secrets

All optional. The app runs in demo mode without any of them.

Postgres database

Optional

Persists businesses, leads, subscriptions. Without it the in-memory demo store is used.

DATABASE_URL

CRM (contact + lead sync)

Optional

Sync contacts and log leads to the connected CRM.

GHL_API_KEY

CRM location

Optional

Required alongside the CRM key.

GHL_LOCATION_ID

Email notifications

Optional

Sends the owner a lead notification and the homeowner a confirmation.

RESEND_API_KEY

SMS (lead alerts)

Optional

Texts owners new lead alerts.

TWILIO_ACCOUNT_SID

SMS auth

Optional

Required alongside the Twilio account SID.

TWILIO_AUTH_TOKEN

Geocoding + maps

Optional

Resolves ZIP codes to coordinates and renders maps.

GOOGLE_MAPS_API_KEY

Lead-status webhook HMAC

Optional

Verifies POST /api/v1/webhooks/lead-status signatures.

WEBHOOK_SIGNING_SECRET

Adding a new market

  1. Add a Market + its City entries to src/lib/db/seed.ts.
  2. Seed businesses referencing the new marketId / cityId.
  3. Update DEFAULT_MARKET in src/lib/constants.ts if it becomes the default.

Adding a new category

  1. Add a Category to src/lib/db/seed.ts.
  2. The category page at /categories/$slug picks it up automatically.

Adding a new business

  1. Add a Business to businessSeed with a unique slug.
  2. Mark sample: true until details are confirmed.
  3. It appears in search, category pages, and the home grid automatically.