mpociot/blacksmith
Blacksmith is a Laravel code generation tool that turns a simple YAML schema definition into Eloquent models, migrations, and related scaffolding, cutting boilerplate when starting new projects or adding database-backed features.
Verify what you actually installed before anything else. The package metadata labels mpociot/blacksmith as "the unofficial Laravel Forge API," but the repo and its documentation describe a schema-driven CRUD scaffolder. Two different products. Run composer show mpociot/blacksmith and open vendor/mpociot/blacksmith/ to confirm which artifact you have before planning around it. If it's the scaffolder (which the code and docs indicate), the rest of this applies. If it's genuinely a Forge client, stop — this assessment doesn't cover it.
Install it as a dev dependency in a sandbox, not the app you care about.
composer require --dev mpociot/blacksmith
php artisan vendor:publish # config + stubs
php artisan list | grep -i blacksmith # confirm the real command name for your version
Last release is November 2016. Expect Composer to reject it on PHP 8 / Laravel 8+. Check early:
composer why-not mpociot/blacksmith
If that fails on your target stack, don't fight it — switch to reading the package as a reference implementation instead of installing it, and build a thin internal Artisan command with the same stub structure. That path costs a few days and is where most of the value is.
First use case: one model, end to end. Don't start with a schema that describes your whole domain. Define a single Post — title, body, published_at, user_id → belongsTo User — run the generator, and diff the output against a hand-written equivalent. That diff tells you more about whether the tool is usable verbatim than any README:
$fillable vs $guarded, relationship methods, casts)Where to look first in the source: the Artisan command class (src/Commands), the schema parser, and the stubs/ directory. The stubs are the entire product — everything else is plumbing. Read them before customizing anything.
Schema-as-source-of-truth, generate-once-then-own. Treat the schema file as an input to a one-shot bootstrap, not a live artifact synced with the codebase. The durable workflow:
Generate in dependency order. Parents before children. Define User before Post if Post has a user_id FK; otherwise you get migrations referencing tables that don't exist yet, or relationship methods pointing at the wrong model. Circular relationships need two generation passes.
One resource at a time. A schema with ten models means ten controllers, ten migrations, and one review that nobody does properly. Small batches keep review honest and make a bad generation cheap to throw away.
Customize stubs, not generated output. The publishable stubs are the legitimate extension point. Adjust the model stub to add declare(strict_types=1), swap the controller stub for a FormRequest-based one, add final to generated classes. Do it once, commit the stubs into your repo, then generate. If you're patching generated files one-by-one instead, you've picked the wrong layer.
Use generated tests as a scaffold, not as coverage. The PHPUnit output gives you endpoint stubs and a working baseline — status codes, happy paths. Rewrite assertions to match your actual domain rules before they count for anything. Generated tests that assert 200 on a create endpoint will pass while validation is wrong.
If you're on a modern stack, invert the workflow. Read Blacksmith's schema grammar and stub design, then write a small internal Artisan command (make:resource-style) with your own stubs. YAML input plus templates you control is a few days of work and gives you an upgrade path the package does not have. For most teams this is the recommended path, not the fallback.
Diff-against-manual as a calibration step. Every time you're about to hand-write a routine CRUD feature, generate it in a scratch branch, diff against what you'd have written, and keep whatever is better. Over time this tells you which parts of your conventions the generator actually captures — and which are worth encoding into your own stub set.
Regeneration is destructive. There's no three-way merge. Re-running the generator overwrites your edits. If you must re-run, generate into a scratch directory first (configurable output paths) and diff by hand. Never wire generation into CI or a Composer post-install script.
Silent correctness drift is the real failure mode. A misdeclared relationship produces a plausible-looking belongsTo with the wrong foreign key. It compiles. It runs. You find it weeks later. Every relationship in your schema needs explicit review of both the generated migration and the model method — not a skim of the diff.
Expect 2016-era conventions throughout. No typed properties, no constructor promotion, older Blade syntax, validation in controllers rather than FormRequests, factories in the pre-class style, and route model binding that may not match what you use today. Generated code that compiles but violates your team's conventions is a maintenance cost you're choosing to take on. Budget for it or fix it in the stubs.
The abandoned-dependency tax is asymmetric. The generator itself is dev-only, so production traffic is safe. But sitting in require-dev with a pinned old framework constraint, it can block composer update across the whole application long after the feature that motivated it is gone. Keep it out of the lockfile of any app you intend to upgrade.
Zero dependents means zero search results. No ecosystem corpus, no issue activity, no vendor. Every edge case is yours alone. Budget for reading source rather than searching for an answer.
Metadata mismatch is a trust signal. Package registries describe this as a Forge API client; the repo describes a scaffolder. Correct the record before anyone cites "Blacksmith" in a roadmap or onboarding doc. This kind of stale metadata is itself worth noting when evaluating maintenance posture.
Debugging tips:
-v to see what it's actually writing where.json or decimal will silently fall back to a default.Extension points worth knowing: publishable config (output paths, namespace, generation toggles) and publishable stubs are the only supported customization surfaces. Anything else is a fork, and a fork you own forever.
State your exit criteria up front. Before you start, decide what "good enough" looks like: a working internal admin CRUD in an afternoon, or a validated reference for an internal generator. If it's neither — if someone wants this standardized org-wide — the answer isn't Blacksmith. It's a small generator you own, built from what you learned reading this one.
How can I help you explore Laravel packages today?