Capstone topics from the end of the program: how to set up a full-stack backend project, work with npm and Git, test APIs with Postman or curl, apply layering and REST habits, and prepare for deployment and the mock interview. These patterns tie Express, SQL, and deployment lessons into day-to-day engineering practice.
Misc / Other
Capstone topics from the end of the program: how to set up a full-stack backend project, work with npm and Git, test APIs with Postman or curl, apply layering and REST habits, and prepare for deployment and the mock interview. These patterns tie Express, SQL, and deployment lessons into day-to-day engineering practice.
Select a function type from the sidebar, or browse topics below.
Separate app entry, routers, controllers, services, and database code into predictable folders.
Learn: A consistent folder layout helps you find code quickly and mirrors how professional teams organize Express APIs. Each resource gets router + controller + service files; shared pieces (db, errors, config) live at the top level.
Standard scripts to start the server, run migrations, and seed the database.
Learn: npm scripts are the team’s shared commands—everyone runs the same start and migrate steps. Document them in README so onboarding takes minutes, not hours.
Clone the program starter, install dependencies, copy .env.example, and run locally before customizing.
Learn: Starters encode conventions the course expects. Clone, install, configure .env, migrate, and seed before changing behavior—prove the baseline works, then implement features incrementally.
git clone <starter-repo-url>
cd <project-folder>
npm install
cp .env.example .env # then fill in DATABASE_URL, PORT, etc.
npm run migrate
npm run seed
npm start
Use Git to save incremental work; commit working slices (feature, fix, migration) with clear messages.
Learn: Small, focused commits make code review and debugging easier. Commit when a vertical slice works (e.g. ‘users list endpoint returns 200’), not only at the end of the week.
Supplementary examples
Check what will be committed
git diff
git diff --staged
git commit -m "feat(users): add GET /users list endpoint"
Course example
git status
git add src/users/users.service.js
git commit -m "Add list users service function"
git push origin main
Switch behavior between development (verbose logs, pretty output) and production (structured logs, no secrets in responses).
Learn: NODE_ENV signals runtime context. Development favors readable logs; production favors performance and security (no stack traces to clients, stricter log levels).
Send GET/POST/PUT/DELETE requests with JSON bodies and headers; verify status codes and response shape.
Learn: Postman is the GUI you used throughout the program to exercise REST endpoints. Build a collection per resource with example bodies so regressions are easy to spot after refactors.
Supplementary examples
Headers for JSON APIs
Content-Type: application/json
Accept: application/json
# Optional when using cookies/sessions:
# Cookie: session=...
Course example
# Example workflow (Postman UI):
# 1. Method: POST URL: http://localhost:5001/users
# 2. Body (raw JSON): { "username": "demo_user" }
# 3. Expect: 201 + JSON body with created user
# 4. Follow-up GET http://localhost:5001/users to list all
Trace the path: client → middleware → router → controller → service → database; read logs and status codes at each step.
Learn: When a request fails, resist random changes—follow the pipeline. Confirm the server port, route match, validation, service/SQL, then global error handler. Logs with request IDs from pino make this faster.
Routers wire URLs, controllers handle HTTP, services own data—avoid SQL or business rules in route files.
Learn: Layers exist so each file has one reason to change. If SQL appears in a router, move it to a service. If HTTP status logic sprawls across services, return errors and map them in the controller.
Quick reference for common API response codes used in the backend program: what each code means and which HTTP verb / situation it pairs with.
Learn: Status codes tell the client what happened without reading the body. In this program you most often use: 200 for successful reads/updates that return JSON, 201 when POST creates a row, 204 when DELETE succeeds with no body, 400 when validation fails, 404 when the id or route does not exist, and 500 when an unexpected error reaches errorHandler. Match the code to the HTTP verb and outcome—not every success is 200.
Supplementary examples
2xx — success responses
// 200 — GET /users, GET /users/3, PUT /users/3 (with JSON body)
res.status(200).json({ data: users });
// 201 — POST /users (resource created)
res.status(201).json({ data: newUser });
// 204 — DELETE /users/3 (nothing to return)
res.status(204).end();
4xx — client / request problems
// 400 — validation middleware or controller check
return res.status(400).json({ error: "username is required" });
// 404 — service found no row, or notFound middleware
const err = new Error("User not found");
err.status = 404;
throw err;
5xx — server failures
// 500 — default in errorHandler when err.status is missing
// Avoid sending 500 for validation (use 400) or missing rows (use 404)
function errorHandler(err, req, res, next) {
const status = err.status || err.statusCode || 500;
res.status(status).json({ error: err.message });
}
Verb → status cheat sheet (typical REST API)
GET /resources 200 (list)
GET /resources/:id 200 (found) | 404 (missing)
POST /resources 201 (created)
PUT /resources/:id 200 (updated) | 404 (missing)
DELETE /resources/:id 204 (deleted) | 404 (missing)
Common codes (program reference)
Code
Name
When to use in your API
200
OK
GET success; PUT success when returning updated resource
201
Created
POST created a new resource (include body or Location header)
204
No Content
DELETE success; no response body (use .end())
400
Bad Request
Validation failed, missing/invalid fields, bad JSON
404
Not Found
Unknown route (notFound) or id not in database
500
Internal Server Error
Unhandled exception; default in errorHandler
Course example
# 2xx Success
200 OK GET list/detail, PUT update (return body)
201 Created POST created a new resource
204 No Content DELETE succeeded (no response body)
# 4xx Client error (caller or request is wrong)
400 Bad Request Validation failed, malformed JSON, missing field
404 Not Found Resource id does not exist; unknown route (notFound)
# 5xx Server error (bug, database, unhandled exception)
500 Internal Unhandled error; errorHandler default
Use nouns for resources, HTTP verbs for actions, and meaningful status codes (200, 201, 204, 400, 404, 500).
Learn: REST is a convention, not a framework feature. Collections use plural nouns; IDs live in the path; verbs express intent via HTTP methods—not via path names like /getUsers.
Supplementary examples
Nested resource path
GET /users/42/pastes # pastes belonging to user 42
POST /users/42/pastes # create paste for user 42
Course example
GET /users -> 200 list
POST /users -> 201 created
GET /users/:id -> 200 one | 404
PUT /users/:id -> 200 updated | 404
DELETE /users/:id -> 204 no content | 404
Use JSON error objects and appropriate status codes; centralize formatting in error middleware.
Learn: Clients and frontends depend on predictable error JSON. Pick a shape (e.g. { error: string }) and use it for validation, not found, and server errors.
// Validation
res.status(400).json({ error: "username is required" });
// Not found (in service or controller)
const err = new Error("User not found");
err.status = 404;
throw err;
// errorHandler sends: { error: err.message }
Use descriptive names, small functions, early returns, and comments only for non-obvious business rules.
Learn: Readable code reduces bugs in team settings. Prefer const, async/await over nested callbacks, and functions under ~30 lines. Rename until intent is obvious without comments.
Supplementary examples
Extract validation helper
function requireString(value, field) {
if (typeof value !== "string" || !value.trim()) {
const err = new Error(`${field} is required`);
err.status = 400;
throw err;
}
return value.trim();
}
Course example
// Prefer explicit names
async function listActiveUsers() {
return knex("users").where({ is_active: true });
}
// Prefer early return over deep nesting
if (!req.body.name) {
return res.status(400).json({ error: "name is required" });
}
Review REST, Express layers, Knex CRUD, error handling; practice explaining decisions aloud; use official docs for syntax only during the assessment.
Learn: The mock interview combines live coding (Qualified) with verbal explanation. Practice narrating your structure out loud; passing tests is necessary but interviewers also assess how you think through tradeoffs.
Supplementary examples
Explain-aloud template
# 1. Restate the endpoint requirement
# 2. Name files you will touch (router, controller, service)
# 3. Describe data model / migration if needed
# 4. Implement smallest test-passing slice
# 5. Mention edge cases (404, 400, empty list)
Course example
# Preparation checklist
# - All Qualified challenge tests pass
# - Can explain router vs controller vs service
# - Can write a migration + Knex query from scratch
# - Know when to use 201 vs 204 vs 404
# - Behavioral stories ready (STAR format)
Appropriate uses: brainstorming structure, explaining errors, documentation lookup. Verify output; disclose use when required; do not substitute for understanding in graded interviews.
Learn: AI can accelerate learning when you verify suggestions against docs and run tests. For graded interviews, follow program rules: official docs for syntax, honest disclosure if you used AI while practicing.
Supplementary examples
Good prompt for learning
# "Explain why this Knex query returns undefined when no row exists"
# Then fix it yourself using .first() and an explicit 404 check.
Course example
# Responsible uses
# - Explain an error message or stack trace
# - Suggest test cases for an endpoint
# - Draft commit message or PR description
# Avoid for graded work unless allowed
# - Generating full solutions without understanding
# - Copying code you cannot explain in the interview
Push to GitHub, connect host (e.g. Render), set env vars, run migrations, confirm health endpoint and CORS for the frontend origin.
Learn: Deployment connects Git, hosting, database, and frontend CORS. The same repo runs locally with .env and in production with host-managed secrets—never commit real credentials.
# Deployment checklist
# 1. .env values set on host (DATABASE_URL, PORT, NODE_ENV=production)
# 2. Build command: npm install
# 3. Start command: npm start
# 4. Run knex migrate:latest against production DB
# 5. Smoke test: GET /health or GET /