A modern, fully-featured Todo List application with local storage persistence, real-time search, edit/copy/delete operations, status toggles, and Progressive Web App (PWA) capabilities. Built with TypeScript and compiled to optimized JavaScript.
- Overview
- Features
- Live Demo
- Technologies Used
- Project Structure
- Installation & Setup
- Core Functionality
- Class Architecture
- TypeScript Definitions
- PWA Features
- Responsive Design
- Error Handling & Validation
- Browser Support
- Performance Optimizations
- Future Enhancements
The Todo List PWA is a complete task management solution that runs entirely in the browser. It stores tasks in the browser's local storage, ensuring data persistence across browser sessions. The application supports creating, reading, updating, deleting, copying, searching, and toggling task statuses — all with a sleek, dark-themed user interface.
| Category | Features |
|---|---|
| Task Management | ➕ Create, ✏️ Edit, 🗑️ Delete (single/all), 📋 Copy, ✅ Toggle status |
| Data Persistence | 💾 Local storage with JSON serialization |
| Search | 🔍 Real-time filtering by task title |
| UI/UX | 🌙 Dark theme, glowing effects, responsive design, visual feedback |
| Validation | |
| PWA Ready | 📱 Installable, offline-capable, service worker integration |
| TypeScript | 📘 Fully typed with interface definitions |
After installation, the application runs at http://localhost:8000 (or your configured web root).
| Technology | Purpose |
|---|---|
| HTML5 | Structure |
| CSS3 | Styling, animations, responsive design |
| TypeScript | Type-safe application logic |
| JavaScript (ES6+) | Compiled output |
| Local Storage API | Data persistence |
| PWA | Service worker, manifest, offline support |
todo-list-pwa/
├── assets/
│ ├── css/
│ │ └── styles.css # Main stylesheet
│ ├── js/
│ │ └── bundle.min.js # Compiled & minified JavaScript
│ └── pwa/ # PWA assets (if applicable)
├── configs/
│ └── ts/
│ └── app.ts # TypeScript source code
├── index.html # Main HTML entry point
├── service-worker.js # PWA service worker
├── manifest.json # PWA manifest
├── offline.html # Offline fallback page
└── README.md # Documentation
# 1. Clone or download the project
cd todo-list-pwa
# 2. Serve with any local server
# Using Python
python -m http.server 8000
# Using PHP
php -S localhost:8000
# Using Node.js (http-server)
npx http-server -p 8000
# 3. Open browser at http://localhost:8000- Upload all files to your web server
- Ensure HTTPS is enabled (required for PWA features)
- Configure service worker path in
index.html(if needed)
| Operation | Description | User Action |
|---|---|---|
| Create | Add a new todo with unique ID | Type text → Click "Create One" or Enter |
| Read | View all todos in table | Page load / after any operation |
| Update (Edit) | Change todo title | Click "Edit" → Modify text → Submit |
| Delete (Single) | Remove one todo | Click "Delete" button |
| Delete (All) | Remove all todos | Click "Delete All" button |
| Copy | Copy todo title to clipboard | Click "Copy" button |
| Toggle Status | Mark as completed/incomplete | Click checkbox |
Each todo is stored as a separate key-value pair:
// Storage key format: todo ID (number)
// Storage value format: JSON string of Todo object
{
"id": 1,
"title": "Buy groceries",
"status": false
}Storage methods:
TodoStorage.add(todo)– Store new todoTodoStorage.removeOne(todoId)– Delete single todoTodoStorage.removeAll()– Clear all todosTodoStorage.update(todoId, todo)– Update existing todoTodoStorage.getAll()– Retrieve all todosTodoStorage.editStatus(todoId)– Toggle completion status
Real-time search filters todos by title:
searchInput.addEventListener("input", () => {
const query = searchInput.value.trim().toLowerCase();
// Show/hide rows based on title match
});| Component | Element ID | Purpose |
|---|---|---|
| Header | #header |
Main container |
| Form | #todo-form |
Create/Edit submission |
| Create Input | #create-todo |
New todo title / edit field |
| Search Input | #search-todo |
Real-time filter |
| Todo Table | #table |
Display todos |
| Todo Body | #tbody |
Dynamic rows container |
| Delete All | #delete-all |
Bulk delete button |
Static utility for displaying user messages.
class Alert {
static error(message: string | number): void;
static success(message: string | number): void;
}Features:
- Auto-clears after 5 seconds
- Prevents message overlap
- Visual feedback (red for error, green for success)
Represents a single todo item.
interface TodoInterface {
id: number;
title: string | number;
status: boolean;
}
class Todo implements TodoInterface {
id: number;
title: string | number;
status: boolean;
constructor(todo: TodoInterface);
}Handles all local storage operations.
| Method | Parameters | Returns | Description |
|---|---|---|---|
add |
todo: Todo |
void |
Store new todo |
removeOne |
todoId: string |
void |
Delete by ID |
removeAll |
– | void |
Clear all todos |
update |
todoId: number, todo: object |
void |
Update existing |
getId |
todoId: number |
number |
Get ID from storage |
getTitle |
todoId: number, todoTitle: string |
string |
Get title |
getStatus |
todoId: number, todoStatus: boolean |
boolean |
Get status |
getAll |
– | TodoInterface[] |
Retrieve all |
editStatus |
todoId: number |
void |
Toggle status |
Manages DOM manipulation and event handling.
| Method | Description |
|---|---|
loadTodosFromStorage() |
Initial load of all todos |
addTodo(todo) |
Append new todo to table |
updateTodo(id, newTitle) |
Update todo title in DOM and storage |
removeAllTodo() |
Clear all todos from DOM and storage |
removeOneTodo() |
Delete single todo (event delegation) |
editStatusTodo() |
Toggle status (event delegation) |
editOneTodo() |
Handle edit mode (populate input) |
copyTodo() |
Copy title to clipboard (async) |
Manages real-time filtering.
class Search {
private static items: Array<{element: HTMLElement, text: string}>;
static init(): void; // Initialize search listener
static updateItemsList(): void; // Refresh search index
static refresh(): void; // Trigger search re-index
}The project includes full TypeScript definitions (bundle.min.d.ts).
// Core types
type sn = string | number;
interface TodoInterface {
id: number;
title: sn;
status: boolean;
}
// Global variables
declare const createForm: HTMLFormElement;
declare const createInput: HTMLInputElement;
declare const searchInput: HTMLInputElement;
declare const todoList: HTMLTableElement;
declare const deleteAll: HTMLButtonElement;
declare const todoTable: HTMLTableElement;
declare const ErrorAlert: any;
declare const SuccessAlert: any;
// Class declarations
declare class Alert { ... }
declare class Todo implements TodoInterface { ... }
declare class TodoStorage { ... }
declare class UI { ... }
declare class Search { ... }
// State variables
declare let isEditing: boolean;
declare let editingId: number | null;
declare const ui: UI;The application is fully PWA-ready with:
- Static caching – HTML, CSS, JS
- Dynamic caching – API responses (if applicable)
- Offline fallback – Custom offline page
- Cache versioning – Automatic cleanup
- Network-first strategy for page navigation
- Cache-first strategy for static assets
{
"name": "Todo List App",
"short_name": "TodoList",
"start_url": "/",
"display": "standalone",
"theme_color": "#ffff4e",
"background_color": "#101010"
}The PWA can be installed to the home screen on mobile devices and desktops.
The application adapts to different screen sizes:
| Breakpoint | Styles |
|---|---|
| Desktop (>600px) | Full width table (500px), large fonts |
| Mobile (≤600px) | Compact layout (300px), smaller fonts |
Media Query:
@media screen and (max-width: 600px) {
#create-todo, #search-todo, #table { width: 300px; }
.todo-h { font-size: 50px; }
}if (createInput.value.trim() !== "") {
// Process todo
} else {
Alert.error("⚠️ Please Write Something ⚠️");
}- Edit mode is tracked via
isEditingandeditingId - New todos are only created when not in edit mode
try {
await navigator.clipboard.writeText(textToCopy);
Alert.success("✅ Item Copied ✅");
} catch (err) {
Alert.error("⚠️ Failed to copy ⚠️");
}try {
const parsed = JSON.parse(item);
if (parsed && typeof parsed.id === "number") {
todos.push(parsed);
}
} catch (e) {
console.error("Error parsing storage item", e);
}| Browser | Version | Support |
|---|---|---|
| Chrome | 60+ | ✅ Full |
| Firefox | 55+ | ✅ Full |
| Safari | 12+ | ✅ Full |
| Edge | 79+ | ✅ Full |
| Opera | 47+ | ✅ Full |
| iOS Safari | 12+ | ✅ Full (PWA limited) |
Required APIs:
- Local Storage (all modern browsers)
- Clipboard API (requires HTTPS or localhost)
- ES6+ (Promise, arrow functions, const/let)
| Optimization | Implementation |
|---|---|
| Event Delegation | Single event listener for all dynamic buttons |
| DOM Fragments | Row creation optimized (via innerHTML) |
| Minified JS | bundle.min.js (compressed) |
| CSS Optimization | Single stylesheet, no external fonts |
| Local Storage | Efficient key-value storage |
| Search Index | Pre-computed item list for filtering |
Potential improvements for future versions:
- Drag & Drop – Reorder todos
- Due Dates – Add deadline functionality
- Categories/Tags – Organize todos by category
- Export/Import – Backup/restore data
- Sync across devices – Cloud storage integration
- Dark/Light theme toggle – User preference
- Undo/Redo – Operation history
- Batch operations – Select multiple todos
- Push notifications – Task reminders
- Accessibility improvements – ARIA labels, keyboard nav
MIT – Free for personal and commercial projects.
Developed with TypeScript, compiled to optimized JavaScript. Features a clean, dark-themed UI with glowing accents and smooth interactions.
For issues or questions:
- Check browser console for errors
- Ensure local storage is not full
- Verify JavaScript is enabled
- Clear browser cache if needed
Happy Task Managing! ✅