orchestra/studio
Orchestra Studio is an Orchestra Platform package for Laravel that provides a foundation for building admin panels and back-office applications, with extension-ready scaffolding, reusable UI components, and tooling to speed development.
Confirm the foundation first. Studio is a development-time generator for the Orchestra Platform ecosystem. It only makes sense when orchestra/platform is installed and the /admin surface is reachable. Generating extensions on a vanilla Laravel app produces files that reference an extension manager, ACL, and menu registrations that simply aren't there — so validate the platform before touching Studio.
# 1. Dev-only install — Studio never ships to production
composer require --dev orchestra/studio:3.2.3
# 2. Discover what this build actually exposes (docs are sparse; artisan is the source of truth)
php artisan list | grep -i studio
# 3. Publish config and stubs before generating anything
php artisan vendor:publish --provider="Orchestra\Studio\StudioServiceProvider"
Read the stubs before you generate. Whatever lands in config/studio.php / resources/studio/stubs is the real contract: it encodes namespace casing, declare(strict_types=1) presence, base controller choice, route registration style, and default mass-assignment settings. Ten minutes of stub reading saves a week of rewriting generated modules.
First use case: one throwaway extension, end to end. Don't feature-build on day one — prove the round-trip works on your version matrix.
php artisan orchestra:studio # scaffold a disposable extension
composer dump-autoload # the step everyone forgets
# Activate through Orchestra's extension manager (admin UI or artisan)
# Then confirm its menu entry renders at /admin
If the extension shows up in the admin navigation, you're in business. If the menu is empty or the page 500s, you've hit the classic failure mode early — see Gotchas.
Treat every generator run as a proposed patch, never a save.
git checkout -b scaffold/orders-extension
php artisan orchestra:studio # generate
composer dump-autoload
git add -A && git diff --cached # read it like a PR from a stranger
git commit -m "scaffold: generated orders extension (generator output, unedited)"
The "unedited" marker in the commit message matters — six months later, git log --grep="generator output" tells you exactly which files are generator-owned and which are yours.
A broken step 1 silently poisons steps 2–5. Generate in dependency order, review at each step:
orchestra.json$fillable, $casts, relationshipsIf output is 80% right and you hand-fix the same three things every time, fix the stub instead of your muscle memory.
// config/studio.php (published)
'stubs' => resource_path('studio/stubs'),
Override only the templates you care about — strict types, your base controller, a FormRequest stub replacing inline validation, standard PSR-4 casing. Overlays compound: every future generation inherits the fix.
One documented path beats memorized flags:
# scripts/scaffold.sh
set -e
NAME="$1"
php artisan orchestra:studio # generate the slice
composer dump-autoload
php artisan migrate --pretend # show the SQL, don't run it blind
echo "→ Review the diff, then activate via the extension manager."
Generated CRUD is scaffolding, not a feature. Before opening the PR:
$guarded = [] with an explicit $fillable.index, store, show) plus a factory. Generated code has zero coverage by default.You can't regenerate over edited files without losing work. Instead, from a clean checkout on a scratch branch, regenerate and diff against committed output. That measures template drift after a Laravel or Orchestra upgrade without touching real code.
Plain php artisan make:model -mcr + your stub overlays + manual extension registration. Document it before you need it — with zero stars and zero dependents, no upstream party is obligated to keep Studio working across upgrades.
An empty admin menu almost never means Studio is broken. It means the extension isn't activated in Orchestra's extension manager, or orchestra.json was generated with invalid metadata. Dropping files on disk does nothing on its own — verify the extension is listed, active, and that its provider registers.
Class not found immediately after generation is autoload. Run composer dump-autoload. If it persists, composer dump-autoload -o, then check the PSR-4 root in composer.json actually covers the generated path.
Namespace casing is a live hazard on 3.x. The v3.2.3 changelog is literally "Use Laravel standard on opening tag/namespace" — meaning earlier stubs emitted non-standard casing. Files generated before that release can disagree with new output, and on case-sensitive filesystems (Linux CI, Docker) that's an autoload failure that never reproduces on macOS. Grep for mixed app\ / App\ and inconsistent <?php before blaming Composer.
Regeneration overwrites. It is not idempotent. Never run it over a module you've already edited. Keep a GENERATED.md in each module listing which files were generator output and which were hand-written — that list is your safety net.
Pin exactly and keep a compatibility matrix. orchestra/studio → orchestra/platform → Laravel. One incompatible transitive constraint blocks the whole toolchain with a confusing Composer resolution error. Pin all three, write them down, and before any Laravel upgrade run a generator regression: scaffold the reference throwaway extension on a branch, diff against known-good output, run its tests.
Publish the config and commit it. A published config/studio.php silently diverges from package defaults after every update. Committing it puts that drift in code review.
Review generated code for secure defaults as if a contractor wrote it — because the stub author effectively did. Look specifically at mass assignment, missing authorization checks, unvalidated request input passed straight to create(), and hardcoded route prefixes that bypass middleware.
Debugging techniques that actually work here:
resources/studio/stubs so they're version-controlled and greppable.-v and read the emitted file list — the output paths reveal its conventions fastest.git stash before any speculative generation run, so cleanup is one command.Scope check, quarterly. Studio buys velocity on repetitive extension and CRUD boilerplate. It does nothing for domain modeling, API design, or product architecture. If you're hand-rewriting more than half of what it emits, the generator has stopped paying rent — fork the stubs, swap to artisan make:* plus your overlays, or move to a maintained alternative such as Filament or Nova.
How can I help you explore Laravel packages today?