Skip to content

Running the Deployment course project locally

Use this page to run the extracted Dream Catcher project on your computer. The version you have uses either the included SQLite database or a separate PostgreSQL database. Identify that version first, then follow its local setup.

What you need first

Install a supported LTS version of Node.js. Node 24 is recommended and includes npm. Prepare a key and model name for the provider imported by your project.

The PostgreSQL version also needs a reachable PostgreSQL database and its connection string, the postgresql:// URL that names its user, password, host, and database. A hosted service's free tier works if you do not run PostgreSQL locally. The SQLite version includes its database file and does not need a separate database service.

JunoWhat you need first Install Node.js LTS and have your AI provider key ready before anything else. If your version uses PostgreSQL, create that database first; I once started the app before the database existed, and it failed at startup every single time!
JunoWhat you need first Node includes npm, so one install covers the tooling. Only the later version needs a separate database: a connection string of the shape postgresql://user:password@host:5432/database, from a local install or a hosted service's free tier.
JunoWhat you need first The SQLite version starts from its bundled database file; the PostgreSQL one will not even listen until its database is reachable. Get network access, credentials, and TLS working before npm start, not after the first stack trace.

Identify the version you extracted

If the extracted project includes dreams.db, use the SQLite instructions. It does not need a separate database service. If its server expects DATABASE_URL, use the PostgreSQL instructions and prepare a reachable PostgreSQL database.

Open a terminal in the folder containing package.json:

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

The bundled README is stale

The README in the downloads describes a Claude and SQLite application even after the code has moved to OpenAI or Gemini and PostgreSQL. Use the downloaded package.json, imports, and server files as the authority.

The dependencies in package.json confirm the version: pg appears in the PostgreSQL version, a native SQLite driver appears in the earlier one, and the server file's import shows which database module is live.

JunoIdentify the version you extracted Look for dreams.db or a server that wants DATABASE_URL; that tells you whether to follow the SQLite or the PostgreSQL instructions. Ten seconds of checking now saves you from working through the wrong set of instructions later.
JunoIdentify the version you extracted The migration changes both the database and the required environment values, so identify before configuring. Trust the extracted code and package.json rather than the README, which describes an older snapshot.
JunoIdentify the version you extracted Read the dependencies in package.json: pg means the PostgreSQL version, and a native SQLite driver means the earlier one. The server file's import shows which is actually live, whatever else ships in the folder. I trust imports rather than READMEs, and this download is a good example of why.

Load a local .env file

The downloaded server reads process.env, but its start command does not load a local .env file. Open package.json and change:

json
"start": "node server.js"

to:

json
"start": "node --env-file=.env server.js"

This uses Node's built-in environment-file support without adding another dependency. Node stops with an error if the file named by --env-file is missing, and variables already set in your shell take precedence over the file's values. The Intro to AI Engineering project needs the same --env-file change for its backend.

Make sure .gitignore contains both lines:

txt
.env
node_modules/

One course snapshot contains the typo mode_modules; correct it to node_modules/ before committing your project. The Git handbook covers why these entries matter in ignoring files and good habits.

JunoLoad a local .env file Add --env-file=.env to the start script so Node reads your settings file, and keep .env and node_modules/ out of Git. My first leaked key taught me that lesson faster than any course could.
JunoLoad a local .env file The server reads process.env, but nothing loads your local file into it. Node's built-in --env-file flag does that loading without adding a dependency, so make the one-line script change and continue.
JunoLoad a local .env file The dotenv package continues silently when its file is missing, while --env-file stops Node with an error, which turns a quiet misconfiguration into an immediate failure at startup. A variable already set in your shell always takes precedence over the same name in the file, so an old export from an earlier session keeps winning until you clear it. I have lost real time to one of those old exports.

Run the SQLite version

The Push to GitHub snapshot imports the OpenAI implementation by default. Create .env beside package.json:

dotenv
OPENAI_API_KEY=your-api-key-here
OPENAI_MODEL=your-model-id
PORT=3001

DATABASE_PATH is optional. Without it, the server uses dreams.db in the project folder. If you set a custom path, make sure its directory exists and is writable.

