Create Project
Create the Application
Run this step by hand; agents take over after the project exists.
bash
laravel new vehub-app --database=mysql --sveltePest, npm, and Boost are the installer's interactive defaults. The starter kit then asks which authentication features to enable: keep all five selected and press Enter; later chapters assume them.
Enter the project directory:
bash
cd vehub-appCreate the Repository
Commit the untouched starter before changing anything, so every later diff is against it. Keep any history the installer created; git init is a no-op then.
bash
git init
git add -A
git commit -m 'Initial Commit'
git branch -M mainCreate a new private remote and push. Replace zoonix; this assumes no existing origin or GitHub repo.
bash
gh repo create zoonix/vehub-app --private --source=. --remote=origin
git push -u origin mainAdd Spatie Guidelines
bash
composer require spatie/boost-spatie-guidelines --devLaravel AI SDK
bash
composer require laravel/aiLink Storage
bash
php artisan storage:linkInstall the Boost Guidelines
Rerun Boost to pick up the Spatie guidelines and drop the agents the installer auto-detected. At the agents prompt keep Claude Code and Codex and deselect Pi and Zed: Pi already reads Codex's AGENTS.md and .agents/skills, so its own .pi/skills copy collides. Select the Spatie package at the third-party prompt. There is no flag for choosing agents; later boost:update runs reuse this selection from boost.json.
bash
php artisan boost:install
rm -rf .pi .zedConfigure Composer
Require PHP 8.5
Use PHP 8.5 for both the CLI and Herd site, then update composer.json and the lockfile:
bash
composer require "php:^8.5"Skip Frontend Formatting in CI
In composer.json, update scripts.ci:check to pass --no-fmt. Keep lint, type checks, and tests enabled:
json
"ci:check": [
"Composer\\Config::disableProcessTimeout",
"npm run check -- --no-fmt",
"npm run types:check",
"@test"
],Configure Vite Formatting
File: vite.config.ts
Merge fmt.ignorePatterns for local formatting; CI skips formatting through --no-fmt. Keep the existing plugins and the svelte-check environment guard. server.watch.ignored affects watching only.
ts
import inertia from '@inertiajs/vite';
import { wayfinder } from '@laravel/vite-plugin-wayfinder';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import tailwindcss from '@tailwindcss/vite';
import laravel from 'laravel-vite-plugin';
import { bunny } from 'laravel-vite-plugin/fonts';
import { defineConfig, lazyPlugins } from 'vite-plus';
const isSvelteCheck = process.argv.some((argument) =>
argument.includes('svelte-check'),
);
if (isSvelteCheck) {
process.env.LARAVEL_BYPASS_ENV_CHECK ??= '1';
}
export default defineConfig({
plugins: lazyPlugins(() => [
laravel({
input: ['resources/css/app.css', 'resources/js/app.ts'],
refresh: true,
fonts: [
bunny('Instrument Sans', {
weights: [400, 500, 600],
}),
],
}),
inertia(),
tailwindcss(),
svelte(),
wayfinder({
formVariants: true,
}),
]),
server: {
watch: {
ignored: [
'**/.agents/**',
'**/.claude/**',
'**/.cursor/**',
'**/.junie/**',
'**/vendor/**',
],
},
},
lint: {
ignorePatterns: [
'vendor/**',
'node_modules/**',
'public/**',
'bootstrap/ssr/**',
'tailwind.config.js',
'resources/js/actions/**',
'resources/js/components/ui/*',
'resources/js/routes/**',
'resources/js/wayfinder/**',
],
options: {
denyWarnings: true,
typeAware: true,
},
},
fmt: {
printWidth: 80,
tabWidth: 4,
singleQuote: true,
semi: true,
singleAttributePerLine: false,
htmlWhitespaceSensitivity: 'css',
ignorePatterns: [
'.agents/skills/**',
'.claude/skills/**',
'.github/**',
'.mcp.json',
'.pi/skills/**',
'AGENTS.md',
'CLAUDE.md',
'boost.json',
'composer.json',
'resources/js/components/ui/*',
'resources/views/mail/*',
],
sortTailwindcss: {
functions: ['clsx', 'cn', 'cva'],
entryPoint: 'resources/css/app.css',
},
},
});Configure the GitHub Test Workflow
File: .github/workflows/tests.yml
Add job-level env so composer setup can migrate without a MySQL service:
yaml
jobs:
ci:
runs-on: ubuntu-latest
env:
DB_CONNECTION: sqlite
DB_DATABASE: ':memory:'
# Existing steps follow here.Set Setup PHP to php-version: '8.5' and Setup Node to node-version: '24' to match local tools.
Configure the Environment
Merge the snapshot into .env.example, then apply the local values to .env. Editing .env.example alone does not configure the application. Preserve the generated APP_KEY; keep real credentials only in .env.
Match APP_URL to the Herd site, including HTTPS if secured. Use local database credentials and keep MAIL_MAILER=log until mail setup.
File: .env.example
dotenv
APP_NAME="Vehub"
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=https://vehub-app.test
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
# PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=vehub_app
DB_USERNAME=root
DB_PASSWORD=
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=database
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"Initialize the Database
Create the database named by DB_DATABASE (vehub_app) in the local MySQL server if the installer has not already created it.
bash
php artisan config:clear
php artisan migrateVerify
bash
composer lint
composer ci:check
npm run buildStart npm run dev and open the Herd URL. Check the login page; wait until after the name split to create users.
Commit
bash
git add -A
git commit -m '01 - Create Project'