Secure REST API with event-driven reminders, category/tag management, and simulated external webhook integration.
- Node.js + Express.js
- PostgreSQL (
pg) for users - MongoDB (
mongodb) for tasks, categories, tags - JWT auth (
jsonwebtoken), password hashing (bcryptjs) - Validation with
joi
- Register/login with hashed password and JWT.
- Authenticated profile endpoint.
- Task CRUD scoped by
userId(no cross-user access).
- On task create/update with
dueDate(due_datealias supported), system schedules in-memory reminder. - Reminder fires
REMINDER_LEAD_MINUTESbefore due date (default60). - If due date updated, old reminder canceled and new one scheduled.
- If task marked
completedor deleted, reminder canceled. - Reminder event logs to console +
logs/notifications.log. - Optional reminder webhook call if
REMINDER_WEBHOOK_URLexists.
- Dynamic user-owned categories (
/api/categoriesCRUD). - Dynamic user-owned tags (
/api/tagsCRUD), tag text is free-form. - Task supports
category(string) andtags(array of strings). - Filter endpoint supports category/tags/status:
GET /api/tasks/filter.
- When task status transitions to
completed, API emits event. - Event handler sends
POSTwebhook toANALYTICS_WEBHOOK_URL. - Retry logic: up to 3 retries, exponential backoff (
1s,2s,4s). - Delivery logs written to console +
logs/notifications.log.
npm installCreate .env (or copy from .env.example):
PORT=3001
POSTGRES_URI=postgres://taskuser:taskpassword@localhost:5433/taskdb
MONGODB_URI=mongodb://localhost:27017/taskapp
JWT_SECRET=replace_with_strong_secret
# Reminder config
REMINDER_LEAD_MINUTES=60
REMINDER_WEBHOOK_URL=
# Analytics webhook on task completion
ANALYTICS_WEBHOOK_URL=docker-compose up --buildApp runs on http://localhost:3001.
Run databases first:
docker-compose up -d postgres mongodbRun API locally:
npm run devor
npm startsrc/config/DB connection config.src/controllers/route handlers.src/events/event bus + event handler registration.src/middlewares/auth + global error handler.src/models/DB collection/table wrappers.src/routes/API route definitions.src/services/reminder scheduler, notifications, webhook retry logic.src/validators/Joi schemas.
- Chosen dynamic user-defined categories.
- Reason: flexible for personal/team workflows, no hardcoded enum migration.
- Category rename/delete cascades into user tasks for consistency.
- Tags stored as free-form strings in task docs.
- Separate tag CRUD endpoints maintain reusable tag list per user.
- Tag rename/delete propagates to existing user tasks.
- In-memory
setTimeoutscheduler for simplicity. taskId -> timeoutmap enables cancellation/reschedule.- Scheduler rehydrates on server boot by scanning pending tasks with due date.
- Tradeoff: in-memory jobs lost if process restarts; acceptable for simulation scope.
- Event-driven completion webhook (decoupled from request/response path).
fetch+ retry loop with exponential backoff.- Logs every retry/success/failure to file + console.
All endpoints below require Authorization: Bearer <token> except register/login.
{
"email": "user@example.com",
"password": "password123"
}{
"email": "user@example.com",
"password": "password123"
}{
"title": "Finish report",
"description": "Quarterly report",
"dueDate": "2026-04-12T20:00:00.000Z",
"status": "pending",
"category": "Work",
"tags": ["High Priority", "Client A"]
}Notes:
due_datealso accepted (converted todueDate).statusdefault =pending.
Get all user tasks.
Filter by any combination of category, comma-separated tags (all tags must match), and status.
Partial updates allowed.
{ "name": "Work" }{ "name": "Personal" }{ "name": "High Priority" }{ "name": "Bug Fix" }400validation or malformed IDs.401missing/invalid JWT.404not found.500internal errors.
- Setup (docker + npm run dev).
- Register/login.
- Create task with due date and show reminder log line.
- Create categories/tags and create tasks using them.
- Filter tasks with
/api/tasks/filter. - Mark task completed and show webhook payload delivery on webhook.site.
- Show reminder cancel/reschedule by updating due date and completing task.