- Add @project-e/db package with Drizzle schema and migrations - Replace PocketBase client with PostgreSQL-based database client - Migrate auth from custom to NextAuth.js - Add Docker Compose with PostgreSQL container - Update worker to use new database client - Remove PocketBase-specific files and migrations - Add drizzle config and initial migration
147 lines
5.0 KiB
Markdown
147 lines
5.0 KiB
Markdown
# Development Guide
|
|
|
|
Use this guide to run Project E locally, change the database schema, and prepare a pull request.
|
|
|
|
## Prerequisites
|
|
|
|
- Node.js 22.13.0 or later
|
|
- npm 10.0.0 or later
|
|
- Docker and Docker Compose, for PostgreSQL 16
|
|
- Git
|
|
|
|
## Set up your local environment
|
|
|
|
1. Clone the repository and install dependencies.
|
|
|
|
```bash
|
|
git clone <repository-url>
|
|
cd ProjectE
|
|
npm install
|
|
```
|
|
|
|
2. Copy the environment template.
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
3. Set the database and authentication values in `.env`.
|
|
|
|
```bash
|
|
DATABASE_URL=postgresql://project_e:your_postgres_password@localhost:5432/project_e
|
|
POSTGRES_PASSWORD=your_postgres_password
|
|
NEXTAUTH_SECRET=your_long_random_secret
|
|
INITIAL_ADMIN_EMAIL=admin@example.com
|
|
INITIAL_ADMIN_PASSWORD=your_initial_admin_password
|
|
```
|
|
|
|
`DATABASE_URL` connects local processes to PostgreSQL. `POSTGRES_PASSWORD` must match the password in that URL. Generate `NEXTAUTH_SECRET` with `openssl rand -base64 32`.
|
|
|
|
4. Start PostgreSQL 16.
|
|
|
|
```bash
|
|
docker compose up db -d
|
|
```
|
|
|
|
Docker initializes the `project_e` database and applies `drizzle/0000_first_mauler.sql` when it creates an empty database volume.
|
|
|
|
5. Start the app.
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
6. Open `http://localhost:3000` and sign in with `INITIAL_ADMIN_EMAIL` and `INITIAL_ADMIN_PASSWORD`.
|
|
|
|
The credentials create the first admin account only when the `users` table has no accounts.
|
|
|
|
## Project structure
|
|
|
|
```
|
|
project-e/
|
|
├── apps/web/ # Next.js application
|
|
│ ├── app/ # App Router pages and API routes
|
|
│ ├── components/ # React components
|
|
│ ├── hooks/ # Custom React hooks
|
|
│ └── lib/ # Services, database adapter, and NextAuth config
|
|
├── packages/
|
|
│ ├── db/ # Drizzle schema and PostgreSQL client
|
|
│ └── shared/ # Shared schemas, types, and constants
|
|
├── drizzle/ # Generated PostgreSQL migrations
|
|
├── worker/ # Background job worker
|
|
├── e2e/ # Playwright tests
|
|
├── tests/ # Unit and component tests
|
|
├── drizzle.config.ts # Drizzle Kit configuration
|
|
└── docker-compose.yml # Web, PostgreSQL, and worker services
|
|
```
|
|
|
|
## Data access and authentication
|
|
|
|
The app uses Drizzle ORM with PostgreSQL. `packages/db/src/schema.ts` defines the schema, and `packages/db/src/index.ts` creates the database client from `DATABASE_URL`.
|
|
|
|
Application records live in the `records` table as JSONB data grouped by collection. The `users` table stores email addresses and bcrypt password hashes. API routes use the database adapter in `apps/web/lib/database.ts` for collection operations.
|
|
|
|
NextAuth uses the credentials provider. It creates JWT sessions after a user signs in with an email address and password. Keep `NEXTAUTH_SECRET` stable for an environment; changing it invalidates existing sessions.
|
|
|
|
## Add a feature
|
|
|
|
1. Define or update the data shape in `packages/db/src/schema.ts`.
|
|
2. Generate a Drizzle migration.
|
|
|
|
```bash
|
|
npm run db:generate
|
|
```
|
|
|
|
3. Review and commit the generated SQL in `drizzle/`.
|
|
4. Apply the migration to your local PostgreSQL database before testing. The initial Docker setup applies `drizzle/0000_first_mauler.sql`; apply later migrations through your deployment migration process.
|
|
5. Update shared Zod schemas in `packages/shared/` when validation changes.
|
|
6. Update the relevant API route, service, state, and UI.
|
|
7. Add tests for the new behavior.
|
|
|
|
## Database schema changes
|
|
|
|
- Do not edit a migration after another environment has applied it.
|
|
- Keep the Drizzle schema and generated SQL in the same pull request.
|
|
- Test a migration against a database with representative data.
|
|
- Add indexes for fields used in common filters or sorts.
|
|
- Back up production data before applying a migration.
|
|
|
|
`drizzle.config.ts` reads `DATABASE_URL` and writes generated migrations to `drizzle/`.
|
|
|
|
## Testing
|
|
|
|
Run the checks that match your change:
|
|
|
|
```bash
|
|
npm run typecheck
|
|
npm run lint
|
|
npm run test
|
|
npm run test:e2e
|
|
```
|
|
|
|
Unit tests cover validation, utilities, services, and store actions. Component tests cover rendering and user interactions. Playwright tests cover browser flows such as signing in, creating a task, and completing it.
|
|
|
|
## Code conventions
|
|
|
|
- Use TypeScript strict mode.
|
|
- Prefer `unknown` over `any` for external input.
|
|
- Keep React components focused and extract shared logic into hooks.
|
|
- Use Tailwind utility classes, `cn()` for class merging, and `cva` for variants.
|
|
- Validate API input with shared Zod schemas.
|
|
- Catch errors at API boundaries and log request context.
|
|
|
|
## Git workflow
|
|
|
|
Use conventional commits and keep each commit focused. Before pushing, run the relevant checks and review `git diff --stat`.
|
|
|
|
Use these branch prefixes:
|
|
|
|
```
|
|
feature/description
|
|
fix/description
|
|
refactor/description
|
|
chore/description
|
|
```
|
|
|
|
Pull requests should explain the change, its reason, and the tests you ran. Include screenshots for UI changes.
|