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

Nova Documentation Laravel Package

dniccum/nova-documentation

dniccum/nova-documentation adds a complete documentation system to Laravel Nova. Write, organize, and publish Markdown-based guides, help pages, and internal docs directly inside Nova with a built-in editor, navigation, and versioning—no separate CMS needed.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish

composer require dniccum/nova-documentation
php artisan vendor:publish --tag=nova-documentation

The publish tag gives you config/nova-documentation.php. Read it before writing any markdown — disk, path, home, and the menu label all live there, and every "it doesn't work" failure traces back to this file.

Register the tool in app/Providers/NovaServiceProvider.php:

public function tools()
{
    return [
        new \Dniccum\NovaDocumentation\NovaDocumentation,
    ];
}

Drop a landing document at {path}/{home}.md on the configured disk (default convention is home.md). One file is enough to confirm the tool boots and renders in /nova. Don't assume the path — resolve it concretely:

Storage::disk(config('nova-documentation.disk'))
    ->exists(config('nova-documentation.path').'/home.md');

If that returns false, you have your answer before you open a browser.

First realistic day-to-day use case: the internal admin handbook. Create docs/getting-started.md, docs/billing/refunds.md, docs/permissions.md in the repo, deploy, and you have a navigable runbook set for support and ops staff living inside the panel they already use. This is the pattern 90% of teams stick with — it's the package's sweet spot and the reason to adopt it at all.

Where to look first when something breaks: the published config (disk + path together), then php artisan route:list | grep -i document, then whether home.md exists at that resolved location, then whether config is cached. That order resolves nearly everything.

Version note: v3.6.0 is a maintenance release — Laravel 13.x compatibility plus markdown link-processing fixes (#45, #36). Start at 3.6.0 or later; there is no new feature surface versus 3.5.x, so the integration API you learn today is stable across the 3.x line.

Implementation Patterns

The directory tree is the sidebar. Nested folders become nested nav. This is the primary organizing mechanism and it's worth respecting: keep nesting to two levels, group by audience or workflow (onboarding/, runbooks/, policies/), and let filenames be short and stable.

Front matter for display, filenames for identity. Control titles and ordering in YAML front matter, not by renaming files — filenames typically drive URLs, so a rename is a broken inbound link and a broken bookmark.

---
title: Refund Processing
order: 2
---

# Refund Processing
...

Use order aggressively once you pass ~10 pages; it's the only knob you get for nav sequencing across directories.

Multiple doc sets via multiple tool instances. Need "Developer Docs" and "Support Playbooks" as separate Nova sidebar entries? Register two instances pointed at different paths:

public function tools()
{
    return [
        (new \Dniccum\NovaDocumentation\NovaDocumentation)->withPath('docs/engineering'),
        (new \Dniccum\NovaDocumentation\NovaDocumentation)->withPath('docs/support'),
    ];
}

(Check the actual method name in your installed version — the package is single-path per instance, so if there's no fluent setter, duplicate the config or subclass and override it.) Two thin instances beat faking sections inside one tree.

Gate access at the tool level with canSee. There is no per-document permission system. The only access control seam is whether the tool appears in Nova at all:

public function tools()
{
    return array_filter([
        auth()->user()?->isAdmin() ? new \Dniccum\NovaDocumentation\NovaDocumentation : null,
    ]);
}

For finer-grained scoping, split into multiple tool instances and gate each one on a different ability. Anything beyond that means overriding views or forking — don't fight it.

Relative cross-document links. Prefer [Invoices](../billing/invoices.md) over hardcoded /documentation/... URLs. Relative links survive base-URI changes; absolute ones don't. If you applied workarounds for broken links on 3.5.x, re-test them after upgrading to 3.6.0 — the link processor changed.

Ship docs with the code. Keep the markdown directory in the repo, deployed alongside the feature it describes. Add a PR checklist item ("updated the runbook") so the docs don't rot. The entire value proposition is proximity — if docs live in a separate wiki, you've paid the integration cost for nothing.

Seed content in local dev. Committing markdown means every developer gets the same docs on php artisan migrate --seed deploys or a git pull. No import step, no sync job. For a docs system, that's the correct amount of infrastructure.

Branding via published views. Publish views and edit under resources/views/vendor/nova-documentation/. Pin the package version in composer.json ("3.6.*" or exact) the moment you do this — view paths shift between releases and a composer update will silently break your layout.

Version by copying. "Current" vs "archived" docs: duplicate the tree, point a second tool instance at the copy. Cheap, obvious, works. The package has no versioning concept and bolting one on is more effort than it's worth.

Gotchas and Tips

  • path is a prefix within the disk, not a filesystem path. /var/www/docs silently resolves to nothing. Always test disk and path together, never in isolation.
  • local ≠ storage/app/public. With disk => 'local', path is relative to storage/app. Putting files in storage/app/public and wondering why they don't render is the single most common integration failure.
  • Strict front matter parsing fails silently. A missing --- fence, or order: "3" instead of order: 3, can drop a page from the nav with no error. When a file "disappears," validate the front matter before anything else — the symptom doesn't point at the cause.
  • The home document is required. Delete it and you get an empty state that looks exactly like a routing error.
  • Filenames become URLs. Rename = broken links. Change the displayed title via front matter instead.
  • Clear caches after production edits. Adding or moving files on a deployed environment often needs php artisan cache:clear (and config:clear if config is cached). Locally, a hard refresh is usually enough — which is exactly why this bites in production and not in dev.
  • No search. Past a dozen pages, plan for nav browsing plus a hand-maintained index.md of links. Don't promise full-text search to stakeholders; it isn't there and won't be added by config.
  • Menu label collisions. Nova doesn't dedupe tool labels. Rename this to "Help" and another tool already uses that name, and users see two identical entries.
  • v3.6.0 link fixes are behavioural. After upgrading, spot-check pages with anchors, query strings, links to non-.md files, and links inside fenced code blocks — both the previously broken cases and any workaround markup you wrapped around them.
  • Three extension seams, no hook API. (1) the config file, (2) published views, (3) canSee on the tool instance. No events, no middleware, no per-document policies. Keep all customization at those three points; anything else is a fork.
  • Debugging checklist, in order: tool registered and not filtered by canSee → config resolves → path/home.md exists on that disk → config not stale → route in route:list. Work down it; almost every failure is in the first three.
  • Lint front matter in CI. A 10-line script that walks the docs directory and asserts every file starts with ---, parses as YAML, and has a unique order will save you the silent-disappearance debugging session. Cheap insurance for a package with no validation.
  • Pin the version and re-diff the config on every minor bump. New config keys are added without loud breaking changes; missing keys fall back to defaults that may not match your intent. The Laravel 13 support in 3.6.0 came via an automated laravel-shift PR, so re-read composer.json constraints after any bump — the supported framework range can shift at either end.
  • Supply-chain reality check. ~37 stars, effectively zero dependents, small maintainer base. Two new contributors in v3.6.0 is a genuine positive signal, but treat this as a thin, forkable utility you may need to own — not a platform. Budget a day to vendor or fork it if your dependency policy is strict. If you're not already on Nova, an authenticated route plus a markdown renderer gets you the same outcome with no dependency at all.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment