Skip to content

Running Embeddings and Vector Databases locally

Use this page to run the extracted course chatbot on your computer. On this page you install two missing packages, adapt the chatbot's OpenAI and Supabase settings for Vite, and start the browser project with the database you built during the course.

What you need first

Install a supported LTS version of Node.js. Node 24 is recommended and includes npm. You also need an OpenAI API key and an existing Supabase project containing the course data.

For Supabase, use a publishable key or the legacy anon key. These keys are designed to appear in browser code: anyone who copies one can only do what your Row Level Security policies (Supabase's per-row read rules) permit. Never put a secret key or service_role key in this browser project. See Supabase API keys for the current key types.

The OpenAI key has no equivalent scoping: any copy of it can make requests billed to your account, so in production it never belongs in client code. This learning setup sends it to the browser anyway; the warning in the Vite section explains the limits of doing that. The server-side counterpart of this setup, the Vercel AI SDK project, uses the same Supabase project but with a secret key. A secret key is acceptable there because that project runs on a server, so its keys never reach a browser.

JunoWhat you need first Install Node.js LTS, then have your OpenAI key and the Supabase project you built during the course ready. For Supabase, use a publishable or anon key, the kind designed for browsers, never a server secret. I once used the wrong key type and spent an evening learning the difference between them!
JunoWhat you need first This project needs Node plus two live services: OpenAI and the Supabase database from the course. The Supabase key you configure becomes readable in client code, so it must be a publishable or anon key whose access Row Level Security limits. Do not put any server-side key in this project.
JunoWhat you need first A leaked anon key is limited: it can only do what your Row Level Security policies permit, which is exactly why that key type is designed for browser code. The OpenAI key has no equivalent scoping, and any copy of it spends your money until you revoke it. That difference decides the architecture: a Supabase key in client code is a policy question, an OpenAI key in production client code is a mistake.

Open the project folder

Open a terminal in the extracted chatbot folder containing package.json:

bash
$ cd path-to-your-downloaded-project

To confirm you have the right download, open package.json: the chatbot export declares Vite, and the source beside it includes the config.js and index.js files the next sections edit. These instructions fit the completed chatbot, whose code imports both openai and @supabase/supabase-js; the folder name alone does not distinguish it from an earlier lesson's export.

JunoOpen the project folder Work in the extracted folder that holds package.json; every install and every file on this page belongs there. If the terminal is anywhere else, the commands run in the wrong folder and nothing after this works. I check the folder listing for package.json before typing anything, a habit I built after making that mistake several times.
JunoOpen the project folder Confirm the folder before editing anything: package.json at the top level, Vite declared inside it, and config.js and index.js sitting beside it. Thirty seconds of checking here costs less than repairing a different project's files. Every command on this page assumes you are in this folder.
JunoOpen the project folder Verify the milestone before you repair it: these instructions fit the export whose source imports both OpenAI and Supabase and runs the completed chatbot flow. An earlier lesson's export looks nearly identical if you only read the folder name. Two minutes spent reading the imports costs less than an afternoon spent debugging a repair the project never needed.

Prepare the project for Vite

Install the declared Vite dependency, then the two packages the source imports but the downloaded package.json does not declare:

bash
$ npm install
$ npm install openai @supabase/supabase-js

Open config.js and replace every Scrimba environment read. Keep the existing imports, exports, and validation, but replace three environment names across four occurrences; OPENAI_API_KEY appears twice:

js
process.env.OPENAI_API_KEY
import.meta.env.VITE_OPENAI_API_KEY

process.env.SUPABASE_API_KEY
import.meta.env.VITE_SUPABASE_API_KEY

process.env.SUPABASE_URL
import.meta.env.VITE_SUPABASE_URL

The two OPENAI_API_KEY reads sit in the validation check and the OpenAI client, so change both.

Open index.js and change the chat model from gpt-4 to gpt-4o-mini. Leave the supplied text-embedding-ada-002 embedding model unchanged while following the course. Existing vectors in the course database must have the same dimensions as the query embeddings; changing that model is a separate database migration, not part of local setup.

Create .env beside package.json:

dotenv
VITE_OPENAI_API_KEY=your-openai-api-key
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_API_KEY=your-publishable-or-anon-key

Also create .gitignore:

txt
.env
node_modules/

Sending .env to a Git repository is the most common way a key leaks; ignoring files and good habits covers the habit in full.

These credentials are visible in the browser

Vite copies VITE_ values into the frontend bundle. Use restricted learning credentials, enable Row Level Security in Supabase, and never publish this version. A production app must move the OpenAI request to a backend.

JunoPrepare the project for Vite Install the missing packages, replace every old environment read with its Vite equivalent, and put your keys in .env with a browser-safe Supabase key. Then keep .env out of Git. I once published a key with my first project and spent the evening replacing it, so this order is written from experience.
JunoPrepare the project for Vite The source imports two SDKs the download never declared and reads Scrimba's environment names, so install both packages and change all four environment reads before starting Vite. If you leave one of those reads unchanged, the app fails at runtime rather than at build time. The .env and .gitignore pair finishes the repair.
JunoPrepare the project for Vite Installing the SDKs fixes the imports; the VITE_ names are what place the values in the bundle, which also delivers the OpenAI key to browser code. That is acceptable for a lesson and disqualifying for production, so move the OpenAI call behind a backend before real users reach this chatbot. I have seen a project skip that step, and it finished with a revoked key and an unexpected invoice.

Run the project

bash
$ npm start

Open the Local URL printed by Vite and ask the chatbot a question covered by the course data. A useful answer shows that the page, Supabase retrieval, and OpenAI request are all working. Restart the command after changing .env, and stop it with Ctrl+C.

JunoRun the project Run npm start, open the Local URL, and ask the chatbot something the course data covers. If you change .env, restart the command so Vite reads the new values, and press Ctrl+C when you finish. Forgetting that restart once confused me for a whole afternoon, so I hope this note saves you one.
JunoRun the project Vite starting cleanly proves the repaired project bundles; a useful answer proves the rest. One good question tests OpenAI access along with the Supabase rows and policies at the same time, so treat it as your integration test. Restart after any .env change.
JunoRun the project A page that loads is not a passing test. Verify local serving, Supabase retrieval, embedding lookup, and answer generation as separate checkpoints, because each one can fail silently behind a perfectly rendered page. I once declared a project finished after seeing only the landing screen, and the bug appeared during the demo.

Troubleshooting

Failed to resolve import "openai" or "@supabase/supabase-js": Run both of the install commands shown earlier on this page, and run them in the folder that contains package.json.

process is not defined: A process.env reference remains in config.js. Replace it with the matching import.meta.env.VITE_... value.

Supabase returns no rows or a permissions error: Confirm the project URL, use a publishable or anon key, and check that the course table and Row Level Security policies exist in that same project.

OpenAI rejects the model or key: Confirm billing and key access in the OpenAI account. Use a current model available to that project.

JunoTroubleshooting Read the error as a clue: a missing import means the extra packages are not installed, an environment error means a Vite name is still wrong, and empty answers usually indicate a problem with Supabase data or permissions. Take them one at a time. Every problem on this list is reversible, so you can fix each one and keep going.
JunoTroubleshooting Check in dependency order: package resolution, then all four environment substitutions, then the Supabase URL and RLS policies, then the OpenAI key and model. Each layer depends on the one before it, so an out-of-order fix can look like a brand-new failure. Stop at the first broken layer and repair it there.
JunoTroubleshooting A chatbot with no useful answer fails in one of three layers: the browser bundle, Supabase permissions and rows, or the OpenAI request, and each one can fail while the page renders beautifully. Check them in that order. A page that opens proves only that Vite is running.