How many times have you started a Laravel project manually creating models, controllers, migrations, factories, form requests, and tests one by one? If you’re like most Laravel developers, you’ve probably wasted countless hours on these repetitive tasks that, while necessary, don’t add direct value to your application’s business logic.
Laravel Blueprint is completely changing this paradigm. This code generation tool, created by Jason McCreary (the same genius behind Laravel Shift), allows you to generate multiple Laravel components from a single, readable, and expressive YAML file. In this deep analysis, we’ll explore how Blueprint can transform your development workflow and why it’s gaining traction in the Laravel community.
The Problem: The Tedious Manual Scaffolding Process
The Reality of Traditional Laravel Development
When we start a new Laravel project or add new functionality, the typical process is:
# For each entity in your application...
php artisan make:model Post -m
php artisan make:controller PostController --resource
php artisan make:factory PostFactory
php artisan make:request StorePostRequest
php artisan make:request UpdatePostRequest
php artisan make:seeder PostSeeder
php artisan make:test PostTest
The problems are evident:
- ⏱️ Time wasted: 10-15 minutes per entity just for scaffolding
- 🔄 Constant repetition: The same process for each model
- 🐛 Inconsistency errors: Names, conventions, relationships
- 📝 Manual configuration: Fillables, casts, relationships
- 🧪 Outdated tests: Rarely match the actual implementation
The Hidden Cost
In a typical project with 10-15 main entities:
- 2-3 hours just on initial scaffolding
- 30-45 minutes for each structural change
- Additional hours fixing inconsistencies
- Testing time to verify everything works
Total: Easily 5-8 hours of purely mechanical work.
Blueprint: A Revolution in YAML Syntax
What is Laravel Blueprint?
Laravel Blueprint is an open-source tool that generates multiple Laravel components from a single, readable, and expressive YAML definition. Think of it as a “compiler” that translates high-level intentions into functional Laravel code.
Core philosophy:
Define once, generate everything needed following Laravel best practices.
Quick Installation
# Install Blueprint
composer require --dev laravel-shift/blueprint
# Create initial draft file
php artisan blueprint:new
# Generate components
php artisan blueprint:build
Your First Blueprint: Complete Blog
Let’s see how to create a complete blog with Blueprint:
# draft.yaml
models:
Post:
title: string:400
content: longtext
published_at: nullable timestamp
author_id: id:user
relationships:
belongsTo: User
hasMany: Comment
Comment:
content: text
author_id: id:user
post_id: id:post
relationships:
belongsTo: User, Post
controllers:
Post:
index:
query: all
render: post.index with:posts
create:
render: post.create
store:
validate: title, content, author_id
save: post
send: ReviewPost to:post.author.email with:post
dispatch: SyncMedia with:post
fire: NewPost with:post
flash: post.title
redirect: posts.index
show:
render: post.show with:post
edit:
render: post.edit with:post
update:
validate: title, content
update: post
fire: PostUpdated with:post
redirect: posts.index
destroy:
delete: post
redirect: posts.index
Comment:
store:
validate: content, post_id, author_id
save: comment
fire: CommentPosted with:comment
redirect: posts.show with:comment.post
What Blueprint Automatically Generates
From these ~40 lines of YAML, Blueprint generates:
1. Complete Models:
// app/Models/Post.php
class Post extends Model
{
protected $fillable = [
'title',
'content',
'published_at',
'author_id',
];
protected $casts = [
'published_at' => 'timestamp',
];
public function user()
{
return $this->belongsTo(User::class, 'author_id');
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
2. Controllers with Complex Logic:
// app/Http/Controllers/PostController.php
class PostController extends Controller
{
public function index()
{
$posts = Post::all();
return view('post.index', compact('posts'));
}
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'content' => 'required',
'author_id' => 'required',
]);
$post = Post::create($request->all());
Mail::to($post->author->email)->send(new ReviewPost($post));
SyncMedia::dispatch($post);
NewPost::dispatch($post);
return redirect()->route('posts.index')
->with('success', $post->title);
}
// ... rest of methods
}
3. Structured Migrations:
// database/migrations/create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title', 400);
$table->longText('content');
$table->timestamp('published_at')->nullable();
$table->foreignId('author_id')->constrained('users');
$table->timestamps();
});
4. Factories for Testing:
// database/factories/PostFactory.php
class PostFactory extends Factory
{
public function definition()
{
return [
'title' => $this->faker->sentence(4),
'content' => $this->faker->paragraphs(3, true),
'published_at' => $this->faker->dateTimeBetween('-1 month', '+1 month'),
'author_id' => User::factory(),
];
}
}
5. Validated Form Requests:
// app/Http/Requests/StorePostRequest.php
class StorePostRequest extends FormRequest
{
public function rules()
{
return [
'title' => ['required'],
'content' => ['required'],
'author_id' => ['required'],
];
}
}
6. Events, Jobs, and Mailables:
// app/Events/NewPost.php
class NewPost
{
public function __construct(public Post $post) {}
}
// app/Jobs/SyncMedia.php
class SyncMedia implements ShouldQueue
{
public function __construct(public Post $post) {}
}
// app/Mail/ReviewPost.php
class ReviewPost extends Mailable
{
public function __construct(public Post $post) {}
}
7. Functional Tests:
// tests/Feature/Http/Controllers/PostControllerTest.php
class PostControllerTest extends TestCase
{
use RefreshDatabase;
public function test_index_displays_view()
{
$posts = Post::factory()->count(3)->create();
$response = $this->get(route('post.index'));
$response->assertOk();
$response->assertViewIs('post.index');
$response->assertViewHas('posts');
}
public function test_store_uses_form_request_validation() { /* ... */ }
public function test_store_saves_and_redirects() { /* ... */ }
// ... more tests
}
Advanced Blueprint Features
1. Expressive Syntax and Shorthands
Blueprint offers intelligent shortcuts that maximize productivity:
models:
User:
name: string
email: string
email_verified_at: nullable timestamp
password: string
remember_token: nullable string:100
# Shorthand for soft deletes
softdeletes: true
# Automatic timestamps (enabled by default)
timestamps: true
Product:
name: string:500
description: text
price: decimal:8,2
category: enum:'electronics','clothing','books'
status: enum:'active','inactive','pending'
# Automatic relationships based on convention
user_id: id:user
category_id: id:category
# Automatic indexes
sku: string:50 index
slug: string unique
2. Controllers with Advanced Actions
controllers:
Product:
index:
query: all
render: products.index with:products
store:
validate: name, description, price, category, user_id
save: product
# Multiple events and actions
fire: ProductCreated with:product
dispatch: ProcessProductImages with:product
send: ProductNotification to:admin@example.com with:product
# Dynamic flash messages
flash: product.name
redirect: products.show with:product
# Custom actions
publish:
update: product
fire: ProductPublished with:product
redirect: products.index
feature:
find: product
update: product
dispatch: UpdateSearchIndex with:product
redirect: products.show with:product
3. Smart Validation
controllers:
User:
store:
# Basic validation
validate: name, email, password
update:
# Validation with specific rules
validate: name, email
save: user
# Implicit conditional validation
changePassword:
validate: current_password, password, password_confirmation
update: user
4. Complex Relationships
models:
User:
relationships:
hasMany: Post, Comment
hasOne: Profile
belongsToMany: Role
morphMany: Image
Post:
relationships:
belongsTo: User
hasMany: Comment
morphToMany: Tag
morphOne: Image
Profile:
user_id: id:user
relationships:
belongsTo: User
Role:
relationships:
belongsToMany: User
Tag:
relationships:
morphedByMany: Post, Video
Image:
imageable_id: id
imageable_type: string
relationships:
morphTo: Imageable
Comparison: Traditional vs Blueprint
Traditional Development
# For a complete Post CRUD
php artisan make:model Post -m
php artisan make:controller PostController --resource
php artisan make:factory PostFactory
php artisan make:request StorePostRequest
php artisan make:request UpdatePostRequest
php artisan make:test PostTest
# Then manually edit:
# - Migration (table structure)
# - Model (fillable, casts, relationships)
# - Controller (logic for each method)
# - Factory (fake data definition)
# - Form Requests (validation rules)
# - Tests (test cases)
Estimated time: 45-60 minutes per entity Manual code lines: 200-300 lines Error possibility: High
With Blueprint
# draft.yaml (15-20 lines)
models:
Post:
title: string:400
content: longtext
published_at: nullable timestamp
author_id: id:user
relationships:
belongsTo: User
controllers:
Post:
index:
query: all
render: post.index with:posts
store:
validate: title, content, author_id
save: post
redirect: posts.index
# ... more actions
Estimated time: 5-10 minutes per entity Manual code lines: 15-20 lines YAML Error possibility: Very low Consistency: Guaranteed
Real Use Cases
1. E-commerce Platform
models:
Product:
name: string:500
description: text
price: decimal:10,2
cost: decimal:10,2
sku: string:100 unique
stock: integer default:0
status: enum:'active','inactive','discontinued'
category_id: id:category
brand_id: id:brand
relationships:
belongsTo: Category, Brand
hasMany: OrderItem, Review
morphMany: Image
Order:
order_number: string:50 unique
total: decimal:10,2
status: enum:'pending','processing','shipped','delivered','cancelled'
user_id: id:user
shipping_address_id: id:address
billing_address_id: id:address
relationships:
belongsTo: User
hasMany: OrderItem
belongsTo: Address
OrderItem:
order_id: id:order
product_id: id:product
quantity: integer
price: decimal:10,2
relationships:
belongsTo: Order, Product
controllers:
Product:
index:
query: all
render: products.index with:products
store:
validate: name, description, price, category_id, brand_id
save: product
dispatch: UpdateSearchIndex with:product
fire: ProductCreated with:product
redirect: products.index
Order:
store:
validate: user_id, items
save: order
dispatch: ProcessPayment with:order
send: OrderConfirmation to:order.user.email with:order
fire: OrderPlaced with:order
redirect: orders.show with:order
2. Content Management System
models:
Article:
title: string:500
slug: string:500 unique
excerpt: text
content: longtext
status: enum:'draft','published','archived'
published_at: nullable timestamp
author_id: id:user
category_id: id:category
featured_image: string nullable
meta_title: string:60 nullable
meta_description: string:160 nullable
relationships:
belongsTo: User, Category
hasMany: Comment
morphToMany: Tag
Category:
name: string:200
slug: string:200 unique
description: text nullable
parent_id: id:category nullable
relationships:
hasMany: Article
belongsTo: Category
hasMany: Category
controllers:
Article:
index:
query: all
render: articles.index with:articles
store:
validate: title, content, status, author_id, category_id
save: article
fire: ArticleCreated with:article
dispatch: GenerateSitemap
redirect: articles.show with:article
publish:
find: article
update: article
fire: ArticlePublished with:article
dispatch: NotifySubscribers with:article
redirect: articles.index
3. Learning Management System
models:
Course:
title: string:500
description: text
price: decimal:8,2
duration_hours: integer
level: enum:'beginner','intermediate','advanced'
status: enum:'draft','published','archived'
instructor_id: id:user
category_id: id:category
relationships:
belongsTo: User, Category
hasMany: Lesson, Enrollment
morphMany: Review
Lesson:
title: string:500
content: longtext
video_url: string nullable
duration_minutes: integer
order: integer
course_id: id:course
relationships:
belongsTo: Course
hasMany: LessonCompletion
Enrollment:
user_id: id:user
course_id: id:course
enrolled_at: timestamp
completed_at: nullable timestamp
progress_percentage: integer default:0
relationships:
belongsTo: User, Course
hasMany: LessonCompletion
controllers:
Course:
enroll:
validate: user_id, course_id
save: enrollment
dispatch: ProcessPayment with:enrollment
send: WelcomeToCourse to:enrollment.user.email with:enrollment
fire: UserEnrolled with:enrollment
redirect: courses.show with:course
Commands and Advanced Workflow
Main Commands
# Create new draft.yaml
php artisan blueprint:new
# Generate components from draft.yaml
php artisan blueprint:build
# Generate from specific file
php artisan blueprint:build custom-draft.yaml
# Undo last build changes
php artisan blueprint:erase
# Preview what files would be generated without creating them
php artisan blueprint:build --dry-run
# Generate only models
php artisan blueprint:build --only=models
# Generate everything except tests
php artisan blueprint:build --skip=tests
Recommended Development Workflow
# 1. Plan structure
php artisan blueprint:new
# 2. Define models and controllers in draft.yaml
# [edit draft.yaml]
# 3. Preview (optional)
php artisan blueprint:build --dry-run
# 4. Generate components
php artisan blueprint:build
# 5. Run migrations
php artisan migrate
# 6. Run generated tests
php artisan test
# 7. If errors, fix and regenerate
php artisan blueprint:erase
# [edit draft.yaml]
php artisan blueprint:build
Git Integration
# .gitignore
draft.yaml # Optional: some prefer to version it
.blueprint # Blueprint state files
# Workflow with Git
git add draft.yaml
git commit -m "Add Blueprint definition for blog feature"
php artisan blueprint:build
git add .
git commit -m "Generate blog components with Blueprint"
Customization and Extensibility
Custom Stubs
Blueprint allows you to customize generated code templates:
# Publish stubs for customization
php artisan vendor:publish --tag=blueprint-stubs
Advanced Configuration
// config/blueprint.php
return [
'app_path' => app_path(),
'namespace' => 'App',
'models_namespace' => 'Models',
'generate' => [
'models' => true,
'migrations' => true,
'factories' => true,
'controllers' => true,
'form_requests' => true,
'events' => true,
'jobs' => true,
'mailables' => true,
'tests' => true,
],
'use_constraints' => true,
'use_guarded' => false,
'fake_nullables' => true,
'model_defaults' => [
'id' => true,
'timestamps' => true,
],
];
Addons and Extensions
Blueprint has an ecosystem of addons:
# Blueprint Nova addon (generates Nova resources)
composer require --dev blueprint/nova-addon
# Blueprint Livewire addon
composer require --dev blueprint/livewire-addon
# Blueprint API addon (generates APIs)
composer require --dev blueprint/api-addon
Limitations and Considerations
What Blueprint Does NOT Do
- Complex business logic: Only generates base structure
- Complete views: Generates basic views, need customization
- Advanced validation: Only basic rules, complex validation requires manual code
- Complex polymorphic relationships: Limited support
- Advanced migrations: Complex schema changes
When NOT to Use Blueprint
- Legacy projects: With non-standard structure
- Very specific logic: That doesn’t follow Laravel conventions
- Small microservices: Unnecessary overhead
- Rapid prototyping: When you need maximum flexibility
Best Practices
- Plan structure first: Design entities and relationships before writing YAML
- Incremental iteration: Add entities gradually
- Draft versioning: Keep history of structural changes
- Post-generation testing: Verify generated functionality
- Post-customization: Use Blueprint as base, not final product
Pros and Cons
✅ Advantages
- Development speed: 80-90% faster for scaffolding
- Guaranteed consistency: Same conventions always
- Fewer errors: Eliminates typos and manual inconsistencies
- Living documentation: The YAML documents the structure
- Automatic testing: Generated and functional tests
- Best practices: Automatically follows Laravel conventions
- Easier refactoring: Simpler structural changes
⚠️ Disadvantages
- Learning curve: Specific YAML syntax
- Limited flexibility: For very specific cases
- External dependency: Another tool in the stack
- Post-customization: Generated code needs adjustments
- Updates: Dependent on package maintenance
The Future: Blueprint and Laravel 11+
Compatibility and Roadmap
Blueprint evolves with Laravel:
- Laravel 11: Full support
- New features: Always up to date with Laravel
- Active community: Constant contributions
- Growing ecosystem: More addons and integrations
Emerging Trends
- AI-assisted blueprints: AI that generates YAML from descriptions
- Visual blueprint editors: Graphical editors for YAML
- Team collaboration: Tools for teams
- CI/CD integration: Automation in pipelines
Conclusion: Is Blueprint Worth It?
For New Projects: Absolutely Yes
If you’re starting a new Laravel project, especially one that follows standard conventions, Blueprint is a game-changer. The benefits far outweigh the learning time.
For Existing Projects: Depends
- Projects with standard structure: Ideal for new features
- Complex legacy projects: Evaluate case by case
- Large teams: Excellent for standardization
For Laravel Developers: Essential
Regardless of the project, knowing Blueprint makes you more productive and helps you write more consistent code.
Typical ROI
Initial investment: 2-4 hours learning Blueprint Savings per project: 5-15 hours on scaffolding Net benefit: Positive from the first medium project
Final Recommendation
Blueprint represents the best of the Laravel ecosystem: tools that amplify productivity without sacrificing quality. It’s not perfect for all cases, but for 80% of typical Laravel projects, it’s a dramatic improvement in the development workflow.
My advice: Invest an afternoon in learning Blueprint. Your future self will thank you every time you start a new feature and instead of wasting an hour on manual scaffolding, you have everything working in 10 minutes.
Software development is about solving business problems, not writing boilerplate. Blueprint allows you to focus on what really matters: creating value for your users.
Have you tried Blueprint in your Laravel projects? What tools do you use to accelerate your development? Share your experience and tips in the comments!
Helpful links:
- Blueprint Official Site
- GitHub Repository
- Laravel Shift (tools from the same author)
- Full Documentation












Comments