Work in progress!
- Use the latest version of the Laravel Framework and additional packages.
- Use the least amount of additional packages, and avoid solutions that require the installation of additional tools on the server.
- Stay close to first-party Laravel-style conventions and guidelines. Carefully read the framework documentation and navigate its source code and first-party packages for inspiration.
- Everything should work with Inertia SSR and Laravel Octane.
- Write tests for everything. Also, every endpoint should have a Laravel Dusk E2E test, and every feature should have its own test.
- Keep controllers minimalistic and use actions similar to Laravel Fortify. For example, an interface would be named
UpdatesUserProfileInformation
, and its implementationUpdateUserProfileInformation
. - Keep an activity log of all non-GET requests.
- Implement CSP and other security-related headers from the start. Don't think of it as an after sight.
- Use translation strings, don't hard-code strings. This also applies to data like the app name, company name, company address, etc. Things may change over time.
- When querying the database, always use pagination.
- Never leak Eloquent Models into the front-end. Always use API Resources and don't use
toArray()
on a Model. Also, never directly use a request to save a model (e.g.Model::create($request->all())
). Always validate and manually specify all fields (e.g.Model::create($request->validated())
). This way, we can unguard the models. - Use the static
query()
method to begin querying an Eloquent Model. - For all data, write a mechanism to delete it as well. Make sure files and database records are deletable without breaking the application.
- Create sensible Model Factories and Seeders. After cloning this repo, there should be a single seeder that you can run to interact with all parts of the app.
- Prefer storing settings in the database rather than configuration files.
- Avoid events/listeners. As always, it depends on the situation. If we're talking about 5+ actions, this might become cumbersome, and you want to use listeners. But my starting point is to keep it simple within the controller and refactor when it becomes more complex.
- Use Incrementing IDs as the internal primary key. Use UUIDs for consumer-facing endpoints.
- Use atomic locks for actions like account creation, order confirmation, etc.
- Prefer attaching a PDF to a Mailable rather than using more text or data in the mail contents.
- There must be a way for users to resend a Mailable, for example, an order confirmation.
npm install eslint eslint-plugin-vue --dev
NPM script:
"scripts": {
"eslint": "./node_modules/.bin/eslint resources/js/ --ext .js,.vue --fix"
}
composer require friendsofphp/php-cs-fixer --dev
Composer script:
"scripts": {
"php-cs-fixer": [
"vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --verbose"
],
}
npm install @babel/plugin-syntax-dynamic-import --dev
npm install laravel-mix-polyfill --dev
webpack.mix.js
const mix = require("laravel-mix");
require("laravel-mix-polyfill");
mix.js("resources/js/app.js", "public/js").vue()
.postCss("resources/css/app.css", "public/css", [
require("tailwindcss"),
])
.alias({
"@": "resources/js",
})
.polyfill({
enabled: true,
useBuiltIns: "usage",
targets: { "ie": 11 }
});
mix.options({
terser: {
terserOptions: { safari10: true }
}
});
if (mix.inProduction()) {
mix.version();
}