Rather than having a template repository for new Laravel Projects, I'm going after a step-by-step script that outlines the changes that I typically make and why. I feel this approach will be easier to maintain and will provide more value to guests.
And let's be honest... we're replacing this repo with AI instructions before much longer, right?
This repository customizes a new Laravel 12 application. Instructions are accurate as of October 2025.
- Essentials — Essentials is a package created by Nuno Maduro that provides better defaults for your Laravel applications.
In 2024, the Laravel Team launched starter kits that enable you to get a new Laravel application up and running quickly with the stack of your choice. I prefer the Inertia.js + React + Pest stack.
laravel new --react --pest <name>This starter repo is specific to that stack.
I try really hard to embrace the framework defaults. However, I do make a few modifications that include:
APP_NAME— Apply a custom valueAPP_URL— Apply a custom valueCACHE_STORE— Set toredis. I use this locally and in production.DB_CONNECTION— Set tomysqlDB_NAME— Apply a custom valueQUEUE_CONNECTION— Set tosync. In production, I useredisand Laravel Horizon.SESSION_DRIVER— Set toredis
Execute the following command to download the custom .env.example:
curl -o .env.example https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.env.exampleThe Laravel Installer generates an APP_KEY value for you automatically. You can run the following from the root of the repo to refresh your .env and create a new APP_KEY before applying your custom values.
cp .env.example .env && php artisan key:generateI currently use Cursor as my IDE. This repository contains a .vscode folder that contains my preferred settings and extensions.
To replicate this setup within your project:
mkdir -p .vscode && \
curl -o .vscode/extensions.json https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.vscode/extensions.json && \
curl -o .vscode/settings.json https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.vscode/settings.jsonA new Laravel application comes with Prettier, ESLint, and Laravel Pint to maximize code quality by analyzing your code to detect issues. It also contains a set of settings for EditorConfig.
This repository contains my preferred configuration files for each tool. You can download these files into your repository via the following commands:
curl -o .editorconfig https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.editorconfig && \
curl -o .prettierrc https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.prettierrc && \
curl -o eslint.config.js https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/eslint.config.js && \
curl -o pint.json https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/pint.jsonLarastan is a PHPStan extension and code analysis tool for Laravel. It focuses on finding errors in your code before you even write any tests.
composer require --dev "larastan/larastan:^3.0"Larastan requires a phpstan.neon configuration file. You can review the PHPStan documenation to create a custom config, or you can download my default.
curl -o phpstan.neon https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/phpstan.neonThe Laravel starter kits use GitHub Actions to lint and test the code. While I still run tests in the CI/CD space, I prefer to use Husky to run ESlint, Prettier, Laravel Pint, and Larastan.
I use pre-commit to run ESLint and Prettier and pre-push for Laravel Pint and Larastan.
First, install Husky and lint-staged. Then, issue the following commands from the root of the repo:
npm install --save-dev husky lint-staged && \
npx husky initYou can download the relevant files into your repository via the following commands:
curl -o .lintstagedrc.js https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.lintstagedrc.js && \
curl -o .husky/pre-commit https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.husky/pre-commit && \
curl -o .husky/pre-push https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/.husky/pre-pushAfter setting up Husky, you no longer need the lint workflow.
rm .github/workflows/lint.ymlI always install the following first-party packages:
# Laravel Boost
composer require laravel/boost --dev
php artisan boost:install
# Laravel Horizon
composer require laravel/horizon
php artisan horizon:install
# Laravel Pulse
composer require laravel/pulse
php artisan vendor:publish --provider="Laravel\Pulse\PulseServiceProvider"
php artisan migrate
# Laravel Telescope
composer require laravel/telescope
php artisan telescope:install
php artisan migrateI always install the following third-party packages:
- spatie/laravel-backup
- spatie/laravel-data
- spatie/laravel-ray
- spatie/laravel-view-models
- predis/predis
- pestphp/pest-plugin-faker
composer require spatie/laravel-backup spatie/laravel-data spatie/laravel-ray spatie/laravel-view-models predis/predis
composer require --dev pestphp/pest-plugin-fakerLaravel Nova is the simplest and fastest way to build production-ready administration panels using Laravel.
Since Nova is a paid package, installation is a little more in-depth than a simple composer require command. First, add the repository to your composer.json:
composer config repositories.nova '{"type": "composer", "url": "https://nova.laravel.com"}' --file composer.jsonEnsure you have a valid auth.json configured for installation, and then add laravel/nova to your list of required packages in your composer.json file:
composer require laravel/novaI have a few preferences that require modifications to the User model that comes out-of-the-box with a new Laravel application.
The default User model in Laravel comes with a single name field. I prefer to split that into first and last fields. This is a non-trivial change that results in updates to several files:
database/migrations/0001_01_01_000000_create_users_table.phpapp/Models/User.phpdatabase/factories/UserFactory.phpdatabase/seeders/DatabaseSeeder.phpresources/js/types/index.d.tsapp/Http/Controllers/RegisteredUserController.phpapp/Http/Requests/Settings/ProfileUpdateRequest.phptests/Feature/Auth/RegistrationTest.phptests/Feature/Settings/ProfileUpdateTest.phpresources/js/pages/auth/register.tsxresources/js/components/user-info.tsxresources/js/pages/settings/profile.tsx
By default, Laravel expects created_at and updated_at columns to exist on a model's corresponding database table. I prefer to use last_updated and date_created field names for a model's timestamps.
I have updated the users table and User model accordingly.
I prefer to use the $guarded model attribute as opposed to $fillable to manage mass assignment protection. As a result, I have updated the User model accordingly.
protected $guarded = [
'id',
'date_created',
'last_updated',
];Execute the following ridiculous series of commands to download these customizations into your project.
curl -o app/Models/User.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/app/Models/User.php && \
curl -o database/factories/UserFactory.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/database/factories/UserFactory.php && \
curl -o database/migrations/0001_01_01_000000_create_users_table.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/database/migrations/0001_01_01_000000_create_users_table.php && \
curl -o database/seeders/DatabaseSeeder.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/database/seeders/DatabaseSeeder.php && \
curl -o resources/js/types/index.d.ts https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/resources/js/types/index.d.ts && \
curl -o app/Http/Controllers/Auth/RegisteredUserController.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/app/Http/Controllers/Auth/RegisteredUserController.php && \
curl -o app/Http/Requests/Settings/ProfileUpdateRequest.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/app/Http/Requests/Settings/ProfileUpdateRequest.php && \
curl -o tests/Feature/Auth/RegistrationTest.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/tests/Feature/Auth/RegistrationTest.php && \
curl -o tests/Feature/Settings/ProfileUpdateTest.php https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/tests/Feature/Settings/ProfileUpdateTest.php && \
curl -o resources/js/pages/auth/register.tsx https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/resources/js/pages/auth/register.tsx && \
curl -o resources/js/components/user-info.tsx https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/resources/js/components/user-info.tsx && \
curl -o resources/js/pages/settings/profile.tsx https://raw.githubusercontent.com/dascentral/laravel-starter/refs/heads/main/resources/js/pages/settings/profile.tsxI will manually add the following scripts to the composer.json:
"analyze": [
"./vendor/bin/phpstan analyse --ansi --memory-limit 512M"
],
"analyze:baseline": [
"./vendor/bin/phpstan analyse --generate-baseline"
],
"format": [
"./vendor/bin/pint"
],