cnvs/easel
Easel is a lightweight Laravel/PHP package that provides a clean, expressive toolkit for common development tasks. It offers simple APIs, sensible defaults, and seamless framework integration to reduce boilerplate and help teams ship features faster.
Easel is a Laravel package from the CNVS org (the team behind the Canvas publishing platform) and is best understood as a scaffolding/UI layer for Canvas-style applications rather than a standalone framework. Treat the package as “glue you compose with,” not something you build on top of in isolation.
Minimal steps:
composer require cnvs/easel and confirm your Laravel major is compatible — check the require block in the package’s composer.json before trusting the README, since CNVS packages track Laravel releases closely.Cnvs\Easel\EaselServiceProvider. Verify with php artisan about or by grepping vendor/cnvs/easel/composer.json for the extra.laravel.providers key.php artisan vendor:publish --provider="Cnvs\Easel\EaselServiceProvider" (list available tags first with --list — CNVS packages typically split config, views, and assets tags).README.md, src/EaselServiceProvider.php (bindings + publish paths), config/easel.php (the knobs you can turn), then src/ alphabetically to see the surface area.First use case: boot an existing Laravel app, publish the config and views, register the package’s route/middleware group (if it ships one) behind auth, and render the default Easel view in a throwaway route. That one loop tells you whether the package is “config-only,” “view-only,” or expects to own a chunk of your admin surface.
Service-provider-first integration. CNVS packages lean on Laravel’s container. Bind the package’s contracts in AppServiceProvider::register() if you need to swap implementations, and reach for config('easel.*') in your own service providers rather than hard-coding values the package already exposes.
View namespace overrides. Most Easel-style packages register a easel:: view namespace. To customize without forking, publish the views and override via View::prependNamespace('easel', resource_path('views/vendor/easel')) in a service provider’s boot(), or override at the Blade component level if the package ships class-based components.
Compose, don’t extend. If the package exposes Blade components (cards, canvases, panels), your application views should wrap them rather than subclass them. Wrapping gives you a stable seam when the package bumps versions.
Pair with cnvs/canvas deliberately. Easel is most useful when a Canvas install already owns content models (posts, users, tags). Read Canvas’s models into your own view-models/controllers and let Easel render the presentation layer; don’t reach across package boundaries into Canvas internals from Blade.
Middleware and route grouping. If Easel ships routes, keep them in their own route file and wrap with your own auth/verified middleware rather than editing the vendor routes. Mirror the pattern you’d use for Horizon or Telescope: isolate, don’t mutate.
Testing. Use RefreshDatabase and the package’s own test helpers if present (grep -r "function assert" vendor/cnvs/easel/src). For UI behavior, assert on rendered view names (e.g., $response->assertViewIs('easel::...')) rather than raw HTML, so package view changes don’t break your suite.
composer.json ("cnvs/easel": "x.y.*") and read the changelog before any composer update.env() call inside the package config file stops resolving after php artisan config:cache. If behavior changes between serve and a cached deploy, this is why — move environment reads into your own config.vendor:publish --list first; guessing the tag silently no-ops and you’ll spend an hour wondering why your view override isn’t taking.Cnvs\. An accidental use Cnvs\Easel\... in a file that wanted a Canvas class is a real risk; rely on the IDE’s fully-qualified hint rather than autocompletion.resources/ in the package before you assume it just emits markup.php artisan route:list --path=easel and php artisan view:cache are your first two commands when “it renders blank.” A missing view namespace produces a silent empty render more often than an exception.How can I help you explore Laravel packages today?