styleguide

Laravel (Inertia, React, TypeScript) Coding Style Guide

Table of Contents

  1. General Principles
  2. Folder and File Structure
  3. Naming Conventions
  4. Code Formatting
  5. Blade Templates
  6. Eloquent Models
  7. Controllers
  8. Routes
  9. React and TypeScript
  10. Testing
  11. Best Practices
  12. Recommend Tools & Configuration

General Principles


Folder and File Structure

Example Structure

app/
  Models/
  Http/
    Controllers/
  Services/
resources/
  js/
    components/
      ui/
    layouts/
    pages/
    utils/
  views/
routes/
  web.php
  api.php
  auth.php

Naming Conventions

Backend

Frontend

Examples

// Good (React)
interface LoginProps {
status?: string;
canResetPassword: boolean;
  
}

export default fanction LoginForm({status, canResetPassword}: LoginProps){

return (
  <div>LoginForm</div>

 )
}

// Bad
const user_card = (props) => {
  return <div>{props.username}</div>;
};

Code Formatting

Backend

Frontend

Auto format using Laravel Pint learn more

./vendor/bin/pint --repair

Blade Templates

Example

resources/views/app.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    @viteReactRefresh
    @vite(['resources/js/app.tsx'])
</head>
<body>
    @inertia
</body>
</html>

Eloquent Models

Example

class User extends Model {
    protected $fillable = ['name', 'email'];

    public function posts() {
        return $this->hasMany(Post::class);
    }
}

Controllers

Example

    /**
     * Display the user's Account form.
     */
    public function edit(Request $request): Response
    {
        return Inertia::render('account/edit', [
            'mustVerifyEmail' => $request->user() instanceof MustVerifyEmail,
            'status' => session('status'),
        ]);
    }

Routes

Example

// Account
Route::middleware('auth')->group(function () {
    Route::get('/account', [AccountController::class, 'edit'])->name('account.edit');
    Route::patch('/account', [AccountController::class, 'update'])->name('account.update');
    Route::delete('/account', [AccountController::class, 'destroy'])->name('account.destroy');
});

React and TypeScript

Folder Structure

Component Structure

State Management

Examples

// Custom Hook
import { useState } from 'react';

function useCounter(initialValue: number) {
  const [count, setCount] = useState(initialValue);
  const increment = () => setCount(count + 1);
  return { count, increment };
}

// Component
export default function Counter(){
  const { count, increment } = useCounter(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

Testing

Example

for Backend learn more

php artisan make:test AccountTest
// PHPUnit Test
    public function test_account_page_is_displayed(): void
    {
        $user = User::factory()->create();

        $response = $this
            ->actingAs($user)
            ->get('/account');

        $response->assertOk();
    }
php artisan test

for Frontend

// Jest Test
import { render, screen } from '@testing-library/react';
import Counter from './Counter';

test('renders counter', () => {
  render(<Counter />);
  const buttonElement = screen.getByText(/increment/i);
  expect(buttonElement).toBeInTheDocument();
});

Best Practices


Recommend Tools & Configuration