acmecorp/reference-extension
A lightweight Laravel/PHP reference extension offering reusable helpers and integration points for common package workflows. Simple to add, but limited adoption and likely sparse docs make it best suited to small projects or experimentation.
This package is a scaffold, not a library. Treat it as a template you copy once per extension you build, then own the resulting code. Installing it as a runtime dependency (composer require acmecorp/reference-extension) gives you nothing — there is no service to call from your app code.
Minimal path to a first working extension:
git clone https://github.com/bolt/reference-extension my-extension && cd my-extension && rm -rf .git composer.lock vendor.composer.json first. It carries the three things Bolt actually keys off: "type": "bolt-extension", the PSR-4 autoload mapping (Acme\ReferenceExtension\ → src/), and the require block pinning bolt/core / PHP versions. Rename the package (acmecorp/reference-extension → yourorg/your-extension) and the namespace here and everywhere under src/.src/. It extends Bolt's base Extension class and is where services, routes, Twig functions, and event subscribers are wired. This one file is 80% of what the template is teaching.config/ and templates/ next. The config file plus its schema shows how extension config gets merged with site config; the templates show the Twig namespace registration pattern."repositories": [{ "type": "path", "url": "../my-extension", "options": { "symlink": true } }]
then composer require yourorg/your-extension:@dev and clear cache.
First use case to validate the scaffold: make the extension expose one Twig function (e.g. {{ my_greeting('world') }}) and one backend route. If both work, discovery, autoloading, DI, and config are all correct — everything else is additive.
Fork-per-extension, not shared base. The healthy pattern is one copy of this repo per extension, with divergent src/ code. Resist the urge to abstract a shared parent package until you have three extensions with genuinely identical needs; the coupling cost with a 5-star, zero-dependent template is not worth it.
Service registration over fat classes. Keep the extension class thin: register services in the container, and put logic in plain injectable classes under src/. This is the single biggest maintainability lever, and it makes the code testable outside of Bolt's kernel.
Event subscribers for cross-cutting behaviour. Rather than editing templates or core, subscribe to the events the template already demonstrates (request/kernel, storage, backend menu). Each subscriber is a small class; the extension class just lists them. This keeps upgrade pain localized.
Twig extensions as the public surface. For most day-to-day work — exposing data to templates, formatting helpers, small queries — a Twig function/filter is what you ship. Register it once in the extension class, keep the implementation in a service, and template authors get a stable API.
Config with a schema, always. Define extension config in config/ with a schema file rather than reading ad-hoc values. It documents the knobs, gives validation errors instead of silent nulls, and means site owners can override without touching your code.
Path repository during development, VCS repository for staging. Symlink locally for instant feedback; only tag a release when the extension stabilizes. Because this template ships no versioning contract, pin your own tags and use @dev explicitly rather than relying on implicit constraints.
Frontend assets: build, don't commit node_modules. The template's asset pipeline expects a build step. Commit the built output only if the host site's deploy can't run the build; otherwise document the build command in your README, because nobody will guess it.
Testing harness is the real value. Port the PHPUnit/PHPStan/ECS configs into your fork and keep them green. With no dependents and no external users, your own CI is the only thing catching regressions.
bolt/core at whatever version was current when it was generated. Check composer.json against the Bolt version on the host site before copying code, and expect the extension-class API (service registration signature, event names, base class location) to have moved between major versions. Diff the template's src/ against the docs for your installed version rather than trusting it.composer.json, all of src/, and templates/ in one pass, then composer dump-autoload.cache:clear your reflex before debugging anything.acmecorp strings in composer.json, the extension's display name, translations, or the README are the most common review finding on scaffolds. Grep for the original vendor and extension name before your first commit.src/ before depending on it (it's small enough to read), vendor-copy rather than require it, and don't file issues expecting SLA responses. MIT license means forking is the sanctioned escape hatch — take it early rather than working around template limitations.How can I help you explore Laravel packages today?