TaskFlow is a lightweight full-stack Kanban task management application designed for small teams, inspired by tools such as Trello.
It provides a persistent task board with multiple columns, task creation and editing, task deletion, priority filtering, search, task movement, and database-backed persistence.
- React
- TypeScript
- Vite
- Custom CSS
- HTML5 Drag and Drop API
- Node.js
- Express
- TypeScript
- SQLite
sql.js- Raw SQL queries
- Vitest
- Supertest
Live Application: TODO โ Add deployed frontend URL
Backend API: TODO โ Add deployed backend URL
GitHub Repository: TODO โ Add GitHub repository URL
The live URLs will be added after deployment.
Follow these steps to run TaskFlow locally from a fresh clone.
- Node.js: v18.x or higher
- npm: v9.x or higher
Check your installed versions:
node --version
npm --versiongit clone <repository-url>
cd taskflowInstall dependencies for both the backend and frontend:
npm run install:allAlternatively, install them separately:
cd backend
npm install
cd ../frontend
npm installOpen a terminal and run:
cd backend
npm run devThe Express API will start at:
http://localhost:5000
The SQLite database is initialized automatically when the backend starts. The schema and seed data are provided in:
backend/src/db/schema.sql
backend/src/db/seed.sql
Open a second terminal:
cd frontend
npm run devThe frontend will be available at:
http://localhost:3000
Open the URL in your browser.
The backend test suite covers API validation, task movement, and direct database-layer queries.
From the backend directory:
cd backend
npm test-
Empty Title Validation Verifies that creating or editing a task with an empty or whitespace-only title returns HTTP
400. -
Task Movement Verifies that moving a task updates its
column_idcorrectly. -
Task Count SQL Query Executes the task-count query against known seed data and verifies the returned counts, including columns containing zero tasks.
-
Priority and Search Filtering Verifies database-level filtering by task priority and keyword search.
TaskFlow uses SQLite as a relational database.
The data model follows:
Board
โ
โโโ Column
โ โโโ Task
โ โโโ Task
โ โโโ Task
โ
โโโ Column
โ โโโ Task
โ
โโโ Column
โโโ Task
| Field | Description |
|---|---|
id |
INTEGER primary key |
name |
Board name, required |
created_at |
Creation timestamp |
| Field | Description |
|---|---|
id |
INTEGER primary key |
board_id |
Foreign key โ boards(id) |
name |
Column name, required |
position |
Column ordering |
created_at |
Creation timestamp |
| Field | Description |
|---|---|
id |
INTEGER primary key |
column_id |
Foreign key โ columns(id) |
title |
Required task title |
description |
Optional description |
priority |
Low, Medium, or High |
position |
Task ordering within a column |
created_at |
Creation timestamp |
Foreign-key relationships use cascading deletes where appropriate.
The complete schema is available in:
backend/src/db/schema.sql
Seed data is available in:
backend/src/db/seed.sql
TaskFlow uses raw SQL for database-level operations rather than fetching all records and performing filtering entirely in the frontend.
The task-count query uses a LEFT JOIN and COUNT(t.id) so columns with no tasks are still included in the results.
SELECT
c.id AS column_id,
c.name AS column_name,
c.position,
COUNT(t.id) AS task_count
FROM columns c
LEFT JOIN tasks t ON c.id = t.column_id
WHERE c.board_id = ?
GROUP BY c.id, c.name, c.position
ORDER BY c.position ASC;This query is used to display the number of tasks in each board column.
Task filtering is implemented at the database layer.
The task query joins tasks with columns, restricts results to the requested board, and applies the requested priority and search conditions.
The results are ordered by creation time:
ORDER BY t.created_at DESC, t.id DESC;The implementation is available in:
backend/src/db/queries.ts
This approach avoids retrieving all tasks and performing the filtering only in the React application.
GET /api/boards/:idReturns the board, its columns, and associated tasks.
GET /api/tasksSupported query parameters:
boardId
priority
search
Example:
/api/tasks?boardId=1&priority=High
POST /api/tasksExample request:
{
"column_id": 1,
"title": "Build API",
"description": "Create the required REST endpoints",
"priority": "High"
}PUT /api/tasks/:idExample request:
{
"title": "Updated task title",
"description": "Updated description",
"priority": "Medium"
}PATCH /api/tasks/:id/moveExample request:
{
"column_id": 2,
"position": 0
}DELETE /api/tasks/:idGET /api/boards/:id/statsReturns task counts for each column using the custom SQL aggregation query.
TaskFlow performs validation on the backend to prevent invalid data from reaching the database.
For example, an empty or whitespace-only task title is rejected with HTTP 400:
{
"success": false,
"error": "Task title is required and cannot be empty."
}The backend also validates:
- Board IDs
- Task IDs
- Column IDs
- Target columns
- Task titles
- Task priorities
API errors follow a consistent structure:
{
"success": false,
"error": "Error description"
}This allows the frontend to display meaningful error messages instead of exposing raw server errors.
The application provides a clean Kanban-style interface with:
- Separate task columns
- Task priority badges
- Task search
- Priority filtering
- Create/edit task modal
- Task deletion
- HTML5 drag-and-drop
- Quick-move dropdown fallback
- Task counts per column
- Error notifications
- Responsive layout
The implementation focuses on functionality and usability rather than unnecessary visual complexity.
The current application uses a default primary board:
board_id = 1
The database schema supports relationships between multiple boards, allowing the application to be extended to support multiple boards in the future.
SQLite was selected because it provides a real relational database without requiring a separate database server.
This keeps local setup simple while still demonstrating:
- Primary keys
- Foreign keys
- Constraints
- SQL joins
- Aggregation
- Parameterized queries
- Database persistence
SQLite is accessed through sql.js using a small database wrapper for database initialization, SQL execution, and test isolation.
Task movement supports two mechanisms:
- HTML5 drag-and-drop
- Quick-move dropdown
The dropdown provides a reliable fallback when drag-and-drop is unavailable or inconvenient.
Priority and search filtering are performed through SQL rather than downloading all tasks and filtering them entirely in React.
This keeps data filtering within the database layer and demonstrates practical SQL usage.
If more development time were available, the following improvements could be added:
- Column creation, renaming, deletion, and reordering
- Task activity history
- User accounts and task assignment
- Tags and advanced filtering
- More advanced task ordering
- Real-time updates
- Persistent production database storage
- Additional frontend automated tests
These features were intentionally not prioritized because the core assignment focuses on a reliable task board.
Approximately 3.5 hours were spent building the project.
| Area | Approximate Time |
|---|---|
| Setup & schema design | 30 minutes |
| Backend API, SQL & tests | 1 hour |
| Frontend UI, drag-and-drop & filtering | 1.5 hours |
| Testing, debugging & documentation | 30 minutes |
| Total | ~3.5 hours |
One interesting part of the implementation was working with LEFT JOIN and aggregation in SQLite.
When counting tasks per column, using:
COUNT(t.id)correctly returns 0 for a column containing no tasks.
In contrast, using:
COUNT(*)would count the row produced by the LEFT JOIN, even when the task columns are NULL.
This reinforced the importance of choosing the correct aggregate expression when working with outer joins.
| Requirement | Status |
|---|---|
| Board โ Columns โ Tasks relational model | โ |
| Create task | โ |
| Edit task | โ |
| Delete task | โ |
| Move task between columns | โ |
| Backend/database persistence | โ |
| Priority filtering | โ |
| Task title search | โ |
| Backend empty-title validation | โ |
| Error handling | โ |
| SQLite database | โ |
| Database schema file | โ |
| Seed data | โ |
| Custom SQL query #1 | โ |
| Custom SQL query #2 | โ |
| Backend tests | โ |
| README/setup instructions | โ |
| Live deployment | ๐ Add URL before submission |
This project was created as a take-home assignment for evaluation purposes.