# 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 | |-----|------|------|------| | **SPA** | `apps/app/` | 5174 | Single-SPA product covering **organizers, volunteers, crew, super admins** (context-routed in-app), plus token-based access for artists, suppliers, press. Includes **Platform Admin** section for super admins (`/platform/*`). | The SPA talks 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/ │ ├── app/ # Organizer SPA (primary UI + platform admin) │ └── 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 app make portal ``` Detailed setup: **[docs/SETUP.md](docs/SETUP.md)**. --- ## Development URLs | Service | Development | Env / notes | |---------|-------------|-------------| | API | http://localhost:8000/api/v1 | Base path `/api/v1` | | 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 + portal SPAs, transactional email from the app, seeds, etc.). **`crewli.nl`** is reserved for a future **public marketing site** only — do not point this codebase's `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` | | Organizer | `https://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 app's env for production builds. `SANCTUM_STATEFUL_DOMAINS` must list the **hostnames only** of the two SPAs (e.g. `crewli.app,portal.crewli.app`). --- ## Makefile commands ```bash make services # MySQL, Redis, Mailpit make services-stop make api # Laravel on :8000 make app # Organizer on :5174 make portal # Portal on :5175 make migrate make fresh # migrate:fresh --seed make db-shell ``` --- ## Documentation | Resource | Contents | |----------|----------| | [CLAUDE.md](CLAUDE.md) | Project conventions, vibe-coding principles, Vuexy-first decision tree (auto-loaded by Claude Code). | | [.cursor/rules/](.cursor/rules/) | Workspace, Laravel, Vue, testing conventions. | | [dev-docs/SETUP.md](dev-docs/SETUP.md) | Environment and local setup. | | [dev-docs/SCHEMA.md](dev-docs/SCHEMA.md) | Database schema (kept in sync with migrations). | | [dev-docs/API.md](dev-docs/API.md) | API contract. | | [dev-docs/design-document.md](dev-docs/design-document.md) | Product specification. | --- ## Testing ```bash cd api && php artisan test ``` Feature tests should cover happy paths plus **401** (unauthenticated), **403** (wrong organisation), and **422** (validation) where applicable.