Install the locked dependencies and start the server. npm ci installs exactly the versions in the lockfile, and the native SQLite package needs that, because it is compiled for your operating system and Node version:

bash
$ npm ci
$ npm start

Open http://localhost:3001/, or the port you put in .env. Stop the server with Ctrl+C.

The project also contains a Gemini implementation, but the route imports the OpenAI file by default. If you follow the course's provider-switching code, use GEMINI_API_KEY and optional GEMINI_MODEL instead.

JunoRun the SQLite version Create .env, run npm ci and npm start, then open port 3001 in your browser. The database file already comes with the project, so there is nothing extra for you to set up here.
JunoRun the SQLite version The imported provider file decides which AI variables you need, so match the names to the import. A working page and dream list prove that the database works. They prove nothing about the AI request, so create a new dream to confirm the provider as well.
JunoRun the SQLite version The SQLite driver is a native module, compiled for your exact operating system and Node major version, so an install carried over from another machine fails to load. npm ci on the recommended LTS from a clean extraction rebuilds it correctly. When installation fails, fix that before changing database paths or provider settings.

Run the PostgreSQL version

The later project replaces SQLite with PostgreSQL. Create a database first, then add its connection string to .env along with the AI configuration:

dotenv
DATABASE_URL=postgresql://user:password@host:5432/database
OPENAI_API_KEY=your-api-key-here
OPENAI_MODEL=your-model-id
PORT=3001

Then run:

bash
$ npm ci
$ npm start

The final project initializes its tables before listening. If the database is unreachable or rejects its TLS settings, startup stops with a database error. The error text points at the cause: ENOTFOUND means the hostname did not resolve, password authentication failed means the credentials, and an SSL or TLS message means the encryption settings. The course code asks for an SSL connection, so a local PostgreSQL without TLS needs that requirement adjusted in the connection string. The /health endpoint checks the connection after startup:

text
http://localhost:3001/health

Remove the temporary shutdown route

The Terminating Processes & Signals lesson includes a /shutdown endpoint only for testing graceful termination. Follow the lesson instruction to delete that route before sharing or deploying the application. Leaving a public URL that terminates your server is unsafe.

JunoRun the PostgreSQL version Create your database first, put its connection string in .env, start the app, then visit /health to confirm the connection. Remove the temporary shutdown route before you share the app with anyone; I have forgotten that step myself, and it is not one you want to leave in a shared app.
JunoRun the PostgreSQL version Database connection and table initialization happen before Express listens, so network, credentials, or TLS problems stop startup entirely. When the server never prints its listening line, look at the database first, not the app code.
JunoRun the PostgreSQL version Read the startup error before changing anything: ENOTFOUND is DNS, password authentication failed is credentials, and an SSL complaint is TLS. The course code asks for SSL, so a local PostgreSQL without TLS needs the connection string adjusted to match. I have picked the wrong one of those three causes more than once.

Troubleshooting

OPENAI_API_KEY environment variable is missing or empty: Confirm that the start script contains --env-file=.env, that .env is beside package.json, and that the variable name matches the imported provider file.

The page opens but creating a dream returns an AI error: Check the provider key and model together. No live AI request is needed to verify that the page and existing-dream API work.

SQLite reports a native-module error: Reinstall from a clean extraction with the supported Node LTS release, using npm ci. Do not copy node_modules from another operating system.

PostgreSQL startup fails: Check the full DATABASE_URL, database network access, credentials, and TLS requirements. The final course code asks for an SSL connection.

The database is empty after switching versions: SQLite data in dreams.db does not automatically appear in PostgreSQL. Run the course's migration steps or seed the new database separately.

JunoTroubleshooting Check environment loading first, then the provider, then the database, in that order. And remember that SQLite data does not move into PostgreSQL on its own; I once stared at an empty dream list for far too long before I understood that.
JunoTroubleshooting Separate dependency issues, provider requests, SQLite paths, and PostgreSQL connectivity before changing the project. Data does not carry itself between the SQLite and PostgreSQL versions; migrate or seed the new database deliberately.
JunoTroubleshooting Debug in startup order: .env loading, then the SQLite install or the PostgreSQL connection and TLS, then table setup, then the provider request. The first error in the terminal is the real one; everything printed after it is usually a consequence of that first failure.