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

Mod Laravel Package

tey/mod

A lightweight Laravel/PHP package for building modular applications: organize code into self-contained modules, register providers, and keep large projects maintainable with a simple, configurable structure. Ideal for teams splitting features into reusable components.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. tey/mod remains a developer-time placement and generation toolkit, not a runtime library. It hooks into Artisan generators so that mod:model, mod:controller, mod:dto and ~30 sibling commands write to wherever the configured layout says, instead of Laravel's fixed app/ conventions. The architecture is deliberately thin: layouts are declarative (config/mod.php plus Mod::layout(...) calls in a service provider), file types are registered with ->generates(), group folders with ->path(), nesting with ->allowsNesting(). There is no opinionated scaffold shipped and no business-logic pattern imposed — it reuses Laravel's own stubs and conventions. For a TPM the framing is unchanged: the package is an architecture codifier, and its value is that "where does this class go" stops being a code-review argument and becomes configuration plus a generator default. v0.7.2 does not alter that architecture — it strengthens the preview surface, which is the part of the design we were already leaning on.

Integration feasibility. High, with a caveat, and v0.7.2 materially improves the middle of that story. The default layout is still laravel — identical output to make:* — so the zero-risk adoption wedge holds: require-dev, change nothing, run mod:list --json and commit a baseline. The release's headline addition is that scaffold dry runs now report existing whole-file members as unchanged or edited by byte-comparing against what the current recipe would write, exposed as an optional state field in JSON and as a label in human output. That converts the dry-run from "where would files go" into "what would actually change," which is the difference between a soft guardrail and a CI-enforceable one. The remaining caveat is unchanged: any layout with roots outside app/ (ddd maps Domain\ to src/Domain/) requires php artisan mod:autoload, which mutates composer.json and shells out to Composer. That is still the only place this package writes outside generated source files, and still needs a deliberate, reviewed pipeline step.

Technical risk. The dominant risk is still maturity, not design: 0.x versioning, a single maintainer (Jasper Tey / Teylabs), and a first-release-date metadata field of 2026-10-13 that should be verified against Packagist before it appears in a dependency audit. The engineering signals remain strong — ~2,000 Pest tests, PHPStan across src and tests, Pint, a Linux+Windows CI matrix on PHP 8.3–8.5 and Laravel 12–13, plus a published-API snapshot and audits that contributors are told never to weaken. v0.7.2 is a good signal on cadence and on responsiveness to correctness bugs: #164 fixes tree scaffolds ignoring --force/--skip-existing and mispredicting existing-file outcomes between human and JSON dry runs, and #165 fixes parts/inserts losing a root migration's resolved identity and timestamp. Both were latent correctness traps in exactly the workflow we intended to gate on.

