chore(docs): rewrite SETUP.md as continue-existing-project guide
Replaces the bootstrap-from-scratch document (Step 2 told readers to run 'composer create-project laravel/laravel api' on an existing codebase) with a continue-existing-project guide. Scope: prerequisites, first-time setup (clone + install + .env + migrate), daily workflow (three terminals + optional queue worker), env-config explained, common tasks (test/migrate/route:list/build), documentation reference linking the dev-docs/ canonical files, troubleshooting. Drops apps/portal references throughout (single SPA at port 5174). Drops dual-port SANCTUM_STATEFUL_DOMAINS guidance. Replaces .cursor/ instructions reference with /CLAUDE.md as auto-loaded source of truth.
This commit is contained in:
@@ -1,269 +1,216 @@
|
||||
# Crewli - Setup Guide
|
||||
# Crewli — Working in this repo
|
||||
|
||||
This guide walks you through setting up the Crewli project from scratch.
|
||||
|
||||
## Cursor AI Configuration
|
||||
|
||||
The project includes comprehensive AI instructions:
|
||||
|
||||
```
|
||||
.cursor/
|
||||
├── instructions.md # Quick start and common prompts
|
||||
├── ARCHITECTURE.md # System design and database schema
|
||||
└── rules/
|
||||
├── 001_workspace.mdc # Project structure and conventions
|
||||
├── 100_laravel.mdc # Laravel API patterns
|
||||
├── 101_vue.mdc # Vue + Vuexy patterns
|
||||
└── 200_testing.mdc # Testing strategies
|
||||
```
|
||||
|
||||
**Read these files first!** They contain everything Cursor needs to generate code correctly.
|
||||
A guide for developers continuing work on the Crewli codebase. Assumes you've cloned the repo and have basic terminal familiarity.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install these before starting:
|
||||
Install these once before starting:
|
||||
|
||||
### macOS (Homebrew)
|
||||
| Tool | Version | Install (macOS via Homebrew) |
|
||||
|------|---------|------------------------------|
|
||||
| PHP | 8.4 | `brew install php@8.4 && brew link php@8.4` |
|
||||
| Composer | 2.x | `brew install composer` |
|
||||
| Node.js | 20 LTS | `brew install fnm && fnm install 20 && fnm use 20` |
|
||||
| pnpm | 9.x | `npm install -g pnpm` |
|
||||
| Docker Desktop | latest | https://www.docker.com/products/docker-desktop/ |
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
# PHP 8.3
|
||||
brew install php@8.3
|
||||
brew link php@8.3
|
||||
|
||||
# Composer
|
||||
brew install composer
|
||||
|
||||
# Node.js (via fnm)
|
||||
brew install fnm
|
||||
fnm install 20
|
||||
fnm use 20
|
||||
|
||||
# pnpm
|
||||
npm install -g pnpm
|
||||
|
||||
# Docker Desktop
|
||||
# Download from: https://www.docker.com/products/docker-desktop/
|
||||
php -v # 8.4.x
|
||||
composer -V # 2.x
|
||||
node -v # v20.x
|
||||
pnpm -v # 9.x or 10.x
|
||||
docker -v # any recent version
|
||||
```
|
||||
|
||||
### Verify Installation
|
||||
## First-time setup
|
||||
|
||||
From the repo root:
|
||||
|
||||
```bash
|
||||
php -v # Should show 8.3.x
|
||||
composer -V # Should show 2.x
|
||||
node -v # Should show v20.x
|
||||
pnpm -v # Should show 8.x or 9.x
|
||||
docker -v # Should show Docker version
|
||||
```
|
||||
# 1. Backend dependencies
|
||||
cd api && composer install
|
||||
|
||||
---
|
||||
# 2. Frontend dependencies
|
||||
cd ../apps/app && pnpm install
|
||||
|
||||
## Step 1: Start Docker Services
|
||||
# 3. Backend env file
|
||||
cd ../../api
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
|
||||
```bash
|
||||
cd crewli
|
||||
# 4. Frontend env file
|
||||
cd ../apps/app
|
||||
cp .env.example .env.local
|
||||
|
||||
# 5. Start Docker services (MySQL, Redis, Mailpit)
|
||||
cd ..
|
||||
make services
|
||||
```
|
||||
|
||||
This starts:
|
||||
- **MySQL 8.0** on port 3306
|
||||
- **Redis** on port 6379
|
||||
- **Mailpit** on port 8025 (email testing UI)
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Create Laravel API
|
||||
|
||||
Open the project in Cursor and use this prompt:
|
||||
|
||||
```
|
||||
Create a new Laravel 12 project in the api/ folder.
|
||||
|
||||
Requirements:
|
||||
- Use the command: composer create-project laravel/laravel api
|
||||
- After creation, install Sanctum: composer require laravel/sanctum
|
||||
- Configure for API-only (we don't need web routes)
|
||||
- Set up CORS for localhost:5174, localhost:5175
|
||||
- Use MySQL with these credentials:
|
||||
- Host: 127.0.0.1
|
||||
- Database: crewli
|
||||
- Username: crewli
|
||||
- Password: secret
|
||||
|
||||
Follow the conventions in .cursor/rules for code style.
|
||||
```
|
||||
|
||||
### Manual Alternative
|
||||
|
||||
```bash
|
||||
cd crewli
|
||||
composer create-project laravel/laravel api
|
||||
# 6. Database setup
|
||||
cd api
|
||||
composer require laravel/sanctum
|
||||
php artisan install:api
|
||||
php artisan migrate --seed
|
||||
|
||||
# 7. Frontend post-install (icon build + MSW worker)
|
||||
cd ../apps/app
|
||||
pnpm run build:icons
|
||||
pnpm run msw:init
|
||||
|
||||
# 8. Verify everything works
|
||||
cd ../../api
|
||||
php artisan test
|
||||
```
|
||||
|
||||
Then configure `api/.env`:
|
||||
If `php artisan test` is green, you're ready.
|
||||
|
||||
## Daily workflow
|
||||
|
||||
Three terminal tabs, plus an optional fourth for the queue worker:
|
||||
|
||||
| Terminal | Command | Where it runs | Port |
|
||||
|----------|---------|---------------|------|
|
||||
| 1. Services | `make services` (from repo root) | Docker | 3306 (MySQL), 6379 (Redis), 8025 (Mailpit) |
|
||||
| 2. API | `make api` (from repo root) | Laravel dev server | 8000 |
|
||||
| 3. SPA | `make app` (from repo root) | Vite dev server | 5174 |
|
||||
| 4. Queue worker (optional) | `cd api && php artisan queue:listen redis --queue=emails` | Local PHP | n/a |
|
||||
|
||||
The queue worker is only needed when you're triggering email flows (registration, password reset, email change, invitations). Routine UI work doesn't require it.
|
||||
|
||||
Stop services when done: `make services-stop`.
|
||||
|
||||
## Environment variables
|
||||
|
||||
### `api/.env`
|
||||
|
||||
The defaults from `.env.example` cover local development. Key entries:
|
||||
|
||||
```env
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=crewli
|
||||
DB_USERNAME=crewli
|
||||
DB_PASSWORD=secret
|
||||
|
||||
FRONTEND_APP_URL=http://localhost:5174
|
||||
FRONTEND_PORTAL_URL=http://localhost:5175
|
||||
SANCTUM_STATEFUL_DOMAINS=localhost:5174,localhost:5175
|
||||
QUEUE_CONNECTION=redis
|
||||
SESSION_DOMAIN=localhost
|
||||
FRONTEND_APP_URL=http://localhost:5174
|
||||
SANCTUM_STATEFUL_DOMAINS=localhost:5174
|
||||
APP_URL=http://localhost:8000
|
||||
```
|
||||
|
||||
**Production (domain `crewli.app`):** set `APP_URL=https://api.crewli.app`, point `FRONTEND_APP_URL` / `FRONTEND_PORTAL_URL` to `https://crewli.app` and `https://portal.crewli.app`, and `SANCTUM_STATEFUL_DOMAINS=crewli.app,portal.crewli.app` (hostnames only). Each SPA build should use `VITE_API_URL=https://api.crewli.app/api/v1`. Full template: `api/.env.example`. The product uses **`crewli.app`** only; **`crewli.nl`** is for a future public marketing site, not this API or SPAs.
|
||||
For production deployment (registered domain `crewli.app`):
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Vuexy frontends (this repo)
|
||||
|
||||
This monorepo already contains two SPAs under `apps/`:
|
||||
|
||||
| Directory | Role | Typical Vuexy source |
|
||||
|-----------|------|----------------------|
|
||||
| `apps/app/` | Organizer + Platform Admin (main product) | full-version (TypeScript) |
|
||||
| `apps/portal/` | External portal (volunteers, token links) | stripped starter / custom layout |
|
||||
|
||||
Super admin functionality lives in `apps/app/` under `/platform/*` routes, accessible to `super_admin` users.
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Configure SPAs
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
cd apps/app && pnpm install
|
||||
cd ../portal && pnpm install
|
||||
```
|
||||
|
||||
### Create Environment Files
|
||||
|
||||
**apps/app/.env.local**
|
||||
```env
|
||||
VITE_API_URL=http://localhost:8000/api/v1
|
||||
VITE_APP_NAME="Crewli Organizer"
|
||||
APP_URL=https://api.crewli.app
|
||||
FRONTEND_APP_URL=https://crewli.app
|
||||
SESSION_DOMAIN=.crewli.app
|
||||
SANCTUM_STATEFUL_DOMAINS=crewli.app
|
||||
```
|
||||
|
||||
**apps/portal/.env.local**
|
||||
`crewli.nl` is reserved for a future marketing site only — not the application.
|
||||
|
||||
### `apps/app/.env.local`
|
||||
|
||||
```env
|
||||
VITE_API_URL=http://localhost:8000/api/v1
|
||||
VITE_APP_NAME="Crewli Portal"
|
||||
VITE_API_URL=http://localhost:8000
|
||||
VITE_APP_NAME="Crewli"
|
||||
```
|
||||
|
||||
### Dev server ports
|
||||
For production: `VITE_API_URL=https://api.crewli.app`.
|
||||
|
||||
From the repo root, `make app` and `make portal` start Vite on **5174** and **5175** respectively. If you run `pnpm dev` manually, configure the same ports in each app’s `vite.config.ts` under `server.port`.
|
||||
## Common tasks
|
||||
|
||||
---
|
||||
|
||||
## Step 5: API client in SPAs
|
||||
|
||||
`apps/app/src/lib/api-client.ts` and `apps/portal/src/lib/api-client.ts` share the same pattern: `VITE_API_URL` base, Bearer token from the `accessToken` cookie, 401 → clear cookies and redirect to `/login`. Build new composables on `apiClient`; keep Vuexy `useApi` for template demos only.
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Create database schema
|
||||
|
||||
Implement migrations from the canonical schema, not a legacy intranet model:
|
||||
|
||||
- **`docs/SCHEMA.md`** — table list, columns, indexes
|
||||
- **`.cursor/ARCHITECTURE.md`** — overview and relationships
|
||||
- **`.cursor/rules/103_database.mdc`** — ULIDs, soft deletes, index rules
|
||||
|
||||
**Checked-in foundation (this repo):** Laravel defaults (`users`, `cache`, `jobs`) then `2026_04_07_*` migrations: Sanctum tokens → Spatie permission → activity log → `organisations` → `organisation_user` → `events` → `user_invitations` → `event_user_roles`. New modules should append migrations with a later timestamp in dependency order.
|
||||
|
||||
Typical next expansion order from `103_database.mdc`: festival sections, time slots, persons, shifts, …
|
||||
|
||||
Then run:
|
||||
### Run tests
|
||||
|
||||
```bash
|
||||
cd api && php artisan migrate
|
||||
# Backend (PHPUnit, all tests)
|
||||
cd api && php artisan test
|
||||
|
||||
# Backend (specific filter)
|
||||
cd api && php artisan test --filter=ShiftTest
|
||||
|
||||
# Backend (with coverage)
|
||||
cd api && php artisan test --coverage
|
||||
|
||||
# Frontend (Vitest, all tests)
|
||||
cd apps/app && pnpm test
|
||||
|
||||
# Frontend (typecheck)
|
||||
cd apps/app && pnpm typecheck
|
||||
|
||||
# Frontend (lint)
|
||||
cd apps/app && pnpm lint
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 7: Start development
|
||||
|
||||
Open separate terminals (or use the Makefile from the repo root):
|
||||
### Database reset
|
||||
|
||||
```bash
|
||||
# Tab 1: Services (Docker)
|
||||
make services
|
||||
|
||||
# Tab 2: Laravel API
|
||||
make api
|
||||
|
||||
# Tab 3: Organizer SPA (optional)
|
||||
make app
|
||||
|
||||
# Tab 4: Portal SPA (optional)
|
||||
make portal
|
||||
cd api && php artisan migrate:fresh --seed
|
||||
```
|
||||
|
||||
---
|
||||
This drops all tables, re-runs migrations, and re-seeds. Useful when schema changes or seeders are updated.
|
||||
|
||||
## Building features
|
||||
### Inspect routes
|
||||
|
||||
Use Cursor with **`CLAUDE.md`** and **`.cursor/instructions.md`**. Example directions:
|
||||
|
||||
### Authentication
|
||||
|
||||
```
|
||||
Wire Sanctum API auth: login, logout, me; form requests; API resources; Vue apps use axios + token storage (see .cursor/rules).
|
||||
```bash
|
||||
cd api && php artisan route:list --path=api/v1
|
||||
```
|
||||
|
||||
### Events module (Crewli)
|
||||
### Build for production
|
||||
|
||||
```
|
||||
Events nested under organisations: ULID PK, OrganisationScope, policies, EventResource, feature tests (200/401/403/422).
|
||||
```bash
|
||||
cd apps/app && pnpm build
|
||||
```
|
||||
|
||||
### Portal token flow
|
||||
Output lands in `apps/app/dist/`. The `deploy.sh` script handles the rest for VPS deploys.
|
||||
|
||||
```
|
||||
Portal token middleware and routes for artist/supplier contexts; document links on https://portal.crewli.app/... (see .cursor/rules/102_multi_tenancy.mdc).
|
||||
### Static analysis (optional)
|
||||
|
||||
```bash
|
||||
cd api && composer analyse # Larastan / PHPStan level 6
|
||||
cd api && composer rector --dry-run # Rector findings
|
||||
```
|
||||
|
||||
---
|
||||
## Documentation reference
|
||||
|
||||
The `dev-docs/` directory is the developer source of truth. The most-used files:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `/CLAUDE.md` | Project conventions, vibe-coding principles, Vuexy-first decision tree (auto-loaded by Claude Code) |
|
||||
| `dev-docs/SCHEMA.md` | Database schema (current version v2.x, kept in sync with migrations) |
|
||||
| `dev-docs/API.md` | API contract |
|
||||
| `dev-docs/AUTH_ARCHITECTURE.md` | Auth design (httpOnly cookies, MFA, impersonation, portal tokens) |
|
||||
| `dev-docs/CLAUDE_CODE_TOOLING.md` | The `.claude/` deterministic guard-rail layer (hooks, subagent, slash commands) |
|
||||
| `dev-docs/VUEXY_COMPONENTS.md` | Vuexy component registry — consult before writing any frontend |
|
||||
| `dev-docs/BACKLOG.md` | Tracked tech debt and follow-ups |
|
||||
| `dev-docs/ARCH-*.md` | Architecture decisions per workstream (consolidation, form builder, bindings, API validation) |
|
||||
|
||||
The `docs/` directory (separate from `dev-docs/`) is end-user VitePress documentation in Dutch.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### MySQL Connection Refused
|
||||
```bash
|
||||
# Check if Docker is running
|
||||
docker ps
|
||||
### MySQL connection refused
|
||||
|
||||
# Restart services
|
||||
make services-stop
|
||||
make services
|
||||
```bash
|
||||
docker ps # check containers are up
|
||||
make services-stop && make services # restart
|
||||
```
|
||||
|
||||
### CORS Errors
|
||||
Check `api/config/cors.php` allows your frontend origins.
|
||||
### Port 8000 already in use
|
||||
|
||||
Something else is bound to port 8000. Find it: `lsof -i :8000`. Kill it or change `make api` to use another port.
|
||||
|
||||
### Frontend TypeScript errors after pulling main
|
||||
|
||||
### Vuexy TypeScript Errors
|
||||
```bash
|
||||
cd apps/app
|
||||
pnpm install
|
||||
pnpm type-check
|
||||
pnpm install # picks up new dependencies
|
||||
pnpm typecheck # confirm clean
|
||||
```
|
||||
|
||||
---
|
||||
### Queue worker not picking up jobs
|
||||
|
||||
## Next steps
|
||||
Confirm Redis is running: `docker ps | grep redis`. If yes, restart the queue worker — long-running listeners can drift after long idle periods.
|
||||
|
||||
1. Services running (Docker)
|
||||
2. Laravel API configured and migrated
|
||||
3. SPAs installed (`apps/app`, `apps/portal`)
|
||||
4. Environment files for API + each SPA
|
||||
5. Authentication and organisation switching
|
||||
6. Events, sections, time slots, shifts
|
||||
7. Persons, crowd types, portal flows
|
||||
8. Accreditation, briefings, operational modules per roadmap in `.cursor/instructions.md`
|
||||
### Test suite is slow
|
||||
|
||||
PHPUnit defaults to a single process. Parallel: `cd api && php artisan test --parallel`.
|
||||
|
||||
Reference in New Issue
Block a user