A modern team task management application built with React, TypeScript, Tailwind CSS v4, and Supabase.
-
Install dependencies:
npm install
-
Initialize Supabase locally:
npx supabase init
-
Start local Supabase:
npm run supabase:start
This will start a local Supabase instance with Docker. Note the API URL and anon key in the output.
-
Configure environment variables: Update
.env.localwith local Supabase credentials:VITE_SUPABASE_URL=http://127.0.0.1:54321 VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
-
Run database migrations:
npx supabase migration up
This creates all necessary tables for task management, including tasks, checklists, assignments, and tags.
-
Start the development server:
npm run dev
-
Access the services:
- App:
http://localhost:5173 - Supabase Studio:
http://127.0.0.1:54323 - API:
http://127.0.0.1:54321
- App:
-
Install dependencies:
npm install
-
Set up Supabase Cloud:
- Create a project at supabase.com
- Copy your project URL and anon key from Settings > API
- Update
.env.local:
VITE_SUPABASE_URL=https://your-project.supabase.co VITE_SUPABASE_ANON_KEY=your-anon-key-here
-
Link your local project to Supabase (optional but recommended):
npx supabase link --project-ref your-project-ref npx supabase db push
-
Start the development server:
npm run dev
- Atoms: Basic building blocks (Button, Input, TagBadge, UserAvatar, etc.)
- Molecules: Simple combinations of atoms (TaskCard, FormField, Pagination, etc.)
- Organisms: Complex UI components (Header, Sidebar, DashboardTaskList, etc.)
- Templates: Page-level layouts
src/
βββ components/ # Atomic design components
β βββ atoms/ # Basic components (Button, Input, Logo, TagBadge, UserAvatar)
β βββ molecules/ # Component combinations (FeatureCard, TaskCard, DashboardTaskCard, Pagination)
β βββ organisms/ # Complex components (Header, Sidebar, TaskList, DashboardTaskList)
β βββ templates/ # Page layouts
βββ pages/ # Page components (Home, Dashboard, SignIn, SignUp, CreateTask)
βββ services/ # API services
β βββ authService.ts # Authentication service
β βββ taskService.ts # Task management service (25+ functions)
β βββ userService.ts # User profile lookup service
β βββ supabase.ts # Supabase client configuration
βββ types/ # TypeScript type definitions
β βββ auth.ts # Authentication types
β βββ task.ts # Task, checklist, tag types
βββ hooks/ # Custom React hooks
β βββ useAuth.ts # Authentication hook
βββ utils/ # Utility functions
supabase/
βββ migrations/ # Database migrations
βββ 20251028093317_create_tasks_system.sql
tests/
βββ e2e/ # End-to-end tests (Playwright)
βββ helpers/ # Test utilities
- Comprehensive Task System with title, description, and status tracking
- Nested Checklists - Organize tasks with named checklists, each containing multiple checkable items
- Progress Tracking - Automatic calculation of task progress based on completed checklist items
- User Assignments - Assign tasks to team members with role-based access control
- Tagging System - Reusable, color-coded tags for task categorization
- Access Control - Owner-based permissions with granular access for assigned users
- Task States - Active, Completed, or Canceled status management
- Task Listing - View all tasks you own or are assigned to
- Active/Archived Sections - Tasks automatically organized by status
- Tag Filtering - Filter tasks by tag name in real-time
- Pagination - Navigate through tasks with 10 items per page (separate pagination for active and archived)
- Progress Visualization - Color-coded progress bars (teal for active, green for completed, gray for canceled)
- User Badges - Visual representation of assigned users with initials and consistent colors
- Task Status Indicators - Clear badges for DONE and CANCELED tasks
- Email/Password authentication via Supabase Auth
- Session management
- Password reset functionality
- React 19 - UI framework
- TypeScript - Type safety
- Tailwind CSS v4 - Styling with modern CSS features
- Vite - Fast build tool and dev server
- Supabase - Backend as a Service (Authentication, Database, Row Level Security)
- React Router - Client-side routing
- Playwright - End-to-end testing
- ESLint - Code linting
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLint
npm run test:e2e- Run end-to-end tests with Playwrightnpm run test:e2e:ui- Run e2e tests with Playwright UInpm run test:e2e:debug- Debug e2e tests
npm run supabase:start- Start local Supabase (requires Docker)npm run supabase:stop- Stop local Supabasenpm run supabase:status- Check Supabase statusnpm run supabase:reset- Reset local databasenpm run supabase:migrate- Push database migrations
The project follows these architectural principles:
Component Organization:
- Atomic Design System for component organization
- Components are broken down into reusable, single-purpose units
- Pages are composed from smaller components for better maintainability
Backend Architecture:
- Layered Architecture with clear separation between UI, services, and data
- Service Layer (
src/services/) handles all backend communication and business logic - Type Safety with TypeScript interfaces for all data structures
- User Service - Provides user profile lookup by IDs for displaying assigned users
Task Service Layer:
The task management system is implemented through a comprehensive service layer (src/services/taskService.ts) that provides:
- 25+ Service Functions covering all CRUD operations for tasks, checklists, items, assignments, and tags
- Automatic Authentication - All service functions validate user authentication
- Permission Validation - Access control enforced at the service layer before database operations
- Type-Safe APIs - Full TypeScript typing for inputs and outputs
- Descriptive Error Handling - Clear error messages distinguishing between permission, not-found, and validation errors
- Progress Calculation - Dynamic progress calculation based on completed checklist items
Key Design Decisions:
- Progress is Calculated, Not Stored - Task progress is computed on-demand from checklist item states rather than stored in the database, ensuring accuracy
- Cascade Deletes - Deleting a task automatically removes all related checklists, items, assignments, and tag associations
- Position-Based Ordering - Checklists and items use integer position fields for custom user-defined ordering
- Owner vs. Assigned Access - Task owners have full control including deletion and assignment management, while assigned users can view and edit
- Reusable Tags - Tags are shared across all users and tasks for consistency
- Row Level Security - Database-level security policies ensure data access rules are enforced even if bypassing the service layer
Dashboard Implementation:
- Separation of Concerns - Dashboard uses dedicated components (DashboardTaskCard, DashboardTaskList) separate from marketing components
- Client-Side Pagination - 10 tasks per page with independent pagination for active and archived sections
- Real-Time Filtering - Tag filtering resets pagination and updates instantly
- Efficient Data Fetching - Bulk user profile lookup for all assigned users in a single request
Styling:
- Tailwind CSS v4 for modern styling (no PostCSS required)
- Consistent design system with gradient backgrounds and modern UI patterns
- Glassmorphism Design - Frosted glass effect with backdrop blur on cards and UI elements
The project supports local Supabase development using Docker:
-
Prerequisites:
- Install Docker Desktop
- Ensure Docker is running
-
Initialize Supabase (first time only):
npx supabase init
-
Start local Supabase:
npm run supabase:start
This starts:
- PostgreSQL database
- Auth server
- Storage server
- Realtime server
- Studio (web UI)
-
Access Supabase Studio:
- Open
http://127.0.0.1:54323in your browser - Create tables, set up auth, and manage your local database
- Open
-
Stop local Supabase:
npm run supabase:stop
The application uses a comprehensive task management schema with migrations stored in supabase/migrations/.
Apply all migrations to your local database:
npx supabase migration upOr migrate specific files:
npx supabase db pushThe schema includes the following tables:
Core Task Tables:
tasks- Main task table with title, description, owner, status (active/completed/canceled), and timestampstask_checklists- Named checklists within tasks with positioning for custom orderingtask_checklist_items- Individual checkable items within checklists with checked state and positioningtask_assignments- Many-to-many relationship linking tasks to assigned userstags- Reusable tags with name and optional colortask_tags- Many-to-many relationship linking tasks to tags
Authentication:
auth.users- Automatically created by Supabase for user authentication
All tables have Row Level Security enabled with comprehensive policies:
Tasks:
- Users can read tasks they own or are assigned to
- Users can update tasks they own or are assigned to
- Only task owners can delete tasks
Checklists & Items:
- Access permissions inherited from parent task
- Users with task access can create, read, update, and delete checklists and items
Assignments:
- Readable by users with task access
- Only task owners can create or remove assignments
Tags:
- All authenticated users can read tags
- Authenticated users can create and manage tags
Task-Tags:
- Users with task access can add or remove tags
To create a new migration:
npx supabase migration new your_migration_nameOr generate a migration from schema changes:
npx supabase db diff -f your_migration_nameThe app uses Supabase Auth with:
- Email/Password authentication
- Session management
- Password reset functionality
See src/services/authService.ts for available auth methods.
The task management system is accessed through src/services/taskService.ts. Here are some examples:
Creating a Task:
import { createTask } from './services/taskService';
const newTask = await createTask({
title: 'Implement Dashboard',
description: 'Build the main dashboard UI',
checklists: [
{
title: 'Design Phase',
items: [
{ content: 'Create wireframes' },
{ content: 'Design mockups' }
]
},
{
title: 'Development Phase',
items: [
{ content: 'Setup components' },
{ content: 'Implement features' },
{ content: 'Add tests' }
]
}
],
assignedUserIds: ['user-id-1', 'user-id-2'],
tagIds: ['tag-id-1']
});Fetching Tasks:
import { getTasks, getTask } from './services/taskService';
// Get all tasks accessible to current user
const allTasks = await getTasks();
// Get a specific task with full details
const task = await getTask('task-id');
console.log(`Progress: ${task.progress}%`);Managing Checklists:
import {
addChecklist,
addChecklistItem,
toggleChecklistItem
} from './services/taskService';
// Add a new checklist to a task
const checklist = await addChecklist('task-id', 'Testing Phase', [
{ content: 'Write unit tests' },
{ content: 'Write e2e tests' }
]);
// Add an item to a checklist
const item = await addChecklistItem('checklist-id', 'Code review');
// Toggle an item as complete/incomplete
await toggleChecklistItem('item-id');Managing Tags:
import {
createTag,
getTags,
addTagToTask,
getOrCreateTag
} from './services/taskService';
// Create a new tag
const tag = await createTag({ name: 'urgent', color: '#ff0000' });
// Get all available tags
const allTags = await getTags();
// Add a tag to a task
await addTagToTask('task-id', 'tag-id');
// Get existing tag or create if it doesn't exist
const tag = await getOrCreateTag('frontend', '#3b82f6');Managing Task Status:
import { updateTask, updateTaskStatus } from './services/taskService';
import { TaskStatus } from './types/task';
// Update task properties
await updateTask('task-id', {
title: 'Updated Title',
description: 'Updated description'
});
// Mark task as completed
await updateTaskStatus('task-id', TaskStatus.COMPLETED);All service functions automatically handle authentication and permission checks, throwing descriptive errors when operations fail.
The user service provides functions for fetching user profiles. Located in src/services/userService.ts:
Getting User Profiles:
import { getUsersByIds } from './services/userService';
// Get profiles for multiple users (returns a Map)
const userIds = ['user-id-1', 'user-id-2', 'user-id-3'];
const userProfiles = await getUsersByIds(userIds);
// Lookup a specific user
const user = userProfiles.get('user-id-1');
console.log(user?.full_name, user?.email);Note: The current implementation returns profile data for the authenticated user and creates placeholders for other users. For production use with multiple team members, you should create a public.profiles table that mirrors user info from auth.users.
The dashboard uses a modular component architecture:
Key Components:
DashboardTaskList- Main container for displaying tasks with active/archived sectionsDashboardTaskCard- Individual task card with tags, progress, and user badgesTagBadge- Colored badge for displaying task tagsUserAvatar- Circular avatar with user initialsPagination- Navigation controls for paginated task lists
Component Hierarchy:
Dashboard (page)
βββ DashboardHeader (tag filter, create button)
βββ DashboardTaskList (receives tasks, userProfiles, tagFilter)
βββ Active Tasks Section
β βββ DashboardTaskCard (multiple)
β β βββ TagBadge (multiple)
β β βββ UserAvatar (multiple)
β βββ Pagination
βββ Archived Tasks Section
βββ DashboardTaskCard (multiple)
βββ Pagination
The dashboard fetches tasks on mount and manages state for filtering and pagination.
Simply change the environment variables in .env.local:
Local:
VITE_SUPABASE_URL=http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0Production:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-actual-anon-keyCreate a .env.local file with:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_keyImportant: Never commit .env.local to version control. It's already in .gitignore.