Skip to content

LXMachado/lead-capture-plumbing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lead Capture Plumbing

Lead capture MVP for a plumbing business, with a React frontend and an Express/Postgres API.

Structure

  • web/: React + Vite frontend
  • api/: Express API + PostgreSQL storage

Backend features

  • SQL-file migrations applied automatically on API startup
  • Expanded leads schema with operational fields such as source, page, next_action_at, assigned_to, quote_amount, created_at, and updated_at
  • lead_notes table for lead history
  • Indexed filtering on created_at, status, and service_type
  • Admin-protected lead listing and status updates
  • Input validation and lightweight rate limiting on lead submission

Local setup

1. Start PostgreSQL

Create a database and provide its connection string through DATABASE_URL.

Example:

createdb lead_capture_plumbing

2. Configure API env

Copy api/.env.example to api/.env and update values as needed.

Required for local API use:

  • DATABASE_URL
  • ADMIN_TOKEN

Optional:

  • PORT
  • SMTP settings for new-lead notification emails

3. Run the API

cd api
npm install
npm run dev

On startup, the API will apply any pending SQL migrations automatically.

4. Run the frontend

cd web
npm install
npm run dev

If the frontend is served separately from the API, set:

VITE_API_URL=http://localhost:4000/api

Optional frontend env:

VITE_DEMO_MODE=true

When VITE_DEMO_MODE is not set to true, the form and admin page use the live API.

API

POST /api/leads

Creates a lead.

Example payload:

{
  "name": "Jane Smith",
  "phone": "0400 111 222",
  "email": "[email protected]",
  "service_type": "Blocked drain",
  "urgency": "medium",
  "suburb": "Robina",
  "contact_time": "morning",
  "message": "Kitchen sink blocked",
  "source": "webform",
  "page": "/contact"
}

Allowed values:

  • urgency: low, medium, emergency
  • contact_time: any, morning, afternoon, evening
  • source: webform, call

GET /api/leads

Requires:

Authorization: Bearer <ADMIN_TOKEN>

Supported query params:

  • service_type
  • status
  • from (YYYY-MM-DD)
  • to (YYYY-MM-DD)

PATCH /api/leads/:id/status

Requires:

Authorization: Bearer <ADMIN_TOKEN>
Content-Type: application/json

Example payload:

{
  "status": "contacted",
  "next_action_at": "2026-04-04T09:00:00.000Z"
}

Allowed status values:

  • new
  • contacted
  • booked

Testing

API tests are mock-based and do not require a running database:

cd api
npm test

About

Local service businesses often rely on outdated websites that don’t convert visitors into actual jobs. The goal of this project was to design a modern, conversion-focused website tailored for a plumbing business, prioritising fast contact, trust, and ease of use on mobile devices.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors