Vibe Code an HVAC Dispatch App

Build a live HVAC job dispatch board using Cursor AI with no coding required.

Introduction

30 Second Summary

When your AC breaks on the hottest day of the year, someone at an HVAC company creates a service job, assigns a technician, and tracks it until your house is cool again. That dispatch workflow is the beating heart of every field service business.

In this project, you will build a working job dispatch application for HVAC companies. You'll use Cursor AI to generate all the code by describing what you want in plain English.

What You'll Build

A Next.js web application backed by Supabase, with email authentication, a job dispatch dashboard, and live deployment on Vercel.

By the end of this project, you'll have:

  • A live deployed URL you can share with anyone to demo your dispatch board.
  • A portable codebase stored in GitHub that you fully own and can move to any hosting provider.
  • A proven vibe coding workflow you can reuse to keep building features independently.
  • Secret Mission: a mobile-friendly technician view where assigned techs see only their jobs and can update status on the go.

Are there any prerequisites?

No coding experience is required. You'll describe features in plain English and Cursor's AI generates the code. All you need is a computer with internet access.

Before We Start

Before you can build your HVAC dispatch app, you need the right tools on your machine and accounts ready to go.

In this step you will install Node.js (which powers your app), create accounts on GitHub, Supabase, and Vercel, and connect Cursor to your GitHub account so you can push code later.

In this step, get ready to:
  • Install Node.js and verify it works in your terminal.
  • Create accounts on GitHub, Supabase, and Vercel, and set up a Supabase project.
  • Open Cursor and connect it to your GitHub account.
Install Node.js and verify it works

Node.js is the runtime that lets your app run JavaScript on a server. It also comes bundled with npm, the package manager you will use to install libraries.

  • Open your terminal.
  • Check whether Node.js is already installed by running this command:
node -v

✔️ I see a version number

Node.js is already installed. Confirm npm is available too by running:

npm -v

You should see a version number printed. You are ready to move on.

ⓧ Command not found

Node.js is not installed yet. You will install it using nvm (Node Version Manager), which is the recommended way to manage Node.js on Linux.

  • Install nvm by running this command:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
  • Load nvm into your current terminal session by running:
. "$HOME/.nvm/nvm.sh"
  • Install the latest LTS version of Node.js by running:
nvm install --lts
  • Verify the installation by running:
node -v
npm -v

Both commands should print a version number. Node.js is now installed and ready.

Seeing command not found after running the install script?

If nvm is not found after running the install script, close your terminal completely and open a new one. Then try nvm install --lts again.

On some Ubuntu systems, curl may be installed via Snap, which causes permission errors. If you see a permission denied error during download, install curl from apt instead by running sudo apt install curl and retrying.

Help me troubleshoot this issue

What is Node.js?

Node.js is a JavaScript runtime that runs outside the browser. Your HVAC dispatch app uses Node.js to serve pages, connect to the database, and handle authentication.

npm comes bundled with Node.js. It downloads and manages the libraries (packages) your project depends on.

Create accounts on GitHub, Supabase, and Vercel

You need three free accounts. Each one handles a different part of your workflow: GitHub stores your code, Supabase hosts your database, and Vercel deploys your app to a live URL.

  • Open your browser and go to github.com.
  • Click Sign up and follow the prompts to create a free account.
  • Open supabase.com in a new tab.
  • Click Start your project and sign up using your GitHub account.
  • Open vercel.com in a new tab.
  • Click Sign Up and sign up using your GitHub account.

Why sign up with GitHub?

Supabase and Vercel both support signing in with your GitHub account. This means fewer passwords to remember and makes connecting your code repositories seamless later.

Now create a new Supabase project on the free tier.

  • In the Supabase dashboard, click New Project.
  • Enter a project name. Something like hvac-dispatch works well.
  • Set a secure database password. Save this somewhere safe.
  • Choose a region closest to you.
  • Click Create new project.
  • Wait for your database to finish launching. This takes about 30 seconds.

Where do I find my project URL and anon key?

Once your project is ready, click Project Settings in the left sidebar, then open the Data API section. You will see your project URL and anon key listed there. You will need these values in a later step.

Open Cursor and connect it to GitHub

