Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Canvas Laravel Package

orchestra/canvas

Canvas brings Laravel's make artisan code generators to applications and packages, including package development outside a full Laravel install. Customize stub classes and namespaces while scaffolding controllers, models, commands, migrations, and more.

View on GitHub
Deep Wiki
Context7

Getting Started

Canvas is a dev-only Composer package that reimplements every make:* Artisan generator, plus ships a vendor/bin/canvas binary so the same commands work outside a full Laravel app (i.e. when authoring a package).

composer require --dev orchestra/canvas

Then pick a preset and emit canvas.yaml at the repo root:

# Inside a Laravel app
vendor/bin/canvas preset laravel

# Inside a package / skeleton — must pass or edit a namespace
vendor/bin/canvas preset package --namespace="Foo\Bar"

The first command to try is the one you already know:

vendor/bin/canvas make:migration CreatePostsTable --create
vendor/bin/canvas make:controller PostController --resource

Where to look first:

  1. canvas.yaml — this is the whole contract. Paths, namespaces, migration prefix, factory location, testing namespace, and user-auth-provider all resolve from here.
  2. vendor/orchestra/canvas/stubs/ — the actual templates used for generation. Anything you don't like, override rather than patch.
  3. preset output — the generated YAML literally tells you every knob it resolved, so it doubles as documentation.

First real use case: you're writing a reusable Laravel package (e.g. Foo\Bar) with src/, migrations, and a service provider, but no host app to run artisan against. vendor/bin/canvas make:provider BarServiceProvider scaffolds with Foo\Bar\BarServiceProvider and drops it in src/ — not app/Providers/.

Implementation Patterns

1. Package-authoring mode. This is the differentiating workflow. Generate a package preset, commit canvas.yaml, then scaffold the package skeleton:

vendor/bin/canvas make:provider BarServiceProvider   # Foo\Bar\BarServiceProvider → src/
vendor/bin/canvas make:model Post                    # Foo\Bar\Post
vendor/bin/canvas make:command SyncPosts             # Foo\Bar\Console\SyncPosts
vendor/bin/canvas make:migration CreatePostsTable    # database/migrations/, no prefix
vendor/bin/canvas make:test PostTest                 # Foo\Bar\Tests\PostTest

Because namespaces are resolved from the preset rather than from app/, generated files are immediately autoload-correct — no manual namespace edits after each scaffold.

2. App mode where you like Laravel's defaults. Run vendor/bin/canvas preset laravel and you get namespace: App / model.namespace: App. Once the service provider is discovered, plain php artisan make:* produces Canvas-shaped output too. The vendor/bin/canvas prefix becomes optional but is useful in composer scripts and CI where you want to be explicit about which generator ran.

3. Composer scripts for repeatable scaffolding. Wire generation into composer.json so it's versioned and consistent:

"scripts": {
  "make:model": "canvas make:model",
  "make:controller": "canvas make:controller"
}

composer exec canvas make:model Foo also works and is friendlier in monorepos where vendor/bin isn't on PATH.

4. Custom stubs when house style diverges. Copy the stub you want to change into a project directory (e.g. stubs/), edit it, and point Canvas at it. This is the correct extension point — do not fork the package. It's also the cheapest way to keep upstream stub drift from leaking into your generated code.

5. Extra generators beyond Laravel's baseline. Canvas ships things make doesn't:

  • make:class, make:enum, make:interface (since v9.0.0)
  • make:job-middleware (since v9.1.3)
  • make:user-model — Sanctum-aware
  • make:diagnostic — for laravel/doctor (v11.1.0+)

These are the ones to reach for when a junior dev is about to touch src/Foo.php by hand.

6. Pair with Testbench. Canvas lives in the same Orchestra lineage as orchestra/testbench. If you're already testing packages with Testbench, Canvas is the natural scaffolding counterpart — Testbench runs the package, Canvas produces it.

Gotchas and Tips

Package discovery silently overrides artisan make:*. Once installed in a Laravel app, Orchestra\Canvas\LaravelServiceProvider is auto-discovered and replaces the framework's generators. That makes adoption repo-wide, not per-developer. If you only wanted Canvas for one package boundary, audit this before adding it to every project — every tutorial command, CI script, and muscle-memory make:* now yields Canvas output.

Version-lock is Laravel-major-coupled. v9 → Laravel 11, v10 → Laravel 12, v11 → Laravel 13. A framework major bump is now a coordinated change: bump Laravel, bump Canvas, and re-validate every custom stub (Canvas chases upstream stub changes — see 10.2.1/11.0.1 fixes to factory.stub and user-factory.stub). Budget for it before you pin.

Stub-contract drift is real but visible. Canvas re-implements generators, so it must track upstream changes (e.g. make:mail from Laravel 11.20, MigrationGeneratorCommand from 10.26, make:migration hidden from CLI until 8.11.8/9.0.1). If you're on an old pin and a command "doesn't work", check whether the fix landed in a release you skipped before assuming a bug.

preset package writes PackageName literally. Either edit the emitted YAML by hand or pass --namespace="Foo\Bar" at preset time. Forgetting this means every generated class has the wrong root namespace and your autoloader will silently miss them.

canvas.yaml must be committed. Without it, commands fall back to Laravel defaults and you lose the entire package-scoped path/namespace resolution — the generated files land in app/ even inside a package repo.

user-auth-provider only matters for make:user-model. It's set to App\User by default in both presets; if your package ships its own user model or you replaced Sanctum, change it explicitly. make:user-model behavior varies with/without laravel/sanctum installed — pin the environment if output must be deterministic.

Prefer custom stubs over config hacks. Most "Canvas did the wrong thing" complaints are better solved by overriding the stub once than by post-processing the output with sed.

Diagnosing mismatched output. If php artisan make:model and vendor/bin/canvas make:model disagree, that's almost always a version/coupling issue, not a bug — the artisan path goes through the discovered service provider while the binary may resolve differently (a fix specifically landed in 9.0.2 for exactly this). Confirm the provider is loaded (php artisan about) and that you're not mixing an old canvas binary with a new canvas.yaml schema.

Trivial exit plan. composer remove --dev orchestra/canvas && rm canvas.yaml restores Laravel's default generators. That's the reason this package is low-risk to trial even in a conservative shop — it's the same governance bucket as Pint or PHPStan, not a runtime dependency.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo