Skip to content

Package authoring jobs

Start with the job the package performs, then choose the smallest extension points that make that job installable and testable.

Use this when the package owns a new kind of content, not just extra fields on an existing type.

  1. Declare content and usually admin in capell.json surfaces.
  2. Add a page-type contribution with the class that registers the type.
  3. Register the page type from a runtime provider with CapellCore::registerPageType(...).
  4. Add admin configurators or schema extenders only for fields the package owns.
  5. Add tests that assert the page type appears in the registry and unsupported contexts fall back to the base type list.

Keep rendering data outside public Blade. Load page data in Actions, controllers, payload builders, or view components before rendering.

Use this when the package renders public HTML through Layout Builder, a frontend component alias, or a render hook.

  1. Declare frontend in surfaces.
  2. Declare the closest contribution type: frontend-component, render-hook, asset, route, or section.
  3. Register frontend behavior from the frontend/runtime provider, not an admin-only provider.
  4. Pass hydrated data into Blade. Public package views must not query models, lazy-load relations, or inspect the current admin user.
  5. Add anonymous public-output safety tests proving no authoring selectors, model IDs, field paths, permissions, package internals, or signed admin URLs leak.

Use RenderHookRegistry::registerView() for view-name hooks, registerInlineBlade() for inline Blade snippets, registerCallable() for closures, and registerExtension() for class-based render hooks. Package-owned keyed hooks should use RenderHookContributionData::view(), inlineBlade(), or extension() so diagnostics, stable dedupe keys, and cache-safety metadata stay attached.

Use this when the package changes editorial state, review, approval, reminders, or release windows.

  1. Declare workflow and admin surfaces.
  2. Put state changes in Actions. UI, commands, jobs, and subscribers should delegate to those Actions.
  3. Declare permissions and settings in capell.json.
  4. Register admin pages, widgets, table columns, notifications, or validation subscribers through Admin bridges or typed extenders.
  5. Test the Action directly, then test the UI/command only for delegation, permissions, prompts, and visible state.

Packages that affect publishing should also document whether they block publish, warn editors, or provide advisory information only.

Use this when package data can change public output.

  1. Declare delivery and any public surface the package affects.
  2. Declare cache-related capabilities such as cache-invalidation, cache-blocking, public-static, or frontend-assets where accurate.
  3. Register model dependencies with CacheInvalidationRegistry::registerDependency(...).
  4. Set performance.cacheSafety accurately in capell.json. For a package with a frontend contribution and cacheable: true, capell:extension-audit reports an error (“unsafe public cache variance”) when variesBy lists any of auth, locale, preview-token, role, site, user or workspace. Output that genuinely varies on one of those axes is not publicly cacheable: declare cacheable: false rather than removing the axis to pass the audit.
  5. Test both the invalidation path and the safe fallback when the package is missing or disabled.

If public output varies by user, role, preview token, workspace, or other private state, mark it clearly. Cached HTML must be safe for anonymous visitors, normal signed-in users, admins, crawlers, and static exports.

Use this when the package will be listed, sold, bundled, or installed through Marketplace.

  1. Fill product, commercial, and marketplace metadata in capell.json.
  2. Declare every shipped contribution; do not leave contributes empty for a package with runtime surfaces.
  3. Add screenshots with useful alt and caption text, and commit referenced assets.
  4. Document setup, support, compatibility, safety caveats, and screenshot capture instructions.
  5. Add tests that validate manifest metadata, contribution contracts, screenshot paths, docs links, commercial tier, support policy, and compatibility.

Marketplace copy should explain the outcome the package improves before naming implementation details.

The normal path is:

  1. Scaffold with php artisan capell:make-extension vendor/example --profile=minimal --path=packages.
  2. Fill capell.json with identity, surfaces, provider buckets, dependencies, contributions, capabilities, performance, commercial, and marketplace metadata.
  3. Put domain behavior in src/Actions and structured state in src/Data.
  4. Register runtime behavior from the provider bucket that owns it.
  5. Add the admin/editor surface through an Admin bridge when there is more than one admin concern.
  6. Add public output through frontend registries with safe hydrated render data.
  7. Add migrations and settings migrations with existence guards.
  8. Add tests for Actions, manifest/contribution contracts, install/setup behavior, public-output safety, and safe fallbacks.
  9. Add screenshots and docs when the package is Marketplace-ready.
  10. Run the package tests, audit the manifest, and verify docs links before release.

Use extension point chooser when deciding which registry or contract fits the job. Use extension point API reference only after the job and surface are clear.