Build a Task Management App
Build a full-featured task management application with CRUD operations, drag-and-drop, local storage persistence, and keyboard shortcuts.
Planning the task manager architecture
A task management app is a CRUD application at its core — Create, Read, Update, Delete — but a good one requires thoughtful data modelling and state management. Before writing code, define the data model. Ask Claude Code: Create a Next.js project with TypeScript and Tailwind for a task management app. Define types at src/types.ts for: Task (id as string using crypto.randomUUID, title, description optional, status as todo or in_progress or done, priority as low or medium or high or urgent, labels as array of strings, dueDate as Date or null, createdAt as Date, updatedAt as Date, order as number for sorting within a column), Board (id, name, columns as array of Column), and Column (id, name, status mapping, tasks as array of Task references, colour). Design the initial board with three columns: To Do, In Progress, and Done. Each column maps to a task status. When a task moves between columns, its status updates automatically. Ask Claude Code: Create a data store at src/lib/store.ts using React context and useReducer. Define actions for ADD_TASK, UPDATE_TASK, DELETE_TASK, MOVE_TASK, REORDER_TASK, ADD_LABEL, and CLEAR_COMPLETED. The reducer should handle each action immutably — never mutate state directly. This architecture separates your UI from your data logic. The components dispatch actions, the reducer updates state, and the components re-render with the new state. Common error: generating IDs with Math.random is not safe for unique identifiers. Use crypto.randomUUID() in modern browsers or the uuid package as a fallback.
Building the Kanban board layout
The Kanban board is the main view — columns of tasks that flow from left to right as work progresses. Ask Claude Code: Create a KanbanBoard component that renders three columns side by side. Each column has a header showing the column name, task count, and a colour-coded top border. Below the header, tasks are listed vertically as cards. At the bottom of each column, show an Add Task button. The board should scroll horizontally on mobile (columns as a horizontal scrollable row) and show all three columns on desktop. Create a TaskCard component for individual tasks. Each card shows: the task title (bold, truncated to 2 lines), priority indicator (coloured dot — red for urgent, orange for high, blue for medium, grey for low), labels as small coloured pills, due date with visual urgency (red text if overdue, orange if due today, grey if future), and a subtle hover effect revealing edit and delete buttons. Ask Claude Code: Add a quick-add feature. Clicking Add Task at the bottom of a column should show an inline form — not a modal — where the user types a task title and presses Enter to create it. The task is created in the column where they clicked. Pressing Escape cancels the creation. After creation, the input stays focused so the user can rapidly add multiple tasks. This inline creation pattern is much faster than modal-based creation for power users who add many tasks at once. For detailed editing, clicking a task card opens a side panel. Ask Claude Code: Create a TaskDetailPanel component that slides in from the right. Show all task fields as editable inputs: title, description (markdown textarea), status dropdown, priority dropdown, labels (tag-style input where you type and press Enter to add), and due date picker. Changes save automatically with a debounce — no explicit save button needed. Show a "last saved" timestamp to confirm changes persisted.
Implementing drag-and-drop
Drag-and-drop is the signature interaction of a Kanban board. Users drag task cards between columns to update their status and within columns to reorder priorities. Ask Claude Code: Implement drag-and-drop for the Kanban board using the HTML5 Drag and Drop API (no external library). Each TaskCard should be draggable. Each Column should be a drop target. When dragging starts, add a visual indicator: reduce the opacity of the dragged card and show a dotted placeholder where the card will be dropped. When dragging over a column, highlight the column with a subtle border colour change. When dropped, update the task's status to match the target column and update the order to reflect its new position. The drag-and-drop implementation needs three event handlers on each card: onDragStart (store the task ID in dataTransfer, set the visual effect), onDragOver on columns (call preventDefault to allow dropping, show the drop indicator), and onDrop on columns (read the task ID from dataTransfer, dispatch a MOVE_TASK action). Ask Claude Code: Add drop position tracking so tasks can be dropped between specific cards in a column, not just at the end. Show a horizontal line indicator between cards during drag-over to show exactly where the task will land. Calculate the insertion index based on the mouse position relative to the existing cards. For touch devices, the HTML5 Drag and Drop API does not work. Ask Claude Code: Add touch support using pointer events. Track touchstart, touchmove, and touchend events. On touchstart, begin tracking the touch position. On touchmove, move a clone of the card element to follow the finger, calculate which column and position the finger is over, and show the drop indicator. On touchend, perform the drop action. Common error: flickering during drag. If the drag indicator itself triggers dragover events, you get an infinite loop of enter/leave events. Set pointer-events: none on the drag preview element to prevent this.
Filtering, sorting, and search
As the task list grows, users need ways to find and organise their tasks. Ask Claude Code: Create a toolbar above the Kanban board with filter, sort, and search controls. The search bar filters tasks in real-time as the user types — matching against task title, description, and labels. Show matching text highlighted in the task cards. Priority filter: a row of toggle buttons (All, Urgent, High, Medium, Low) that filter the board to show only tasks of the selected priority. Multiple priorities can be active at once. Label filter: a dropdown showing all labels used across tasks. Selecting a label filters to tasks with that label. Status filter: toggle columns on and off to focus on specific stages. Sort options: within each column, sort tasks by priority (urgent first), due date (earliest first), created date (newest first), or alphabetical. The current sort is shown in the column header. Ask Claude Code: Implement all filters as URL query parameters so the current view is shareable. If I filter to urgent tasks and copy the URL, another person opening that URL should see the same filtered view. Use Next.js useSearchParams to read and write query parameters. Add a saved views feature. Ask Claude Code: Let users save the current combination of filters and sorts as a named view. Store saved views in localStorage. Show them as quick-access buttons below the toolbar. Default views: My Urgent Tasks (urgent and high priority, sorted by due date), Overdue (past due date, any status except done), and Recently Added (created in the last 7 days, sorted by creation date). The filter system should feel instant. For up to a few hundred tasks, client-side filtering is fast enough. Filter on every keystroke without debouncing for immediate feedback. Common error: when multiple filters are active, combine them with AND logic (task must match all active filters), not OR logic. Show a clear indication of active filters and a Reset All button.
Keyboard shortcuts and productivity features
Power users want to manage tasks without touching the mouse. Ask Claude Code: Add keyboard shortcuts to the task manager. N opens the quick-add form in the first column. 1, 2, 3 switch focus to columns To Do, In Progress, Done. Arrow up and down navigate between task cards within a column. Arrow left and right move a focused task to the adjacent column (changing its status). E opens the detail panel for the focused task. Delete or Backspace deletes the focused task (with a confirmation). Escape closes any open panel or form. Forward slash focuses the search bar. Show a keyboard shortcut legend when the user presses the question mark key. Ask Claude Code: Create a keyboard shortcut help modal that shows all available shortcuts grouped by category (navigation, task management, views). Display it when the user presses Shift+?. Add undo and redo for all task actions. Ask Claude Code: Implement an undo/redo system. Every task action (create, edit, move, delete) pushes the previous state to an undo stack. Ctrl+Z pops from the undo stack and pushes to the redo stack. Ctrl+Shift+Z (or Ctrl+Y) pops from the redo stack. Show a toast notification on undo and redo: Undo: task deleted restored or Redo: moved Task Name to Done. Add a bulk actions mode. Ask Claude Code: Let users select multiple tasks by holding Shift and clicking. Show a floating action bar with bulk actions: move all to a column, set priority, add a label, or delete. Show the count of selected tasks. Click anywhere outside the selection to deselect all. Add task templates for recurring task types. Ask Claude Code: Create a template system where users define task templates with pre-filled fields (title pattern, default priority, default labels, checklist items). When creating a new task, offer to create from a template. Common error: keyboard shortcuts should not fire when the user is typing in an input or textarea. Check if the active element is an input before handling shortcut keys.
Local storage persistence and data management
The task manager must persist data across page reloads and browser sessions. Ask Claude Code: Implement localStorage persistence for the task store. After every state change, serialise the entire state to JSON and save it to localStorage under a key like enigmatica-tasks. On initial load, check localStorage for existing data and use it as the initial state. Handle the case where the stored data is corrupted or from an incompatible version — fall back to empty state with a console warning. Add data versioning. Ask Claude Code: Include a version number in the stored data. When the data format changes (new fields, renamed fields), increment the version and write a migration function that transforms old data to the new format. This prevents data loss when you update the application. Version 1 might have tasks with a status of todo or done. Version 2 adds in_progress. The migration function sets all version 1 tasks with status todo to remain as todo — no data is lost. Add import and export functionality. Ask Claude Code: Create an Export button that downloads all tasks as a JSON file. Create an Import button that reads a JSON file, validates its structure, and merges or replaces the current tasks. Add a CSV export option for users who want to open their tasks in a spreadsheet — columns for title, description, status, priority, labels, due date, and created date. Add a data management section in settings. Ask Claude Code: Create a settings page with options to clear all completed tasks, archive tasks older than 30 days (move to a separate archived storage), export data as JSON or CSV, import data from JSON, and reset all data (with a strong confirmation — type DELETE to confirm). Show storage usage: how many tasks exist, how much localStorage space is used, and the maximum available. Common error: localStorage has a 5 to 10 MB limit depending on the browser. If the user has thousands of tasks with long descriptions, you might hit this limit. Show a warning when usage exceeds 80 percent and suggest exporting and archiving old data.
Deployment and progressive web app setup
Deploy the task manager as a progressive web app (PWA) so users can install it on their device and use it offline. Ask Claude Code: Configure the task manager as a PWA. Create a manifest.json with the app name, short name, icons in multiple sizes, theme colour matching the app's design, and display set to standalone (removes the browser chrome when installed). Create a service worker that caches the application shell — all HTML, CSS, JavaScript, and static assets. Since all data is in localStorage, the app works fully offline without any special data syncing. Add an install prompt. Ask Claude Code: Detect when the browser shows the beforeinstallprompt event and display a custom Install App banner at the top of the page. The banner should explain the benefit: Install Enigmatica Tasks for offline access and a native app experience. Dismiss if the user clicks Not Now, and do not show again for 30 days. After installation, remove the banner permanently. Add a share feature. Ask Claude Code: Create shareable task links using URL encoding. A share link encodes a single task's data in the URL — when someone opens it, they see the task details and can add it to their own board. This is useful for teams sharing task templates without needing a backend. Deploy to Vercel. Ask Claude Code: Configure the project for Vercel deployment with proper caching headers. Static assets should be cached for a year. The service worker should not be cached (so updates deploy immediately). Set up a custom domain if available. Test the complete app: add tasks, drag between columns, filter, search, close the browser, reopen, and verify all data persists. Test on mobile: install as PWA, add tasks offline, verify they are there when you reopen. Test the import/export cycle: export from one browser, import into another. The task manager is complete — a production-quality application built entirely with AI assistance.
Building Real Applications
This guide is hands-on and practical. The full curriculum covers the conceptual foundations in depth with structured lessons and quizzes.
Go to lesson