grafite / scaffold
An opinionated Laravel boilerplate.
Requires
- php: ^8.4
- aws/aws-sdk-php: ^3.192
- bacon/bacon-qr-code: ^3.0
- barryvdh/laravel-debugbar: ^4.0
- bepsvpt/secure-headers: ^9.0
- dedoc/scramble: ^0.13.0
- erag/laravel-disposable-email: ^5.2
- grafite/auth: ^1.0
- grafite/blacksmith: ^1.0
- grafite/charts: ^3.0
- grafite/database: ^2.5.2
- grafite/forms: ^7.0
- grafite/html: ^1.0
- grafite/maintenance: ^0.7.0
- grafite/mission-control-laravel: ^3.4
- grafite/support: ^1.1
- guzzlehttp/guzzle: ^7.8|^8.0
- hisorange/browser-detect: ^5.0
- intervention/image: ^4.0
- laravel-notification-channels/webpush: ^13.0
- laravel/ai: ^1.2
- laravel/cashier: ^16.9
- laravel/framework: ^13.0
- laravel/helpers: ^1.1
- laravel/mcp: ^1.0
- laravel/passport: ^13.8
- laravel/sanctum: ^4.0
- laravel/socialite: ^5.24
- livewire/livewire: ^4.0
- pragmarx/google2fa-laravel: ^3.0
- pragmarx/recovery: ^0.2.1
- pusher/pusher-php-server: ^7.2
- shiftonelabs/laravel-sqs-fifo-queue: ^3.0
- silviolleite/laravelpwa: ^2.0
- spatie/laravel-honeypot: ^4.0
- symfony/http-client: ^8.0
- tightenco/ziggy: ^2.0
- yorcreative/laravel-scrubber: ^3.0
Requires (Dev)
- fakerphp/faker: ^1.10
- laravel/dusk: ^8.0
- laravel/pint: ^1.10
- laravel/sail: ^1.14
- mockery/mockery: ^1.3
- phpunit/phpunit: ^13.0
- spatie/laravel-ignition: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v3.0.0
- v2.23.0
- v2.22.0
- v2.21.0
- v2.20.2
- v2.20.1
- v2.20.0
- v2.19.2
- v2.19.1
- v2.19.0
- v2.18.0
- v2.17.2
- v2.17.1
- v2.17.0
- v2.16.3
- v2.16.2
- v2.16.1
- v2.16.0
- v2.15.2
- v2.15.1
- v2.15.0
- v2.14.1
- v2.14.0
- v2.13.0
- v2.12.1
- v2.12.0
- v2.11.0
- v2.10.1
- v2.10.0
- v2.9.0
- v2.8.0
- v2.7.0
- v2.6.1
- v2.6.0
- v2.5.1
- v2.5.0
- v2.4.0
- v2.3.0
- v2.2.0
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.0
- v1.5.1
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.1
- v1.0.0
- dev-develop
- dev-feature/laravel-13-skeleton
- dev-saml-concept
- dev-docker-ideas
- dev-shift-ci-v8.25.0
- dev-simple-checkout
This package is auto-updated.
Last update: 2026-11-02 16:30:07 UTC
README
About Grafite Scaffold
Grafite Scaffold was created as a highly opinionated boilerplate of Laravel's base application structure. In comes loaded with a variety of packages for various needs including:
- grafite/auth
- grafite/charts
- grafite/database
- grafite/forms
- grafite/html
- grafite/maintenance
- hisorange/browser-detect
- intervention/image
- guzzlehttp/guzzle
- bepsvpt/secure-headers
- livewire/livewire
- laravel/framework
- laravel/cashier
- laravel/dusk
- laravel/helpers
- laravel/sanctum
- lasserafn/php-initial-avatar-generator
- tightenco/ziggy
- pragmarx/google2fa-laravel
- pragmarx/recovery
- pusher/pusher-php-server
- silviolleite/laravelpwa
- spatie/laravel-honeypot
Scaffold is intended to be used to start a project and then be heavily altered.
Author(s):
- Matt Lantz (@mattylantz, mattlantz at gmail dot com)
Requirements
- PHP 8.2+
Setup
Local development (Sail)
cp .env.example .env # then set DB_HOST=mysql, REDIS_HOST=valkey, MAIL_HOST=mailpit, MAIL_PORT=1025
./vendor/bin/sail up -d
./vendor/bin/sail artisan key:generate
./vendor/bin/sail artisan migrate
./vendor/bin/sail npm run dev
compose.yaml runs the app with MySQL, Valkey and Mailpit.
Production image
The Dockerfile builds one image (PHP 8.4 on serversideup/php fpm-nginx, with the Vite assets compiled in) that runs every part of the app: the web server by default, and queue:work, schedule:work or migrate when given that command. To try it locally the way production runs it:
docker compose -f compose.production.yaml up --build # https://localhost:8443
Configuration comes only from environment variables (.env files are not copied into the image). The container filesystem is temporary, so production sends uploads to S3/Spaces (FILESYSTEM_DISK=s3), logs to stderr, and reads Passport keys from PASSPORT_PRIVATE_KEY / PASSPORT_PUBLIC_KEY.
Deploying to DigitalOcean App Platform
After the Tests workflow passes on main, .github/workflows/deploy.yml builds the image, pushes it to DigitalOcean Container Registry, and deploys .do/app.yaml. You can also run the workflow by hand from the Actions tab. The app spec defines:
web: the HTTP service, health-checked at/upqueue: aqueue:workworkerscheduler: aschedule:workworker. Keep it at one instance.migrate: a pre-deploy job. A failed migration stops the deploy.dbandcache: managed MySQL and managed Valkey. Valkey handles cache, sessions, queues and scheduler locks.
One-time setup
- In DigitalOcean, create:
- a Container Registry
- a managed MySQL cluster, with a database and user for the app
- a managed Valkey cluster
- a Spaces bucket and a Spaces access key
- an API token with read/write access, for GitHub
- Generate the app and Passport keys locally. The Passport keys must be stored on a single line with
\n:php artisan key:generate --show php artisan passport:keys --force awk '{printf "%s\\n", $0}' storage/oauth-private.key # PASSPORT_PRIVATE_KEY awk '{printf "%s\\n", $0}' storage/oauth-public.key # PASSPORT_PUBLIC_KEY - In GitHub, go to Settings → Secrets and variables → Actions. You can add these to the
productionenvironment or to the repository.- Variables:
DOCR_REGISTRY,DOCR_REPOSITORYDO_APP_NAME,DO_PROJECT_ID(optional)DO_MYSQL_CLUSTER,DO_MYSQL_DATABASE,DO_MYSQL_USER,DO_VALKEY_CLUSTERSPACES_REGION(for exampletor1),SPACES_BUCKETMAIL_HOST,MAIL_PORT,MAIL_FROM_ADDRESSPUSHER_APP_ID,PUSHER_APP_KEY,PUSHER_APP_CLUSTERSTRIPE_KEY,PLAN_MONTHLY,PLAN_YEARLYVAPID_SUBJECT,VAPID_PUBLIC_KEYMISSION_CONTROL_PROJECT_UUID
- Secrets:
DIGITALOCEAN_ACCESS_TOKENAPP_KEY,PASSPORT_PRIVATE_KEY,PASSPORT_PUBLIC_KEYSPACES_ACCESS_KEY_ID,SPACES_SECRET_ACCESS_KEYMAIL_USERNAME,MAIL_PASSWORDPUSHER_APP_SECRETSTRIPE_SECRET,STRIPE_WEBHOOK_SECRETANTHROPIC_API_KEY,OPENAI_API_KEYVAPID_PRIVATE_KEYMISSION_CONTROL_USER_TOKEN,MISSION_CONTROL_PROJECT_KEY
- Variables:
- Push to
main, or run the Deploy workflow by hand. The first run creates the app; later runs update it. - To use a custom domain, uncomment
domains:in.do/app.yamland point a CNAME at the app'sondigitalocean.appaddress.
Every deploy replaces the app's configuration with .do/app.yaml, so set secrets in GitHub, not in the DigitalOcean dashboard. A secret or variable that isn't set is sent as an empty value. To add a new setting, add it to .do/app.yaml, to the deploy step's env: in deploy.yml, and to GitHub.
Connecting Claude (MCP)
The app ships with an MCP server for user accounts at /mcp/users, authorized with OAuth 2.1 via Laravel Passport.
- Run
php artisan migrateandphp artisan passport:keysonce per environment (the keys are gitignored). - In Claude, add a custom connector pointing at
https://{your-app}/mcp/users. Claude registers itself, and you approve access on the app's authorize page.
Add servers and tools in routes/ai.php and app/Mcp/ (php artisan make:mcp-server, php artisan make:mcp-tool).
Compatibility and Support
Since Grafite Scaffold is a starter project it offers no support, and no compatibily guarantees.
Installation
composer create-project grafite/scaffold {project-name} --prefer-dist
Documentation
https://docs.grafite.ca/scaffold/introduction
License
Grafite Scaffold is open-sourced software licensed under the MIT license
Bug Reporting and Feature Requests
Please add as many details as possible regarding submission of issues and feature requests
Disclaimer
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.