pollora/assets
pollora/assets provides asset handling for Pollora applications, making it easy to register, version, and enqueue CSS and JavaScript, resolve built asset paths, and integrate modern build tooling such as Vite with Laravel-style configuration.
What shipped: v0.1.0 is the first standalone extraction of the Pollora framework's asset layer. It contains the full asset pipeline (AssetManager, AssetContainer, AssetEnqueuer, AssetFile), plus a missing-build notice mechanism, three environment-binding contracts (ViteManagerFactory, RuntimeContext, PublicPath), a native/no-Laravel NativeViteManager that reads the Vite manifest and hot file directly, and a Pollora\Asset\Asset facade for classic themes, plugins, and Bedrock sites.
Architecture fit: The design is deliberately layered and that is the package's main architectural virtue. The three contracts are the seam: Laravel binds them one way, WordPress binds them another, and NativeViteManager is a framework-free implementation of the Vite resolution contract. That means the core asset model (containers, enqueueing, file resolution) is not coupled to the Laravel container, which is what makes a non-Laravel WordPress story credible rather than aspirational. The fluent entry point (Asset::add()->container()->useVite()->toFrontend()) is a thin DSL over the manager, which is good for readability but means the facade is a public API surface we would be committing to.
Integration feasibility: Feasible, with two dependencies to manage. First, the PHP side needs container declarations (Asset::addContainer()) and an environment binding — trivial in Laravel, manual but small in WordPress. Second, the build side expects @pollora/vite-config with layout: 'standalone', so PHP package version and JS config version are coupled artifacts that must be upgraded together. That coupling is the single largest integration cost and should be treated as a two-artifact release train, not a Composer-only upgrade.
Technical risk:
NativeViteManager reads the hot file directly, so the guardrails (if any) need verification.PublicPath abstraction helps, but Bedrock's web/app layout, symlinked releases, CDN domains, and WordPress multisite all stress path assumptions differently.Key questions:
@pollora/vite-config — is compatibility declared anywhere machine-readable?NativeViteManager tested for parity against the framework resolver, and against real manifests from @pollora/vite-config?type="module" and crossorigin handling, CSP/nonce support, escaping of emitted tags, sanitization of manifest keys.WP_CONTENT_URL behavior; how is the public path derived in each case?Stack fit: Strong fit for teams already on Vite who are fighting WordPress enqueueing manually — hashed filenames, manifest lookups, module scripts, and HMR are exactly the recurring boilerplate this removes. The package is stack-neutral by construction: Laravel consumers get the framework bindings, WordPress consumers get NativeViteManager and the facade. Bedrock and plugin authors are first-class, not afterthoughts, which is unusual and worth crediting. The cost of entry is the @pollora/vite-config build config, so this is not a drop-in for teams with a bespoke Vite setup already in production — they will be evaluating adoption of a build convention, not just a library.
Migration path:
wp_enqueue_*: lowest risk. Introduce one container for one entry point, keep existing enqueues untouched, and compare emitted markup before expanding.Compatibility: Two axes — PHP/framework versions and the JS config package version. The second is undocumented in this release note and is the one that will bite. Pin both in composer.json and package.json together, and record the validated pair in our own upgrade notes.
Sequencing:
@pollora/vite-config for teams with bespoke builds.Gate the whole sequence on questions 1, 2, and 4. Do not adopt broadly while the package is pre-1.0 and the framework relationship is unclear.
Maintenance: Low surface, but two artifacts to keep in lockstep (Composer package + @pollora/vite-config). Budget for paired upgrades. Pre-1.0 means reading changelogs on every minor bump, not just majors. Because class names are inherited from the framework, upstream renames propagate as breaking changes for us — worth tracking the framework's release notes in parallel.
Support: Operational burden concentrates in build/deploy, not runtime. The two recurring support tickets will be "styles are unstyled in production" (manifest not found, or built to the wrong outDir/public path) and "site is loading from localhost" (hot file left in a release artifact). Both need a runbook entry and a deploy-time check rather than developer diagnosis. The missing-build notice is only useful if someone reads it — wire it to logs or a health check, and consider making it fatal in CI/staging and non-fatal in production.
Scaling: Runtime cost is negligible — manifest parsing per request is the only real hot path, so verify the parsed manifest is cached (per-request at minimum, ideally persistent) rather than re-read on every wp_enqueue callback. Static asset delivery scales with the CDN, not this package. Multisite and high-theme-count environments multiply the number of containers and public paths, which is a configuration-management concern more than a performance one.
Failure modes:
web/app, symlinked releases, CDN base URL, multisite) → 404s with correct-looking HTML. Highest-probability misconfiguration; needs an explicit config checklist.type="module", defer, crossorigin, CSP nonces — subtle breakage in older themes or strict CSP setups.Ramp-up: Moderate. A developer fluent in Vite and WordPress enqueueing will be productive in a day; the fluent API is self-documenting. The real learning curve is conceptual — understanding what a container is, which contract binds it to the environment, and where the public path comes from. Write a short internal guide covering container declaration, the Laravel-vs-native binding choice, and the deploy checklist; that guide is worth more than any upstream docs at v0.1.0. Keep the adoption team small and opinionated through the pilot so the container conventions are set once rather than per project.
How can I help you explore Laravel packages today?