Files
crewli/README.md
bert.hausmans 0d24506c89 feat: consolidate frontend API layer, add query-client, and harden backend Fase 1
Frontend:
- Consolidate duplicate API layers into single src/lib/axios.ts per app
- Remove src/lib/api-client.ts and src/utils/api.ts (admin)
- Add src/lib/query-client.ts with TanStack Query config per app
- Update all imports and auto-import config

Backend:
- Fix organisations.billing_status default to 'trial'
- Fix user_invitations.invited_by_user_id to nullOnDelete
- Add MeResource with separated app_roles and pivot-based org roles
- Add cross-org check to EventPolicy view() and update()
- Restrict EventPolicy create/update to org_admin/event_manager (not org_member)
- Attach creator as org_admin on organisation store
- Add query scopes to Event and UserInvitation models
- Improve factories with Dutch test data
- Expand test suite from 29 to 41 tests (90 assertions)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:35:34 +02:00

151 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Crewli
Multi-tenant SaaS platform for **event and festival operations**: planning, people, accreditation, artist advancing, volunteer shifts, briefings, and show-day tooling (Mission Control). The backend is a **JSON-only** Laravel API; all user interfaces are **Vue 3** single-page apps.
---
## What Crewli covers
- **Organisations & events** — Multi-tenant data with organisation-scoped access; events move through a defined lifecycle (draft → published → registration → buildup → show day → teardown → closed).
- **Festival structure** — Sections, time slots, shifts, assignments, claiming/approval flows for volunteers and crew.
- **People & crowds** — Crowd types (crew, volunteers, artists, guests, press, partners, suppliers), persons, lists, and (planned) rich accreditation (items, zones, hand-out).
- **Artists & advancing** — Booking status, stages/timetable concepts, advance sections and token-based portal access for external artists.
- **Communication** — Briefings, campaigns, and operational messaging (see architecture doc for target modules).
- **Portal (external users)** — One portal app, two modes: **login** (Sanctum) for long-term users such as volunteers, and **token** access for per-event links (e.g. artists, suppliers).
Implementation is phased; the authoritative feature and schema list lives in the architecture and design references below.
---
## Applications
| App | Path | Port | Role |
|-----|------|------|------|
| **Admin** | `apps/admin/` | 5173 | Platform **super admin**: organisations, billing-style flags, global settings. Full Vuexy shell. |
| **Organizer** | `apps/app/` | 5174 | Main product for **org and event staff**: events, sections, shifts, people, artists, accreditation, briefings, reports, etc. |
| **Portal** | `apps/portal/` | 5175 | **External** users: stripped layout; login- or token-based access. |
All apps talk to the API over **CORS** with **Laravel Sanctum** tokens.
---
## Tech stack
| Layer | Technology |
|-------|------------|
| API | PHP 8.2+, Laravel 12, Sanctum, Spatie Permission (and Activity Log / Media Library where used) |
| Data | MySQL 8, Redis (cache/queues) |
| Frontends | Vue 3, TypeScript, Vite, Vuexy + Vuetify, Pinia, TanStack Query, VeeValidate + Zod |
| Local services | Docker Compose (MySQL, Redis, Mailpit) |
**Rule of thumb:** business tables use **ULID** primary keys; event-related data is scoped by **organisation** (global scopes + policies), not ad hoc `where` clauses in controllers.
---
## Project structure
```
crewli/
├── api/ # Laravel 12 REST API (JSON only)
├── apps/
│ ├── admin/ # Super Admin SPA
│ ├── app/ # Organizer SPA (primary UI)
│ └── portal/ # External portal SPA
├── docker/ # Docker / Compose assets
├── docs/ # SETUP, API notes, schema notes
├── resources/
│ ├── design/ # Product source of truth (design docs, see table below)
│ └── vuexy-admin-*/ # Vuexy template reference (bundled kit)
├── .cursor/ # ARCHITECTURE.md, instructions.md, rules for AI/helpers
└── Makefile # Dev commands
```
Vuexy **`@core/`** and **`@layouts/`** in each app should stay untouched; customize via app config, navigation, and app-level components.
---
## Quick start
```bash
# 1. Infrastructure
make services
# 2. API env, dependencies, database (see docs/SETUP.md)
cd api && cp .env.example .env && composer install && php artisan key:generate && php artisan migrate
# 3. Run API + the SPAs you need (separate terminals)
make api
make admin # optional
make app # optional
make portal # optional
```
Detailed setup: **[docs/SETUP.md](docs/SETUP.md)**.
---
## Development URLs
| Service | Development | Env / notes |
|---------|-------------|-------------|
| API | http://localhost:8000/api/v1 | Base path `/api/v1` |
| Admin | http://localhost:5173 | `FRONTEND_ADMIN_URL` in Laravel CORS |
| Organizer | http://localhost:5174 | `FRONTEND_APP_URL` |
| Portal | http://localhost:5175 | `FRONTEND_PORTAL_URL` |
| Mailpit | http://localhost:8025 | Local mail capture |
### Production (crewli.app)
**Domains:** **`crewli.app`** is this product (API + organizer/admin/portal SPAs, transactional email from the app, seeds, etc.). **`crewli.nl`** is reserved for a future **public marketing site** only — do not point this codebases `APP_URL`, CORS, Sanctum, or app mail at `crewli.nl`.
Typical layout (configure the same values in `api/.env` — see `api/.env.example`):
| Service | URL | Env variable |
|---------|-----|----------------|
| API | `https://api.crewli.app` | `APP_URL` |
| Admin | `https://admin.crewli.app` | `FRONTEND_ADMIN_URL` |
| Organizer | `https://app.crewli.app` | `FRONTEND_APP_URL` |
| Portal | `https://portal.crewli.app` | `FRONTEND_PORTAL_URL` |
Frontends: set `VITE_API_URL=https://api.crewli.app/api/v1` in each apps env for production builds. `SANCTUM_STATEFUL_DOMAINS` must list the **hostnames only** of the three SPAs (e.g. `admin.crewli.app,app.crewli.app,portal.crewli.app`).
---
## Makefile commands
```bash
make services # MySQL, Redis, Mailpit
make services-stop
make api # Laravel on :8000
make admin # Admin on :5173
make app # Organizer on :5174
make portal # Portal on :5175
make migrate
make fresh # migrate:fresh --seed
make db-shell
```
---
## Documentation
| Resource | Contents |
|----------|----------|
| [resources/design/](resources/design/) | **Canonical product specs** in Markdown. Referenced by `.cursor` and `CLAUDE.md` as source of truth for features and data model: `design-document.md`, `dev-guide.md`, `start-guide.md`. |
| [.cursor/ARCHITECTURE.md](.cursor/ARCHITECTURE.md) | System diagram, apps, multi-tenancy, roles, event lifecycle, API route map, core schema overview (summarises `resources/design` when present) |
| [.cursor/instructions.md](.cursor/instructions.md) | Quick reference, phased roadmap, module build order |
| [.cursor/rules/](.cursor/rules/) | Workspace, Laravel, Vue, testing conventions |
| [docs/SETUP.md](docs/SETUP.md) | Environment and local setup |
| [docs/API.md](docs/API.md) | API notes (if maintained) |
| [docs/SCHEMA.md](docs/SCHEMA.md) | Schema notes (if maintained) |
---
## Testing
```bash
cd api && php artisan test
```
Feature tests should cover happy paths plus **401** (unauthenticated), **403** (wrong organisation), and **422** (validation) where applicable.