Cursor is the AI code editor you will use to build this entire app. Connecting it to GitHub lets you push your code to a repository later without extra setup.

  • Open Cursor from your applications menu or launcher.
  • Press Ctrl+Shift+P to open the Command Palette.
  • Type Sign in and select the option to sign in to GitHub.
  • Your browser will open asking you to authorize Cursor. Click Authorize.
  • Return to Cursor. You should see your GitHub username in the bottom-left corner of the editor, confirming the connection.

Don't see the sign-in option?

If you do not see a GitHub sign-in prompt in the Command Palette, try typing GitHub instead. Cursor's built-in GitHub support handles authentication. You do not need any additional extensions.

If the browser authorization page does not appear, check that your default browser is set correctly in your system settings.

Help me connect Cursor to GitHub

Your tools are installed and accounts are ready. Next up, you will write a product spec and scaffold your Next.js project.

Write Your Product Spec and Create the Project

Your tools are installed and your accounts are ready. Now it's time to define what you're building and bring the project to life.

In this step, you'll write a product spec that tells Cursor exactly what to build, then use the AI to scaffold your project. By the end, you'll have a running app and a GitHub repository you own.

In this step, get ready to:
  • Write a product specification that describes your HVAC dispatch board.
  • Scaffold a Next.js project with Tailwind CSS using Cursor's AI.
  • Push your code to GitHub.
Create your project folder and product spec

