albertoarena/laravel-truss
Laravel Truss scans your live database schema and renders it as a scrollable, zoomable ER diagram inside your app. Structure only, never row data. Focus mode, searchable tables, themes, and export.
Architecture fit. Truss is a self-contained Laravel package: auto-discovered service provider, publishable config, a single gated route (/truss), vendored Mermaid and fonts (no CDN, CSP-safe, no Node build step), and a cached schema snapshot. It reads structure only via Laravel's connection layer, so it introduces no migrations, no schema changes, and no write path into the application database. That makes it architecturally inert in the best sense — it can be added and removed without touching application code. The multi-connection support (per-connection excluded_tables, connection picker, URL-persisted selection) is the detail that matters most for us: it means modular monoliths and main-plus-module database topologies are first-class, not an afterthought.
Integration feasibility. Very high for a standard Laravel 12 application. composer require --dev plus a visit to /truss is the entire local onboarding. Nothing needs publishing to get started. The interesting seam is environment promotion: --dev installs are stripped by composer install --no-dev, so any staging/production deployment requires promoting Truss to a regular dependency, which means the package, its route, its views, and its assets ship in the production artifact. That is a deliberate, documented decision rather than a surprise, but it converts a zero-risk dev tool into a production surface that needs an explicit authorization decision (the viewTruss gate) and an owner.
Technical risk. The dominant risk is not technical, it is supply-chain and lifecycle:
SELECT *) is real and consistently stated across the CLI, facade, and export pipeline, but "structure only" is still sensitive for regulated data models.Key questions.
viewTruss gate policy — is it role-based, SSO-backed, or an allowlist in config — and is that auditable?Verdict. High value, low blast radius, real but manageable lifecycle risk. Best positioned as a developer-experience and documentation tool, not as production infrastructure.
Stack fit. Composer, Artisan, and CI — no Node toolchain, no frontend build, no CDN dependency. Three surfaces matter to us:
/truss) for interactive schema exploration, focus mode, and the Health panel.truss:export, truss:diff, truss:doctor) for CI and docs generation, all deterministic and offline.Truss facade and the export pipeline for programmatic use — the immutable builder (only(), focus(), compact(), toDbml(), toLlm(), …) shares one source of truth with the command and the dashboard, so anything we generate in CI is byte-identical to what a developer sees in the browser. That consistency is the property that makes the CI drift check trustworthy.Migration path. There is no migration. Adoption is additive and reversible in a single composer remove. Start as a dev dependency; only promote to a regular dependency in the specific environments where we want the gated dashboard, and only after the gate is configured.
Compatibility. Constraints to validate before rollout:
truss.connections; unlisted connections are invisible, which is good for safety but can look like a bug during rollout.truss:doctor and truss:export --check to be meaningful.Sequencing. Five stages, each independently valuable:
--dev install in two or three Laravel 12 repos, one with a single connection and one with multiple. Measure onboarding time for a new engineer and whether focus mode holds up on our largest schema (hundreds of tables is the stated design target).docs/schema.dbml (or Markdown data dictionary) generated by truss:export, and add --check to PR pipelines so a migration that changes structure without refreshing the committed file fails the build. This is the highest-leverage, lowest-risk win: it makes the schema a reviewable artifact and gives reviewers a diff they can read.truss:doctor --format=json with --preset=recommended and --fail-on=error in report-only mode for a sprint, tune severity and ignore patterns to kill false positives under truss.doctor, then flip to blocking on error only. Do not start at strict.viewTruss to our standard SSO/role check, and publish a short runbook. Restrict to engineers and on-call; do not enable in production initially.config/truss.php (per-table, per-column, global notes), expose --format=llm --compact --focus=<table> as the standard context payload for coding agents. Evaluate the MCP server separately, after the export path is trusted.Resist the temptation to compress stages 2–3 into one; the drift check and the doctor have different failure semantics (drift is objective, doctor findings are heuristic and need calibration).
Maintenance. Low effort, moderate attention. Pin the version in composer.json, watch releases (the project asks for Watch > Custom > Releases, which is a reasonable signal of how it expects to be tracked), and review changelogs before bumping — the CLI exit codes and doctor rule set are the parts most likely to shift. Because the package is MIT-licensed, small, and self-contained, a fork is a credible contingency if the maintainer disappears; budget for that only if we reach stage 4 and beyond.
Support. Local usage generates essentially no support tickets — it either renders or it does not. The support burden concentrates in two places: (a) the authorization gate on any non-local deployment, which needs an owner, a policy, and a documented "why is /truss 404 for me" answer; and (b) CI exit codes, where 1 (drift found / finding at or above --fail-on) and 2 (usage or runtime error: bad option, unwritable path, unmanaged connection, --check without --output, no tables matched) must be distinguished in pipeline error messages or engineers will misdiagnose a broken path as a schema regression. The accessibility work (keyboard operation, screen reader descriptions, axe-core on every push) is a genuine differentiator if we ever expose the diagram beyond engineering, and it costs us nothing to inherit.
Scaling. The read path is cheap by design: structure only, cached snapshot, no row queries, no SELECT *. The scaling variables are snapshot generation time and payload size on very large schemas (introspection of hundreds of tables, plus the Mermaid render in the browser), and cache invalidation cadence. On multi-connection setups, introspection is scoped per database — the README is explicit that a shared server never shows another database's tables, which is the right default. Export output is deterministic by construction, which is what makes committing generated schema files viable at scale across many repos.
Failure modes to plan for.
| Failure | Symptom | Mitigation |
|---|---|---|
| Gate misconfigured on staging/prod | Schema structure publicly reachable | Treat gate config as a security-reviewed change; smoke-test anonymous access in CI or a synthetic check |
--dev install promoted to staging |
/truss returns 404 after --no-dev build |
Decide per-environment install type deliberately; document it |
| Stale snapshot after out-of-band DDL | Diagram, diff, and doctor disagree with reality | Use --fresh in CI exports; document manual-DDL invalidation in the runbook |
| Doctor false positives | Alert fatigue, engineers disabling the check | Tune severity and ignores under truss.doctor; start recommended, not strict |
| Drift check noise across DB versions | --check fails with no real schema change |
Verify determinism on our actual engines during the pilot before making it blocking |
| Maintainer abandonment | No upstream fixes | Version pin plus a cheap fork path; revisit only at stage 4+ |
Ramp-up. Effectively zero for engineers already comfortable with Laravel — the local path is a composer command and a URL. Realistic budget: under an hour per engineer for the dashboard, and roughly half a day for whoever owns the CI wiring and the doctor calibration. The annotation authoring in config/truss.php is the only piece that asks for sustained human input, and it is also the piece that compounds: it is what turns a diagram into a data dictionary and what makes the llm export genuinely useful as agent grounding rather than a column dump. Assign that work to the domain owner of each schema, not to a platform team guessing at business meaning.
Overall. Adopt in stages, cap the exposure at local plus a gated staging dashboard, and let the CI drift check and the schema export carry most of the value. The 288-star, single-maintainer profile is the reason to keep the tool on a lease rather than a mortgage: it earns its place every sprint through onboarding speed, reviewable schema diffs, and better agent output, and it is removable in one command if it stops earning it.
How can I help you explore Laravel packages today?