folklore/laravel-folklore
A Laravel package from folklore that integrates with your app via Composer. It follows standard Laravel package conventions for configuration and setup; see the repository README for installation steps and usage details.
Architecture fit
Assessment reflects v1.1.7. No architectural change in this release; the structural findings below stand.
folklore/laravel-folklore is not a general-purpose library — it is the shared application foundation for sites built by one agency. It bundles four things that would normally be separate decisions:
| Layer | Contents | Coupling cost |
|---|---|---|
| Domain core | Contracts, Entities, Repositories, JsonDataCast |
High — dictates how every model, query and JSON column is written |
| Feature modules | Pages/blocks, medias (via folklore/laravel-mediatheque), users + custom repository auth provider |
High — touches routing, storage and authentication |
| Third-party glue | Customer.io, Google Maps/Places/Drive, PubNub broadcaster, PubSubHubbub | Medium — but is where most supply-chain and PII risk sits |
| Developer tooling | make:* generators, view composers, Panneau fields/resources |
Medium — bakes vendor conventions into scaffolding |
The design intent stated in AGENTS.md ("a module a site doesn't use must cost it nothing: no side effects at boot, no heavy mandatory dependency") is the right principle and is still the single most important thing to verify. If it holds, the package is a buffet. If it does not, adopting any one module means inheriting Google, PubNub and Customer.io SDKs. Note the v1.1.7 notes reinforce the modular intent — Google Places and request-helper fixes are scoped to the modules that use them — but they are not evidence that unused modules are free at boot.
Architecturally, the fit is good only for a Laravel app that intends to be a Folklore-shaped app: entity/repository pattern, pages and blocks, mediatheque-backed media. For any other codebase this is an opinionated framework layered on a framework.
Integration feasibility
Feasible, with conditions. v1.1.7 improves two of them:
AGENTS.md specifies PHP ^8.3 and Laravel 11–13. Treat the description as stale metadata and read composer.json as the source of truth. Any estate on Laravel 10 or PHP 8.2 must upgrade first — that is a prerequisite project, not a line item.^7.15.2|^8.0.1, closing the highest-probability install blocker for a Laravel 13 estate. The constraint is now asymmetric by design: Laravel 11 and 12 sites stay on Guzzle 7, Laravel 13 sites can move to Guzzle 8. This is a sensible resolution of the framework's own version gate rather than a free choice for us — we cannot "pick" Guzzle 8 on Laravel 12.7.15.2 / 8.0.1) are pinned deliberately to include the fix for GHSA-v5mv-p594-2x33, which the media download host checks depend on. That is good supply-chain hygiene and worth crediting, but it converts a routine patch bump into a mandatory upgrade for any site locked below those versions. Our dependency floor must be checked against it in Phase 0.folklore/laravel-mediatheque. That doubles the review surface (storage drivers, image handling, upload validation) and the upgrade surface. Its Guzzle constraint must be verified alongside this one.repository provider is a security-sensitive change touching login, password reset, remember-me and session invalidation. This needs its own threat model and regression suite, not a code review.Technical risk
JsonDataCast, generators and view composers are load-bearing conventions. Exit cost is a re-implementation project across the whole app, not a dependency swap.MakesRequests because Guzzle 8 only exposes a response on some exceptions. Expect this fork to be a recurring source of conditional logic, and expect Guzzle 7 to be dropped on the maintainers' schedule, not ours.MakesRequests no longer fails on Guzzle request exceptions, and on Laravel 11 requestJson()/requestData() now return a Laravel response where callers may previously have caught a PSR-7 object. The release says Guzzle 7 sites "see no change", but this is exactly the class of change that alters caller-side error handling without a version-major signal. Anyone already on the package should test the exception path, not just the happy path.phpstan-baseline.neon ships known Larastan errors; the "never add new errors" rule is good governance but the baseline is real debt on day one.require, suggest, or require-dev determines whether "unused" modules are actually free. v1.1.7 does not change this and the notes do not clarify it.src/migrations means schema changes arrive from a dependency. Ordering, rollback and prod-migration review need an explicit process.Verdict: Conditional, marginally improved. Viable as a foundation if we are deliberately building a Folklore-style application and have a contractual relationship with the maintainers. Not viable as a utility dependency pulled into an existing or non-Folklore codebase. The Laravel 13 install blocker is now cleared and dependency-floor discipline is demonstrably in place; nothing about lock-in, bus factor or support has changed.
Key questions
folklore/laravel-mediatheque public, maintained, and on the same Laravel 11–13 and Guzzle 7/8 matrix?suggest/require-dev) genuinely zero-cost at boot, and is there a test proving it?MakesRequests change alter exception handling for callers already on Laravel 11 + Guzzle 7, or only for Guzzle 8? Which response type (PSR-7 vs Laravel) do we get in each combination?repository auth provider been reviewed for password reset, remember-me, session invalidation and rate limiting?UPGRADE.md?lang/vendor publishing)?Stack fit
Greenfield Laravel 11–13 on PHP 8.3+, MySQL 8, using a pages/blocks CMS model and mediatheque-backed media: strong fit, low friction. An existing Laravel app with Eloquent models, query scopes and its own auth: poor fit — the repository/entity layer would be a parallel architecture, not a refactor.
Migration path
Do not retrofit. The realistic paths are:
JsonDataCast, view composers) and drop the rest. Rejects the buffet framing but removes most lock-in. Note this forfeits upstream updates, including advisory-driven security floors like the one in v1.1.7.Compatibility
^8.3, Laravel 11–13. Anything older blocks adoption outright.^7.15.2|^8.0.1, with Guzzle 8 reachable only under Laravel 13. Verify our lock file already meets the 7.15.2 floor or that the upgrade is scheduled; a security-pinned floor is not negotiable. Run composer why-not guzzlehttp/guzzle 7.15.2 across the full intended dependency set, and repeat for 8.0.1 if we are targeting Laravel 13.laravel-panneau is only required when the Panneau module is used; CI runs a dedicated job against it (1.3), which suggests it is a soft dependency — validate.repository auth provider driver name must not collide with app-level equivalents.Sequencing
| Phase | Work | Exit criteria |
|---|---|---|
| 0. Diligence (1–2 wks) | Read composer.json for hard vs optional deps; install into a throwaway Laravel 13 app; run composer test; inventory migrations, translations, config keys, service providers |
Dependency tree contains no unexpected SDKs; providers are conditional; published config/migration list is complete; Guzzle floor satisfied in the target lock file |
| 1. Feasibility spike (2 wks) | Build one vertical slice — a page with blocks and an uploaded media — plus login through the repository provider; exercise a failing external request through MakesRequests |
Slice passes our own tests; auth threat model reviewed and signed off; exception-handling behaviour documented for both Guzzle majors |
| 2. Pilot (1 project, 4–6 wks) | One greenfield site, or one isolated module in an existing app (e.g. JsonDataCast only) |
No production incidents attributable to the package; upgrade to next Laravel patch is routine; Guzzle 7→8 transition rehearsed if on Laravel 13 |
| 3. Standardise | Document conventions, add generators to our templates, decide fork-vs-depend | Runbook, on-call notes, and an owner named in the platform team |
| 4. Expand | Second and third sites | Time-to-first-feature measurably lower than baseline |
Gate between Phase 1 and 2: if the auth provider cannot be adopted with confidence, adopt the domain core only and keep Laravel's native auth.
Maintenance
Ongoing cost is dominated by lock-in, not by patch frequency. v1.1.7 is a low-risk patch with no upgrade steps for Guzzle 7 sites, which is the right shape. Budget for:
composer outdated review — rather than discovering it in a package release note.JsonDataCast) are enforced in review — otherwise the codebase drifts into a hybrid that is worse than either approach.AGENTS.md.Support
There is no community support channel. Zero stars, zero dependents, no public issue corpus. Support is whatever the maintainer relationship provides — get it in writing: response time, security-patch commitment, notice period for breaking changes, and a commitment to ship composer constraints that reflect patched dependency versions. Their own rule ("avoid breaking changes: deprecate before removing") is good intent but unenforceable without a contract or a fork right. v1.1.7 is a reasonable data point on responsiveness; one release is not an SLA.
Secondary support obligations we absorb: folklore/laravel-mediatheque, plus the Google, PubNub and Customer.io SDKs.
Scaling
JsonDataCast encourages schemaless JSON. Convenient early, painful at volume — no indexes, no constraints, migration-by-backfill. Cap its use to genuinely variable attributes.Failure modes
| Failure | Blast radius | Mitigation |
|---|---|---|
| Maintainer stops releasing | Whole app pinned to an ageing Laravel | Fork right in contract; vendor the package internally |
| Laravel major upgrade unsupported | Blocks platform upgrade across all adopting sites | Track their CI matrix as our earliest signal; keep a fork branch current |
| Guzzle floor bump breaks our lock file | Blocks install or forces a wider dependency upgrade mid-sprint | Advisory-driven floor review on a schedule; pin and test before a package release forces it |
| Guzzle 7 support dropped while we are on Laravel 12 | Package upgrade becomes gated on a Laravel major upgrade we have not scheduled | Ask for the Guzzle 7 EOL plan now; keep our position tied to Laravel 11/12 EOL dates, not theirs |
| Request-helper error-handling regression | Silent failures or uncaught exceptions in Google/media calls | Contract tests on the exception path for both Guzzle majors; wrap each integration in an internal adapter |
repository auth provider regression |
Login outage / auth bypass | Own regression suite around the provider; canary deploy; fallback to native provider |
| Package migration conflicts in prod | Failed deploy or partial schema state | Review package migrations like app migrations; test rollback on a prod-like DB |
| Optional module boot side effects | Latency or failures in sites not using the module | Explicit test asserting providers are not registered when the module is disabled |
| Third-party API change (Google/Customer.io/PubNub) | Feature-level outage, possible PII spill | Wrap each in an internal adapter; key rotation and quota alerts |
Ramp-up
Non-trivial and under-documented for humans. AGENTS.md is written for AI coding agents and contributors — it is excellent on workflow, CI and conventions, but it does not teach a new engineer why entities differ from models or how pages and blocks compose. Expect:
How can I help you explore Laravel packages today?