Two new risks introduced or made visible by this release. First, a behavioural change in patch scope: dry runs no longer repeat placeholder warnings for class members because each member is now rendered by its own generator. Anything parsing human-readable dry-run output will see different text on a 0.7.1 → 0.7.2 bump; parse --json only. Second, the changelog shows two new automated-review workflows merged (#161 comment-triggered OpenCode review, #163 review via the free LongCat model). That is an upstream supply-chain question for us, not a defect: an org evaluating this package should know whether PR diffs transit a third-party free model endpoint and whether that is acceptable under its own procurement and IP rules. It does not affect our runtime — the package is a dev dependency with no runtime surface — but it belongs in the vendor questionnaire.

Key questions.

  • Who is the second maintainer, and what is the stated release cadence and Laravel-major support policy (does a Laravel 14 ship day-one, or is there a lag)?
  • Is the published-API snapshot (tests/Fixtures/published-api.json) intended as a semver contract we can rely on for custom layouts — and does it cover the new state field in scaffold dry-run JSON?
  • What is the boundary between @api and @internal, and will our custom layouts only ever touch @api?
  • Does mod:autoload handle a composer.json that already contains hand-written PSR-4 mappings, or do conflicts have to be resolved manually every time?
  • How does the package behave alongside an existing modules package or a pre-existing src/Domain tree?
  • Given 0.x versioning, what is the upstream policy on behavioural changes in patch releases (the placeholder-warning change in this release is the precedent)?
  • Do the OpenCode and LongCat review workflows transmit full diffs to third-party endpoints, and what is the retention policy?

Integration Approach

Stack fit. Laravel 12/13 on PHP 8.3–8.5, any frontend — the docs explicitly say to inspect page_name and frontend paths in mod:list --json rather than assume an Inertia stack, and ->frontend(pages:, components:, css:, views:) is opt-in. The agent-facing surface (AGENTS.md, skills/mod-development/SKILL.md, resources/boost/) remains the differentiator and is now sharper: agents get a deterministic contract — run mod:list --json, preview with --dry-run --json, read warnings, would_write and the new state, then generate. The unchanged/edited distinction is directly useful for agent loops, because it lets an agent distinguish "this scaffold is already correct" from "this scaffold exists but diverges" without re-reading files.

Migration path. Four gated phases, unchanged in shape:

  1. Observe — require-dev tey/mod, keep the laravel layout, generate nothing. Run mod:list --json and commit the output as the baseline inventory.
  2. Pilot — pick one bounded, low-coupling domain and adopt the modules or features layout for it only. Measure review friction and agent retry rate on that domain, and now also measure scaffold re-run noise (state: unchanged rate) as a signal that the recipe is stable.
  3. Decide — adopt ddd only if there is genuine domain complexity demanding it; ddd is the highest-cost layout (roots outside app/, controllers/requests living separately from domain code, mod:autoload required). Do not adopt it "for symmetry".
  4. Extend — if built-ins don't fit, Mod::layout('areas')->extends('modules') with ->path('src/Areas/{area}') and ->generates(...) is the escape hatch. extends() must come first and copies the parent at that moment, so pin it and review it like any architecture decision.

Compatibility. Coexists with native make:* — conflicts are generation-time only, and the package refuses --path/--realpath on mod:migration, a deliberate guardrail. The shared mutable state is the Composer PSR-4 map; gate it. Pin at 0.7.2 or tighter for the pilot: 0.x patches have shipped behavioural changes, and the fixes in this release are only valuable if the whole team and all agents run the same build.

Sequencing and gates. Per PR: composer test, composer analyse, composer lint. In our CI, additionally: mod:autoload --dry-run (fails if composer.json would change), and mod:list --json diffed against the committed baseline (fails on unintended layout drift). Add composer format, and set MOD_FRONTEND_BUILD=1 only if we adopt frontend paths. Agents must be instructed to use --dry-run --json before every real generation and to treat would_write: false as a blocker, not a warning. With v0.7.2, extend the scaffold gate: capture state in the JSON and fail if a re-run of an existing scaffold reports edited where unchanged was expected — that is now a cheap, deterministic drift detector for generated code. Do not parse human dry-run text in CI; this release changed it.

Operational Impact

Maintenance. Low and reversible. No runtime footprint, no migrations, no cache driver, no queue worker change. The maintenance burden shifts from code to config: config/mod.php and the service-provider layout declarations become load-bearing architecture and should carry CODEOWNERS. Upgrades are a composer update on a dev dependency — but validate against the published-API snapshot, re-run the inventory diff, and re-check the changelog for behavioural changes (as in this release) before bumping across even a patch boundary.

Support. No vendor SLA, one maintainer, draft-PR-only contribution model where maintainers do all merging, tagging and releasing. This release shows the model producing regular, scoped fixes — a positive signal — but throughput still depends on one person, so expect upstream fixes to be slow and plan to vendor a fork or pin a commit if a blocker lands. Posture: treat the version constraint as exact-ish, watch the releases feed, and keep a documented "remove this package" runbook.

Scaling. The package scales with team and agent count, which is the argument for it: placement stops being tribal knowledge. The only scaling cost remains discovery cache (mod:cache / mod:clear) — build-time, not request-time — plus case-sensitivity behaviour across macOS, Windows and Linux, which the CI matrix suggests is taken seriously but which we should still spot-check on a mixed-OS team. The new state reporting scales well in agent-heavy workflows because it lets automated re-runs converge on unchanged rather than blindly rewriting.

Failure modes to instrument.

Failure Signal Mitigation
Files written into a non-autoloaded root Generation warns but still writes Fail CI on class not found; make mod:autoload mandatory post-layout-change
composer.json mapping conflict mod:autoload refuses --dry-run gate in CI; resolve mappings by hand
Agent uses make:* instead of mod:* Files land in app/ Instruct via AGENTS.md/skill; code-review checklist; inventory diff
Custom layout drift after upgrade extends() re-copies parent semantics Pin version; re-run mod:list --json diff; snapshot tests
Scaffold silently diverges on re-run state: edited where unchanged expected (v0.7.2+) CI gate on state; review edited diffs like hand-written code
Placeholder-warning behaviour change breaks tooling Parsed dry-run text changes between patches Parse --json only; never scrape human output in CI
Stale dry-run plan --json plan written against older HEAD Re-run preview immediately before the real command
Migration identity/timestamp mismatch across scaffold parts Duplicate or misnamed migrations Resolved in v0.7.2 (#165); pin ≥ 0.7.2 before adopting tree scaffolds with migrations
Case-only folder collision (API Resources vs resources/) Compilation check Move frontend paths under ui/ as documented
Maintainer abandonment No releases against new Laravel majors Dev-only dependency; fork-and-patch runbook owned by platform team
Upstream review workflows leak diffs Vendor questionnaire gap Confirm OpenCode/LongCat data handling; do not enable comment-triggered review on our mirrors

Ramp-up. Low and slightly improved. A developer who knows make:* needs roughly a half-day to be productive, and the real training artefact is not the tool but the layout decision, written down once and derived from mod:list --json. The dry-run state labels make the re-run story easier to teach: "preview, read state, then write." For agents, onboarding is a single skill file plus a rule: inventory, preview, then write. Budget one engineer-week end-to-end for install, pilot domain, CI gates and the written "where files go" standard — and treat the pilot's exit criteria as measured review friction and agent misplacement rate on one domain, plus a stable unchanged rate on scaffold re-runs, rather than "package installed."

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource