A simple task‑tracking API powered by Node.js, Express, and PostgreSQL, containerized with Docker Compose.
Run the entire stack with one command — no manual setup required.
Installation & Run
# 1. Clone the repository
git clone <your-repo-url>
cd hello-server
# 2. Install dependencies
npm install
# 3. Start the server
node app.js
- Server runs at: http://localhost:3000
- Swagger UI at: http://localhost:3000/docs
Endpoints Table
| Method | Endpoint | Description | Status Codes |
|---|---|---|---|
| GET | /tasks |
List all tasks | 200 |
| GET | /tasks/{id} |
Get a single task by ID | 200, 404 |
| POST | /tasks |
Create a new task | 201, 400 |
| PUT | /tasks/{id} |
Update a task | 200, 400, 404 |
| DELETE | /tasks/{id} |
Delete a task | 204, 404 |
Example curl -i Output
curl -i http://localhost:3000/tasks
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 123
[
{ "id": 1, "title": "Read a bible", "done": false },
{ "id": 2, "title": "Build an app", "done": true },
{ "id": 3, "title": "Go for lecture", "done": false }
]
Swagger UI Screenshot
Notes
- Uses Express ESM syntax ("type": "module" in package.json).
- In-memory task list (no database).
- Fully documented with OpenAPI 3.0 spec served via swagger-ui-express.
Docker Implementation
QuickStart
docker compose up
This command builds and starts both the API and Postgres services.
Environment Variables
Copy .env.example to .envand set:
DATABASE_URL=postgres://postgres:dev@db:5432/tasks
PORT=3000
Database Verification
After running docker compose up, connect to Postgres:
docker exec -it self-version-db-1 psql -U postgres -d tasks
Then check your data:
\dt
SELECT * FROM "Tasks";
AI vs Me
My full prompt.
I’m building a simple Task API using Node.js, Express, and ESM modules.
Follow these stages to implement a complete CRUD API with Swagger UI documentation and a README.
Stage 0 – Hello Server
Set up a basic Express server on port 3000.
Return a “hello” message at /.
Confirm with curl -i http://localhost:3000 → status 200.
Stage 1 – Root and Health Endpoints
Add GET / returning JSON:
{ "name": "Task API", "version": "1.0", "endpoints": ["/tasks"] }
Add GET /health returning { "status": "ok" }.
Stage 2 – Read Endpoints
Create an in‑memory array of 3 tasks: each with id, title, and done.
Add GET /tasks → returns all tasks.
Add GET /tasks/:id → returns one task or { "error": "Task not found" } with status 404.
Stage 3 – Create Endpoint
Add POST /tasks → accepts JSON { "title": "Buy milk" }.
Assign next id, set done: false, return created task with status 201.
Validate input: missing/empty title → status 400.
Stage 4 – Update & Delete
Add PUT /tasks/:id → updates title and/or done. Unknown id → 404, invalid body → 400.
Add DELETE /tasks/:id → removes task, returns 204 or 404 if not found.
Confirm CRUD works with correct status codes (200, 201, 204, 400, 404).
Stage 5 – Swagger UI
Install swagger-ui-express.
Write a small openapi.json describing the five task endpoints.
Serve it at /docs.
In Swagger UI, use “Try it out” to create, list, update, and delete tasks.
/docs should show all endpoints and support the full CRUD cycle.
Stage 6 – README
Write a README that includes:
What the project is and what it does.
How to install and run it (one documented command).
A table listing all endpoints with their methods and expected responses.
One pasted curl -i output example.
A screenshot of your Swagger UI page.
Use modern JavaScript (ESM imports/exports) and keep everything in a single file for simplicity.
Comparing AI Code with My Code
- What did the AI do better — and do you understand its version well enough to explain it? The AI generated the code with better error handling with a detailed documentation.
- What did it get wrong or quietly ignore from your prompt? - The AI did not ignore anything or got anything wrong from my prompt.
- What did your prompt forget to specify — My prompt did not forget any details. I described the complete details of the project in my prompt.
Why I Did Not Use SQLite
I initially planned to use SQLite (via better‑sqlite3) because it’s simple, lightweight, and requires no external server. However, on my Windows 10 system, the installation failed with a native C++ compilation error.
better‑sqlite3 depends on node‑gyp and Visual Studio Build Tools to compile its bindings. My setup lacked the required “Desktop development with C++” workload, and Node 22 no longer supports older Visual Studio versions. As a result, the module couldn’t build successfully — even after verifying Python and Node‑gyp versions.
Why I Chose Postgres + Sequelize
To avoid native compilation issues and gain a more scalable setup, I switched to PostgreSQL with Sequelize ORM.
This choice offers several advantages:
- No native compilation —
Sequelizeuses pure JavaScript drivers (pg and pg‑hstore). - Cross‑platform reliability — works seamlessly on Windows without extra build tools.
- Automatic table creation and seeding — the app initializes the database automatically on startup.
The server connects to Postgres, creates the Tasks table, and seeds three example tasks — no manual setup required.
DB Screenshot
- GitHub link: Flyrank.ai


Top comments (0)