cnvs/canvas
Canvas is a lightweight Laravel publishing platform for creating and managing a beautiful blog with ease. It offers a clean admin interface, Markdown writing, tags, customizable templates, and SEO-friendly pages, all seamlessly integrated into your Laravel application.
Architecture fit. Canvas is a package, not an app — that is the single most scoping-relevant fact. It ships a PHP API surface (Canvas\, PSR-4), package routes, published config, migrations, and a prebuilt React admin SPA served out of public/vendor/canvas. The host Laravel app remains the runtime: auth guard, queues, storage disks, database, and cache all stay with the host. For a TPM this means Canvas slots in as a bounded publishing/admin subsystem rather than a platform decision — no new service to operate, no data plane to migrate onto. It depends on illuminate/* contracts only, deliberately not laravel/framework, which keeps the blast radius small during host framework upgrades. That is the correct seam and it lowers the "does this constrain our framework roadmap" risk materially.
Integration feasibility. Install is a Composer require plus a short publish sequence (config, migrations, assets). No sidecar container, no Node toolchain required on the host — a real operational win for teams without a frontend build pipeline. Feasibility hinges on three things to verify early: (1) whether Canvas' auth/roles model composes with the host's identity model or expects a specific user shape; (2) whether its migrations introduce tables, FKs, or routes that collide with existing host conventions; (3) whether the SPA's API assumes a route prefix or middleware group the host may already occupy.
Technical risk. Five clusters:
resources/dist/ is checked in and served directly. Good for deploy simplicity, weak for supply-chain review: hosts serve whatever the maintainer compiled, with no host-side rebuild step. SPA security patching flows only through package releases.composer update → php artisan canvas:migrate → php artisan canvas:publish, which does not match the php artisan migrate / canvas:ui sequence assumed in earlier planning. Low severity, but a runbook that names the wrong command is precisely the self-inflicted failure mode described below — reconcile against the package's actual command list before writing the checklist.Key questions. (a) What are the actual production dependents, and can we name two reference deployments? (b) Is Canvas intended to replace existing CMS content or run alongside it — and does it assume a single-tenant user table? (c) Which Laravel auth guard does it bind to, and can it be scoped to a separate guard or middleware group? (d) What is the release cadence and the length of the supported major window — and does the observed patch velocity (7.2.2 → 7.2.3 inside the current minor) reflect a stable line or a hotfix-heavy one? (e) How are uploads (featured images, Unsplash imports) persisted — host disk, S3, its own storage? (f) Does the AI-writing integration call out to a third-party LLM using host-provided keys, and what content leaves the host? (g) Is the reported last-release date (2026-10-10) accurate, or is the metadata malformed? (h) Do canvas:migrate and canvas:publish wrap the standard migrate / asset-publish / config-publish steps, or do they diverge from them?
Stack fit. Canvas lands inside a Laravel 12/13 app: Composer for distribution, the host's default guard for auth, host filesystem disks for media, host queues for webhooks and the weekly digest. Teams on a standard Laravel deploy (Forge/Vapor/Envoy/Docker) will find no new infrastructure to stand up. The prebuilt SPA removes the need for Node 22 in CI just to serve the admin UI — but teams that do want to customize the SPA forfeit that convenience and effectively fork the package.
Migration path. Treat this as a greenfield subsystem, not a data migration, unless a legacy CMS is being retired. Phased sequence: install package → publish config and migrations → review the migration diff against the host schema (table names, FK targets, index collisions) → run in a staging clone first → publish/refresh the SPA assets → assign Canvas roles (Contributor / Editor / Admin) to existing users via HasCanvasAccess or the Role enum → configure webhooks and external integrations → only then expose the admin SPA to real editors. Content import from an existing CMS (WordPress, Ghost, custom) is not a first-class feature and should be planned as a scripted ETL you own.
Compatibility. Two surfaces to lock down before commitment: the framework/PHP matrix (12|13, 8.3+) and the auth/role composition. The former is explicit and enforced; the latter is implicit and needs a spike. Also verify that public/vendor/canvas does not conflict with other vendor-published assets and that HTTP cache headers are set correctly, or users will hit a stale SPA talking to a newer API after every upgrade. v7.2.3 introduces no schema, route, config, or API changes that we can see from the notes — it is a slug-generation fix — so it is safe to absorb during a normal patch window and does not reset any of the above verification work.
Sequencing. Run the whole thing behind a feature flag or non-production route prefix first. Concretely: (1) spike in an isolated branch against a copy of the host DB; (2) verify auth and role mapping end-to-end; (3) confirm migrations are reversible; (4) confirm asset publishing is reproducible in CI; (5) pilot with one editorial team; (6) write and enforce the deploy checklist (composer update → canvas:migrate → canvas:publish → cache clear → CDN purge, per the vendor's documented upgrade block) before broad rollout. Treat the vendor's upgrade block as the source of truth and treat any deviation in our runbook as a defect in the runbook, not in the package.
Maintenance. The host owns DB, queues, storage, logs, and backups, so maintenance reduces to "composer update, re-publish assets, re-run migrations" — which is easy to under-scope. Two recurring obligations: (i) read .github/UPGRADE.md on every minor/major bump, because host-visible contracts (routes, middleware, config keys, webhook payloads, asset stubs, access/roles) are tracked there; (ii) keep the deploy checklist honest — forgetting the asset-publish step after a package update is the most likely self-inflicted outage. Budget ongoing effort to stay on a supported Laravel major, since the package tracks the newest two.
Support. Community-only. That is acceptable for internal editorial tooling where the team can absorb a bug for a week; it is not acceptable if publishing is revenue-critical and needs a response SLA. The low opportunity score (1.55) reinforces this: there is no commercial support tier or plugin marketplace to lean on, so escalation is a local fork or a pinned, tested patch version. Mitigations: pin versions, keep a path-repo fork for emergency fixes, and record the maintainer's responsiveness before committing. Engineering hygiene signals are strong — Pest + Orchestra Testbench, Larastan level 6, a 98% coverage floor, Pint, Playwright e2e, 17-locale i18n with enforced key parity — which lowers defect risk but does not substitute for a support contract. The v7.2.3 fix is a good illustration of the expected cadence: small, single-issue, clearly scoped, safe to take on a routine update.
Scaling. Canvas inherits the host's scaling story almost entirely: the PHP API scales with the app tier, the SPA is static and edge-cacheable, DB load is bounded by the added tables and pagination on list endpoints. Webhook fan-out and the weekly digest are the two components that must run on the queue, not synchronously — verify before enabling in production. The realistic bottleneck is editorial query performance at large content volume, not the SPA. One new scaling-adjacent consideration from v7.2.3: slug uniqueness is now derived from titles, so at high content volume expect more slug-collision suffixing and slightly more write-path contention on the posts table under concurrent publishing. Low risk, worth a load check if the editorial team publishes in bursts.
Failure modes. Watch for: (1) stale SPA after a package upgrade without re-publishing assets; (2) migration collisions (or non-reversible migrations) blocking rollback; (3) auth/role drift when the host changes its user model or guard — Canvas roles could silently fail open or closed depending on the HasCanvasAccess seam; (4) webhook delivery failures without a dead-letter queue, creating silent downstream content-sync gaps; (5) AI-writing and Unsplash integrations leaking credentials or host content to third parties if keys are misconfigured; (6) CDN caching a pre-upgrade asset manifest and serving a mixed-version admin; (7) slug instability — v7.2.3 fixes new-post slugs to follow the title rather than the post-{uuid} placeholder, which is the desirable behavior, but it means titles that are edited post-publish can now change public URLs. Confirm whether slug regeneration is opt-in per post, and if not, require an editorial rule (freeze the slug on publish) or a redirect layer at the web server/CDN. Each failure mode has a cheap mitigation, but all require a written runbook.
Ramp-up. The host-facing docs/ set (install, config, auth, UI, content, webhooks) plus UPGRADE.md is the right shape for a package — scannable, code-first, versioned with releases. The gap is a reference integration: there is no full example host app, so the first team's spike is the reference. Expect roughly one engineer-week to a working pilot in a standard Laravel 12 app, plus another week for auth/role mapping and deploy-checklist hardening. Editors need almost no training — the SPA is the product — but they do need one behavioral instruction: understand when a slug freezes, since that is now the difference between a stable public URL and a 404. Admins need to understand roles, webhooks, and the publish-state model, which is where onboarding effort should concentrate.
How can I help you explore Laravel packages today?