Before the AI can build anything, it needs to know what you want. A product spec is a plain-English document that describes your app's features, data, and user roles. Cursor reads this file to understand your vision.

  • Open the integrated terminal in Cursor by pressing Ctrl+` (that's the backtick key, usually above Tab).
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir hvac-dispatch
cd hvac-dispatch
  • Open this folder in Cursor by clicking File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the hvac-dispatch folder, and click Open.

Why open the folder this way?

When you open a folder in Cursor, it becomes your workspace. The AI Agent can see all files in the workspace, which means everything you put here becomes context for the AI's suggestions.

  • Create a new file by clicking the New File icon at the top of the Explorer sidebar (it looks like a page with a plus sign).
  • Name the file PRODUCT_SPEC.md and press Enter.
  • Paste the following product spec into the file:
# HVAC Job Dispatch Board

## Overview

A web application for HVAC companies where an office manager can create service jobs, assign them to technicians, and track job status from open to complete.

## User Roles

- **Office Manager**: Creates jobs, assigns technicians, monitors all job statuses from a central dashboard.

## Features

- **Authentication**: Email/password signup and login. After login, redirect to the dashboard. Logout button on all pages.
- **Dispatch Dashboard**: A table showing all jobs with columns for customer name, address, assigned technician, status, and scheduled date. A blue "New Job" button in the top right.
- **Job Creation**: A form to create a new job with fields for customer name, customer phone, customer address, job description, scheduled date, and a dropdown to assign a technician.
- **Technician Assignment**: Dropdown to assign an available technician when creating or editing a job.
- **Status Tracking**: Jobs move through statuses: Open, Assigned, In Progress, Complete.

## Data Model

- **Jobs**: status, description, customer address, scheduled date, assigned technician, created date
- **Technicians**: name, phone number, specialization (e.g., residential, commercial, installation, repair)
- **Customers**: name, phone number, address

## Tech Stack

- Frontend: Next.js with Tailwind CSS
- Backend/Database: Supabase (PostgreSQL)
- Authentication: Supabase Auth
- Hosting: Vercel

What does this spec do?

This file is the single source of truth for your product. When you ask Cursor to build features, it reads this spec to understand the full picture. The clearer your spec, the better the AI's output.

The spec covers user roles (who uses the app), features (what it does), data model (what information it stores), and tech stack (what tools power it).

  • Save PRODUCT_SPEC.md by pressing Ctrl+S.
  • Confirm the file appears in the Explorer sidebar on the left.

Don't see the file in the sidebar?

Make sure you opened the hvac-dispatch folder as your workspace (not a parent folder). If you see your whole Desktop listed, go to File and Open Folder again, selecting only the hvac-dispatch folder.

Help me find my PRODUCT_SPEC.md file in Cursor's sidebar

✔️ Awesome, I've got everything!

Great. Double check you've saved PRODUCT_SPEC.md and you can see it in the Explorer sidebar.

ⓧ I'd like to double check the full code

Here's the complete PRODUCT_SPEC.md file:

# HVAC Job Dispatch Board

## Overview

A web application for HVAC companies where an office manager can create service jobs, assign them to technicians, and track job status from open to complete.

## User Roles

- **Office Manager**: Creates jobs, assigns technicians, monitors all job statuses from a central dashboard.

## Features

- **Authentication**: Email/password signup and login. After login, redirect to the dashboard. Logout button on all pages.
- **Dispatch Dashboard**: A table showing all jobs with columns for customer name, address, assigned technician, status, and scheduled date. A blue "New Job" button in the top right.
- **Job Creation**: A form to create a new job with fields for customer name, customer phone, customer address, job description, scheduled date, and a dropdown to assign a technician.
- **Technician Assignment**: Dropdown to assign an available technician when creating or editing a job.
- **Status Tracking**: Jobs move through statuses: Open, Assigned, In Progress, Complete.

## Data Model

- **Jobs**: status, description, customer address, scheduled date, assigned technician, created date
- **Technicians**: name, phone number, specialization (e.g., residential, commercial, installation, repair)
- **Customers**: name, phone number, address

## Tech Stack

- Frontend: Next.js with Tailwind CSS
- Backend/Database: Supabase (PostgreSQL)
- Authentication: Supabase Auth
- Hosting: Vercel
Scaffold your Next.js project with Cursor's AI

Now that Cursor knows what you're building, you'll use its Agent mode to scaffold the project. Agent mode can create files, run terminal commands, and set up your entire project structure from a single prompt.

  • Open Cursor's Agent by pressing Ctrl+I to open the Composer panel.
  • Make sure Agent mode is selected (look for the Agent toggle at the top of the panel).
  • Type the following prompt into the Agent chat and press Enter:
Set up a new Next.js project in this directory with Tailwind CSS. Use TypeScript and the App Router. Use npm as the package manager. After setup, make sure I can run it with npm run dev. Read PRODUCT_SPEC.md to understand what we're building.

What happens next?

Cursor's Agent will start working. It may run terminal commands (like scaffolding with create-next-app) and create files. You'll see each action appear in the panel.

The Agent will ask for your approval before running commands. Click Accept or Run when prompted. If it asks interactive questions (like whether to use TypeScript or Tailwind), the prompt already covers those choices. Let the Agent handle them.

  • Wait for the Agent to finish scaffolding. This may take 1-2 minutes as it downloads dependencies.
  • Once the Agent reports success, start the development server by running this command in your terminal:
npm run dev
  • Open your browser and navigate to http://localhost:3000.

You should see the default Next.js welcome page. This confirms your project is running.

Not seeing the welcome page?

  • Check that npm run dev is still running in your terminal. If it crashed, read the error message and share it with the Agent.
  • Make sure you're visiting http://localhost:3000 (not https).
  • If the Agent failed to scaffold, try typing a simpler follow-up prompt: "The setup failed. Please try again and fix any errors."

Help me get my Next.js dev server running

Why Next.js, Supabase, and Vercel?

This stack is the most documented combination for AI-assisted development. Cursor generates its highest-quality code for Next.js + Supabase + Tailwind CSS because this stack dominates its training data. Non-technical founders have shipped real SaaS products using this exact combination.

Initialize Git and push to GitHub

Your project is running locally. Now you'll save it to GitHub so you have a backup, version history, and a way to deploy later.

  • Stop the development server by pressing Ctrl+C in the terminal.
  • Initialize a Git repository and make your first commit by running these commands:
git init
git add .
git commit -m "Initial commit: project scaffold and product spec"

What do these commands do?

  • `git init` turns your folder into a Git repository that tracks changes.
  • `git add .` stages all your files for the next commit.
  • `git commit -m "..."` saves a snapshot of your project with a message describing what changed.
  • Open your browser and go to github.com.
  • Click the + icon in the top right corner, then click New repository.
  • Enter hvac-dispatch as the repository name.
  • Leave it set to Private.
  • Do NOT check any boxes (no README, no .gitignore, no license). You already have these locally.
  • Click Create repository.

GitHub will show you a page with setup instructions. Look for the section titled "push an existing repository from the command line."

  • Copy the commands GitHub shows you and run them in your terminal. They will look similar to this:
git remote add origin https://github.com/[[GITHUB_USERNAME="your-github-username"]]/hvac-dispatch.git
git branch -M main
git push -u origin main
  • Refresh the GitHub page in your browser.

You should see your project files listed on GitHub, including PRODUCT_SPEC.md and all the Next.js files the Agent created.

Push failed or asking for credentials?

  • If Git asks for a username and password, use your GitHub username and a Personal Access Token (not your password). You can create a token at github.com/settings/tokens.
  • If you see "remote origin already exists", run git remote remove origin first, then try the remote add command again.
  • Since Cursor is connected to your GitHub account, you can also ask the Agent: "Push this repository to GitHub for me" and it may handle authentication automatically.

Help me push my code to GitHub

Your product spec is written, your app is scaffolded, and your code is safely on GitHub. Next up, you'll build the database tables and add authentication so real users can log in.

Build the Database and Authentication

Your Next.js project is scaffolded and running locally. Now it needs somewhere to store data and a way to control who can access it.

In this step, you will create a Supabase database with tables for jobs, technicians, and customers. Then you will wire up authentication so only logged-in users can reach the dispatch dashboard.

In this step, get ready to:
  • Generate and run the SQL to create your database tables in Supabase.
  • Add email/password signup and login pages to your app using Cursor AI.
  • Test the full auth flow and commit working code to GitHub.
Describe your data model and create the database tables

Every field service business revolves around three things: the jobs that need doing, the technicians who do them, and the customers who request them. Your database mirrors this structure exactly.

  • Switch back to Cursor and open the AI chat panel by pressing Cmd+L (macOS) or Ctrl+L (Windows/Linux).
  • Type the following prompt into the chat to have Cursor generate the SQL for your three tables:
Generate the Supabase SQL to create three database tables for an HVAC dispatch app:

1. customers - columns: id (uuid primary key, default gen_random_uuid()), name (text), phone (text), address (text)

2. technicians - columns: id (uuid primary key, default gen_random_uuid()), name (text), phone (text), specialization (text), user_id (uuid referencing auth.users)

3. jobs - columns: id (uuid primary key, default gen_random_uuid()), status (text, default 'Open'), description (text), address (text), scheduled_date (date), customer_id (uuid referencing customers), technician_id (uuid referencing technicians), created_at (timestamptz, default now())

Output only the SQL statements, nothing else.

What does this prompt do?

You are describing your data model in plain English so Cursor generates the exact SQL you need. The uuid primary keys let Supabase auto-generate unique IDs. The foreign keys (customer_id, technician_id, user_id) link tables together so you can track which technician is assigned to which job and which customer requested it.

The status column defaults to 'Open' because every new job starts as unassigned.

  • Review the SQL that Cursor generates. It should create three tables with the columns described above.
  • Copy the generated SQL to your clipboard.
  • Open your Supabase project dashboard in your browser.
  • In the left sidebar, click SQL Editor.
  • Paste the SQL into the editor and click Run.
  • After running the SQL, click Table Editor in the left sidebar to verify your tables exist.
  • You should see three tables listed: customers, technicians, and jobs.

SQL failed to run?

Check for syntax errors like missing commas or mismatched parentheses. Also confirm that customers and technicians are created before jobs, since jobs references both.

If the SQL references auth.users and fails, make sure you are running it inside the Supabase SQL Editor (which has access to the auth schema) and not an external tool.

My SQL won't run in Supabase. Can you help me debug it?

Connect Supabase to your app and add authentication

Your database is ready. Now your Next.js app needs credentials to talk to it, and your users need a way to log in.

  • In your Supabase dashboard, navigate to Settings in the left sidebar.
  • Click API Keys.
  • Locate your Project URL and your anon key. Keep this page open.

What is the anon key?

The anon key is a public key designed to be used in client-side code. It can only access data that your Row Level Security policies allow. It is safe to include in your front-end app.

  • Return to Cursor. In the AI chat, type the following prompt to have Cursor install the Supabase client library and set up environment variables:
Install the @supabase/supabase-js package. Then create a .env.local file with NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY. Also create a utility file that initializes the Supabase client using these environment variables.
  • When Cursor suggests running a terminal command (npm install @supabase/supabase-js), allow it to run.
  • When Cursor creates the .env.local file, replace the placeholder values with your actual Project URL and anon key from the Supabase dashboard page you kept open.

Your .env.local file should look like this (with your own values):

NEXT_PUBLIC_SUPABASE_URL=your-project-url-here
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

Why NEXT_PUBLIC_ prefix?

In Next.js, environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Since the Supabase anon key is designed for client-side use, this is safe and necessary for your app to communicate with Supabase from the front end.

  • Now prompt Cursor to build your authentication pages:
Add email/password signup and login pages to this Next.js app using Supabase Auth. After login, redirect to a /dashboard page. Add a logout button on the dashboard. The signup and login pages should have simple forms with email and password fields.

What is Cursor doing here?

Cursor reads your project structure, the Supabase client utility you just created, and your prompt. It then generates complete page files for signup, login, and the dashboard with all the auth logic wired up. You describe the feature. The AI writes the code.

This is the core vibe coding workflow: describe what you want, review what the AI generates, and iterate if something is off.

  • Review the files Cursor creates. Accept them.
  • Save all files.

Cursor not generating the right files?

If Cursor generates files in an unexpected location or uses a routing pattern you do not recognize, try rephrasing your prompt to be more specific. Include the exact file paths you want (for example, app/login/page.js or app/signup/page.js).

Cursor is not creating the auth pages correctly. Can you help me fix my prompt?

Test the auth flow and commit to Git

Before you commit, you need to confirm the full authentication loop works end to end.

  • Make sure your development server is running. If it stopped, start it again by running this in the Cursor terminal:
npm run dev
  • Open your browser and navigate to your signup page (typically http://localhost:3000/signup).
  • Enter a test email and password, then submit the form.
  • After signup, you should be redirected to the /dashboard page.
  • Click the logout button on the dashboard. You should be redirected back to the login page.
  • Log back in with the same credentials. You should land on the dashboard again.

What should I see?

A successful test means: signup creates an account and lands you on the dashboard, logout sends you to the login page, and logging back in returns you to the dashboard. All three transitions should happen without errors in the browser console.

Supabase email confirmation

By default, Supabase requires email confirmation for new signups. For local testing, you can disable this in your Supabase dashboard under Authentication in the left sidebar, then Providers, then Email. Toggle off Confirm email. This lets you test without checking an inbox.

Signup not working?

Double-check that your NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY values in .env.local are correct. A common mistake is copying extra whitespace or missing a character.

Also make sure you restarted the dev server after creating .env.local. Next.js only reads environment variables at startup.

My Supabase auth is not working. Can you help me troubleshoot?

  • Once the full auth flow works, commit your code. In the Cursor terminal, run:
git add .
git commit -m "Add database schema and authentication"
git push
  • You should see your commit pushed successfully to GitHub.

Git push rejected?

If the push fails, check that your .gitignore file includes .env.local. Next.js projects generated by create-next-app include this by default. You should never push environment variables to GitHub.

My git push is failing. Can you help?

Your database and authentication are locked in. Next up, you will build the dispatch dashboard that brings this data to life.

Build the Dispatch Dashboard

Your app handles authentication. Users can sign up, log in, and reach a protected dashboard page.

Now you need to build the thing users actually came to see: the dispatch board. This is the main screen where office staff view every job at a glance, and where they create new jobs to send technicians into the field.

In this step, get ready to:
  • Build a jobs table on the dashboard showing customer name, address, technician, status, and date.
  • Create a New Job form that saves jobs to your Supabase database.
  • Test the full flow from job creation to dashboard display.
Describe the dispatch dashboard to Cursor

The dashboard needs to pull every job from your Supabase database and display it in a scannable table. You will describe exactly what you want in Cursor's agent chat, and the AI will build it.

  • Switch back to Cursor.
  • Start a new agent chat by pressing Cmd+N (macOS) or Ctrl+N (Windows/Linux).
  • Type the following prompt into the agent chat and press Enter:
Build a dashboard page that shows all jobs in a table with columns for customer name, address, assigned technician, status (Open, Assigned, In Progress, Complete), and scheduled date. Add a blue 'New Job' button in the top right. The dashboard should fetch jobs from the Supabase jobs table and join with the customers and technicians tables to display names instead of IDs. Refer to PRODUCT_SPEC.md for the full feature description.

What does this prompt do?

The agent reads your codebase (including your PRODUCT_SPEC.md and your existing Supabase connection) and generates the dashboard page.

Mentioning PRODUCT_SPEC.md gives the AI project-level context so it makes decisions consistent with your product vision.

  • Wait for the agent to finish generating files.
  • Review the changes the agent proposes. Look for a dashboard page file that imports from your Supabase client, runs a query joining jobs, customers, and technicians, and renders a table.
  • Click Accept to apply the changes.

Start a new chat for each feature

Cursor's agent works best with a fresh context window per feature. Starting a new chat prevents old conversation history from confusing the AI.

  • Confirm your development server is still running. If it stopped, start it again by running:
npm run dev
  • Open your browser and navigate to http://localhost:3000.
  • Log in with the account you created earlier.
  • You should see the dashboard page with a table (it will be empty since you have no jobs yet) and a blue New Job button in the top right.

Dashboard not showing the table?

  • Check your browser's developer console for errors. A common issue is a missing or incorrect Supabase URL in .env.local.
  • Make sure you accepted all of Cursor's proposed changes. If a file was skipped, the component may be missing.
  • If the page loads but shows no table structure at all, start a new chat and re-prompt the agent with more detail about your existing file structure.

Ask for help: My dashboard page loads but I don't see a jobs table. I'm using Next.js with Supabase. How do I debug this?

Build the New Job form with Cursor

The blue button needs somewhere to go. You will prompt Cursor to build a job creation form that collects all the details an office manager needs to dispatch a technician.

  • Start a new agent chat by pressing Cmd+N (macOS) or Ctrl+N (Windows/Linux).
  • Type the following prompt and press Enter:
Create a form to add a new job. It should have fields for customer name, customer phone, customer address, job description, scheduled date, and a dropdown to assign a technician. The technician dropdown should be populated from the technicians table in Supabase. When submitted, save the job to Supabase (create the customer record if needed, then create the job linked to that customer and the selected technician). After saving, redirect back to the dashboard. Make the 'New Job' button on the dashboard link to this new form page.

What will the agent generate?

The agent creates a new page (something like /jobs/new) with a form component. It also updates your dashboard to link the blue button to this new route.

The form handles creating both a customer record and a job record in Supabase, because your database schema links jobs to customers via customer_id.

  • Wait for the agent to finish, then review the proposed changes.
  • Confirm that the form includes all six fields: customer name, customer phone, customer address, job description, scheduled date, and a technician dropdown.
  • Click Accept to apply the changes.

Add sample technicians to your database

The technician dropdown will be empty if your technicians table has no data. Open your Supabase dashboard, go to the SQL Editor, and run a quick insert to add test technicians:

insert into technicians (name, phone, specialization)
values
  ('Mike Johnson', '555-0101', 'Residential AC'),
  ('Sarah Chen', '555-0102', 'Commercial HVAC'),
  ('Carlos Rivera', '555-0103', 'Heat Pumps');

Click Run to execute the query. Now your form will have technicians to choose from.

  • Return to your browser and refresh the dashboard.
  • Click the blue New Job button. You should see the job creation form with all six fields and a technician dropdown populated with names.

Technician dropdown empty or form not loading?

  • Make sure you ran the SQL insert in the correct Supabase project. Check the project URL matches what is in your .env.local.
  • If the form page gives a 404, check that Cursor created the new page file. Look for a file at a path like app/jobs/new/page.js or pages/jobs/new.js in your project.
  • If the form renders but the dropdown is empty, open the browser console and look for Supabase permission errors. You may need to disable Row Level Security on the technicians table for now (you can tighten it later).

Ask for help: My technician dropdown is empty even though I inserted data. How do I fix Supabase permissions?

Test the full flow and commit to Git

The dashboard and form are built. Now you will create a real job through the form and verify it flows through to both the dashboard and your Supabase database.

  • In your browser, click the blue New Job button from the dashboard.
  • Fill out the form with test data:
  • Click the submit button on the form.
  • You should be redirected back to the dashboard. Your new job should now appear in the table with the customer name, address, assigned technician, status of Open, and the scheduled date.
  • Verify the data in Supabase by opening your Supabase dashboard.
  • Click Table Editor in the left sidebar.
  • Select the jobs table. You should see your new job row with a status of Open and a customer_id and technician_id filled in.
  • Select the customers table. You should see the customer record the form created.

Why check both places?

The dashboard proves your front-end queries work. The Supabase Table Editor proves the data actually persisted in your database. Checking both catches bugs where the UI shows stale or cached data.

  • Return to Cursor and open the terminal.
  • Commit your working code and push to GitHub by running:
git add .
git commit -m "Add dispatch dashboard and new job form"
git push

Git push failing?

  • If you see an authentication error, make sure your GitHub account is still connected in Cursor. You may need to re-authenticate.
  • If the push is rejected because of remote changes, run git pull --rebase first, then try pushing again.

Ask for help: My git push is failing. How do I fix authentication or remote rejection issues?

Your dispatch board is live. Office staff can now create jobs and see them on the dashboard. Next up, you will add the ability to update job status and deploy the whole app to a live URL.

Add Job Status Updates and Deploy

Your dispatch dashboard shows jobs and your form creates new ones. The missing piece is the ability to update a job's status as it moves through its lifecycle.

In this step, you'll add an interactive side panel that appears when you click a job row, letting office staff update job status with a single click. Then you'll deploy the whole app to a live URL on Vercel so anyone can access it.

In this step, get ready to:
  • Add a job detail side panel with status update buttons.
  • Deploy the app to Vercel with a live URL.
  • Test the full workflow on your live deployment.
Add job status management with Cursor

Right now, jobs stay at their initial status forever. In a real dispatch workflow, jobs move from Open to Assigned to In Progress to Complete. You need a way for office staff to trigger those transitions.

  • Switch to the Cursor AI chat panel.
  • Describe the feature you want by typing this prompt:
When I click a job row on the dashboard, show the job details in a side panel. Add buttons to change the status: Mark as Assigned, Mark In Progress, Mark Complete. Each button updates the job status in Supabase and refreshes the dashboard.

What does this prompt do?

This single prompt tells Cursor to build three things: a click handler on each job row, a slide-out side panel component showing the full job details, and three action buttons that write status changes back to your Supabase database.

Cursor will generate the code to query your jobs table, update the status column, and re-fetch the dashboard data so it reflects the change immediately.

  • Review the diff that Cursor proposes. Look for a new side panel component and an onClick handler on your job table rows.
  • Accept the changes.

Review before accepting

Always scan the diff for anything unexpected. Make sure Cursor didn't accidentally remove your existing table columns or the New Job button. If something looks off, tell Cursor in the chat what to fix.

  • Save all files and check your browser.
  • Click on a job row in the dashboard. You should see a side panel slide in from the right showing the job's full details.
  • Click Mark as Assigned. The panel should close or update, and the job's status in the table should change to Assigned.
  • Test Mark In Progress and Mark Complete the same way.

Side panel not appearing?

If clicking a job row does nothing, check your browser's developer console for errors. The most common issue is a missing onClick handler on the table row element.

If the status buttons don't update the database, confirm your Supabase Row Level Security (RLS) policies allow updates. You may need to tell Cursor: "The status update isn't working. Check that RLS allows authenticated users to update the jobs table."

help me debug why my job status buttons aren't updating Supabase

Deploy to Vercel

Your app works locally. Now it's time to put it on the internet so anyone with the link can use it. Vercel is built by the same team that makes Next.js, so it deploys your app with zero configuration.

  • First, commit your latest changes to Git and push to GitHub by running these commands in your terminal:
git add .
git commit -m "Add job status side panel"
git push
  • Open your browser and go to vercel.com.
  • Sign in with your Vercel account.
  • Click the Add New... dropdown button, then select Project.
  • Select your HVAC dispatch GitHub repository from the list. If you don't see it, click Adjust GitHub App Permissions to grant Vercel access.
  • On the configuration page, Vercel auto-detects your Next.js project. Leave the default settings for Framework Preset, Root Directory, and Build Command.

Before you click Deploy, you need to add your Supabase environment variables. Without them, your deployed app won't be able to connect to your database.

  • On the same configuration page, expand the Environment Variables section.
  • Add your first variable. In the Name field, type NEXT_PUBLIC_SUPABASE_URL. In the Value field, paste your Supabase project URL (the same value from your .env.local file).
  • Add your second variable. In the Name field, type NEXT_PUBLIC_SUPABASE_ANON_KEY. In the Value field, paste your Supabase anon key.
  • Click Deploy.

Why add environment variables here?

Your .env.local file only works on your local machine. It's excluded from Git (via .gitignore) so your secrets stay safe. Vercel needs its own copy of these values to connect to Supabase when it builds and serves your app in the cloud.

Vercel will build your project and deploy it. This takes 1-2 minutes. Once complete, you'll see a success screen with your production URL.

  • Copy your production URL. It will look something like your-project-name.vercel.app.

What is continuous deployment?

Now that your GitHub repo is connected to Vercel, every time you push code to your main branch, Vercel automatically rebuilds and redeploys your app. You never need to manually deploy again.

Build failed on Vercel?

The most common cause is a missing environment variable. Check that both NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY are set in your Vercel project settings. Variable names are case-sensitive.

If the build log shows a code error, fix it locally first, push again, and Vercel will automatically retry the deployment.

help me fix my Vercel deployment build failure

Vercel Hobby plan and commercial use

The Vercel Hobby plan is free for development and demos. However, it is restricted to non-commercial personal use only. When you're ready to sell your dispatch app to real customers, you'll need Vercel Pro at $20/user/month.

For now, the free tier is perfect for building, testing, and showing your app to potential customers.

Test the live deployment and commit final code

A deployment isn't done until you've verified the live version works end-to-end. Your local environment and the deployed version can behave differently if environment variables are misconfigured.

  • Open your production URL in a new browser tab.
  • Log in with the account you created earlier.
  • Click New Job and create a test job with any details.
  • Confirm the new job appears on the dashboard.
  • Click the job row to open the side panel.
  • Click Mark as Assigned, then Mark In Progress, then Mark Complete. Verify each status change appears in the dashboard table.

Dashboard loads but shows no data?

This usually means your Supabase RLS policies allow local requests but block requests from your Vercel domain. Open the Supabase dashboard and check your RLS policies on the jobs table allow SELECT and UPDATE for authenticated users.

help me fix my Supabase RLS policies for my deployed app

  • If everything works, commit any remaining changes and push your final code by running:
git add .
git commit -m "Final working deployment"
git push

Your code is now saved in GitHub and automatically deployed to Vercel. Every future push triggers a fresh deployment.

Your HVAC dispatch app is live on the internet. You have a shareable URL, a GitHub repo you fully own, and a deployment pipeline that updates automatically. Next up, you'll tackle the Secret Mission and build a mobile-friendly technician view.

Secret mission

Build a Mobile Technician View

Your dispatch dashboard works great for office staff on desktop. But what about the technicians out in the field? They need a simple, phone-friendly view that shows only their assigned jobs with big, easy-to-tap buttons to update job status on the go.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses free tiers for all services, so there are no ongoing costs while your resources stay active.

Planning to sell this to real customers?

For building, demoing, and getting your first test users, the free tiers work perfectly. When you're ready for commercial use, you'll need Vercel Pro ($20/user/month) and Supabase Pro ($25/month per organization) for production reliability.

Resources you used:

  • Supabase project (free tier, pauses after 1 week of inactivity).
  • Vercel deployment (free Hobby plan, for non-commercial personal use).
  • GitHub repository (free, private).
  • Local project folder on your computer.

Keep everything running

No action needed. Choose this if you're still actively building or planning to add features like invoicing, scheduling, or a customer portal.

  • Your Supabase project stays live. It will auto-pause after 1 week of inactivity, but you can unpause it anytime from the Supabase dashboard.
  • Your Vercel deployment stays live at your URL. It costs nothing while on the free Hobby tier.
  • Your GitHub repository remains accessible for future development.
  • Your local project folder stays on your computer, ready to open in Cursor.

Pause - I'll come back to this later

Your Supabase project auto-pauses after 1 week of inactivity. Paused projects are restorable for 90 days. No manual action is required to pause.

  • Your Vercel deployment stays live but uses no resources if there's no traffic.
  • Your GitHub repository and local files stay as they are.
  • When you return, open the Supabase dashboard and click the unpause button on your project to restore it.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow each step below to fully clean up.

  • Delete your Supabase project:
  • Delete your Vercel deployment:
  • Delete your GitHub repository:
  • Delete your local project folder:
cd ~/Desktop
rm -rf your-project-folder-name

On Windows, run:

cd ~\Desktop
rmdir /s /q your-project-folder-name

That's a Wrap!

That's a Wrap!

Nice work! You just built a real HVAC job dispatch application and deployed it to a live URL, all without writing a single line of code manually.

You've learned how to:

  • Built a working HVAC job dispatch application using Cursor AI and the vibe coding workflow: describe what you want in plain English, review what the AI generates, iterate, and deploy.
  • Created and own a portable codebase stored in GitHub that you can move to any hosting provider at any time.
  • Deployed a live application to a shareable Vercel URL with a Supabase backend handling authentication, database storage, and real-time updates.
  • Secret Mission: Built a mobile-friendly technician view with role-based access, so technicians see only their assigned jobs and can update status from their phone.

Ready to quiz yourself?