Running the Vercel AI SDK course locally
Use this page to run the extracted customer-support agent on your computer. You connect its Express server to OpenAI and the Supabase data created in the course, then make one start-script change so Node loads those values from .env. The Embeddings and Vector Databases guide runs a related project against the same kind of Supabase vector setup.
What you need first
Install a supported LTS version of Node.js. Node 24 is recommended. You also need:
- an OpenAI API key with billing and model access;
- the Supabase project and data created during the course;
- a key with server-side database access: either a Supabase secret key or the legacy
service_rolekey.
A Supabase secret key and the legacy service_role key both bypass Row Level Security. A key of either type belongs only in this server-side .env, never in browser code. See Supabase API keys.
Open and install the project
Open a terminal in the extracted folder containing package.json, then install the locked packages:
$ cd path-to-your-downloaded-project
$ npm cinpm ci in the extracted folder, the one containing package.json. It installs exactly the package versions the course was built with, so there is nothing to configure or guess here. Make Node load .env
Open package.json and change the start script from:
"start": "node server.js"to:
"start": "node --env-file=.env server.js"The code uses the legacy variable name SUPABASE_SERVICE_ROLE_KEY. You can store a current Supabase secret key in that variable without renaming anything in the code. The value has to be a Supabase secret key or the legacy service_role key, not a publishable key.
Create .env beside package.json:
OPENAI_API_KEY=your-openai-api-key
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-server-side-secret-key
PORT=3000Create .gitignore:
.env
node_modules/The Git handbook covers this habit in ignoring files and good habits.
Keep the Supabase key on the server
Never rename the Supabase secret key with a VITE_ prefix or move it into client.js. That key has elevated database access. Do not commit .env or share it in a ZIP.
--env-file=.env to the start script, create the file with all four values, and keep it out of Git. The Supabase secret key stays on the server, always. A .gitignore with .env in it is the first file I create in any project, a habit I formed only after committing a key once. Keep the supplied models
The downloaded constants.js uses gpt-4o for answer generation and classification and text-embedding-3-small for embeddings. Local setup does not require changing either model. Keep them unchanged unless OpenAI rejects one for your project. If you later replace a model, test the complete agent flow and confirm that new query embeddings remain compatible with the stored Supabase vectors. Replacing the embedding model can fail without any error message: a model with the same dimension count but a different vector space returns poor matches and reports no error, so regenerate the stored vectors after changing the embedding model.
Run the agent
$ npm startOpen http://localhost:3000, or use the port you set in .env. Stop the server with Ctrl+C.
The page loading shows that the local server is running. Ask a question covered by the course data: a useful answer shows that Supabase retrieval and OpenAI generation are working too. If an answer fails, the server terminal prints the first failing call in the chain: embedding, retrieval, or generation. The RAG chapter explains why the agent bases its answers on retrieved course data.
npm start and open the local address in your browser. The page loading proves the server runs; a full answer also needs OpenAI and the course's Supabase data, so treat those as two separate checks. Troubleshooting
Missing OPENAI_API_KEY: Confirm that the start script includes --env-file=.env, that .env is beside package.json, and that the variable name matches exactly.
Supabase authentication or relation error: Confirm the URL and the Supabase secret key belong to the same project, then complete the course's schema and data steps. This server-side operation needs a Supabase secret key; a publishable key, which is meant for browser code, does not have the access it requires.
Port 3000 is already in use: Change PORT in .env, restart the server, and open the new port.
The page loads but answers fail: Check the server terminal for the first provider or database error. Local startup alone does not validate either external service.
.env, a Supabase error points to the project or its data, and a loaded page with failed answers points to an external service. Match the symptom to the layer first, and the fix is usually clear from there. 
