iluminar/goodwork
Goodwork is a self-hosted project management and collaboration platform built with Laravel and Vue.js. It combines projects, tasks, discussions, calendars, and team communication in one workspace, helping teams plan work, track progress, and stay organized.
GoodWork is a complete Laravel application, not an installable Composer package — you don't composer require it into an existing project. "Getting started" means standing up your own fork.
git clone https://github.com/iluminar/goodwork.git
cd goodwork
composer install
cp .env.example .env
php artisan key:generate
# configure DB_* in .env (MySQL or PostgreSQL)
php artisan migrate --seed
npm install && npm run build
php artisan serve
Where to look first, in order:
composer.json — confirms the Laravel and Filament major versions you're pinned to. Everything downstream depends on this.app/Filament/ — the admin UI is almost entirely Filament Resources; this is where 80% of day-to-day changes land.app/Models/ — Client, Project, Task, TimeEntry, Invoice and their relationships define the domain.database/migrations/ and database/seeders/ — the schema you'll be extending, plus demo data to click through.config/ — currency, tax, and mail settings that bite later.First use case to validate the install: create a Client → Project → Task, log a TimeEntry against it, then generate an Invoice from tracked time. If that loop works end-to-end (including PDF output), your environment is correct.
Treat it as a starter SaaS, not a dependency. The realistic workflow is fork → rebrand → extend. Keep a clean upstream remote so you can cherry-pick fixes:
git remote add upstream https://github.com/iluminar/goodwork.git
git fetch upstream && git log --oneline upstream/master ^master
Extending the UI via Filament Resources. Custom fields, new columns, and workflow buttons are added by overriding the Resource's form() / table() schema rather than editing Blade. Prefer creating your own Resource in app/Filament/Resources/ and adjusting navigation/permissions, so upgrades touch fewer files.
Schema extension pattern. Add migrations for your fields (php artisan make:migration add_x_to_projects), add the column to the model's $fillable/$casts, then surface it in the Filament form. This trio (migration + model + Resource) is the unit of work for most customizations.
Time tracking and invoicing as the integration seam. Time entries roll up into invoice line items. If you need custom billing rules (rounding, billable rates per role, retainers), implement them as a service class invoked at invoice generation time, not inside the Resource — keeps logic testable and reusable from a command or job.
Background work. Invoice PDF rendering, mail, and any exports should run on queues. Add a queue worker (Supervisor or a container sidecar) and set QUEUE_CONNECTION to Redis/database rather than sync in production.
Deployment. It's a standard Laravel app: Nginx + PHP-FPM, php artisan migrate --force, config:cache, route:cache, view:cache, storage symlink, and a scheduler cron entry. Docker/Forge/Vapor all work; nothing GoodWork-specific is required.
Integration tips. For external systems (accounting, CRMs), prefer Artisan commands + scheduling over hacking controllers, and use model observers on Invoice/TimeEntry to push events outward. If you need an API for a mobile client, add routes in a dedicated routes/api.php guarded by Sanctum rather than reusing web routes.
composer.json first; customizing Resources against v3 while upstream moves on creates painful merge conflicts. Pin Filament and upgrade deliberately, reading the upgrade guide.app/Filament is a future conflict. Prefer new Resources, Filament plugins, and service classes over in-place edits to core files.dompdf/wkhtmltopdf/Browsershot. Verify the binary/extension exists in your container image — this is the most common "works locally, fails in prod" failure.--seed in production; audit the seeders for hardcoded admin credentials and sample clients.php artisan about, check storage/logs/laravel.log, and php artisan filament:optimize-clear after resource changes.How can I help you explore Laravel packages today?