Reviewed-on: #18 Co-authored-by: David Gwilliam <dhgwilliam@gmail.com> Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
8.3 KiB
EuchreCamp - Agent Guide
This document provides guidance for AI agents working on the EuchreCamp project.
Project Overview
EuchreCamp is a Next.js 14+ application for managing Euchre tournaments and tracking partnership analytics.
Key Technologies
- Next.js 14+ (App Router)
- TypeScript
- Prisma ORM (SQLite)
- Tailwind CSS
- Better Auth (Authentication)
- Vitest (Unit Testing)
- Playwright (Acceptance Testing)
Architecture Patterns
Authentication & Authorization
- Session Management: Better Auth with cookie-based sessions
- Role-Based Access Control: Three roles (player, tournament_admin, club_admin)
- Permission Functions: Located in
src/lib/permissions.ts - Session Cache: Disabled to avoid stale role data
Database Schema
- Players:
id,name,currentElo,gamesPlayed,wins,losses - Users:
id,email,role,playerId(foreign key to players) - Events: Tournaments with
ownerIdfor ownership tracking - Matches: Individual match results with
createdByIdfor tracking
Data Flow
- User authentication via Better Auth
- Session stored in HTTP-only cookies
- Permission checks read directly from database
- API routes enforce authorization
Common Tasks
Admin User Creation
To create an admin user, use the provided scripts:
Option 1: Using Better Auth API (Recommended)
node scripts/create-admin-via-api.js
This creates the admin user david@dhg.lol with password adminadmin using Better Auth's internal API.
Option 2: Direct Database Creation
node scripts/create-admin-better-auth.js
This creates the admin user david@dhg.lol with password admin directly in the database.
List All Users:
node scripts/list-users.js
Update Admin Password:
node scripts/update-admin-password.js
This updates the admin password to adminadmin.
Note: All scripts currently create the user david@dhg.lol. If you need to create a different admin user, you can modify the email in the script or use Better Auth's CLI.
Fixing Authentication Issues
If users are redirected incorrectly or permissions aren't working:
- Check if cookie cache is disabled in
src/lib/auth.ts - Verify permission functions read from database, not session
- Ensure
getSession()usesdisableCookieCache=true
Adding New Features
- Create API route in
src/app/api/ - Add permission checks using functions from
src/lib/permissions.ts - Create UI component in
src/app/orsrc/components/ - Add tests in
src/__tests__/ - Run tests:
npm run testandnpm run test:acceptance
Database Changes
- Edit
prisma/schema.prisma - Run
npx prisma migrate dev --name <migration-name> - Run
npx prisma generate - Update affected API routes and components
Database Provider Switching
The application supports both SQLite (default) and PostgreSQL databases.
To switch between databases:
# Switch to SQLite
npm run db:switch sqlite
# Switch to PostgreSQL
npm run db:switch postgresql
To set up PostgreSQL:
npm run db:setup-postgres
Database Configuration:
- Edit
.envfile to setDATABASE_PROVIDERandDATABASE_URL - For PostgreSQL, also set
DATABASE_SHADOW_URLfor migrations
Note: The database provider is automatically detected by Better Auth and Prisma.
Running Tests
Using just (recommended):
- All tests:
just test(unit + acceptance with SQLite) - Unit tests:
just test-unit - Acceptance tests (SQLite):
just test-acceptance-sqlite - Acceptance tests (PostgreSQL):
just test-acceptance-postgres - PR validation:
just pr-validate(what runs on pull requests)
Using npm scripts:
- Unit tests:
npm run test - Acceptance tests:
npm run test:acceptance - Specific test:
npm run test:acceptance -- --grep "test name"
CI-style acceptance tests with SQLite:
DATABASE_PROVIDER=sqlite DATABASE_URL=file:./prisma/ci.db npm run test:acceptance
CI Runner Image
Note: The CI runner image approach has been deprecated for Gitea Actions workflows.
The original attempt to use a pre-built CI runner image with pre-installed dependencies encountered fundamental issues with how Gitea Actions handles workspace mounting. When Gitea Actions runs a container job, it mounts the workspace at a specific path (e.g., /workspace/david/euchre_camp), which hides the container's /app directory where dependencies were installed.
Current Approach:
- Workflows use standard
node:20-alpineormcr.microsoft.com/playwrightcontainers - Dependencies are installed via
npm ciin each workflow run - This is the recommended approach for Gitea Actions
Why the CI image approach doesn't work:
- Dockerfile.ci installs dependencies in
/app - Gitea Actions mounts workspace at
/workspace/david/euchre_camp - Workspace mount hides the
/appdirectory - Symlinks from
/app/node_modulesdon't work because/appis hidden
Alternative for performance: If CI performance becomes an issue, consider:
- Using GitHub Actions cache for node_modules
- Using a self-hosted runner with persistent workspace
- Using the main Dockerfile's
test-runnertarget for release workflows (which works because it builds a complete image)
CI/CD Pipeline
The project uses Gitea Actions for continuous integration:
PR Workflow (.gitea/workflows/pr.yml):
- Runs on pull requests to main
- Executes unit tests and acceptance tests with SQLite
- Analyzes commits for semantic versioning
- Comments suggested bump type on PRs
Test Workflow (.gitea/workflows/test.yml):
- Runs on all branch pushes
- Executes unit tests for quick feedback
- Skips auto-generated version bump commits
Release Workflow (.gitea/workflows/release.yml):
- Runs on main branch pushes
- Determines version bump type
- Bumps version and creates git tags
- Builds Docker images and runs tests
- Pushes to registry and deploys
Database Strategy:
- CI tests use SQLite (fast, no server required)
- Production uses PostgreSQL
- Switch with
DATABASE_PROVIDERenvironment variable
Key Files
Configuration
src/lib/auth.ts- Better Auth configurationsrc/lib/permissions.ts- Authorization functionssrc/lib/elo-utils.ts- Elo calculation logic
API Routes
src/app/api/auth/[[...all]]/route.ts- Better Auth APIsrc/app/api/tournaments/route.ts- Tournament managementsrc/app/api/matches/upload/route.ts- CSV upload processing
UI Components
src/components/Navigation.tsx- Navigation with role-based linkssrc/app/page.tsx- Home page with top players, recent tournament, club presidentsrc/app/players/[id]/profile/page.tsx- Player profile with stats
Tests
src/__tests__/unit/permissions.test.ts- Permission function testssrc/__tests__/unit/elo.test.ts- Elo calculation testssrc/__tests__/e2e/global.setup.ts- Test setup with admin user creationsrc/__tests__/e2e/home-page.test.ts- Home page tests
Troubleshooting
Session Cache Issues
Problem: Updated user roles don't reflect in session Solution: Ensure cookie cache is disabled and permission functions read from database
Test Failures
Problem: Tests timing out or failing unexpectedly Solution:
- Check if dev server is running
- Verify database is accessible
- Run tests with
--headedto see browser
Database Conflicts
Problem: Tests interfering with each other
Solution: Tests run sequentially with fullyParallel: false and workers: 1
Conventions
Commit Messages
- Use conventional commit format:
<type>: <description> - Types:
feat,fix,docs,style,refactor,test,chore,ci
Code Style
- Use TypeScript for type safety
- Prefer React Server Components for data fetching
- Keep business logic in
src/lib/directory - Write tests for new features
File Naming
- Components: PascalCase (e.g.,
Navigation.tsx) - Utilities: camelCase (e.g.,
elo-utils.ts) - Tests:
.test.tsor.test.tsxsuffix
File Organization
See docs/FILE_ORGANIZATION.md for detailed file organization and structure.
Resources
- Better Auth Docs: https://better-auth.com/docs
- Next.js Docs: https://nextjs.org/docs
- Prisma Docs: https://www.prisma.io/docs
- Playwright Docs: https://playwright.dev
- Vitest Docs: https://vitest.dev/