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

Arch Viewer Laravel Package

open-solid/arch-viewer

Open Solid Arch Viewer is a Laravel package that helps you explore your application's architecture. It visualizes classes, dependencies, and relationships in an interactive diagram, making it easier to understand structure, spot coupling, and navigate large codebases.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm you're on the target stack first

Before touching Composer, answer one question: does this codebase actually use OpenSolid conventions? The generator inspects OpenSolid constructs (aggregates, commands, queries, events, handlers) and derives documentation from their shape. If your Laravel app only borrows a trait or two, the output will be thin at best and misleading at worst. Ten minutes in src/ will tell you more than any README will, because the package is single-author, has zero dependents, and almost certainly has no documentation site.

Installation

composer require --dev open-solid/arch-viewer

Keep it in require-dev. This is a documentation tool — it should never appear in the deployable artifact, never sit in the request path, and never be a runtime dependency of anything your app actually executes.

First run

php artisan vendor:publish --tag=arch-viewer   # if a config is shipped
php artisan arch:viewer                        # name may differ — check src/Console

If the artisan command name isn't obvious, grep -r "signature" src/Console is your fastest path. The command typically walks the OpenSolid constructs it understands and emits static output — Markdown, HTML, or both — into a docs/ or build/ directory.

Where to look first

  1. src/ — the whole thing is small enough to read in an afternoon. You want to know: how does it discover constructs? Reflection, AST, or runtime container boot? Static is far safer for CI; a runtime scan can trip on unbound services.
  2. The console command — what arguments does it accept? Can you scope to one namespace, one module, one bounded context? If output is all-or-nothing, note that now.
  3. The config file (if any) — paths, namespaces to include/exclude, output format, output directory.

Your first use case

Pick one bounded context — ideally the messiest, most convention-divergent one you have. Run the generator against it. Then pull up the hand-written architecture summary you'd normally give a new hire and compare. That diff, not the package's star count, is the thing that tells you whether this is worth adopting. Expect roughly half a day for a developer to get through this evaluation.

Implementation Patterns

Commit the output, not the generator

The workflow that makes generated docs useful is the same one you'd use for any other build artifact you want reviewed: generate on demand, commit the result, diff it in PRs. A generated docs/architecture/ directory with a visible timestamp and commit SHA in its header stays honest. A wiki page that nobody regenerates rots within a quarter.

Keep the generator in require-dev and the output in version control. That inverts the usual dependency relationship in a healthy way: if the tool disappears tomorrow, the docs still exist.

Scope by bounded context

Run the generator per context or per module rather than for the whole monolith, and land each output in its own file. This gives you three things at once:

  • Reviewability — a diff on a single context's map is readable in a PR; a 4,000-line full-repo dump isn't.
  • Ownership — the platform team owns the platform map, the orders team owns the orders map.
  • Failure isolation — if one context breaks generation on an unfamiliar construct, the other three still produce output.

Pair it with, don't confuse it with, enforcement tooling

This package documents; it does not police. If your actual goal is failing builds on layering violations, that's Deptrac, PHPat, or Arkitect — different tool, different conversation. The pattern that works is:

  • Deptrac/PHPat — expresses and fails on dependency rules.
  • PHPStan/Pint — static analysis and formatting.
  • arch-viewer — the human-readable artifact you show in a design review, or the diff a reviewer reads when a boundary quietly drifts.

The cheap, useful version: render the model and enforce the rules from the same conceptual source, so the doc review and the rule check are describing the same thing.

CI integration — non-blocking first

Wire it as a non-blocking step before you ever consider gating on it:

- name: Generate architecture docs
  run: php artisan arch:viewer
  continue-on-error: true

Run it twice back-to-back and diff the two outputs. If they're byte-identical, you have determinism and can move toward a soft "docs changed but weren't committed" warning. If they aren't, stop there — a non-deterministic generator in a blocking check will fail spuriously and be disabled within a fortnight.

Onboarding as the day-to-day payoff

