A modern field service management platform built for small-to-medium field operations businesses — HVAC, plumbing, electrical, landscaping, and more. Manage customers, schedule jobs, dispatch technicians, and handle billing from a single, fast web application.
FieldOps Hub gives your team a shared, real-time workspace to run field operations end to end:
| Area | Capabilities |
|---|---|
| Customers & Properties | Customer profiles with multiple service locations, address history, and attachments |
| Job Management | Create, assign, and track jobs through a full status lifecycle (scheduled → en route → in progress → completed) |
| Job Checklists | Per-job-type checklist templates that auto-copy onto new jobs; technicians check off items in the field |
| Estimates | Multi-tier estimate packages (Good/Better/Best); send via shareable public link; customers accept or decline online |
| Dispatch & Live Tracking | Assign jobs to technicians, view a live map of technician locations with current job overlay and location trail |
| Invoicing | Draft, edit, and send invoices tied to completed jobs; track line items, tax, discounts, and balance due |
| Payments | Record payments by method (cash, check, card, bank transfer); Stripe-hosted checkout for online card payments |
| Reporting | Owner dashboard with real-time KPIs; jobs-by-type, job profitability, and technician performance reports |
| Company Settings | Company branding (name, logo, contact info), default tax rate, and billing defaults per organization |
| Integration Settings | Per-organization Stripe, Twilio (SMS), SendGrid (email), and Google Maps API key management — keys stored encrypted at rest |
| Automated Notifications | Job confirmation emails/SMS on creation; en-route and completion status notifications via Twilio and SendGrid |
| Message Templates | Reusable message templates for job notifications and customer communications |
| Item Catalog | Maintain a reusable catalog of services and parts for quick line item entry |
| Roles & Permissions | Five built-in roles scoped per organization with granular permission control |
| Two-Factor Auth | Optional TOTP 2FA for all user accounts via Laravel Fortify |
| Technician PWA | Mobile-optimized progressive web app with offline support and background sync for field technicians |
| Layer | Technology |
|---|---|
| Backend | PHP 8.4 · Laravel 12 |
| Frontend | Vue 3 · TypeScript · Inertia.js |
| Styling | Tailwind CSS v4 · Reka UI (headless primitives) |
| Auth | Laravel Fortify (registration, password reset, 2FA) |
| Permissions | spatie/laravel-permission v7 |
| Route types | Laravel Wayfinder (auto-generated TypeScript bindings) |
| Payments | Stripe (hosted checkout + webhooks) |
| SMS | Twilio |
| SendGrid | |
| Maps | Google Maps API |
| Testing | Pest v4 |
| Dev tooling | Vite 7 · Laravel Pint · Prettier · ESLint |
Organization
├── OrganizationSettings (branding, tax rate, encrypted integration keys)
├── Users (with roles)
├── Customers
│ └── Properties (service locations)
├── Job Types
│ └── JobTypeChecklistItems (checklist templates)
├── Jobs (field_jobs)
│ ├── Job Line Items
│ ├── Job Checklist Items (auto-copied from type template on creation)
│ ├── Job Messages (email/SMS log)
│ ├── Invoice (1:1)
│ └── Attachments (polymorphic)
├── Estimates
│ ├── EstimatePackages (tiered: Good/Better/Best)
│ ├── Estimate Line Items
│ └── Attachments (polymorphic)
├── Items (catalog)
├── Invoices
│ ├── Invoice Line Items
│ ├── Payments
│ └── Attachments (polymorphic)
├── DriverLocations (technician GPS trail)
└── MessageTemplates
Every resource is scoped to an Organization, enabling clean multi-tenant data isolation.
| Role | Description |
|---|---|
owner |
Full access — typically the business owner / org creator |
admin |
Full access — can manage users and settings |
dispatcher |
Manage customers, properties, jobs, invoices, and payments |
technician |
View and update job status; read-only customers and properties |
bookkeeper |
Full invoice and payment access; read-only jobs and customers |
- PHP 8.4+
- Composer
- Node.js 20+ and npm
- A local database (SQLite works out of the box for development)
git clone <repo-url> fieldops-hub
cd fieldops-hub
composer run setupThis single command installs all dependencies, generates your app key, runs migrations, and builds frontend assets.
composer run devStarts four concurrent processes: PHP server, queue worker, Pail log viewer, and Vite HMR — all with color-coded output.
php artisan db:seedCreates a demo organization with four users (one per role), four job types, and three sample customers. All demo users share the password password.
composer run test # Clear config cache then run all tests
./vendor/bin/pest # Run Pest directly
./vendor/bin/pest tests/Feature/Auth # Run a specific directory
./vendor/bin/pest --filter "test name" # Run a single test by nameThe test suite uses an in-memory SQLite database — no setup required. The composer run test script passes -d memory_limit=512M automatically as the suite has grown large.
vendor/bin/pint # PHP (Laravel Pint)
npm run format # Prettier — write
npm run format:check # Prettier — check only
npm run lint # ESLint — auto-fixnpm run build # Client-only Vite build
npm run build:ssr # SSR build (client + server bundle)app/
├── Http/
│ ├── Controllers/
│ │ ├── Owner/ # Owner web app controllers
│ │ │ ├── ReportingController.php # Dashboard KPIs + all reports
│ │ │ ├── SettingsController.php # Company + integration settings
│ │ │ └── ...
│ │ ├── Technician/ # Technician PWA controllers
│ │ ├── Auth/ # Fortify-style auth controllers
│ │ └── Settings/ # Profile, password, 2FA settings
│ ├── Middleware/ # HandleInertiaRequests, HandleAppearance
│ └── Requests/ # Form request validation
├── Models/ # Eloquent models (all org-scoped)
└── Providers/ # FortifyServiceProvider
database/
├── migrations/ # Chronological schema history
├── seeders/ # DemoSeeder, RolesAndPermissionsSeeder
└── factories/ # Model factories for testing
resources/js/
├── pages/
│ ├── Owner/ # Owner web app pages
│ │ ├── Dashboard.vue # KPI dashboard
│ │ ├── Reports/ # JobsByType, JobProfitability, TechnicianPerformance
│ │ ├── Settings/ # Company.vue, Integrations.vue
│ │ └── ...
│ └── Technician/ # Technician PWA pages
├── layouts/ # OwnerLayout, TechnicianLayout, AuthLayout
├── components/
│ ├── *.vue # App-level components (sidebar, nav)
│ └── ui/ # Headless UI primitives (each has index.ts)
├── composables/ # useAppearance, useInitials, useTwoFactorAuth
└── types/index.d.ts # AppPageProps, Auth, User, NavItem, BreadcrumbItem
routes/
├── web.php # Owner + public + technician routes
├── api.php # Technician JSON API (location, jobs)
├── auth.php # Auth routes (login, register, reset, verify)
└── settings.php # Settings routes (profile, password, appearance, 2FA)
- Browser hits a Laravel route (
routes/web.php,routes/auth.php, orroutes/settings.php) - Controller calls
Inertia::render('PageName', $props) - Inertia serves the matching Vue page at
resources/js/pages/PageName.vue HandleInertiaRequestsmiddleware automatically sharesauth.user,name,quote, andsidebarOpento every page
Copy .env.example to .env and adjust as needed. Key settings:
APP_URL=http://fieldops-hub.test
DB_CONNECTION=sqlite # or mysql / pgsql for production
MAIL_MAILER=log # Change for real email delivery
# Stripe — required for online card payments
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
# Twilio — required for SMS notifications
TWILIO_SID=
TWILIO_TOKEN=
TWILIO_FROM=
# SendGrid — required for transactional email
SENDGRID_API_KEY=
# Google Maps — required for dispatch map
GOOGLE_MAPS_API_KEY=Integration keys can also be managed per-organization through the Settings → Integrations UI, where they are stored encrypted in the database.
- All owner routes require authentication (
auth+verifiedmiddleware) - All queries are scoped to
organization_id— no cross-tenant data leakage - Integration API keys are stored using Laravel's
encryptedcast (AES-256-CBC) - Keys are masked in the settings UI (last 4 chars visible); submitting a masked value does not overwrite the stored key
- Logo uploads are validated for file type (
imagerule) and size (2 MB limit) - Stripe webhook endpoint verifies the request signature before processing
- CSRF protection is enabled on all routes except the Stripe webhook
MIT