rifatxtra / laravel-featurekit
Laravel starter template with feature-based architecture, Inertia.js, and React.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:project
pkg:composer/rifatxtra/laravel-featurekit
Requires
- php: ^8.2
- inertiajs/inertia-laravel: ^2.0
- laravel/framework: ^12.0
- laravel/tinker: ^2.10.1
Requires (Dev)
- fakerphp/faker: ^1.23
- laravel/pail: ^1.2.2
- laravel/pint: ^1.13
- laravel/sail: ^1.41
- mockery/mockery: ^1.6
- nunomaduro/collision: ^8.6
- phpunit/phpunit: ^11.5.3
README
A modern Laravel starter template built with feature-based architecture, Inertia.js, and React. Perfect for developers who want to organize their application by features, not layers.
π Table of Contents
- What's Included
- Feature-Based Architecture
- Installation
- Quick Start
- Artisan Commands
- React Hooks
- API Support
- Tailwind CSS Customization
- SEO Configuration
- Database Migrations
- Authentication
- Directory Structure
- Examples
- Contributing
- License
β¨ What's Included
- β‘ Laravel 12 - Latest Laravel framework with modern PHP 8.2+
- βοΈ React 19 + Inertia.js 2 - Build SPAs without building an API
- π¨ Tailwind CSS 4 - Utility-first CSS with new @theme directive
- π¦ Feature-Based Architecture - Organize by features, not MVC layers
- π SEO Ready - Meta tags, Open Graph, Twitter Cards pre-configured
- π Vite - Lightning-fast frontend tooling with HMR
- ποΈ SQLite - Zero-config database (easily switchable)
- π£ Custom React Hooks - Pre-built hooks for auth, flash messages, errors
- π οΈ Artisan Commands - Generate features, controllers, models with CLI
- π± API Support - Optional RESTful API routes per feature
- π Shared Inertia Data - Auto-share auth, flash, errors across all pages
π¦ Feature-Based Architecture
Why Feature-Based?
Traditional Laravel apps organize code by technical layers (Controllers, Models, etc.). FeatureKit organizes by features (Blog, Products, Orders, etc.).
Traditional Structure:
app/
βββ Http/Controllers/
β βββ BlogController.php
β βββ ProductController.php
β βββ OrderController.php
βββ Models/
β βββ Post.php
β βββ Product.php
β βββ Order.php
FeatureKit Structure:
app/Features/
βββ Blog/
β βββ Controllers/BlogController.php
β βββ Models/Post.php
β βββ Requests/
β βββ Services/
β βββ web.php
βββ Products/
β βββ Controllers/ProductController.php
β βββ Models/Product.php
β βββ web.php
βββ Orders/
βββ Controllers/OrderController.php
βββ Models/Order.php
βββ web.php
Benefits
- β Clear boundaries - Each feature is self-contained
- β Easy navigation - Find all Blog code in one place
- β Team collaboration - Different teams work on different features
- β Reusability - Extract features into packages easily
- β Reduced conflicts - Teams don't touch same files
- β Better testing - Test features independently
π Installation
Requirements
- PHP 8.2 or higher
- Composer
- Node.js 18+ and npm
- SQLite, MySQL, or PostgreSQL
Create New Project
composer create-project rifatxtra/laravel-featurekit my-app
cd my-app
Initial Setup
# Generate application key php artisan key:generate # Run database migrations php artisan migrate # Install frontend dependencies npm install
β‘ Quick Start
Start Development Server
Option 1: All-in-one command (recommended)
composer dev
This runs: Laravel server, queue worker, logs viewer, and Vite dev server.
Option 2: Separately
# Terminal 1: Backend php artisan serve # Terminal 2: Frontend npm run dev
Visit: http://localhost:8000
Create Your First Feature
# Generate a complete feature php artisan make:feature Blog # With API support php artisan make:feature Products --api
This creates:
- Feature directory structure
- Controller with example code
- Route file (web.php)
- React page component
- API routes and controller (if --api flag used)
π οΈ Artisan Commands
FeatureKit includes powerful commands to speed up development:
make:feature
Create a complete feature with all necessary files.
# Basic feature php artisan make:feature Blog # With API support php artisan make:feature Products --api # Force overwrite existing php artisan make:feature Blog --force
Creates:
app/Features/Blog/Controllers/BlogController.phpapp/Features/Blog/Models/app/Features/Blog/Requests/app/Features/Blog/Services/app/Features/Blog/web.phpresources/js/Pages/Blog/Index.jsx- (Optional)
app/Features/Blog/api.php - (Optional)
app/Features/Blog/Controllers/BlogApiController.php
make:feature-controller
Add a controller to an existing feature.
php artisan make:feature-controller Blog PostController
make:feature-model
Add a model to an existing feature.
# Without migration php artisan make:feature-model Blog Post # With migration php artisan make:feature-model Blog Post --migration
make:feature-page
Create a React page component for a feature.
php artisan make:feature-page Blog Create
Creates: resources/js/Pages/Blog/Create.jsx
feature:list
List all features with statistics.
php artisan feature:list
Output:
ββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬βββββββββ
β Feature β Web Routes β API Routes β Controllers β Models β
ββββββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌβββββββββ€
β Blog β β β β β 2 β 1 β
β Products β β β β β 1 β 1 β
ββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄βββββββββ
π£ React Hooks
FeatureKit provides pre-built React hooks for common tasks.
Authentication Hooks
import { useAuth, useUser, useIsAuthenticated, useHasRole, useHasPermission } from '@/hooks/useSharedProps'; function MyComponent() { const user = useUser(); const isAuthenticated = useIsAuthenticated(); const isAdmin = useHasRole('admin'); const canEdit = useHasPermission('posts.edit'); return ( <div> {isAuthenticated && <p>Welcome, {user.name}!</p>} {isAdmin && <AdminPanel />} {canEdit && <EditButton />} </div> ); }
Flash Message Hooks
Helpers to read flash data shared via Inertia (success, error, warning, info, or any custom key).
import { useFlash, useFlashMessage, useFlashSuccess, useFlashError, useFlashWarning, useFlashInfo, } from '@/hooks/useSharedProps'; function MyComponent() { const flash = useFlash(); const success = useFlashSuccess(); const error = useFlashError(); const info = useFlashMessage('custom'); return ( <> {success && <div className="alert-success">{success}</div>} {error && <div className="alert-error">{error}</div>} {info && <div className="alert-info">{info}</div>} {flash.warning && <div className="alert-warning">{flash.warning}</div>} </> ); }
FlashToasts component
Flash toasts are rendered via the default layout so they have access to Inertia context. See resources/js/Layouts/AppLayout.jsx:
import FlashToasts from '@/Components/FlashToasts'; export default function AppLayout({ children }) { return ( <> <FlashToasts /> {children} </> ); }
Validation Error Hooks
Helpers to inspect validation errors from Inertia responses: per-field arrays, first error, or overall state.
import { useError, useHasErrors, useFieldErrors, useFirstError, } from '@/hooks/useSharedProps'; function MyForm() { const emailErrors = useFieldErrors('email'); const firstError = useFirstError(); const emailError = useError('email'); const hasErrors = useHasErrors(); return ( <form> <input type="email" name="email" /> {emailErrors.map((msg) => ( <div key={msg} className="text-red-500 text-sm">{msg}</div> ))} {/* Or just the first error */} {emailError && <span className="text-red-500">{emailError}</span>} {hasErrors && <p className="text-sm text-red-600">{firstError}</p>} </form> ); }
Accessibility: busy state on forms
Submit buttons use aria-busy when processing is true, so screen readers announce that the action is in progress. Pair this with a loading label (e.g., βSending...β) for clear feedback.
Available Hooks
| Hook | Description |
|---|---|
useAuth() |
Get auth object with user and check status |
useUser() |
Get authenticated user directly |
useIsAuthenticated() |
Check if user is logged in (boolean) |
useIsGuest() |
Check if user is guest (boolean) |
useHasRole(role) |
Check if user has specific role |
useHasPermission(permission) |
Check if user has permission |
useFlash() |
Get all flash messages |
useErrors() |
Get all validation errors |
useError(field) |
Get error for specific field |
useHasErrors() |
Check if any errors exist |
useAppConfig() |
Get app configuration |
useCsrfToken() |
Get CSRF token |
π Full Documentation: See HOOKS.md
π API Support
Create RESTful APIs within your features.
Generate Feature with API
php artisan make:feature Products --api
This creates app/Features/Products/api.php:
<?php use Illuminate\Support\Facades\Route; use App\Features\Products\Controllers\ProductsApiController; Route::prefix('products')->name('products.')->group(function () { Route::get('/', [ProductsApiController::class, 'index']); Route::post('/', [ProductsApiController::class, 'store']); Route::get('/{id}', [ProductsApiController::class, 'show']); Route::put('/{id}', [ProductsApiController::class, 'update']); Route::delete('/{id}', [ProductsApiController::class, 'destroy']); });
API Controller Example
<?php namespace App\Features\Products\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; class ProductsApiController extends Controller { public function index(Request $request): JsonResponse { return response()->json([ 'success' => true, 'message' => 'Products retrieved successfully', 'data' => Product::all(), ]); } public function store(Request $request): JsonResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', 'price' => 'required|numeric', ]); $product = Product::create($validated); return response()->json([ 'success' => true, 'message' => 'Product created successfully', 'data' => $product, ], 201); } }
API Routes
All feature API routes are automatically registered under /api prefix:
GET /api/products- List productsPOST /api/products- Create productGET /api/products/{id}- Get productPUT /api/products/{id}- Update productDELETE /api/products/{id}- Delete product
π¨ Tailwind CSS Customization
FeatureKit uses Tailwind CSS 4 with the new @theme directive for customization.
Customize Theme
Edit resources/css/app.css to extend Tailwind's theme:
@import 'tailwindcss'; /* Configure source scanning for feature-based architecture */ @source '../../app/Features/**/*.blade.php'; @source "../**/*.blade.php"; @source "../**/*.js"; @source "../**/*.jsx"; @theme { /* Custom Colors */ --color-primary-500: #3b82f6; --color-primary-600: #2563eb; --color-secondary-500: #a855f7; /* Custom Fonts */ --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif; --font-heading: 'Poppins', ui-sans-serif, system-ui, sans-serif; /* Custom Border Radius */ --radius-sm: 0.25rem; --radius-DEFAULT: 0.5rem; --radius-lg: 1rem; /* Custom Spacing */ --spacing-18: 4.5rem; --spacing-72: 18rem; /* Custom Breakpoints */ --breakpoint-3xl: 1920px; }
Usage in Components
export default function MyComponent() { return ( <div className="bg-primary-500 text-white rounded-lg p-6"> <h1 className="font-heading text-3xl">Custom Styled Component</h1> <p className="mt-4">Using custom theme values!</p> </div> ); }
Available Customizations
Tailwind CSS 4 allows you to customize:
- Colors -
--color-{name}-{shade} - Fonts -
--font-{family} - Spacing -
--spacing-{size} - Border Radius -
--radius-{size} - Shadows -
--shadow-{size} - Breakpoints -
--breakpoint-{name} - Transitions -
--transition-{speed} - Z-Index -
--z-index-{level}
π Learn More: Tailwind CSS v4 Theme Documentation
π SEO Configuration
FeatureKit is SEO-ready out of the box.
Global SEO Settings
Configure in .env:
APP_NAME="Your App Name" APP_META_DESCRIPTION="Your app description for search engines" APP_OG_IMAGE="/og-image.png"
Per-Page SEO
Override using Inertia's <Head> component:
import { Head } from '@inertiajs/react'; export default function BlogPost({ post }) { return ( <> <Head> <title>{post.title} - My Blog</title> <meta name="description" content={post.excerpt} /> <meta property="og:title" content={post.title} /> <meta property="og:description" content={post.excerpt} /> <meta property="og:image" content={post.image} /> </Head> <article> <h1>{post.title}</h1> <p>{post.content}</p> </article> </> ); }
Included Meta Tags
- Charset and viewport
- CSRF token
- Canonical URL
- Robots directives
- Open Graph (Facebook)
- Twitter Cards
- Theme color
- Favicon support
οΏ½οΈ Database Migrations
FeatureKit includes pre-configured migrations for common Laravel features.
Available Migrations
1. Users Table (0001_01_01_000000_create_users_table.php)
Creates three tables: users, password_reset_tokens, and sessions.
users Table:
| Column | Type | Description |
|---|---|---|
id |
bigint (primary) | Unique user identifier |
name |
string | User's full name |
role |
string (nullable) | User role (e.g., admin, user, editor) |
profile_image |
string (nullable) | Path to user's profile image |
age |
tinyint (nullable) | User's age (0-255) |
gender |
string(20) (nullable) | User's gender |
email |
string (unique) | User's email address for login |
email_verified_at |
timestamp (nullable) | When email was verified (for Laravel's email verification) |
password |
string | Hashed password |
remember_token |
string (nullable) | Token for "remember me" functionality |
created_at |
timestamp | When user was created |
updated_at |
timestamp | When user was last updated |
password_reset_tokens Table:
| Column | Type | Description |
|---|---|---|
email |
string (primary) | Email requesting password reset |
token |
string | Unique reset token |
created_at |
timestamp (nullable) | When reset was requested |
sessions Table:
| Column | Type | Description |
|---|---|---|
id |
string (primary) | Unique session identifier |
user_id |
bigint (nullable, indexed) | Associated user ID |
ip_address |
string(45) (nullable) | IP address of session |
user_agent |
text (nullable) | Browser/client user agent |
payload |
longtext | Serialized session data |
last_activity |
int (indexed) | Unix timestamp of last activity |
2. Cache Tables (0001_01_01_000001_create_cache_table.php)
cache Table:
| Column | Type | Description |
|---|---|---|
key |
string (primary) | Cache key identifier |
value |
mediumtext | Serialized cached value |
expiration |
int | Unix timestamp when cache expires |
cache_locks Table:
| Column | Type | Description |
|---|---|---|
key |
string (primary) | Lock key identifier |
owner |
string | Process/thread that owns the lock |
expiration |
int | Unix timestamp when lock expires |
3. Queue/Jobs Tables (0001_01_01_000002_create_jobs_table.php)
jobs Table:
| Column | Type | Description |
|---|---|---|
id |
bigint (primary) | Unique job identifier |
queue |
string (indexed) | Queue name the job belongs to |
payload |
longtext | Serialized job data |
attempts |
tinyint | Number of times job has been attempted |
reserved_at |
int (nullable) | When job was reserved for processing |
available_at |
int | When job becomes available for processing |
created_at |
int | When job was created |
job_batches Table:
| Column | Type | Description |
|---|---|---|
id |
string (primary) | Unique batch identifier |
name |
string | Batch name/description |
total_jobs |
int | Total jobs in batch |
pending_jobs |
int | Jobs not yet processed |
failed_jobs |
int | Jobs that failed |
failed_job_ids |
longtext | List of failed job IDs |
options |
mediumtext (nullable) | Batch options/metadata |
cancelled_at |
int (nullable) | When batch was cancelled |
created_at |
int | When batch was created |
finished_at |
int (nullable) | When batch completed |
failed_jobs Table:
| Column | Type | Description |
|---|---|---|
id |
bigint (primary) | Unique failed job identifier |
uuid |
string (unique) | Unique UUID for job |
connection |
text | Queue connection used |
queue |
text | Queue name |
payload |
longtext | Job data |
exception |
longtext | Exception details/stack trace |
failed_at |
timestamp | When job failed |
Running Migrations
# Run all migrations php artisan migrate # Fresh migration (drop all tables and re-migrate) php artisan migrate:fresh # Rollback last migration batch php artisan migrate:rollback # Reset all migrations php artisan migrate:reset
Custom Migrations
Create feature-specific migrations:
# Create migration for a model php artisan make:feature-model Blog Post --migration # Or create standalone migration php artisan make:migration create_posts_table
π Authentication
FeatureKit includes a complete authentication system with Login, Register, Logout, and Password Reset functionality using Inertia.js and React.
Available Auth Routes
The Auth feature provides these routes out of the box:
| Route | Method | Purpose | Access |
|---|---|---|---|
/login |
GET | Display login form | Guest only |
/login |
POST | Handle login | Guest only |
/register |
GET | Display registration form | Guest only |
/register |
POST | Handle registration | Guest only |
/forgot-password |
GET | Display forgot password form | Guest only |
/forgot-password |
POST | Send password reset link | Guest only |
/reset-password/{token} |
GET | Display reset password form | Guest only |
/reset-password |
POST | Handle password reset | Guest only |
/logout |
POST | Handle logout | Authenticated only |
Backend Controllers
LoginController
Handles user authentication with "remember me" functionality:
<?php namespace App\Features\Auth\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Validation\ValidationException; use Inertia\Inertia; class LoginController extends Controller { public function create() { return Inertia::render('Auth/Login'); } public function store(Request $request) { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); $remember = $request->boolean('remember'); if (! Auth::attempt($credentials, $remember)) { throw ValidationException::withMessages([ 'email' => 'The provided credentials do not match our records.', ]); } $request->session()->regenerate(); return redirect()->intended(route('home')) ->with('success', 'Welcome back!'); } }
RegisterController
Handles new user registration:
<?php namespace App\Features\Auth\Controllers; use App\Http\Controllers\Controller; use App\Models\User; use Illuminate\Auth\Events\Registered; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\Rules\Password; use Inertia\Inertia; class RegisterController extends Controller { public function create() { return Inertia::render('Auth/Register'); } public function store(Request $request) { $validated = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'confirmed', Password::defaults()], ]); $user = User::create([ 'name' => $validated['name'], 'email' => $validated['email'], 'password' => Hash::make($validated['password']), ]); event(new Registered($user)); Auth::login($user); return redirect()->route('home') ->with('success', 'Account created successfully!'); } }
LogoutController
Handles user logout and session cleanup:
<?php namespace App\Features\Auth\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class LogoutController extends Controller { public function destroy(Request $request) { Auth::guard('web')->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->route('home') ->with('success', 'You have been logged out.'); } }
ForgotPasswordController
Handles password reset link requests:
<?php namespace App\Features\Auth\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Password; use Illuminate\Validation\ValidationException; use Inertia\Inertia; class ForgotPasswordController extends Controller { public function create() { return Inertia::render('Auth/ForgotPassword'); } public function store(Request $request) { $request->validate(['email' => ['required', 'email']]); $status = Password::sendResetLink($request->only('email')); if ($status === Password::RESET_LINK_SENT) { return back()->with('success', 'Password reset link sent!'); } throw ValidationException::withMessages([ 'email' => [trans($status)], ]); } }
ResetPasswordController
Handles password reset with token:
<?php namespace App\Features\Auth\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Password; use Illuminate\Validation\Rules; use Inertia\Inertia; class ResetPasswordController extends Controller { public function create(Request $request) { return Inertia::render('Auth/ResetPassword', [ 'token' => $request->route('token'), 'email' => $request->query('email'), ]); } public function store(Request $request) { $request->validate([ 'token' => ['required'], 'email' => ['required', 'email'], 'password' => ['required', 'confirmed', Rules\Password::defaults()], ]); $status = Password::reset( $request->only('email', 'password', 'password_confirmation', 'token'), function ($user, $password) { $user->forceFill(['password' => Hash::make($password)])->save(); } ); if ($status === Password::PASSWORD_RESET) { return redirect('/login')->with('success', 'Password reset successfully!'); } throw ValidationException::withMessages(['email' => [trans($status)]]); } }
Frontend Pages
Login Page
Located at resources/js/Pages/Auth/Login.jsx:
- Email and password fields with validation
- "Remember me" checkbox for persistent sessions
- Flash message display for success/error notifications
- Links to registration and password reset
- Responsive design with Tailwind CSS
Register Page
Located at resources/js/Pages/Auth/Register.jsx:
- Full name, email, password, and password confirmation fields
- Real-time validation error display
- Terms of service acknowledgment
- Link to login page for existing users
- Auto-login after successful registration
Forgot Password Page
Located at resources/js/Pages/Auth/ForgotPassword.jsx:
- Email input field
- Sends password reset link via email
- Success/error flash messages
- Link back to login page
Reset Password Page
Located at resources/js/Pages/Auth/ResetPassword.jsx:
- Email, password, and password confirmation fields
- Token automatically included from URL
- Validates and updates password
- Redirects to login after successful reset
Password Reset Flow
- User clicks "Forgot password?" on login page
- Enters email on
/forgot-passwordpage - Laravel sends reset link to email using
password_reset_tokenstable - User clicks link in email (e.g.,
/reset-password/abc123?email=user@example.com) - User enters new password on reset form
- Password is updated and user redirected to login
Usage in Components
Use authentication hooks to protect routes or show/hide UI elements:
import { useUser, useIsAuthenticated } from '@/hooks/useSharedProps'; import { router } from '@inertiajs/react'; export default function MyComponent() { const user = useUser(); const isAuthenticated = useIsAuthenticated(); const handleLogout = () => { router.post(route('logout')); }; return ( <div> {isAuthenticated ? ( <> <p>Welcome, {user.name}!</p> <button onClick={handleLogout}>Logout</button> </> ) : ( <a href={route('login')}>Login</a> )} </div> ); }
Session Security
The authentication system includes:
- Session Regeneration: New session ID after login to prevent session fixation
- CSRF Protection: Automatic CSRF token validation on all POST requests
- Password Hashing: BCrypt hashing via
Hash::make() - Remember Me: Secure persistent login with token rotation
- Logout Cleanup: Session invalidation and token regeneration on logout
Customization
To customize authentication behavior:
- Validation Rules: Edit validation in controller
store()methods - Redirect Path: Change
route('home')to your preferred route - User Fields: Add custom fields in registration (age, role, etc.)
- Styling: Modify
resources/js/Pages/Auth/*.jsxcomponents - Email Verification: Enable by adding verification routes and middleware
οΏ½π Directory Structure
laravel-featurekit/
βββ app/
β βββ Console/
β β βββ Commands/ # Custom Artisan commands
β β βββ MakeFeatureCommand.php
β β βββ MakeFeatureControllerCommand.php
β β βββ MakeFeatureModelCommand.php
β β βββ MakeFeaturePageCommand.php
β β βββ ListFeaturesCommand.php
β βββ Features/ # Feature modules
β β βββ Auth/
β β β βββ Controllers/
β β β β βββ LoginController.php
β β β β βββ RegisterController.php
β β β β βββ LogoutController.php
β β β β βββ ForgotPasswordController.php
β β β β βββ ResetPasswordController.php
β β β βββ web.php
β β βββ Home/
β β β βββ Controllers/
β β β β βββ HomeController.php
β β β βββ web.php
β β βββ Test/
β β βββ web.php
β βββ Http/
β β βββ Controllers/
β β β βββ Controller.php
β β βββ Middleware/
β β βββ HandleInertiaRequests.php
β βββ Models/
β β βββ User.php
β βββ Providers/
β βββ AppServiceProvider.php
β βββ FeatureRouteServiceProvider.php
βββ resources/
β βββ css/
β β βββ app.css # Tailwind CSS with @theme
β βββ js/
β β βββ hooks/
β β β βββ useSharedProps.js # Custom React hooks
β β βββ Components/ # Reusable components
β β βββ Layouts/ # Layout components
β β βββ Pages/ # Inertia page components
β β β βββ Auth/
β β β β βββ Login.jsx
β β β β βββ Register.jsx
β β β β βββ ForgotPassword.jsx
β β β β βββ ResetPassword.jsx
β β β βββ Welcome.jsx
β β βββ app.jsx # React/Inertia entry point
β β βββ bootstrap.js # Bootstrap code
β βββ views/
β βββ app.blade.php # Root template
βββ database/
β βββ migrations/
β βββ seeders/
βββ config/ # Laravel config
βββ HOOKS.md # Hooks documentation
βββ README.md # This file
βββ composer.json
βββ package.json
βββ vite.config.js # Vite configuration
π‘ Examples
Example 1: Simple Blog Feature
# Generate Blog feature
php artisan make:feature Blog
Route (app/Features/Blog/web.php):
<?php use Illuminate\Support\Facades\Route; use App\Features\Blog\Controllers\BlogController; Route::prefix('blog')->name('blog.')->group(function () { Route::get('/', [BlogController::class, 'index'])->name('index'); Route::get('/{slug}', [BlogController::class, 'show'])->name('show'); });
Controller (app/Features/Blog/Controllers/BlogController.php):
<?php namespace App\Features\Blog\Controllers; use App\Http\Controllers\Controller; use Inertia\Inertia; class BlogController extends Controller { public function index() { return Inertia::render('Blog/Index', [ 'posts' => Post::latest()->paginate(10), ]); } public function show(string $slug) { $post = Post::where('slug', $slug)->firstOrFail(); return Inertia::render('Blog/Show', [ 'post' => $post, ]); } }
React Page (resources/js/Pages/Blog/Index.jsx):
import { Head, Link } from '@inertiajs/react'; export default function BlogIndex({ posts }) { return ( <> <Head title="Blog" /> <div className="container mx-auto px-4 py-8"> <h1 className="text-4xl font-bold mb-8">Blog</h1> <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3"> {posts.data.map((post) => ( <article key={post.id} className="border rounded-lg p-6"> <h2 className="text-2xl font-semibold mb-2"> <Link href={route('blog.show', post.slug)}> {post.title} </Link> </h2> <p className="text-gray-600">{post.excerpt}</p> </article> ))} </div> </div> </> ); }
Example 2: E-commerce with API
# Generate Products feature with API php artisan make:feature Products --api # Add Product model with migration php artisan make:feature-model Products Product --migration
Access your API at:
GET /api/products- List all productsPOST /api/products- Create productGET /api/products/{id}- Get single product
π€ Contributing
Contributions are welcome! Feel free to submit issues and pull requests.
π¨βπ» Author
Created by Md. Rashedul Islam
- GitHub: Laravel FeatureKit
- Website: rifatxtra.com
π License
Laravel FeatureKit is open-sourced software licensed under the MIT license.
π Show Your Support
If you find this project helpful, please give it a β on GitHub!
Happy Coding! π