The clearest day-to-day win for a Laravel team is onboarding and "where does this live?" questions. Keep the generated map in docs/ and link it from the README's architecture section. When a new hire asks "which module owns this?", the answer is a file, not a Slack thread. That's the measurable line item — time-to-first-PR, ramp-up cost per hire — not "better documentation" as an aspiration.

Design review and post-incident use

Post-incident, "which module actually owns this responsibility?" is a real question and the generated map is a fast answer. Same for design review: put the map at the top of the PR description when introducing a new dependency between contexts, so reviewers see the coupling rather than inferring it from a diff.

Gotchas and Tips

Silent omission is the failure mode that will burn you

A doc generator that misses constructs is worse than no doc generator, because the output looks complete. If handlers are registered through a custom service provider, or your team uses attributes where the generator expects annotations, those constructs simply won't appear — and nothing will warn you. Validate the generator's coverage on a real context against a manual inventory, not against a sample repo. The most dangerous output is a map with a confidently blank region.

Determinism is a prerequisite, not a nice-to-have

Before you commit a single generated file, run the generator twice and diff. Stable output means stable diffs, which means CI-checkable, which means the docs can be reviewed like code. Unstable output — timestamps in the body, non-sorted keys, reflection order leaking through — means every regeneration produces a noisy diff and the check gets disabled. The mitigation is cheap: commit generated docs with a header line containing the timestamp and commit SHA, so the only thing that ever varies is what you deliberately put there.

Assume you are the maintainer from day one

Zero stars, zero dependents, no score, single-vendor origin. Pin to a commit SHA, not a version range — release cadence is unknown and a silent upstream bump can change output under you. Mirror the repository internally and record the decision in your dependency register. If it's abandoned, you fork a small tool you already understand; that's a priceable risk, but only if you priced it. The realistic maintainer cost is half a day to evaluate plus one to two days of contingent fork ownership if you adopt.

Version pinning against OpenSolid core is tight

The generator's model of the codebase is built on OpenSolid's constructs, so the constraint on OpenSolid core is likely narrow. That means an OpenSolid or PHP bump can break generation mid-upgrade, and the failure can land in the middle of an unrelated maintenance task. Run the generator as part of your upgrade checklist before the OpenSolid bump, so you know what shape the breakage takes while you still have context.

Static discovery is safer than runtime boot

If the generator discovers constructs via reflection or AST, it's safe in CI. If it boots the container to scan at runtime, it can trip on unbound services, need a database connection, or pull in environment-specific providers. Check src/ early. If it's runtime-based, either isolate it in a separate CI step with a minimal env, or accept that it's a local-only tool and skip CI integration entirely.

Custom service providers are invisibility cloaks

Laravel teams register things in ways static analyzers can't see: deferred providers, container bindings behind conditionals, event subscribers constructed dynamically. If your OpenSolid wiring leans on any of these, the generator will under-report. The mitigation is a manual checklist per bounded context: list what you know exists, compare to what appears in the output, and only then trust the map. Do this once per context, at evaluation time — not every run.

Keep it off the critical path, permanently

The require-dev-only stance isn't just about install size. It's an operational guarantee: the generator can be broken, outdated, abandoned, or uninstalled and it will not affect your deployable artifact. Resist the temptation to make it a hard gate until you've seen stable output across two consecutive runs and have an exit path documented. The exit path is the short in-house script — reflection plus a static docs page, roughly 1–2 engineer-days given the narrow scope. Write that down before the spike, so "no" is a cheap, informed answer rather than a sunk cost.

Extension points are whatever you read in src/

If you need the generator to understand a construct it doesn't ship with — your own base command class, a custom attribute, a project-specific handler pattern — the extension point is whatever the author happened to leave open in the source. There is no documented plugin API and no contributor community to ask. Read the discovery layer, find where constructs are matched, and extend there. Vendoring the fork from day one is the honest posture.

Treat output as generated, reviewable text — not editorial

The generator can tell you what depends on what. It cannot tell you why the boundary exists, what trade-off was made, or what you rejected. Those belong in hand-written ADRs next to the generated map, not in it. The healthy pattern is: generated structure lives in one directory and is never hand-edited; narrative decisions live alongside and cite the map. Mixing the two means the next regeneration wipes someone's careful prose.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums