Aiku ERP Development Guidelines
Expert guidelines for developing the Aiku white-label ERP application built with Laravel 12, Inertia v2, Vue 3, and the full Laravel ecosystem.
Core Technology Stack
**Backend**: Laravel 12, PHP 8.4, Horizon, Octane, Sanctum, Scout, Telescope**Frontend**: Inertia v2, Vue 3, Tailwind CSS 3, Ziggy v2**Testing**: Pest v4, PHPUnit v12**Tooling**: Laravel Pint v1, Prettier v3, Sail v1Fundamental Rules
Code Quality
Write clear, self-explanatory code WITHOUT commentsUse descriptive names: `isRegisteredForDiscounts()` not `discount()`Follow existing code conventions in sibling files for structure, approach, and namingCheck for existing components before creating new onesRun `vendor/bin/pint --dirty` before finalizing changes (DO NOT run with `--test` flag)Architecture Principles
Stick to existing directory structure - don't create new base folders without approvalDo not change dependencies without approvalPrefer PHPDoc blocks over inline commentsUse PHP 8 constructor property promotionAlways use explicit return type declarationsAlways use curly braces for control structures, even single-lineLaravel Best Practices
File Creation
Use `php artisan make:` commands for all new files (migrations, controllers, models, etc.)Pass `--no-interaction` to all Artisan commandsFor generic PHP classes: `php artisan make:class`When creating models, also create factories and seedersDatabase & Eloquent
Always use Eloquent relationship methods with return type hintsAvoid `DB::`; prefer `Model::query()`Use eager loading to prevent N+1 query problemsWhen modifying columns in migrations, include ALL previous attributes to prevent data lossUse `$query->latest()->limit(10)` for limiting eagerly loaded records (Laravel 12 native)Validation & Form Requests
Always create Form Request classes for validation (never inline validation in controllers)Include both validation rules and custom error messagesCheck sibling Form Requests for array vs string validation rule conventionsConfiguration & Environment
NEVER use `env()` outside config filesAlways use `config('app.name')`, not `env('APP_NAME')`URLs & Routing
Generate links using named routes: `route('users.index')`Use `Inertia::render()` for server-side routing instead of Blade viewsAuthentication & Authorization
Use Laravel's built-in features: gates, policies, SanctumBackground Jobs
Use queued jobs with `ShouldQueue` interface for time-consuming operationsAPIs
Default to Eloquent API Resources with versioning (unless existing routes don't, then follow convention)Laravel 10 Structure (Important!)
This project uses the **Laravel 10 structure** (not the new Laravel 12 streamlined structure):
Middleware: `app/Http/Middleware/`Service providers: `app/Providers/`Middleware registration: `app/Http/Kernel.php` (no `bootstrap/app.php`)Exception handling: `app/Exceptions/Handler.php`Console commands: `app/Console/Kernel.php`Rate limits: `RouteServiceProvider` or `app/Http/Kernel.php`Do NOT migrate to new Laravel 12 structure unless explicitly requested.
Inertia v2
Core Concepts
Components live in `resources/js/Pages/` (unless changed in `vite.config.js`)Use all Inertia v2 features: polling, prefetching, deferred props, infinite scrolling, lazy loadingForms
Recommended: Use `<Form>` componentAlternative: `useForm` helper for programmatic controlAvailable props: `resetOnError`, `resetOnSuccess`, `setDefaultsOnSuccess`Search docs with query `form component` for guidanceDeferred Props
Add nice empty states with pulsing/animated skeletons when using deferred propsFrontend Build Issues
If changes don't reflect: user needs `npm run build`, `npm run dev`, or `composer run dev`Vite manifest error: run `npm run build` or ask user to run `npm run dev`Testing with Pest
Test Requirements
**Every change must be programmatically tested**Write new tests or update existing tests, then run them to verifyAll tests MUST use Pest: `php artisan make:test --pest {name}`Never remove tests without approvalTest Structure
```php
it('is true', function () {
expect(true)->toBeTrue();
});
```
Test Coverage
Test happy paths, failure paths, and edge casesFeature tests: `tests/Feature/`Unit tests: `tests/Unit/` (use `--unit` flag)Most tests should be feature testsRunning Tests
All tests: `php artisan test`Specific file: `php artisan test tests/Feature/ExampleTest.php`Filter by name: `php artisan test --filter=testName`Run minimal tests after changes, then ask user if they want full suiteAssertions
Use specific methods: `assertForbidden()`, `assertNotFound()`, `assertSuccessful()`NOT: `assertStatus(403)`Test Data
Use model factories (check for custom states before manual setup)Faker: `$this->faker->word()` or `fake()->randomDigit()` (follow existing convention)Mocking
Import: `use function Pest\Laravel\mock;`Use: `mock(Service::class)` or `$this->mock(Service::class)`PHP Code Standards
Type Declarations
```php
protected function isAccessible(User $user, ?string $path = null): bool
{
// Implementation
}
```
Constructors
```php
public function __construct(public GitHub $github) { }
```
Never allow empty `__construct()` with zero parametersPHPDoc
Add useful array shape type definitions when appropriatePrefer PHPDoc blocks over inline commentsEnums
Keys should be TitleCase: `FavoritePerson`, `BestLake`, `Monthly`Models
Use `casts()` method instead of `$casts` property (follow existing conventions)Feature Flags
This application uses Laravel Pennant for feature flag managementControls feature availability across organizations and user typesSearch docs for Pennant guidance when neededCommunication Style
Be concise - focus on what's important, not obvious detailsOnly create documentation files if explicitly requestedDon't create verification scripts when tests cover functionalityTools & Commands
Laravel Boost MCP Tools
`list-artisan-commands` - Check available Artisan parameters`get-absolute-url` - Get correct scheme/domain/port for project URLs`tinker` - Execute PHP for debugging or querying Eloquent models`database-query` - Read from database directly`browser-logs` - Read recent browser logs, errors, exceptions`search-docs` - Search version-specific Laravel ecosystem documentationDocumentation Search
Use `search-docs` BEFORE other approachesReturns version-specific docs for installed packagesPass array of packages to filter if knownWorks for: Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, etc.**Search Syntax:**
Simple words: `authentication` (auto-stems to 'auth', 'authenticate')Multiple words (AND): `rate limit` (both required)Exact phrases: `"infinite scroll"` (adjacent, ordered)Mixed: `middleware "rate limit"`Multiple queries: `["authentication", "middleware"]` (ANY match)Use broad, simple, topic-based queries. DON'T include package names in queries (already filtered by version).
Workflow
1. Search documentation using `search-docs` before making changes
2. Check sibling files for conventions
3. Use `php artisan make:` commands for file creation
4. Write or update tests for every change
5. Run tests with appropriate filter
6. Run `vendor/bin/pint --dirty` to format code
7. Ask user if they want full test suite
Critical Reminders
NO inline code comments - write self-explanatory codeNEVER remove tests without approvalALWAYS test your changesALWAYS format with Pint before finalizingFollow Laravel 10 structure (not Laravel 12 streamlined structure)Use `search-docs` for accurate, version-specific guidance