175 lines
9.3 KiB
Plaintext
175 lines
9.3 KiB
Plaintext
## Codebase Patterns
|
|
- Project uses Next.js 16 with App Router, TypeScript, and TailwindCSS 4
|
|
- Source files are in `src/` directory (app, components, lib, types)
|
|
- Supabase is configured with @supabase/supabase-js and @supabase/ssr packages
|
|
- Environment variables follow NEXT_PUBLIC_* convention for client-side access
|
|
- Use `npm run typecheck` to run TypeScript type checking (tsc --noEmit)
|
|
- Flowchart types exported from `src/types/flowchart.ts`
|
|
- Supabase migrations go in `supabase/migrations/` with timestamp prefix (YYYYMMDDHHMMSS_*.sql)
|
|
- Database has profiles table (linked to auth.users) and projects table (with flowchart_data JSONB)
|
|
- RLS policies enforce user_id = auth.uid() for project access
|
|
- Supabase client utilities in `src/lib/supabase/`: client.ts (browser), server.ts (App Router), middleware.ts (route protection)
|
|
- Next.js middleware.ts at project root handles route protection using updateSession helper
|
|
- Public auth routes: /login, /signup, /forgot-password, /reset-password
|
|
- Protected routes: /dashboard, /editor/* (redirect to /login if unauthenticated)
|
|
- Auth pages use 'use client' with useState, createClient() from lib/supabase/client.ts, and useRouter for redirects
|
|
|
|
---
|
|
|
|
## 2026-01-21 - US-001
|
|
- What was implemented: Project scaffolding and configuration
|
|
- Files changed:
|
|
- package.json - project dependencies and scripts
|
|
- tsconfig.json - TypeScript configuration
|
|
- next.config.ts - Next.js configuration
|
|
- postcss.config.mjs - PostCSS with TailwindCSS
|
|
- eslint.config.mjs - ESLint configuration
|
|
- .env.example - environment variables template
|
|
- .gitignore - git ignore rules
|
|
- src/app/ - Next.js App Router pages
|
|
- src/components/.gitkeep - components directory placeholder
|
|
- src/lib/.gitkeep - lib directory placeholder
|
|
- src/types/.gitkeep - types directory placeholder
|
|
- **Learnings for future iterations:**
|
|
- Next.js 16 uses `@tailwindcss/postcss` for TailwindCSS 4 integration
|
|
- Use --src-dir flag for create-next-app to put source in src/ folder
|
|
- npm package names can't have capital letters (use lowercase)
|
|
- .gitignore needs explicit exclusion for .env files, but include .env.example
|
|
---
|
|
|
|
## 2026-01-21 - US-002
|
|
- What was implemented: TypeScript types for flowchart data structures
|
|
- Files changed:
|
|
- src/types/flowchart.ts - new file with all flowchart type definitions
|
|
- package.json - added typecheck script (tsc --noEmit)
|
|
- **Learnings for future iterations:**
|
|
- Position is a helper type for {x, y} coordinates used by nodes
|
|
- FlowchartNode is a union type of DialogueNode | ChoiceNode | VariableNode
|
|
- ChoiceOption is a separate type to make options array cleaner
|
|
- All types use `export type` for TypeScript isolatedModules compatibility
|
|
---
|
|
|
|
## 2026-01-21 - US-003
|
|
- What was implemented: Supabase schema for users and projects
|
|
- Files changed:
|
|
- supabase/migrations/20260121000000_create_profiles_and_projects.sql - new file with all database schema
|
|
- **Learnings for future iterations:**
|
|
- Supabase migrations are plain SQL files in supabase/migrations/ directory
|
|
- Migration filenames use timestamp prefix (YYYYMMDDHHMMSS_description.sql)
|
|
- RLS policies need separate policies for SELECT, INSERT, UPDATE, DELETE operations
|
|
- Admin check policy uses EXISTS subquery to check is_admin flag on profiles table
|
|
- projects table references profiles.id (not auth.users.id directly) for proper FK relationships
|
|
- flowchart_data column uses JSONB type with default empty structure
|
|
- Added auto-update trigger for updated_at timestamp on projects table
|
|
---
|
|
|
|
## 2026-01-21 - US-004
|
|
- What was implemented: Supabase client configuration utilities
|
|
- Files changed:
|
|
- src/lib/supabase/client.ts - browser client using createBrowserClient from @supabase/ssr
|
|
- src/lib/supabase/server.ts - server client for App Router with async cookies() API
|
|
- src/lib/supabase/middleware.ts - middleware helper with updateSession function
|
|
- src/lib/.gitkeep - removed (no longer needed)
|
|
- **Learnings for future iterations:**
|
|
- @supabase/ssr package provides createBrowserClient and createServerClient functions
|
|
- Server client requires async cookies() from next/headers in Next.js 16
|
|
- Middleware client returns both user object and supabaseResponse for route protection
|
|
- Cookie handling uses getAll/setAll pattern for proper session management
|
|
- setAll in server.ts wrapped in try/catch to handle Server Component limitations
|
|
---
|
|
|
|
## 2026-01-21 - US-005
|
|
- What was implemented: Protected routes middleware for authentication
|
|
- Files changed:
|
|
- middleware.ts - new file at project root for route protection
|
|
- **Learnings for future iterations:**
|
|
- Next.js middleware.ts must be at project root (not in src/)
|
|
- updateSession helper from lib/supabase/middleware.ts returns { user, supabaseResponse }
|
|
- Use startsWith() for route matching to handle nested routes (e.g., /editor/*)
|
|
- Matcher config excludes static files and images to avoid unnecessary middleware calls
|
|
- Clone nextUrl before modifying pathname for redirects
|
|
---
|
|
|
|
## 2026-01-21 - US-006
|
|
- What was implemented: Login page with email/password authentication
|
|
- Files changed:
|
|
- src/app/login/page.tsx - new file with login form and Supabase auth
|
|
- **Learnings for future iterations:**
|
|
- Auth pages use 'use client' directive since they need useState and form handling
|
|
- Use createClient() from lib/supabase/client.ts for browser-side auth operations
|
|
- supabase.auth.signInWithPassword returns { error } object for handling failures
|
|
- useRouter from next/navigation for programmatic redirects after auth
|
|
- Error state displayed in red alert box with dark mode support
|
|
- Loading state disables submit button and shows "Signing in..." text
|
|
- TailwindCSS dark mode uses dark: prefix (e.g., dark:bg-zinc-950)
|
|
---
|
|
|
|
## 2026-01-21 - US-007
|
|
- What was implemented: Sign up page for invite-only account setup
|
|
- Files changed:
|
|
- src/app/signup/page.tsx - new file with signup form and Supabase auth
|
|
- **Learnings for future iterations:**
|
|
- Supabase invite tokens come via URL hash fragment (window.location.hash)
|
|
- Parse hash with URLSearchParams after removing leading '#'
|
|
- Check for type=invite or type=signup to detect invite flow
|
|
- Use setSession() with access_token and refresh_token to establish session from invite link
|
|
- For invited users, update password with updateUser() then create profile with upsert()
|
|
- Use upsert() instead of insert() for profiles to handle edge cases
|
|
- Validate password confirmation before submission (passwords match check)
|
|
- display_name defaults to email prefix (split('@')[0])
|
|
---
|
|
|
|
## 2026-01-21 - US-008
|
|
- What was implemented: Logout functionality component
|
|
- Files changed:
|
|
- src/components/LogoutButton.tsx - new client component with signOut and redirect
|
|
- src/components/.gitkeep - removed (no longer needed)
|
|
- **Learnings for future iterations:**
|
|
- LogoutButton is a reusable component that will be used in the navbar (US-011)
|
|
- Component uses 'use client' directive for client-side auth operations
|
|
- Loading state prevents double-clicks during signOut
|
|
- Styled with neutral zinc colors to work as a secondary button in navbars
|
|
---
|
|
|
|
## 2026-01-21 - US-009
|
|
- What was implemented: Password reset - forgot password page
|
|
- Files changed:
|
|
- src/app/forgot-password/page.tsx - new file with forgot password form and email reset
|
|
- **Learnings for future iterations:**
|
|
- resetPasswordForEmail requires redirectTo option to specify where user lands after clicking reset link
|
|
- Use `window.location.origin` to get the current site URL for redirectTo
|
|
- Page shows different UI after success (conditional rendering with success state)
|
|
- Use ' for apostrophe in JSX to avoid HTML entity issues
|
|
- Follow same styling pattern as login page for consistency across auth pages
|
|
---
|
|
|
|
## 2026-01-21 - US-010
|
|
- What was implemented: Password reset - set new password page
|
|
- Files changed:
|
|
- src/app/reset-password/page.tsx - new file with password reset form
|
|
- src/app/login/page.tsx - updated to show success message from password reset
|
|
- **Learnings for future iterations:**
|
|
- Supabase recovery tokens come via URL hash fragment with type=recovery
|
|
- Use setSession() with access_token and refresh_token from hash to establish recovery session
|
|
- Show loading state while verifying token validity (tokenValid === null)
|
|
- Show error state with link to request new reset if token is invalid
|
|
- After password update, sign out the user and redirect to login with success message
|
|
- Use query param (message=password_reset_success) to pass success state between pages
|
|
- Login page uses useSearchParams to read and display success messages
|
|
- Success messages styled with green background (bg-green-50)
|
|
---
|
|
|
|
## 2026-01-21 - US-011
|
|
- What was implemented: Dashboard layout with navbar component
|
|
- Files changed:
|
|
- src/app/dashboard/layout.tsx - new file with dashboard layout wrapper
|
|
- src/components/Navbar.tsx - new reusable navbar component
|
|
- **Learnings for future iterations:**
|
|
- Dashboard layout is a server component that fetches user data via createClient() from lib/supabase/server.ts
|
|
- Navbar accepts userEmail prop to display current user
|
|
- Layout wraps children with consistent max-w-7xl container and padding
|
|
- Navbar uses Link component to allow clicking app title to go back to dashboard
|
|
- Navbar has border-b styling with dark mode support for visual separation
|
|
- Use gap-4 for spacing between navbar items (user email and logout button)
|
|
---
|