totalcms/cms
TotalCMS is a Laravel CMS package for adding content management to your application, helping you manage pages and site content within a familiar Laravel workflow. Use it to build customizable, database-backed CMS features.
Architecture fit
Total CMS (tcms) is a Laravel package that layers collections, schemas, auth, feeds, mailer and Site Builder onto a host app, exposing both an admin UI and REST/MCP surfaces. As a TPM I read this release as one that mostly hardens boundaries rather than reshaping the package's architecture — the collection schema stays the unit of configuration, but several things that were previously URL-driven (RSS field mapping, feed filters, per-request draft inclusion) move into persisted schema settings. That is the right direction for a package whose integration contract is "schema is the source of truth," and it makes feed behaviour reviewable in code review rather than hidden in query strings.
Integration feasibility
Two additions are directly useful to a Laravel delivery team. tcms check with --json and exit code 1 is a deploy-gate primitive — it can slot into CI or a release step without scraping HTML, though the notes are explicit that CLI extension/cache checks can differ from the web SAPI, so it should complement, not replace, a post-deploy smoke request as the app server. The markdown/styledmarkdown field pair stores the same string, so schema switching is non-destructive and content migration between the two is a config change rather than a data migration. showRememberMe: false is a trivial but frequently requested compliance control.
Technical risk
This release is high-risk to upgrade despite being a patch version, because three changes are behavioural breaking changes:
/feed/rss/{collection} returns 404 until someone ticks the box. Any site syndicating a non-blog collection loses its feed silently — 404, not an error page, so monitoring may not catch it. Field mapping in URLs is now ignored, so feeds that relied on ?title=…&content=… will render with defaults until the collection's RSS card is filled in.update_object now merges instead of replaces. The merge change is correct (agents never see passwords or binaries), but any agent or script relying on replace semantics will need retesting.Secondary risks: exact-match email lookup means accounts stored with non-normalised addresses may stop resolving at login and password reset (this is a real fix — partial matching was an account-takeover vector — but it needs a data audit before rollout); login errors are now uniform, which is right for security and worse for helpdesk triage; new access groups start with no permissions, so onboarding flows change for admins.
Key questions
/feed/rss/* consumer, and which collections must be re-enabled on upgrade?update_object replace semantics?allowHTML: false now default)?tcms check's extension list authoritative for our container?Stack fit
The package stays a conventional Composer dependency with artisan commands, migrations and an admin surface, so it fits a standard Laravel app without a new runtime. The one architectural expectation it imposes is that the deploy pipeline can run a PHP CLI process with the same extensions as the web tier — otherwise tcms check passes or fails for the wrong reason.
Migration path
Sequence the upgrade as a security remediation, not a feature upgrade:
tcms check --json --config on a staging clone first and diff the config output (secrets redacted) against production expectation.Compatibility
markdown and styledmarkdown are additive and interoperable. The htmlclean: true opt-in on those fields means existing behaviour is unchanged unless configured. cms.adminAssetsHead() now emits Sentry with allowUrls scoped to Total CMS assets, so custom admin pages get error reporting without leaking host-app errors — a safe change, but one that changes what appears in Sentry dashboards.
Sequencing
Do the upgrade in a single window: migrations plus feed re-enablement plus key issuance together, because a partial application leaves a site with 404 feeds and 403 front ends. Treat the markdown fields, showRememberMe, Send History and tcms check CI wiring as a follow-on release — they need no migration and add no risk.
Maintenance
Steady state gets easier: RSS config lives on the collection, so feed behaviour is versioned with schema rather than scattered in templates and URLs. Send History finally gives operational visibility into bulk sends (sent/failed/skipped/pending, test sends flagged), which removes a class of "did the mailout go out?" tickets. Budget maintenance for the migration's after-effects: hidden collections whose Read was cleared cannot be un-ticked in the admin, which is intentional but will confuse whoever next edits them.
Support
Expect a short spike of three ticket types: broken RSS, login failures from non-normalised emails, and agents/integrations that lost write fidelity. The uniform "Invalid login credentials" message reduces information leakage but lengthens diagnosis — support can no longer distinguish unknown account from bad password in the UI, so they need log-level access. Access group defaults changing means admins creating groups must grant permissions explicitly; script the common groups.
Scaling
No scaling-relevant changes. tcms check in CI is cheap; running it against every deploy target is worth the seconds. Feed generation still happens per request, so high-traffic syndication should go through a cache in front of /feed/rss/{collection} — the clean URL makes that routing simpler than the old parameterised form.
Failure modes
update_object now merge, so a partial-object call that previously cleared fields will leave stale values instead — the inverse bug, and quieter.allowHTML: true is set.Ramp-up
Small. The new fields are self-describing and documented; tcms check, Send History and showRememberMe need no training. The real ramp-up is on the security model: the team must internalise that Public Read, feed publication and password exposure are all now explicit, per-schema decisions, and that a collection's settings — not the URL — determine what the outside world can see.
How can I help you explore Laravel packages today?