A simple to-do list CRUD API built with Express, as part of the FlyRank Internship Week 2 assignment. Now backed by a real SQLite database (Week 3).
npm install
node index.jsServer runs at http://localhost:3000. Swagger docs at http://localhost:3000/docs.
This project uses SQLite instead of an in-memory array for storage.
Why SQLite?
- It's a single file (
tasks.db) with no separate database server to install or run. - Perfect for a small project like this — zero configuration, and the whole database is portable.
- Data survives server restarts, unlike the in-memory array used in Week 2.
Where the database lives
The database file is tasks.db, created automatically the first time the server runs. It's excluded from git via .gitignore, so every fresh clone starts with a clean database — the app creates the table and seeds three example tasks automatically.
How to start the project
npm install
node index.jsOn first run, tasks.db is created, the tasks table is created if missing, and three example tasks are seeded (only if the table is empty).
Database viewer
Example SQL query
Ran this in DB Browser's "Execute SQL" tab:
SELECT COUNT(*) FROM tasks;Returned 3 — confirming the seed data was in place before I made any changes through the API.
| Method | Path | Description |
|---|---|---|
| GET | / | API info |
| GET | /health | Health check |
| GET | /tasks | List all tasks |
| GET | /tasks/:id | Get a single task |
| POST | /tasks | Create a new task |
| PUT | /tasks/:id | Update a task |
| DELETE | /tasks/:id | Delete a task |
curl -i http://localhost:3000/tasks/1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":1,"title":"Learn Express","done":true}
My prompt:
I want to build my first CRUD API using Javascript language express(node.js), using this endpoints:
GET /tasks List all tasks
POST /tasks Create a new task
GET /tasks/{id} Get a single task
PUT /tasks/{id} Update a task
DELETE /tasks/{id} Delete a task I expect to see these status codes: 200, 201, 204, 400, 401 The tiltle is required it can't be empty It is in-memory storage no database needed Use Swagger UI
What ChatGPT did better:
- Generated Swagger documentation directly from JSDoc-style comments above each route (
@swaggerblocks), instead of a separate hand-writtenopenapi.jsonfile. This is the "Express lane" stretch goal from the assignment, done automatically without me asking for it. - Used slightly more idiomatic JavaScript, e.g. destructuring
const { title, completed = false } = req.bodyinstead of accessingreq.body.titledirectly. - Split the code into separate files (
index.js,routes/tasks.js,swagger.js) rather than one large file — a cleaner structure as the app grows.
What ChatGPT got wrong or skipped:
- Real bug: every "task not found" case returns status 401 (Unauthorized) instead of 404 (Not Found). 401 means "you're not authenticated," which doesn't apply here — there's no auth in this app at all. This fails the assignment's explicit requirement that unknown ids return 404, and would fail my Stage 2 checkpoint (
GET /tasks/99→ expects 404). - Completely omitted the
/and/healthendpoints required in Stage 1 — it didn't attempt a sensible default here, it just left them out. PUT /tasks/:idrequirestitleon every update and 400s if it's missing — even if I only wanted to togglecompleted. My version allows partial updates (e.g. just marking something done without resending the title).- Started with an empty task list instead of seed/example data, so
GET /tasksreturns[]until something is created.
What my prompt forgot to specify (and the AI silently decided for me):
- The exact status code to use for "not found" — it guessed, and guessed wrong (401 instead of 404).
- Whether PUT should support partial updates or require the full object every time.
- Whether to include seed/example data on startup.
- The field name for completion status (
donevscompleted). - Whether root/health endpoints were needed at all.
One-sentence takeaway after regenerating with a tighter prompt: Pointing out the specific bug (401 vs 404) and the missing partial-update behavior was enough for ChatGPT to fix both immediately and correctly — confirming that a vague first prompt, not the AI's capability, was the real source of the errors.

