Package Documentation Standard
Capell package docs have two jobs: help a developer change the package safely, and help an owner understand why the package belongs in a Capell build. Keep both jobs visible.
Reader Split
Section titled “Reader Split”Every package needs both a non-technical overview and a developer deep dive. They can live in one README when the package is small, but the distinction should be obvious.
| Reader | What they need |
|---|---|
| Site owner, buyer, or operator | What workflow the package adds, which bundle it belongs to, which screens or public routes appear, and what operational risk it reduces. |
| Editor or admin user | What they can create, review, approve, publish, inspect, recover, or hand off without custom development. Editors read docs/overview.md and, for Tier 1 and Tier 2 packages, docs/admin-guide.md. |
| Developer | Real package boundaries: Actions, Data objects, providers, routes, models, settings, extension points, tests, and unsafe integration paths to avoid. |
Use this split when writing examples:
For teams: Customer Portal gives signed-in customers one dashboard for support requests, preferences, and package-contributed self-service links.
For developers: Packages contribute dashboard cards through `PortalDashboardItemRegistry`; billing, document, event, and access packages keep their own domain actions.Avoid examples that only restate the package name:
Weak: Automation Studio automates workflows.Better: Automation Studio listens for package events such as form submissions and access approvals, then records each matched rule/action run in `automation_runs`.Portable command examples
Section titled “Portable command examples”Package Markdown ships to customers independently of this repository. Use installed
package commands, Artisan commands in the customer’s application, or scripts and
tools owned by that package. Keep monorepo wrappers, the private
COMPOSER=composer.local.json overlay, repository-only Composer/npm scripts, and
root test or analysis paths in contributor documentation outside packages/.
A package’s own relative file takes precedence over an identically named root file;
an alias may use its own conventionally named vendor tool when its Composer
require-dev declares that tool. State customer application context explicitly.
Run php scripts/check-package-markdown-commands.php to check every package Markdown
file without installing dependencies. This check runs in composer preflight,
preflight:changed, preflight:all, test:affected, the package review manifest
audit, and the dedicated Package Markdown commands CI workflow. The lightweight
workflow includes Markdown-only PRs without starting the full test matrix.
The guard is a high-precision heuristic over Markdown, not a shell parser. Its accepted limits still require contributor review:
- Subshells, substitutions and
sh -ccommand strings are not interpreted. - Markdown extraction has edge cases around comments, backticks in fenced code, and multiline inline-code spans.
- Customer-application context is inferred heuristically and can both exempt maintainer instructions and reject customer instructions when wording is ambiguous.
- Alias traversal stays within one script manager; cross-manager alias chains and
implicit npm lifecycle scripts such as
prebuildare not followed.
Passing the guard does not prove every command is portable. Keep examples simple and review them in the package’s own checkout or the stated customer application.
README Shape
Section titled “README Shape”Every package README should include these sections, in this order when practical. The current strict audit checks the heading names below.
| Section | Purpose |
|---|---|
| Opening H1 | Title the page with the package or plugin name. |
What This Plugin Adds | Practical job, Capell surface, admin/editor outcome, and status such as Available or Pipeline. |
Why It Matters | Separate developer impact from team/editor/operator value. |
Screens And Workflow | Planned or existing screenshots, diagrams, admin screens, frontend output, and workflow steps. |
Technical Shape | Providers, config, migrations, models, resources, routes, Livewire, policies, events, jobs, views, cache. |
Data Model | Tables, relationships, core records, migration impact, deletion/retention, or no-schema statement. |
Install Impact | Admin navigation, permissions, public routes, database changes, config, queues, schedules, cache paths. |
Common Pitfalls | Practical issues developers and operators should check. |
Troubleshooting | Optional symptom table for packages with routes, commands, jobs, schema, health checks, or external APIs. |
Quick Start | Up to four steps: install the package; run a declared install, setup, or migrate command when one exists; run the declared demo command when one exists; and open/verify the new surface. Omit undeclared command steps entirely. |
Next Steps | Links to configuration, screenshots, ERD/schema, extension points, troubleshooting, related package docs. |
Authored README narrative
Section titled “Authored README narrative”README.md permits fenced PHP and shell examples. Keep fenced code out of docs/overview.md, docs/overview.admin.md and docs/admin-guide.md. Every package-owned extension contract and every manifest actions entry needs a worked PHP snippet in the README or a developer guide linked directly from it. Do not place examples in generated narrative fields or edit generated README inventories to satisfy this requirement; link the maintained developer guide.
The generator owns README structure, status, technical inventories, schema facts, install impact, screenshot plans, pitfalls, quick-start steps, and links. Each package owns the short editorial judgements in docs/readme-narrative.json:
whatThisPluginAdds: the package’s practical job and Capell surface.surfaceOutcome: what an admin, editor, operator, or public user can actually do after install.whyItMatters.developers: real Laravel boundaries and extension points.whyItMatters.teams: the editorial, product, or operational outcome.
Each entry has a short text value and a non-empty evidence list. Evidence paths are relative to the package root, must point to committed files, and should name the smallest useful proof: capell.json, a provider, Action, route, migration, Filament resource, render hook, focused test, or screenshot contract. Generated README.md, generated docs/overview.md, and the narrative file itself are circular evidence and are rejected.
Do not put documentation-only fields in capell.json, and do not parse docs/overview.admin.md as the canonical developer narrative. The manifest is a runtime contract; the admin overview is deliberately written for a different reader.
Use the shared language guides before rewriting package docs:
Admin Documentation
Section titled “Admin Documentation”The README is the developer and owner front door. The admin docs are the editor and operator front door, written in plain language for someone who runs the feature but does not change the code. Follow the admin voice in the Content Language Plan: real on-screen labels in bold, the user’s goal first, the nav path named, no class/table/Action names, no composer/artisan, no fenced code, and no non-ASCII punctuation.
Admin-first overview.md
Section titled “Admin-first overview.md”When a package ships an admin-first overview, it adds a hand-authored fragment at docs/overview.admin.md (admin sections only, no H1, no footer). The generator wraps that fragment into docs/overview.md with the package H1 and a footer linking the admin guide and developer docs. The developer-shaped content is not lost: it stays in the generated README.md. The strict audit then validates overview.md in admin mode (H1 required; the developer headings What This Plugin Adds, Technical Shape, Data Model, Install Impact, and Quick Start are forbidden; install commands are forbidden). Keep the fragment short (about 40 to 70 lines) using plain headings such as:
| Section | Purpose |
|---|---|
What it does for you | Two to four sentences, concrete, in editor language. No class names. |
Your screens | The actual admin nav items and pages, in plain words. |
What you can do | Three to six verbs the user performs: create, schedule, approve, preview, export. |
Where to find it | The nav path, for example “Content > Articles” or “Settings > SEO”. |
Good to know | One to three gotchas in plain language, such as “Drafts stay private until published”. |
Themes and behind-the-scenes packages use their own short headings (see the tier table) rather than this exact set.
admin-guide.md (Tier 1 and Tier 2)
Section titled “admin-guide.md (Tier 1 and Tier 2)”A longer how-to with three parts in one document:
| Section | Purpose |
|---|---|
Using <Package> (editor how-to) | Numbered tasks with real button labels, each titled by the user’s goal (“How to schedule an article for later”). |
Rolling out <Package> (for owners) | What to turn on first, what to add when needed (a Need to Enable table), what not to enable yet, and who does what (role to first useful screen). |
| Troubleshooting for editors | A What you see / What it means / What to do table in plain language. |
Coverage tiers
Section titled “Coverage tiers”| Tier | Treatment |
|---|---|
| 1 (full guide) | Admin-first overview.md plus a full admin-guide.md (how-to, adoption, troubleshooting). |
| 2 (operator note) | Admin-first overview.md plus a lighter admin-guide.md (what you are looking at, what to do when X, settings and retention). |
| 3 (theme template) | One shared admin-first overview.md shape per theme: what this theme gives you, how to use it, what it adds, good to know. No per-theme admin-guide.md. |
| 4 (behind-the-scenes note) | Admin-first overview.md only: what it does, do I need to do anything, where it shows up. No admin-guide.md. |
Workflow Value Rules
Section titled “Workflow Value Rules”Write from the reader’s job:
- For owners: explain what capability this adds in a Capell site, dashboard, workflow, or package bundle.
- For editors: explain what becomes easier to create, approve, reuse, publish, inspect, or recover.
- For developers: explain what extension point, Action, Data object, or provider surface saves custom code.
- For operators: explain what gets monitored, cached, audited, migrated, protected, or debugged.
Avoid vague claims. Use specific outcomes that the code supports. For example:
| Weak | Better |
|---|---|
Adds generic content tools. | Adds article, archive, and tag page types so teams can publish editorial content without custom page schemas. |
Improves performance. | Indexes cached model URLs and exposes admin cache widgets so operators can see stale HTML and refresh affected pages. |
Integrates with Shopify. | Stores site-scoped Shopify OAuth connections and syncs products into local tables for admin-side catalog search. |
Runtime Surface Checklist
Section titled “Runtime Surface Checklist”Check these source locations before documenting a package:
| Surface | Source of truth |
|---|---|
| Composer name and namespace | packages/<package>/composer.json |
| Product group, capabilities, surfaces | packages/<package>/capell.json |
| Providers | composer.json.extra.laravel.providers, src/Providers |
| Config and env vars | config/*.php, settings classes, tests |
| Routes | routes/*.php |
| Commands | src/Console/Commands |
| Actions | src/Actions |
| Data objects | src/Data |
| Models and tables | src/Models, database/migrations |
| Settings | src/Settings, database/settings, Filament settings schemas |
| Admin surfaces | src/Filament, registered CapellAdmin calls |
| Frontend surfaces | resources/views, src/Livewire, render hooks, frontend providers |
| Extension points | contracts, registries, tags, provider registration calls |
| Tests | packages/<package>/tests, shared package tests under tests/Packages |
| Authored README claims | packages/<package>/docs/readme-narrative.json and its evidence paths |
Extension Point Documentation
Section titled “Extension Point Documentation”For every package-owned extension point, document:
| Field | Required answer |
|---|---|
| What to implement | Interface, class, enum, registry payload, or Action call. |
| Where to register it | Provider method, registry call, config key, or container tag. |
| When it runs | Boot, admin render, public request, queue job, install command, sync command, publish flow, cache invalidation. |
| Safe fallback | What happens when no extension is registered or the dependency is not installed. |
| Focused test | Provider/registry test, Action test, admin render test, public output safety test, cache invalidation test, or failure test. |
Do not invent extension points to make docs feel complete. If the package only exposes Actions today, say that and name the Actions.
Worked-example coverage
Section titled “Worked-example coverage”The audit discovers declared PHP interfaces recursively under src/Contracts (the same source directory used for the README contract inventory), plus every key in capell.json’s actions object. An imported interface from another package is not a package-owned contract. Non-interface extension seams still require the documentation above and human review; directory discovery is not a claim to identify every possible extension mechanism.
Put one labelled PHP fence immediately after an HTML comment identifying its
target: <!-- example: contract Fully\\Qualified\\InterfaceName --> or
<!-- example: action setup -->. Contract labels use the actual qualified
interface name; action labels use the actual manifest key, not the class name.
Two action keys pointing to the same class each need their own example.
The invocation or implemented interface must resolve to the actual qualified
class, using its namespace, a direct qualified name or an import (including an
alias or grouped import). Each namespace has its own import context. Mentioning
the expected class alongside a different same-named class
does not count.
Contract recipes must implement the interface and include the implementation
and registration context in the labelled fence. Show non-empty bodies for every
method declared by the interface, then pass that same implementation to the
owning container or registry through bind(), singleton(), scoped(), tag(),
register() or add(), using its class reference or a constructed instance.
An empty implementing class, an unrelated method or registration of a different
implementation does not count. Action recipes must show the actual invocation with
its required inputs: static run(), or app()/resolve() of the declared class
followed by handle(). Use the calling convention the shipped Action supports;
the audit does not make these conventions interchangeable. Do not use empty
fences, symbol-only lists, comments masquerading as code or bare ellipsis stubs.
Argument unpacking such as SetupAction::run(...$inputs) is valid; show where
the inputs come from. A first-class callable reference alone is not an invocation.
Developer guides count only when linked directly from README.md and stored inside that package’s docs directory. Admin-voice documents, external links and another package’s examples cannot fulfil the requirement. Unknown labels and missing per-target examples fail the audit, irrespective of strict-heading mode. The audit uses the checkout’s locked PHP parser and name resolver for contract declarations and snippets, including classes that extend a base class. Invalid PHP fails with the target name and parser diagnostic. The gate checks coverage, method bodies and invocation/registration structure, not PHP execution or semantic correctness: reviewers must verify signatures, registration, inputs, fallbacks and the focused tests against current source.
Troubleshooting Standard
Section titled “Troubleshooting Standard”Use symptom tables:
| Symptom | Likely cause | Check | Fix |
|---|---|---|---|
| Concrete failure visible to a user/operator | Specific code/config/runtime cause | Exact command, table, route, cache key, log message, or config key | Smallest safe fix and verification step |
Include exact names when relevant: route names, command signatures, table names, cache key prefixes, queue/job names, config keys, settings keys, and logs.
Safety Rules
Section titled “Safety Rules”- Public Blade, cached HTML, and theme output must not expose authoring state, package internals, model ids, field paths, permissions, signed admin URLs, tokens, OAuth state, or editor selectors.
- Public Blade views must not query the database or lazy-load relationships. Document render data loaders, Actions, Livewire components, or view components instead.
- Package docs must not advise replacing core classes, bypassing registries, writing provider-side data mutations, or storing designed page/widget markup in seed content.
- Core must not import optional package classes. Cross-package docs should describe events, Actions, registries, string command names, or documented package APIs.
Review Checklist
Section titled “Review Checklist”| Reviewer | Questions to answer |
|---|---|
| Developer | Are all classes, routes, commands, config keys, env vars, tables, settings, Actions, and examples real? |
| Content writer | Does the README explain a concrete workflow benefit in plain language without filler or unsupported claims? |
| Owner | Can a buyer or site owner tell why this package matters and which package bundle it belongs to? |
| Operator | Are install, queue, cache, migration, external API, and rollback risks visible where relevant? |
| Security/cache | Does the doc preserve public-output safety and avoid leaking admin/editor internals? |
| QA | Do local Markdown links resolve, stale package names disappear, and focused package tests pass? |
Verification Commands
Section titled “Verification Commands”Use the narrowest useful checks while editing:
vendor/bin/pest packages/<package>/tests --configuration=phpunit.xmlRun repository-level docs checks before finishing a broad documentation pass:
COMPOSER=composer.local.json composer docs:rewrite-readmes:checkCOMPOSER=composer.local.json composer docs:check:strictCOMPOSER=composer.local.json composer security:surface-report:checkWhen a package README documents behavior covered by tests, run the package-local Pest command or the specific test file named in the README.