vaibhavpandeyvpz/starter-laravel
vaibhavpandeyvpz/starter-laravel is a ready-to-use Laravel starter kit with sensible defaults and common scaffolding, helping you skip repetitive setup and start building features faster. Ideal for new Laravel projects that need a clean, practical foundation.
This is a starter kit, not a Composer package — you don't composer require it, you clone or git clone --depth=1 the repo, strip the .git directory, and treat it as the seed of a new Laravel project. Expect to run git init fresh.
Minimal bootstrap:
git clone https://github.com/vaibhavpandeyvpz/starter-laravel my-app
cd my-app && rm -rf .git && git init
cp .env.example .env
docker compose up -d # dev stack per docker-compose.yml
docker compose exec app composer install
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate --seed
docker compose exec app npm install && npm run dev
Where to look first, in this order:
docker-compose.yml and any Dockerfile/docker/ directory — this defines PHP version, extensions, DB, and how assets are compiled. Understanding this avoids an hour of "why is Vite not hot-reloading."routes/web.php — the RBAC middleware aliases and Livewire route bindings live here.app/Livewire/ (or wherever components are placed) — the CRUD scaffold pattern you'll be copying.resources/views/auth/ — the Bootstrap-flavored login/register/reset views you'd otherwise replace.First use case is almost certainly: log in as the seeded admin, open the users list, and confirm the role-assignment UI works. Then scaffold your first domain resource by copying the users Livewire component pair (list + form) and wiring it into the same pattern. If you can get one CRUD screen live end-to-end (route → Livewire list → modal form → RBAC gate), you've validated the whole stack.
Livewire CRUD as a copy-paste unit. The kit's value is that each resource is a self-contained pair: a list component (search, paginate, inline delete, dispatch to open a form) and a form component (validation, save, reset). The day-to-day workflow is to cp these files, rename the model, and prune fields. Don't try to abstract this into a generic resource class early — you'll spend more time fighting Livewire's public-property model than you save.
RBAC is permission-first, role-second. Typical wiring here is middleware on routes (role:admin, permission:users.edit), Gate checks inside Livewire save()/delete() methods, and a UI for assigning roles to users. Follow the same granularity the seeders already use so newly added resources inherit consistent naming (posts.view, posts.create, etc.) — permission names leaking into Blade and route files are the most common source of drift.
Select2 for all belongsTo/hasMany field inputs. The pattern is a <select wire:model="post.user_id" class="select2"> with a wire:ignore wrapper so Livewire's morphing doesn't clobber Select2's DOM. Initialize via @push('scripts') with a Livewire hook (Livewire.hook('morph.updated', ...)) to re-bind after re-renders. Use it when the related table exceeds ~50 rows; below that a plain select is friendlier.
Flatpickr for date/time. Same wire:ignore treatment, plus dateFormat: 'Y-m-d' to match the DB column and defaultDate bound from the Livewire payload. Let Flatpickr own the display string and let Livewire own the ISO value — don't try to sync on every keystroke.
Docker parity for dev and prod. The intended workflow is: dev container has hot reload, bind-mounted code, and Xdebug-ready PHP; the production Dockerfile is multi-stage (composer install --no-dev, npm run build, then a runtime image with opcache preloaded and Nginx + php-fpm). Treat the production Dockerfile as the source of truth for PHP extensions — anything you add for a library must be added there too.
Auth views as Bootstrap surfaces. Since the views are already Bootstrap 5, customizing them means working in that class system, not adding Tailwind. If you intend to migrate to Tailwind later, do it before building UI — mixing the two is a slow bleed.
Integration tip: For any external service (mail, storage, SSO), keep config/*.php files and .env.example in sync the moment you wire it. Starters drift because someone hardcodes a driver in a provider.
git pull from origin will conflict with your changes forever. If you need upstream fixes, track them manually.wire:ignore is mandatory for Select2 and Flatpickr. Omit it and your widget silently resets — or worse, submits the previous value on wire:model — after every Livewire re-render. This is the single most common bug in this stack.morph.updated doesn't exist in v2 (which uses message.processed). Check the composer constraint before copy-pasting hooks from other tutorials.php artisan permission:cache-reset (or cache:clear) after seeding or editing roles in the DB, or you'll spend an hour debugging 403s that "shouldn't happen."firstOrCreate — if they aren't, db:seed twice silently duplicates. Prefer firstOrCreate/updateOrCreate when you extend them.storage/ and bootstrap/cache/ often become root-owned after in-container artisan commands. Fix with a usermod/chown step in your entrypoint or run the container as your UID (see user: in compose).artisan migrate, double-check it does not also run in prod — migrate on deploy, not on boot. Add a HEALTHCHECK and separate the entrypoint scripts.wireui, Flux, Filament), and scaffolds assume Tailwind. Anything Tailwind-flavored will need porting. Stick with plain Bootstrap components or pick Bootstrap-native extras like livewire-bootstrap-style helpers.save()/delete(). Route middleware won't catch a crafted Livewire call to a method you forgot to guard. Put $this->authorize(...) inside the action, not just in mount().RefreshDatabase and call your role/permission seeder in setUp(). Use Livewire::test(Component::class) with ->actingAs($user->assignRole('admin')). Assert authorization and validation separately — Livewire's assertHasErrors won't catch a missing $this->authorize.npm run build runs in the image, the Vite manifest exists at public/build/manifest.json inside the container — ensure your Nginx layer serves public/ and not resources/. Many "blank white page" reports trace back to this.Concerns/HasRoles trait, a Policies/ directory (even empty), a dedicated config/rbac.php, and a permissions.php catalogue file so you're not editing seeders every time you add a module. Do this on day one — retrofitting RBAC granularity into 20 controllers is painful.v0.1-scaffold) so you can diff later and know exactly which starter version you diverged from.How can I help you explore Laravel packages today?