simai/docara
Docara is a lightweight Laravel/PHP package from simai that simplifies working with documentation inside your applications. It offers straightforward configuration and a clean API, making doc-related features easy to add without extra overhead.
Architecture fit. Docara is a Laravel/PHP static documentation generator: content lives as Markdown plus lang.json per locale, a docara.json site config drives the build, and the build emits a static tree (sitemap.xml, llms.txt, _docara/page-metadata.json, resolved-page-plans.json) that is served by nginx, Apache, or GitHub Pages. v3.7.0 is a good signal that the package is maturing along the axes a documentation platform actually needs: hosting correctness (a real 404 page), i18n and accessibility correctness (source-language marking), and build-contract correctness (validation parity between build and docara validate page). Nothing in this release changes the deployment model, so the architectural fit decision from any prior evaluation stands unchanged.
Integration feasibility. The headline feature is low-effort to adopt. The 404 page is on by default, so a rebuild produces 404.html at the deployment base with no config change; opting out is a single docara.json flag ("not_found": {"enabled": false}), and customization is either a 404.md at the root of the default locale's content or overrides of the error.not_found.* strings in that locale's lang.json. The one piece of real integration work is host-side, and the package documents all three common cases: error_page 404 /404.html; on nginx, ErrorDocument 404 /404.html on Apache, and automatic on GitHub Pages. That is a small, well-bounded platform ticket, not a migration.
Technical risk. Low, with three specific caveats worth tracking:
404.html because the portal owns it, and setting not_found.enabled: true in a portal build stops the build with PORTAL_NOT_FOUND_PAGE_FORBIDDEN. Any shared docara.json used across standalone and portal sites must therefore not force the flag on.border-bottom and surface-0 were never defined by the bundled SIMAI Framework and silently rendered nothing; they are now accepted as aliases for border-bottom-1/border-bottom-solid and bg-surface-0, and each use is recorded as deprecated_utilities in the section provenance or element block data of the page plan. That gives us a machine-readable migration backlog rather than a surprise break — good — but it is a deprecation with a future removal, so it needs an owner.Key questions.
not_found.enabled?error.not_found.* needs translation coverage?deprecated_utilities wired into any CI reporting, or is it only visible on inspection of the page plan?docara validate page as a gate, and are we prepared for the validation output to change in both directions (the Composition Recipe warning disappears; previously-unreached pages after it are now checked and may surface new findings)?Stack fit. The release is additive plus fixes — no removed APIs, no config renames, no content format changes. A Laravel app consuming the package upgrades by bumping the version and rebuilding; the static output is a superset of 3.6.x (one new 404.html file at the base, plus one new resolved-page-plans.json entry with "not_found": true). The package continues to sit cleanly alongside the SIMAI Framework as a bundled dependency rather than a peer we manage.
Migration path. Effectively a no-op migration with two optional cleanups:
404.md at the root of the default locale's content to replace the built-in text — note it publishes as 404.html rather than <locale>/404/, and relative URLs inside it resolve from <locale>/404/, so links should either be root-absolute or written with that resolution in mind.deprecated_utilities out of our layout files and replace border-bottom/surface-0 with the Framework-defined border-bottom-1, border-bottom-solid, and bg-surface-0. This is cosmetic in output terms but removes a future break.Compatibility. Two behavioral changes are worth scheduling rather than absorbing silently. First, the rem breakpoint switch means anyone with a non-default browser font size sees a different layout — include an accessibility pass with enlarged default text in the QA plan. Second, the hero effect's pause button now takes its own row beneath the hero content instead of floating over the media, growing the hero by roughly 48 px on a phone; that is a genuine bug fix (the button was covering hero media at 375 px and 1440 px) but it will move landing-page screenshot diffs. The effects.pause / effects.play labels are now legitimately overridable in content/<locale>/lang.json, which previously failed schema and namespace-allowlist validation — if we attempted that override before and worked around the failure, unwind the workaround.
Sequencing. (1) Host 404 route first — nginx/Apache/GitHub Pages config, reviewed per environment, since a 404 page that the host never serves delivers no value. (2) Upgrade and rebuild in a branch, diff static output. (3) Run docara validate page and compare against the previous run, triaging the newly-reachable pages and the dropped DOCUMENT_IR_INPUT_INVALID warning as expected deltas. (4) Land the utility-name cleanup driven by deprecated_utilities. (5) Visual QA including a large-default-font pass and refreshed landing-page baselines. (6) Fix any translations status automation that relied on the previously-ignored --kind option — it now filters, and an unknown kind fails with TRANSLATION_KIND_INVALID, so a typo'd value that used to pass will now break the job.
Maintenance. Net maintenance cost goes down. Two recurring sources of noise are removed: the per-build Page authoring contract warning: [DOCUMENT_IR_INPUT_INVALID] on Composition Recipe pages (which also, more importantly, halted validation so subsequent pages went unchecked), and the false-positive link check on links written as inline code. The advisory editorial checklist (PAGE_EDITORIAL_REVIEW_REQUIRED) is no longer counted as a build item to review — it remains visible via docara validate page — which means build output now means "things that need a fix." Adopting deprecated_utilities as a tracked backlog item keeps the future alias removal from being a surprise.
Support. Support surface is modest and mostly self-inflicted if we skip steps. The 404 page is noindex, has no hreflang alternates, and is excluded from navigation, backlinks, search index, sitemap.xml, llms.txt, and _docara/page-metadata.json — so it cannot pollute SEO or search results, and a support question of the form "why is 404.html in my sitemap" does not exist. It is still checked by verify-static like any other page, which is the right trade: it must not silently rot. Expect a small uptick in authoring questions about where to put a custom 404.md and how relative links inside it resolve; documenting that once should close it out.
Scaling. No scaling concerns. The 404 page is a single file per site regardless of locale count — multi-locale sites get one root 404.html in the default locale, not one per locale, and everything it links to is addressed from the site root via base_url so it works at whatever missing path the host serves it from. The example-frame fix (making the <base> absolute in srcdoc so Chromium's preload scanner resolves relative images correctly) removes a duplicate fetch per relative image per frame — on the order of 44 pages on the vendor's own site — which is a small but real bandwidth and error-noise reduction at scale. The translations status --kind filter matters more as locale count grows, since it now lets us split page and lang.json reporting instead of reading both.
Failure modes.
PORTAL_NOT_FOUND_PAGE_FORBIDDEN — caused by not_found.enabled: true in a portal build. Expected and intentional; the fix is config, and it should be caught in a pre-merge build rather than at release.verify-static passes, and users still see the host default because the nginx/Apache directive was never added. Verify with a deliberate bad URL per environment, post-deploy.--kind is now honored and an unknown kind fails with TRANSLATION_KIND_INVALID. Any script that passed a stale or misspelled kind and silently got both kinds will now fail.translation_tracking.mode: "publish-current" are explicitly noted as not yet marked, so a screen reader will still read those in the page locale. Worth logging as a known limitation rather than a blocker.DECLARATIVE_VIEW_UTILITY_NOT_ALLOWED; the allow-list is now backed by a test that keeps it and the documentation's layout files aligned to classes the bundled Framework actually defines, which reduces the chance of another silent no-op like surface-0.Ramp-up. Near zero for existing contributors — the authoring model (Markdown, lang.json, docara.json) is unchanged, and the 404 page's default content requires no authoring at all. Two small pieces of new vocabulary: the error group in lang.json for the not-found strings, and the not_found block in docara.json. For platform engineers, the ramp-up is the host 404 directive, which is a one-line change per server type. Budget roughly a half-day of platform work for host configuration plus the visual-QA refresh, and treat the deprecated_utilities cleanup as an opportunistic chore rather than a scheduled project.
How can I help you explore Laravel packages today?