Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Every task in this course runs a real query against a real database, which means the first thing to settle is where that database lives. There is a temptation to hard-code a docker-compose and be done, but that excludes anyone already running Postgres on their machine, anyone whose employer gives them a managed instance, and anyone for whom Docker is awkward. The better arrangement is one layer of indirection: the scripts read two connection strings from the environment, and where those point is your business. That costs about ten lines and buys you a course that works on a laptop, on a free Neon and Atlas tier, and against a staging replica at work. It also teaches the habit worth having anyway — configuration comes from the environment, never from a literal in the script.
A package.json that declares the lab an ES module, a .env with two URLs, a compose file for the zero-setup path, and a connection check that tells you which of the two engines is not reachable rather than failing with a stack trace.
# ── First, the project itself ───────────────────────────────────
# The scripts in this course are ES modules and they use two drivers,
# so the lab needs a package.json before anything will run.
$ mkdir qp-lab && cd qp-lab
$ npm init -y
$ npm pkg set type=module # <- without this, node treats .js as
# CommonJS and every import throws
# "Cannot use import statement
# outside a module"
$ npm install pg mongodb
# package.json should now read:
# {
# "name": "qp-lab",
# "private": true,
# "type": "module",
# "dependencies": { "mongodb": "^6.9.0", "pg": "^8.13.0" }
# }
# If you would rather not set "type": "module", name the files .mjs
# instead — node always treats .mjs as an ES module. Pick one; do not
# mix them.
# ── The layout every later task assumes ─────────────────────────
# Create these as you go. Each is introduced in the task named.
#
# qp-lab/
# package.json this task
# .env this task
# docker-compose.yml this task (option A only)
# lib/
# db.js this task <- the connection helper that
# seed.js and the rest import
# check.js this task
# schema.sql task 3
# schema.js task 3
# seed.js task 5
# verify.js task 6
# baseline.sh task 7
# baseline.js task 7
# reset.sh task 8
#
# Note lib/ is a SUBDIRECTORY. The imports later read "./lib/db.js",
# so the file must sit there, not next to seed.js.
# $ mkdir -p lib
# ── Then .env — the only file the rest of the course needs you to edit.
# Everything reads these two variables. Point them wherever you like.
# ── Option A: the bundled docker compose (zero setup) ────────────
PG_URL="postgres://postgres:qp@localhost:5432/qp"
MONGO_URL="mongodb://localhost:27017/qp"
# ── Option B: managed, free tier ────────────────────────────────
# PG_URL="postgres://user:pass@ep-cool-name.eu-west-2.aws.neon.tech/qp?sslmode=require"
# MONGO_URL="mongodb+srv://user:pass@cluster0.abcde.mongodb.net/qp"
# ── Option C: something you already run ─────────────────────────
# PG_URL="postgres://me@localhost:5432/qp"
# MONGO_URL="mongodb://localhost:27017/qp"
# Dataset size. Covered in task 5 — start with 'default' unless you
# are on a free managed tier, in which case use 'small'.
SCALE=default
# ── Load it ─────────────────────────────────────────────────────
$ set -a && source .env && set +a
# ── And check both are actually reachable BEFORE seeding ────────
$ psql "$PG_URL" -tAc "select version()"
PostgreSQL 16.4 on aarch64-unknown-linux-gnu, compiled by gcc 12.2.0
$ mongosh "$MONGO_URL" --quiet --eval "db.version()"
7.0.14
# If either of those fails, stop here. Seeding against a half-working
# connection produces a half-loaded dataset and every number in the
# rest of the course will be quietly wrong.