Task Management Client
A production-ready, minimalist task management UI built for high-performance state synchronization.
- Version: 1.0.0
- Author: Ashif EK
- Tech Stack: React 19, Vite, Redux Toolkit, Tailwind CSS v4, JSON Server
- Status: Production-Ready
- Last Updated: 2026-05-25
1. Executive Summary
Business Problem
Task management tools often suffer from bloated interfaces, sluggish state updates, and inconsistent offline-to-online synchronization. Users require immediate feedback when creating, editing, or filtering tasks without waiting for network round-trips.
Engineering Problem
Synchronizing complex local state (including Base64 image attachments) with a remote backend while maintaining a 60fps UI requires careful orchestration of asynchronous side effects, debouncing input streams, and handling race conditions.
Why This Project Exists
Task Management Client serves as an enterprise-grade sandbox demonstrating how to properly architecture Redux Toolkit (RTK) async thunks, handle complex side-effects (throttling/debouncing via Lodash), and structure a scalable frontend monolith.
Goals
- Technical Goals: Implement strict unidirectional data flow, decouple API integration from UI components, and maintain O(1) or O(log n) performance for state updates.
- Scalability Goals: Ensure the Redux slice can handle thousands of tasks locally via memoized selectors.
- Security Goals: Validate all inputs and sanitize Base64 payloads to prevent XSS.
2. System Overview
High-Level Architecture
The system employs a standard Client-Server architecture. The frontend is a Single Page Application (SPA) powered by Vite and React, heavily leveraging Redux Toolkit for global state management. The backend is an ephemeral Node.js-based JSON Server acting as a lightweight REST API.
Major Modules
- UI Layer: React components styled with Tailwind CSS v4.
- State Management Layer: Redux Toolkit
todosSlicemanaging synchronous reducers and async thunks. - API Client Layer: Axios-based singleton handling network requests.
- Persistence Layer: JSON Server writing to
db.json.
Data Flow
- User interacts with UI (e.g., typing in search).
- UI dispatches an action (debounced via Lodash).
- Redux Thunk intercepts the action, transitioning state to
loading. - API Client executes the network request.
- On success, Thunk dispatches
fulfilled, updating the Redux store. - Memoized selectors recompute, triggering a React re-render.
3. Architecture Diagrams
System Architecture
graph TD
Client[React SPA Client]
RTK[Redux Toolkit Store]
API[Axios API Client]
Server[JSON Server Backend]
DB[(db.json)]
Client -->|Dispatches Action| RTK
RTK -->|Executes Thunk| API
API -->|HTTP REST| Server
Server -->|File I/O| DB
Server -.->|HTTP Response| API
API -.->|Resolves Thunk| RTK
RTK -.->|Updates State| Client
State Management Flow
sequenceDiagram
participant UI as React Component
participant Dispatcher as Redux Dispatcher
participant Thunk as Async Thunk (addNewTodo)
participant API as Axios Client
participant Server as REST API
UI->>Dispatcher: dispatch(addNewTodo(payload))
Dispatcher->>Thunk: Execute
Thunk->>Dispatcher: dispatch(pending)
Thunk->>API: POST /todos
API->>Server: HTTP Request
Server-->>API: 201 Created
API-->>Thunk: Resolved Data
Thunk->>Dispatcher: dispatch(fulfilled)
Dispatcher-->>UI: State Updated (Re-render)
4. Component & State Architecture
Purpose
The frontend is architected to decouple view logic from business logic. Components should only read state via selectors and mutate state via dispatches.
Internal Working
todosSlice: Central source of truth. HandlesfetchTodos,addNewTodo,toggleTodoStatus,updateTodoText,deleteTodoItem, andclearCompletedTodos.- Memoized Selectors: Uses
selectFilteredTodosandselectStatsto prevent unnecessary re-renders. Computations like percentage completed are derived purely from the Redux state.
Tradeoffs
Using Redux Toolkit for a relatively simple application introduces boilerplate. However, this tradeoff was explicitly chosen to demonstrate enterprise scalability. If this were a simple prototype, React Context or Zustand might have sufficed.
5. API Documentation
REST Endpoints Overview
The application relies on a standard RESTful convention generated by json-server.
Fetch Todos
- Endpoint:
GET /todos - Purpose: Retrieve all task items.
- Response:
200 OK[ { "id": 1, "text": "Complete documentation", "completed": false, "image": "data:image/png;base64,..." } ]
Create Todo
- Endpoint:
POST /todos - Purpose: Create a new task.
- Request Body:
{ "text": "New task", "image": null, "completed": false }
Update Todo
- Endpoint:
PATCH /todos/:id - Purpose: Partially update a task (text or status).
- Request Body:
{ "completed": true }
Delete Todo
- Endpoint:
DELETE /todos/:id - Purpose: Remove a task.
6. Database Documentation
Schema (db.json)
The schema is a flat, NoSQL-like JSON structure.
todosCollection:id(String/Integer): Unique identifier.text(String): The task content.completed(Boolean): Status of the task.image(String, Optional): Base64 encoded image string.
Scaling Considerations
Currently, storing Base64 images directly in db.json is highly inefficient and will bloat the file quickly.
Future Improvement: Implement AWS S3 or Cloudinary for object storage, and save only the image URL in the database.
7. Security Documentation
Current Posture
As a frontend-focused architecture sandbox, security layers are minimal. - XSS Prevention: Handled natively by React's DOM escaping. - CORS: Not strictly enforced in the ephemeral JSON server.
Production Hardening Requirements
If transitioning this to a real backend:
1. API Protection: Implement JWT or Session-based authentication.
2. Payload Validation: The backend must validate that text is an actual string and strip HTML tags.
3. Image Sanitization: Base64 uploads must be validated against malicious payloads and restricted by file size (e.g., < 2MB).
8. Frontend Documentation
Performance Optimization
- Debouncing: Search inputs are debounced via
lodashto prevent firing Redux filter computations on every keystroke. - Throttling: Rapid clicks on "Delete" or "Complete" are throttled.
- CSS Architecture: Tailwind CSS v4 is used for zero-runtime styling, ensuring optimal bundle size.
Component Structure
features/todos: Contains Redux slices and tightly coupled logic.components/: Pure presentation components.api/client.js: Singleton Axios instance.
9. Backend Documentation
Ephemeral JSON Server
The backend is a simple json-server implementation meant purely to support frontend development.
- Middleware: Uses standard json-server defaults (logger, static, cors).
- Limitations: No transaction support, no relational constraints, no horizontal scalability.
10. DevOps Documentation
Development Environment
# Start frontend
npm run dev
# Start backend
cd server && npm start
Production Deployment
- Frontend: Deployable as a static site to Vercel, Netlify, or AWS S3.
- Backend: Render is currently used as the remote host for the JSON server.
11. Performance Documentation
Bottlenecks
- Large Base64 Payloads: Pushing megabytes of Base64 strings through Redux serialization can cause memory spikes.
- Optimization Strategy: Migrate to Multipart Form Data uploads directly to an S3 bucket, bypassing Redux for the binary payload.
12. Error Handling Documentation
Redux Error Boundaries
Thunks utilize standard try/catch and RTK's .rejected lifecycle action to push error messages into state.todos.error.
13. Testing Documentation
(Testing suite is currently a placeholder for future implementation) - Proposed Unit Tests: Test Redux reducers and selectors using Jest. - Proposed E2E: Use Playwright to simulate task creation and attachment uploads.
14. Project Structure
todo-redux-adv/
├── my-app/ # Frontend React Application
│ ├── src/
│ │ ├── api/ # Axios client instances
│ │ ├── features/ # Redux slices (todosSlice)
│ │ ├── store.js # RTK Store configuration
│ │ └── App.jsx # Root layout
│ └── package.json
└── server/ # Backend JSON Server
├── db.json # Flat-file database
└── server.js # Server entry point
15. Engineering Decisions
Why Redux Toolkit?
While React Context is simpler, RTK was chosen to demonstrate state predictability, easy integration with Redux DevTools, and structured handling of async side-effects via Thunks.
Why Tailwind CSS v4?
Tailwind v4 introduces a new engine that drastically reduces build times and removes the need for extensive configuration files, making the project highly portable.
16. Advanced Engineering Insights
[!WARNING] Production Bottleneck Detected The current architecture handles image uploads by encoding them as Base64 strings and passing them through the Redux store into the JSON database.
Impact: As the database grows, the
fetchTodospayload will become massive, leading to high TTFB (Time to First Byte) and potential browser memory exhaustion when RTK attempts to serialize thousands of Base64 strings.Resolution: Implement signed URLs. The client should request an S3 pre-signed URL, upload the binary directly, and only store the S3 URL in the Redux state and Database.