PBS Planning - Implementation Plan
Version: 1.0 Created: 2025-11-06 Status: Ready for Development
This document outlines the complete technical stack, infrastructure, and phased implementation strategy for PBS MVP.
ποΈ Technology Stackβ
Our stack is optimized for speed, simplicity, and maintainabilityβaligned with our "Simplicity First" principle.
Backend (API Layer)β
Core Framework
- Laravel 11 β Routing, controllers, Eloquent ORM, validation, authorization policies
- Laravel Sanctum β SPA authentication via secure httpOnly cookies (no JWT complexity)
- MySQL 8.0 or PostgreSQL 15 β EU-hosted, production-grade RDBMS
- spatie/laravel-permission β Role-based access control (Owner/Admin/Crew roles)
Key Features
β RESTful API architecture
β Multi-tenant row-level security (company_id scoping)
β Database migrations from schema.dbml
β Policy-based authorization (aligned with UC-01 to UC-16 permissions)
β Queue system for emails (Laravel Queue + Redis)
Installation
composer create-project laravel/laravel api
cd api
composer require laravel/sanctum spatie/laravel-permission
composer require --dev pestphp/pest pestphp/pest-plugin-laravel
Frontend (SPA Layer)β
Core Framework
- React 18 β Component-based UI library
- TypeScript β Type-safe development, catch errors at compile time
- Vite 5 β Lightning-fast dev server and optimized production builds
- Tailwind CSS 3 β Utility-first styling with custom design tokens
Routing & State
- React Router v6 β Client-side routing for SPA navigation
- @tanstack/react-query β Server-state management, caching, invalidation
- Zustand (optional) β Lightweight client-state (user preferences, UI state)
Installation
npm create vite@latest app -- --template react-ts
cd app
npm i react-router-dom axios @tanstack/react-query @tanstack/react-table \
react-hook-form zod @hookform/resolvers \
luxon recharts react-big-calendar \
lucide-react class-variance-authority clsx tailwind-merge
npm i -D tailwindcss postcss autoprefixer \
vitest @testing-library/react @testing-library/user-event
UI Component Libraryβ
shadcn/ui (Radix Primitives + Tailwind)
- You own the code β Components copied into your project, fully customizable
- Accessible by default β Radix UI primitives follow WAI-ARIA standards
- Tailwind-integrated β No CSS-in-JS overhead
Core Components Needed
Button, Input, Select, Textarea, Checkbox, Radio
Dialog/Sheet (modals, slideovers)
Dropdown Menu, Popover, Tooltip
Tabs, Accordion, Card
Table (with @tanstack/react-table integration)
Toast (notifications)
Badge, Avatar, Separator
Calendar, Date Picker (for booking dates)
Command (search/command palette - optional)
Theme System
/* tailwind.config.js */
colors: {
primary: '#008B8B', // Petrol/teal (NCP brand)
secondary: '#475569', // Slate gray
danger: '#DC2626', // Red
success: '#16A34A', // Green
}
Data & Formsβ
HTTP & Server State
- Axios β HTTP client with interceptors for auth/errors
- @tanstack/react-query β Data fetching, caching, mutations, optimistic updates
Forms & Validation
- react-hook-form β Performant forms with minimal re-renders
- zod β Schema validation (shared between frontend and backend)
- @hookform/resolvers β Bridge react-hook-form + zod
Data Grids
- @tanstack/react-table β Headless table logic (sorting, filtering, pagination)
- Styled with Tailwind + shadcn/ui table components
Charts & Visualizationsβ
Recharts β Composable charting library for dashboards
- Project timelines
- Staff utilization reports
- Financial summaries
Alternative: @tremor/react (Tailwind-first dashboard components)
Scheduling & Calendarβ
Primary: FullCalendar (@fullcalendar/react)
- Timeline view for multi-day projects
- Resource scheduling (crew availability)
- Drag-and-drop booking
Date Handling: Luxon
- Timezone support (IANA database)
- Date formatting/parsing
- Duration calculations
Why FullCalendar over react-big-calendar?
- Better resource scheduling (crew conflict detection)
- Timeline view matches project booking needs
- Commercial license available for private projects
Testingβ
Backend
- Pest PHP β Modern, elegant testing framework for Laravel
- PHPUnit β Underlying test runner
- Coverage for policies, API endpoints, database logic
Frontend
- Vitest β Fast Vite-native test runner
- @testing-library/react β User-centric component testing
- @testing-library/user-event β Realistic user interaction simulation
E2E (Optional for later)
- Playwright β Cross-browser end-to-end testing
- Test critical user journeys (UC-01, UC-04, UC-11)
π Infrastructureβ
Hosting Architectureβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Production Setup β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Frontend (React SPA)
ββ Host: Cloudflare Pages or Vercel
ββ URL: app.pbsystems.eu (or crew.pbsystems.eu for crew portal)
ββ CDN: Global edge caching
Backend (Laravel API)
ββ Host: Hetzner Cloud (EU), DigitalOcean, or AWS EU regions
ββ URL: api.pbsystems.eu
ββ Server: Ubuntu 22.04 LTS + Nginx + PHP 8.3-FPM
Database
ββ MySQL 8.0 or PostgreSQL 15
ββ Host: Managed DB service (Hetzner, DO, or RDS)
ββ Backups: Daily automated snapshots
Queue & Cache
ββ Redis 7.x
ββ Use: Queue jobs (emails), session cache
ββ Host: Same server or managed Redis
File Storage
ββ Local storage (MVP) or S3-compatible object storage
ββ Use: Road books (PDFs), user avatars, project documents
Environmentsβ
1. Local Development
Frontend: http://localhost:5173 (Vite dev server)
Backend: http://localhost:8000 (php artisan serve)
Database: Docker MySQL/Postgres container
Redis: Docker Redis container
2. Staging
Frontend: https://staging-app.pbsystems.eu
Backend: https://staging-api.pbsystems.eu
Database: Separate staging DB
Purpose: Client demos, QA testing
3. Production
Frontend: https://app.pbsystems.eu
Backend: https://api.pbsystems.eu
Database: Production DB with backups
Monitoring: Laravel Telescope (dev) + Sentry (errors)
Domain & CORS Setupβ
Subdomains
app.pbsystems.eu β React SPA (Admin interface)
crew.pbsystems.eu β React SPA (Crew portal - same codebase, different routing)
api.pbsystems.eu β Laravel API
CORS Configuration (Laravel)
// config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_origins' => [
'https://app.pbsystems.eu',
'https://crew.pbsystems.eu'
],
'supports_credentials' => true,
Sanctum Configuration
// config/sanctum.php
'stateful' => [
'app.pbsystems.eu',
'crew.pbsystems.eu',
'localhost:5173', // local dev
],
Frontend Axios Setup
// src/api/client.ts
axios.defaults.baseURL = 'https://api.pbsystems.eu'
axios.defaults.withCredentials = true // Send cookies
Security Considerationsβ
Authentication Flow
1. Frontend calls /sanctum/csrf-cookie
2. Receives XSRF-TOKEN cookie
3. Subsequent requests include X-XSRF-TOKEN header
4. Session maintained via httpOnly cookies
Multi-Tenancy Security
// Global scope on all models
protected static function booted() {
static::addGlobalScope('company', function ($query) {
if (auth()->check()) {
$query->where('company_id', auth()->user()->company_id);
}
});
}
Role-Based Access
// Spatie permissions
$user->assignRole('admin');
$user->givePermissionTo('create-projects');
// Policies
Gate::define('update-project', function ($user, $project) {
return $user->company_id === $project->company_id
&& $user->hasRole('admin');
});
π Phased Implementation Strategyβ
Overviewβ
Total Duration: 14 weeks (3.5 months) Team Size: 1-2 full-stack developers Methodology: Agile sprints (2-week iterations)
Phase 0: Foundation β Weeks 1-2 (Infrastructure & Auth)
Phase 1: Core Admin β Weeks 3-5 (Projects & Staff Management)
Phase 2: Booking System β Weeks 6-8 (Offers & Assignments)
Phase 3: Crew Portal β Weeks 9-10 (Registration & Responses)
Phase 4: Operations β Weeks 11-12 (Travel & Financials)
Phase 5: Polish & Launch β Weeks 13-14 (Testing & Deployment)
Phase 0: Foundation (Weeks 1-2)β
Goal: Set up development environment, authentication, and database foundation.
Week 1: Scaffoldingβ
Backend
- Laravel 11 installation
- Database setup (MySQL/Postgres)
- Run migrations from
schema.dbml(18 tables) - Install Sanctum + Spatie permissions
- Create seeders for roles (owner, admin, crew)
- API route structure (
routes/api.php)
Frontend
- Vite + React + TypeScript setup
- Install dependencies (React Query, React Router, etc.)
- Configure Tailwind CSS with design tokens
- Set up shadcn/ui components (init + install core components)
- Create folder structure (
/api,/components,/features,/styles)
Infrastructure
- Docker Compose for local DB + Redis
- Environment files (
.env.exampletemplates) - Git repository structure (monorepo or separate repos?)
Week 2: Authentication & Multi-Tenancyβ
Backend
- Sanctum CSRF cookie endpoint
- Login/logout API endpoints
- User registration (admin creates users initially)
- Company scoping middleware
- Policies for user access control
Frontend
- Auth context provider (React Context or Zustand)
- Login page (view from
docs/views.md) - Protected route wrapper
- Axios interceptors for CSRF + error handling
- Basic layout shell (sidebar, header, navigation)
Testing
- Pest tests for auth endpoints
- Vitest setup with sample component test
Deliverable: Working login system with multi-tenant data isolation.
Phase 1: Core Admin (Weeks 3-5)β
Goal: Implement essential admin features for managing projects and staff profiles.
User Cases Coveredβ
- UC-01: Create New Project
- UC-07: Manage Staff Profiles (view/edit)
- UC-02: Define Project Staffing Needs
Week 3: Projects Moduleβ
Backend
- Projects CRUD API (
/api/projects) - Project validation rules (dates, status transitions)
- Policies (only admins can create/edit projects)
- Include company scoping
Frontend
- Projects list view (table with sorting/filtering)
- Create project form (modal or page)
- Edit project form
- Project detail view (read-only summary)
Database
- Projects table with status: draft β active β completed
- Venues and locations fields
Testing
- API tests for CRUD operations
- Component tests for project forms
Week 4: Staff Profiles Moduleβ
Backend
- Staff profiles API (
/api/staff) - CRUD endpoints (list, view, create, edit)
- Profile search/filtering (by function, availability)
- Soft delete support (archive staff)
Frontend
- Staff list view (filterable table)
- Staff profile detail page
- Create/edit staff forms
- Staff functions dropdown (from
project_functionstable)
Database
- Staff table (linked to users for crew login)
- Functions and rates
Testing
- API tests for staff CRUD
- Search/filter tests
Week 5: Project Staffing Needsβ
Backend
- Project functions API (
/api/projects/{id}/functions) - CRUD for defining needed roles per project
- Target rates (work + travel)
Frontend
- Project staffing tab (within project detail)
- Add function modal (select function, quantity, dates, rates)
- Edit/delete functions
- Visual summary of staffing needs vs. assignments
Testing
- Integration tests (project β functions relationship)
Deliverable: Admin can create projects and define staffing requirements.
Phase 2: Booking System (Weeks 6-8)β
Goal: Implement core booking workflowsβoffers, assignments, conflict detection.
User Cases Coveredβ
- UC-04: Send Assignment Offers (includes direct booking)
- UC-05: Track Offer Responses
- UC-06: Manage Confirmed Assignments
Week 6: Assignment Offers (Direct Booking Path)β
Backend
- Assignment offers API (
/api/assignment-offers) - Create offer endpoint (with
is_direct_bookingflag) - Conflict detection logic (soft warnings for date overlaps)
- Email queue job for offer notifications
Frontend
- "Book Staff" button on project detail page
- Staff selection modal (search staff by function)
- Offer form (dates, rates, message, direct booking checkbox)
- Conflict warning display ("Lisa has conflict May 12-14. Send anyway?")
- Success toast notification
Business Logic
Direct Booking Flow:
Admin checks "Direct Booking" β Creates offer with is_direct_booking=true β
System immediately creates assignment (status: confirmed) β
Email sent to crew (informational only)
Testing
- Test direct booking creation
- Test conflict detection logic
- Email job test (queue fake)
Week 7: Offer Tracking & Responsesβ
Backend
- Offer status updates (
/api/assignment-offers/{id}) - Crew response endpoint (accept/decline with note)
- Admin review endpoint (confirm/reject after crew acceptance)
Frontend
- Offers list view for admin (filterable by status, project, staff)
- Offer detail modal (show dates, rates, crew response)
- Admin action buttons (Confirm β Assignment, Reject)
- Status badges (pending, accepted, confirmed, declined, rejected)
Email Jobs
- Offer sent notification
- Crew accepted notification (to admin)
- Admin confirmed notification (to crew)
- Declined/rejected notifications
Testing
- Test full offer flow (send β accept β confirm)
- Test decline/reject flows
Week 8: Assignments Managementβ
Backend
- Assignments API (
/api/assignments) - List confirmed assignments (per project, per staff)
- Update assignment details (dates, rates, notes)
- Assignment documents API (upload road books, contracts)
Frontend
- Assignments list view (project-level and global)
- Assignment detail view (show all booking details)
- Edit assignment modal (update dates, add notes)
- Assignment card/row (compact display for lists)
Business Logic
- Only confirmed assignments appear here
- Link to offers (assignment history)
- Show special instructions, meals, parking, dress code
Testing
- Test assignment CRUD
- Test document upload (if implemented)
Deliverable: Admin can send offers (direct or standard), track responses, and manage confirmed assignments.
Phase 3: Crew Portal (Weeks 9-10)β
Goal: Build crew-facing interfaces for registration, viewing assignments, and responding to offers.
User Cases Coveredβ
- UC-11: Staff Registration (Invite-Only)
- UC-12: View My Assignments
- UC-13: View Assignment Details
- UC-14: Respond to Offers
- UC-15: Update My Profile
Week 9: Crew Registration & Profilesβ
Backend
- Staff invitations API (
/api/invitations) - Admin creates invitation (email, function, message)
- Public registration endpoint (
/api/register/{token}) - Profile submission workflow (pending β approved β profile created)
Frontend (Admin)
- Invite staff modal (enter email, select function)
- Invitations list (track sent invites)
Frontend (Crew Portal)
- Registration page (token-based, public)
- Profile submission form (name, contact, experience, rates)
- Submission confirmation message
Email Jobs
- Invitation email with registration link
- Profile approved email (with login credentials)
Testing
- Test invite flow end-to-end
- Test token validation
- Test duplicate email prevention
Week 10: Crew Assignment Viewsβ
Backend
- Crew assignments endpoint (
/api/me/assignments) - Crew offers endpoint (
/api/me/offers) - Scoped to current authenticated crew user
Frontend (Crew Portal)
- Dashboard (overview of upcoming assignments)
- Assignments list (past and future)
- Assignment detail page (dates, project info, special instructions)
- Offers list (pending offers requiring response)
- Offer detail + action buttons (Accept/Decline with optional note)
Mobile Optimization
- Responsive layout (Tailwind breakpoints)
- Touch-friendly buttons (min 44px tap targets)
- Simplified navigation (bottom nav or hamburger menu)
Testing
- Test crew can only see their own data (auth policies)
- Test responsive layouts on mobile viewport
Deliverable: Crew can register via invite, view assignments, and respond to offers.
Phase 4: Operations (Weeks 11-12)β
Goal: Implement operational featuresβtravel booking, road book generation, financial completion.
User Cases Coveredβ
- UC-08: Book Travel & Hotels
- UC-09: Generate Road Books
- UC-10: Financial Completion
- UC-16: View Travel Details (crew view)
Week 11: Travel & Hotel Bookingsβ
Backend
- Travel bookings API (
/api/assignments/{id}/travel) - Hotel bookings API (
/api/assignments/{id}/hotels) - CRUD endpoints for both
- Link to assignments
Frontend (Admin)
- Travel booking form (flight details, times, terminals)
- Hotel booking form (name, address, check-in/out times)
- Travel tab on assignment detail page
Frontend (Crew)
- Read-only travel details on assignment page
- Formatted display of flight info and hotel details
Data Validation
- Flight date must be before/after project dates
- Hotel check-in/out validation
Testing
- Test travel/hotel CRUD
- Test crew cannot edit travel details (read-only policy)
Week 12: Road Books & Financial Completionβ
Backend (Road Books)
- Road book generation endpoint (
/api/assignments/{id}/road-book) - PDF generation library (e.g.,
barryvdh/laravel-dompdforspatie/laravel-pdf) - Compile data: project venue, travel, hotel, assignment details
- Store generated PDF as document
Frontend
- "Generate Road Book" button on assignment detail
- Download link for existing road books
- Preview modal (optional)
Backend (Financial Completion)
- Financial completion endpoint (
/api/projects/{id}/finalize) - Update assignment actual days/rates
- Lock project financials (set
financials_finalized = true) - Validation: all assignments must have actual data
Frontend
- Financial completion tab on project detail
- Table showing planned vs. actual for each assignment
- Edit actual values form
- "Finalize Financials" button (with confirmation dialog)
- Visual lock indicator when finalized
Business Logic
Financial Completion Flow:
Project active β Admin enters actual days/rates β
Admin clicks "Finalize Financials" β
All assignments locked (cannot edit rates/days) β
Ready for future invoicing
Testing
- Test PDF generation with sample data
- Test financial lock prevents edits
- Test validation (cannot finalize without actual data)
Deliverable: Admin can manage travel, generate road books, and complete project financials.
Phase 5: Polish & Launch (Weeks 13-14)β
Goal: Testing, bug fixes, UI polish, documentation, and production deployment.
Week 13: Testing & Bug Fixesβ
Backend
- Write comprehensive Pest tests for all critical paths
- Test multi-tenancy isolation (ensure company A can't see company B data)
- Test all policies (authorization rules)
- Load testing (simulate 50+ concurrent users)
Frontend
- Write Vitest component tests for key flows
- Manual QA on all 16 user cases
- Cross-browser testing (Chrome, Firefox, Safari)
- Mobile testing (iOS Safari, Chrome Android)
E2E Testing (Optional but Recommended)
- Playwright tests for critical user journeys:
- UC-01: Create project β UC-04: Send offer β UC-14: Crew accepts
- UC-11: Crew registration flow
- UC-10: Financial completion
Bug Triage
- Create GitHub Issues for all found bugs
- Prioritize (Critical, High, Medium, Low)
- Fix critical and high-priority bugs
Week 14: UI Polish & Deploymentβ
UI Polish
- Accessibility audit (keyboard navigation, screen readers)
- Loading states and skeletons
- Error messages and validation feedback
- Empty states (e.g., "No projects yet" with CTA)
- Success animations and micro-interactions
- Mobile touch optimizations
Documentation
- API documentation (OpenAPI/Swagger or Postman collection)
- Deployment runbook (server setup, env vars)
- User guide (basic feature overview for clients)
- Admin onboarding checklist
Production Deployment
- Set up production servers (Hetzner/DO/AWS)
- Configure domain DNS (api.pbsystems.eu, app.pbsystems.eu)
- Install SSL certificates (Let's Encrypt)
- Deploy backend (Laravel) via Git + CI/CD
- Deploy frontend (Cloudflare Pages or Vercel)
- Run database migrations on production
- Seed initial data (company, admin user)
Monitoring Setup
- Laravel Telescope (staging only, not production)
- Sentry for error tracking
- Server monitoring (uptime, disk, memory)
- Log aggregation (Papertrail, CloudWatch, or similar)
Launch Checklist
- Production smoke tests (login, create project, send offer)
- Backup strategy tested (database backups + restore)
- Email delivery working (use transactional email service like Postmark)
- SSL/CORS configured correctly
- Performance baseline recorded (page load times)
Deliverable: Production-ready PBS MVP deployed and accessible at app.pbsystems.eu.
π§ͺ Testing Strategyβ
Backend Testing (Pest PHP)β
Unit Tests β Isolated logic
// tests/Unit/ConflictDetectionTest.php
it('detects date overlap conflicts', function () {
// Create existing assignment May 10-15
// Check new offer May 12-14
// Assert conflict detected
});
Feature Tests β API endpoints
// tests/Feature/ProjectsTest.php
it('creates a project with valid data', function () {
$response = $this->postJson('/api/projects', [
'title' => 'Summer Festival 2025',
'start_date' => '2025-06-01',
'end_date' => '2025-06-05',
]);
$response->assertStatus(201);
});
Policy Tests β Authorization
it('prevents crew from editing projects', function () {
$crew = User::factory()->crew()->create();
$this->actingAs($crew)
->putJson('/api/projects/1', [...])
->assertForbidden();
});
Coverage Goal: 80%+ for models, policies, and critical API endpoints.
Frontend Testing (Vitest + Testing Library)β
Component Tests
// src/components/ProjectForm.test.tsx
it('validates required fields', async () => {
render(<ProjectForm />)
await userEvent.click(screen.getByRole('button', { name: /save/i }))
expect(screen.getByText(/title is required/i)).toBeInTheDocument()
})
Integration Tests β React Query hooks
// src/api/projects.test.ts
it('fetches projects from API', async () => {
const { result } = renderHook(() => useProjects(), { wrapper: QueryWrapper })
await waitFor(() => expect(result.current.isSuccess).toBe(true))
expect(result.current.data).toHaveLength(5)
})
Coverage Goal: 70%+ for critical components and API hooks.
E2E Testing (Playwright) β Optionalβ
Critical User Journeys
// e2e/booking-flow.spec.ts
test('admin books crew directly', async ({ page }) => {
await page.goto('/projects/1')
await page.click('text=Book Staff')
await page.fill('input[name="staff"]', 'Lisa')
await page.check('input[name="direct_booking"]')
await page.click('button:has-text("Create Booking")')
await expect(page.locator('text=Assignment created')).toBeVisible()
})
Run E2E: Only on critical paths (login, booking, registration).
Manual QA Checklistβ
Before launch, manually test all 16 user cases:
Admin Portal
- UC-01: Create project (draft β active)
- UC-02: Define staffing needs (add functions, rates)
- UC-03: Duplicate project
- UC-04: Send offer (direct booking + standard offer)
- UC-05: Track offer responses
- UC-06: Manage assignments
- UC-07: Manage staff profiles (view, edit)
- UC-08: Book travel and hotels
- UC-09: Generate road book (PDF download)
- UC-10: Financial completion (enter actuals, lock)
Crew Portal
- UC-11: Register via invite
- UC-12: View assignments (list)
- UC-13: View assignment details
- UC-14: Respond to offer (accept/decline)
- UC-15: Update profile
- UC-16: View travel details
Cross-Cutting
- Multi-tenancy isolation (create 2 companies, verify data separation)
- Role permissions (admin vs. crew access)
- Mobile responsiveness (crew portal on phone)
- Email delivery (all notification emails)