Thank you for considering contributing to Laravel Starter! This document provides guidelines for contributing to the project.
- Code of Conduct
- How Can I Contribute?
- Development Setup
- Coding Standards
- Testing Guidelines
- Pull Request Process
- Commit Message Guidelines
We pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to a positive environment:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior:
- The use of sexualized language or imagery
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct which could reasonably be considered inappropriate
Before creating bug reports, please check existing issues to avoid duplicates.
When submitting a bug report, include:
- Clear title and description
- Steps to reproduce the issue
- Expected vs actual behavior
- Environment details:
- Laravel Starter version
- Laravel version
- PHP version
- Operating system
- Database (MySQL, PostgreSQL, SQLite)
- Screenshots (if applicable)
- Error messages or logs
Example:
## Bug: User profile update fails
**Environment:**
- Laravel Starter: 12.20.0
- Laravel: 12.0
- PHP: 8.3.4
- OS: Windows 11
- DB: MySQL 8.0
**Steps to reproduce:**
1. Go to profile page
2. Update email field
3. Click save
4. Observe error
**Expected:** Profile updates successfully
**Actual:** Error 500, see logs below
**Logs:**[error] ...
We welcome feature suggestions! Use GitHub Discussions for ideas and feature requests.
Include:
- Clear description of the feature
- Use cases - why it's needed
- Examples from other projects (if applicable)
- Implementation ideas (optional)
Documentation improvements are always welcome:
- Fix typos or unclear explanations
- Add missing documentation
- Translate documentation
- Add code examples
- Update outdated information
See Pull Request Process below.
- PHP 8.3 or higher
- Composer 2.0+
- Node.js 18+ and NPM 9+
- Database (MySQL 8.0+, PostgreSQL 13+, or SQLite)
- Git
-
Fork the repository
# Fork on GitHub, then clone your fork git clone https://github.com/YOUR_USERNAME/laravel-starter.git cd laravel-starter
-
Install dependencies
# Install PHP dependencies composer install # Install Node.js dependencies npm install
-
Environment configuration
# Copy environment file cp .env.example .env # Generate application key php artisan key:generate # Configure database in .env # For quick start, use SQLite: touch database/database.sqlite # Set DB_CONNECTION=sqlite in .env
-
Database setup
# Run migrations php artisan migrate # Seed database with sample data php artisan db:seed
-
Build frontend assets
npm run dev
-
Start development server
php artisan serve
-
Visit application
- Open http://localhost:8000
- Login: admin@admin.com / secret
If you need to work on both laravel-starter and module-manager:
# Clone module-manager in parent directory
cd ..
git clone https://github.com/nasirkhan/module-manager.git
# Link local package
cd laravel-starter
composer config repositories.module-manager path "../module-manager"
composer require nasirkhan/module-manager:@devWe follow PSR-12 coding standards enforced by Laravel Pint.
Run Pint before committing:
# Fix all files
composer pint
# Or use artisan
php artisan pint
# Check specific file
./vendor/bin/pint app/Models/User.php-
Follow Laravel conventions
- Use Eloquent over raw queries
- Use relationships over manual joins
- Use Form Requests for validation
- Use resource controllers
- Use route model binding
-
Use type hints
// ✓ Good public function store(StorePostRequest $request): RedirectResponse { $post = Post::create($request->validated()); return redirect()->route('posts.show', $post); } // ✗ Bad public function store($request) { $post = Post::create($request->all()); return redirect('/posts/' . $post->id); }
-
Add PHPDoc blocks
/** * Store a newly created post. * * @param \App\Http\Requests\StorePostRequest $request * @return \Illuminate\Http\RedirectResponse */ public function store(StorePostRequest $request): RedirectResponse { // ... }
-
Use resource classes for API responses
-
Avoid N+1 queries - use eager loading
// ✓ Good $posts = Post::with('user', 'category')->get(); // ✗ Bad $posts = Post::all(); // N+1 when accessing $post->user
When creating/updating Livewire components:
use Livewire\Component;
use Livewire\Attributes\{Layout, Title, Validate, Locked};
#[Layout('components.layouts.app')]
#[Title('Posts')]
class PostsIndex extends Component
{
#[Validate('required|min:3')]
public string $search = '';
#[Locked]
public int $userId;
public function mount(int $userId): void
{
$this->userId = $userId;
}
public function render()
{
$posts = Post::query()
->when($this->search, fn($q) => $q->where('title', 'like', "%{$this->search}%"))
->latest()
->paginate(15);
return view('livewire.posts-index', compact('posts'));
}
}Rules:
- Always add
#[Layout]attribute - Always add
#[Title]attribute - Use
#[Validate]for validation - Use
#[Locked]for read-only properties - Add type hints to all properties
- Use
mount()for initialization - Avoid
compact()inrender()- pass data directly
- Follow standard JavaScript conventions
- Use ES6+ features
- Add comments for complex logic
- Format with Prettier (if configured)
- Use Blade components over includes
- Follow consistent indentation
- Use slots for flexible components
- Add component documentation
# Run all tests
php artisan test
# Run specific test file
php artisan test tests/Feature/PostTest.php
# Run specific test method
php artisan test --filter test_user_can_create_post
# Run with coverage (requires Xdebug)
php artisan test --coverageFeature tests for user-facing functionality:
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
class PostTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_create_post(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/posts', [
'title' => 'Test Post',
'content' => 'Test content',
]);
$response->assertRedirect();
$this->assertDatabaseHas('posts', [
'title' => 'Test Post',
'user_id' => $user->id,
]);
}
}Unit tests for isolated logic:
namespace Tests\Unit;
use Tests\TestCase;
use App\Services\PostService;
class PostServiceTest extends TestCase
{
public function test_slug_is_generated_from_title(): void
{
$service = new PostService();
$slug = $service->generateSlug('Hello World Test');
$this->assertEquals('hello-world-test', $slug);
}
}Livewire tests:
use Livewire\Livewire;
use App\Livewire\PostsIndex;
public function test_search_filters_posts(): void
{
Post::factory()->create(['title' => 'Laravel Tutorial']);
Post::factory()->create(['title' => 'Vue Guide']);
Livewire::test(PostsIndex::class)
->set('search', 'Laravel')
->assertSee('Laravel Tutorial')
->assertDontSee('Vue Guide');
}- Aim for 70%+ code coverage
- All new features must include tests
- Bug fixes should include regression tests
-
Create a feature branch
git checkout -b feature/add-post-scheduling
-
Make your changes
- Follow coding standards
- Add tests
- Update documentation
-
Run quality checks
# Format code composer pint # Run tests php artisan test # Check for errors php artisan clear-all
-
Commit your changes
git add . git commit -m "feat: add post scheduling feature"
-
Push to your fork
git push origin feature/add-post-scheduling
-
Create PR on GitHub
- Provide clear title and description
- Reference related issues
- Add screenshots for UI changes
-
PR Template:
## Description Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Checklist - [ ] Code follows project style - [ ] Tests added/updated - [ ] Documentation updated - [ ] No breaking changes (or documented) - [ ] Pint passed - [ ] Tests pass ## Related Issues Closes #123 ## Screenshots (if applicable)
-
Respond to feedback
- Address review comments
- Make requested changes
- Re-request review
- Maintainers will review your PR
- May request changes or clarifications
- Once approved, will be merged
- Your contribution will be in the next release!
We follow Conventional Commits specification.
<type>(<scope>): <subject>
<body>
<footer>
- feat: New feature
- fix: Bug fix
- docs: Documentation changes
- style: Code style changes (formatting, no logic change)
- refactor: Code refactoring (no feature/bug change)
- perf: Performance improvements
- test: Adding or updating tests
- chore: Build process or auxiliary tool changes
# Feature
git commit -m "feat(posts): add scheduled publishing"
# Bug fix
git commit -m "fix(auth): resolve login redirect issue"
# Documentation
git commit -m "docs(readme): update installation instructions"
# Breaking change
git commit -m "feat(api)!: change response format
BREAKING CHANGE: API responses now wrapped in data key"php artisan module:build MyModuleFollow the generated structure and examples from existing modules.
Modules/MyModule/
├── Config/
├── Database/
│ ├── Migrations/
│ ├── Seeders/
│ └── Factories/
├── Http/
│ ├── Controllers/
│ ├── Middleware/
│ └── Requests/
├── Models/
├── Resources/
│ └── views/
├── Routes/
│ └── web.php
└── Tests/
- General questions: Use GitHub Discussions
- Bug reports: Use GitHub Issues
- Security issues: Email nasir8891@gmail.com
Contributors will be recognized in:
- README.md contributors section
- Release notes
- GitHub contributors graph
Thank you for making Laravel Starter better! 🙏