A full-stack Task Manager application built with React (frontend) and Node.js/Express (backend).
- Create, view, update, and delete tasks
- Mark tasks as complete / incomplete
- Edit task titles inline (double-click or pencil icon)
- Filter tasks by All / Active / Completed
- Loading and error states throughout
- Docker support for one-command startup
- Node.js 18+
- npm
cd backend
npm install
npm startThe API will be available at http://localhost:3001.
In a separate terminal:
cd frontend
npm install
npm startThe app will open at http://localhost:3000.
The frontend is configured to proxy
/tasksrequests tolocalhost:3001via the"proxy"field inpackage.json, so no CORS configuration is needed in development.
Requires Docker and Docker Compose.
docker-compose up --build- Frontend:
http://localhost:3000 - Backend API:
http://localhost:3001
| Method | Endpoint | Description |
|---|---|---|
| GET | /tasks | Return all tasks |
| GET | /tasks?filter=completed | Filter by status |
| GET | /tasks?filter=incomplete | Filter by status |
| POST | /tasks | Create a new task |
| PATCH | /tasks/:id | Update title or status |
| DELETE | /tasks/:id | Delete a task |
{
"id": "uuid",
"title": "string (max 200 chars)",
"completed": false,
"createdAt": "ISO 8601 timestamp"
}{ "title": "Buy groceries" }{ "completed": true }
{ "title": "Updated title" }
{ "completed": true, "title": "Updated title" }task-manager/
├── backend/
│ ├── src/
│ │ ├── index.js # Express server entry point
│ │ ├── store.js # In-memory data store
│ │ └── routes/
│ │ └── tasks.js # All task route handlers
│ ├── Dockerfile
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Root component
│ │ ├── App.css # Styles
│ │ ├── api.js # API client (fetch wrapper)
│ │ ├── components/
│ │ │ ├── TaskForm.jsx # Add task form
│ │ │ ├── TaskList.jsx # Task list + filter tabs
│ │ │ └── TaskItem.jsx # Individual task row with edit/delete
│ │ └── hooks/
│ │ └── useTasks.js # Data fetching and mutation hook
│ ├── public/index.html
│ ├── nginx.conf # Used in Docker build
│ ├── Dockerfile
│ └── package.json
├── docker-compose.yml
├── .gitignore
└── README.md
-
In-memory storage: Tasks are stored in a JavaScript array on the server. Data resets on server restart. This was chosen to keep the solution simple and dependency-free per the assignment brief. Swapping in SQLite or PostgreSQL would require minimal changes to
store.jsonly. -
No authentication: The API is open, which is appropriate for this scope.
-
Optimistic UI not used: All mutations wait for the server response before updating the UI. This keeps the error handling straightforward and avoids rollback complexity.
-
Proxy in development: The React dev server proxies
/taskstolocalhost:3001. In the Docker build, nginx handles the proxy instead. -
Bonus items included: Filter by status, inline title editing, and Docker setup are all implemented since they fit naturally within the time budget.