# Supabase Setup Guide for Gantt Board ## Step 1: Create a Supabase Project Since Supabase CLI is not installed, we'll use the Supabase Dashboard: 1. Go to https://supabase.com/dashboard 2. Click "New Project" 3. Choose your organization 4. Enter project details: - **Name:** `gantt-board` (or your preferred name) - **Database Password:** Generate a strong password (save this!) - **Region:** Choose closest to your users (e.g., `us-east-1` for US East Coast) 5. Click "Create New Project" 6. Wait for the project to be created (~2 minutes) ## Step 2: Get Your Credentials Once the project is created: 1. Go to **Project Settings** → **API** 2. Copy these values: - **Project URL** (e.g., `https://xxxxxx.supabase.co`) - **anon/public** key (under "Project API keys") - **service_role** key (under "Project API keys" - keep this secret!) ## Step 3: Create the Database Schema 1. Go to the **SQL Editor** in the left sidebar 2. Click "New Query" 3. Copy and paste the contents of `supabase/schema.sql` (created below) 4. Click "Run" This creates all tables with proper: - Primary keys (using UUID) - Foreign key constraints - Indexes for performance - Row Level Security (RLS) policies ## Step 4: Set Environment Variables Create a `.env.local` file in your project root with the credentials from Step 2: ```bash # Supabase Configuration NEXT_PUBLIC_SUPABASE_URL=https://your-project-url.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here SUPABASE_SERVICE_ROLE_KEY=your-service-role-key-here ``` **Important:** Never commit `.env.local` to git. It's already in `.gitignore`. ## Step 5: Install Supabase Client ```bash npm install @supabase/supabase-js ``` ## Step 6: Migrate Data from SQLite Run the migration script to copy your existing data: ```bash npx tsx scripts/migrate-to-supabase.ts ``` This will: 1. Read all data from your local SQLite database 2. Insert it into Supabase 3. Handle conflicts and dependencies (users first, then projects, etc.) ## Step 7: Test Locally ```bash npm run dev ``` Test all functionality: - Login/logout - Create/edit tasks - Create/edit projects - Create/edit sprints - User management Sprint date verification: - Create a sprint with `startDate`/`endDate` from date inputs (for example `2026-02-16` to `2026-02-22`). - Confirm UI displays the same calendar dates without shifting a day earlier in local timezone. - Confirm `sprints.start_date` and `sprints.end_date` are stored as `YYYY-MM-DD` in Supabase. ## Step 8: Deploy to Vercel ### Add Environment Variables in Vercel: 1. Go to your Vercel dashboard 2. Select the gantt-board project 3. Go to **Settings** → **Environment Variables** 4. Add all variables from `.env.local`: - `NEXT_PUBLIC_SUPABASE_URL` - `NEXT_PUBLIC_SUPABASE_ANON_KEY` - `SUPABASE_SERVICE_ROLE_KEY` ### Deploy: ```bash vercel --prod ``` Or push to git and let Vercel auto-deploy. ## Troubleshooting ### Connection Issues - Verify your Supabase URL and keys are correct - Check if your Supabase project is active (not paused) - Ensure your IP is not blocked in Supabase settings ### Row Level Security Errors - The schema includes RLS policies - Anonymous users can only read public data - Authenticated users can only modify their own data - Service role bypasses RLS (used for admin operations) ### Data Migration Issues - If migration fails mid-way, you can re-run it - The script uses upsert, so existing data won't be duplicated - Check the error message for specific constraint violations ### Off-by-One Sprint Date Display - Root cause: using `new Date("YYYY-MM-DD")` directly can parse as UTC and render as the previous day in some local time zones. - Expected behavior in this app: - Sprint start date = local `12:00:00 AM` for selected day. - Sprint end date = local `11:59:59.999 PM` for selected day. - API behavior: - `/api/sprints` normalizes `startDate` and `endDate` to `YYYY-MM-DD` before persistence. - Invalid date format on `PATCH /api/sprints` returns `400`. - API payload examples: - `POST /api/sprints` - `{ "name": "Sprint 1", "startDate": "2026-02-16", "endDate": "2026-02-22", "status": "active", "projectId": "" }` - `PATCH /api/sprints` - `{ "id": "", "startDate": "2026-02-16T00:00:00.000Z", "endDate": "2026-02-22T23:59:59.999Z" }` - stored as date-only values in Supabase `DATE` columns ## Architecture Changes ### Before (SQLite): - File-based database stored in `data/tasks.db` - Sessions stored in SQLite - Works only on single server ### After (Supabase): - PostgreSQL database hosted by Supabase - JWT-based session tokens - Works on multiple servers/Vercel edge functions - Real-time subscriptions possible (future enhancement) ## Security Notes 1. **Never expose `SUPABASE_SERVICE_ROLE_KEY` to the client** - Only use it in server-side code (API routes, server actions) - The anon key is safe to expose (it's in `NEXT_PUBLIC_`) 2. **Row Level Security is enabled** - Tables have policies that restrict access - Users can only see/modify their own data - Admin operations use service role key 3. **Password hashing remains the same** - We use scrypt hashing (same as SQLite version) - Passwords are never stored in plain text