A fully type-safe REST API for managing todos with JWT authentication. Built with Express, Drizzle ORM, and Zod. Have you ever felt THIS type safe before? ...and yes this readme is over the top for a todo rest API but lets face it I have to code something and you know those colored buttons above look cool
- Runtime — Node.js + Express
- Language — TypeScript (strict mode)
- Database — Neon (serverless Postgres) via Drizzle ORM
- Validation — Zod
- Auth — JWT + bcrypt
- Testing — Vitest + Supertest
- Node.js ≥ 18
- A Neon account with a Postgres database ready (or if you know what you are doing Docker and Postgres or any serverless db provider of your choice)
git clone https://github.com/CPoooo/typesafe-todo-api
cd typesafe-todo-api
npm iCopy .env.example to .env generate a secret key and fill in your values:
cp .env.example .envFor generating the secret key:
openssl rand -hex 64Paste the generated value into SECRET_KEY.
| Variable | Description |
|---|---|
DATABASE_URL |
Your Neon Postgres connection string |
PORT |
Port to run the server on (defaults to 3000) |
SECRET_KEY |
Secret used to sign and verify JWT tokens |
Push the schema to your DB:
npm run db:pushnpm run devnpm run testAll /todos routes require an Authorization: Bearer <token> header.
| Method | Route | Auth | Description |
|---|---|---|---|
| POST | /auth/register |
No | Register a new user |
| POST | /auth/login |
No | Login and receive a JWT |
| POST | /auth/signout |
No | Stateless signout |
| Method | Route | Auth | Description |
|---|---|---|---|
| GET | /todos |
Yes | Get all todos for the current user |
| GET | /todos/:id |
Yes | Get a single todo by ID |
| POST | /todos |
Yes | Create a new todo |
| PATCH | /todos/:id |
Yes | Update a todo's title or status |
| DELETE | /todos/:id |
Yes | Delete a todo |
| Param | Type | Description |
|---|---|---|
completed |
true | false |
Filter by completion status |
sort |
createdAt |
Sort ascending by created date (default: descending) |
I can upload the postman collection as well if someone REALLY wants it
POST /auth/register
Content-Type: application/json
{
"email": "cameron@example.com",
"name": "Cameron",
"password": "password123"
}{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}POST /auth/login
Content-Type: application/json
{
"email": "cameron@example.com",
"password": "password123"
}{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}POST /todos
Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Buy milk"
}{
"todo": {
"id": 1,
"userId": 1,
"title": "Buy milk",
"completed": false,
"createdAt": "2025-06-01T00:00:00.000Z"
}
}PATCH /todos/1
Authorization: Bearer <token>
Content-Type: application/json
{
"completed": true
}{
"todo": {
"id": 1,
"userId": 1,
"title": "Buy milk",
"completed": true,
"createdAt": "2025-06-01T00:00:00.000Z"
}
}MIT
As if I need a license for this but hey! Its the MIT one take it and do something cool with this