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

Spatie Price Api Laravel Package

spatie/spatie-price-api

A small Laravel package that retrieves product prices from the spatie.be API, used on promotional sites for Spatie's own products. Open source but not intended for third-party use.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

This is a thin HTTP client plus a Blade/Alpine helper, not a pricing platform. The server-side surface is essentially a single static call — App\Support\SpatiePrices\SpatiePriceApi::getPriceForPurchasable() — and since 1.7.0 a SpatiePriceApi::scripts() helper that registers the spatiePrice(id) and spatieBundlePrice(id) Alpine components and drives a discount countdown in the browser. The footprint is small enough that the question is not "does it fit our architecture?" but "does the pattern fit?" The pattern — thin client → price payload → Blade helper → Alpine component → countdown — maps cleanly onto a Laravel + Blade/Livewire + Alpine front end.

The problem is the dependency, not the shape. The package hard-couples a business-critical value (price) to a host we do not control (spatie.be), with no provider abstraction, no local price store, and no fallback dataset. In 1.7.0 the resolution boundary also moves from our server to the visitor's browser. That is correct for promotional display and wrong for anything authoritative: a client-side fetch and a client clock are both untrusted, so expiry, eligibility, and discount application must still be re-validated server-side at cart and checkout.

Integration feasibility

Composer-installable, MIT, no heavy transitive dependencies, tested in CI. Effort for a Laravel app is minutes. Feasibility is high and relevance is low: the README states plainly that the package is not intended for third-party use, the backing endpoint is undocumented and unversioned, Packagist shows zero dependents, and the release cadence tracks Spatie's own catalogue and Laravel support matrix. Adopting it means pinning our promotional pricing to someone else's internal contract with no migration path if the response shape changes.

The realistic integration is a reference-implementation read (~half a day), followed by an internal equivalent (~2 engineer-days for a scoped spike) against a pricing source we control. The Alpine components are small; re-implementing them is cheaper than the governance overhead of carrying an unsupported dependency.

Technical risk

  • Vendor contract risk (high): undocumented, unversioned endpoint owned by a third party who has stated the package is not for outside consumption. Any catalogue or schema change breaks us silently, with no deprecation notice.
  • Availability risk (high): synchronous external call on the render path with no fallback. Spatie-side downtime or rate limiting becomes a promotional page with no price.
  • Correctness/trust risk (medium-high): browser-side fetch and countdown are advisory. If anyone treats a displayed discount as authoritative, that is a pricing-integrity incident.
  • SEO / no-JS risk (medium): client-side fetch leaves the price out of initial HTML — bad for crawlers, listing pages, and non-JS users. A server-rendered fallback is required regardless.
  • Asset pipeline / CSP risk (low-medium): scripts() injects JS. Verify against Vite entry points and our CSP before assuming inline injection is acceptable; on a Vue/React/Inertia stack the components would be rewritten anyway.
  • Maintenance risk (medium): single maintainer; release history is mostly Laravel 10/11/12/13 bumps plus one Alpine feature. Cadence reflects Spatie's needs, not ours.
  • Scope risk (low): what the package explicitly does not do — checkout totals, tax, entitlements, coupons, contract pricing, multi-currency conversion, seat-based or metered pricing — is exactly where our real pricing complexity lives.

Key questions

  1. Is there any scenario where our promotional pricing legitimately reads from spatie.be? If not (expected), this is a pattern study, not an integration.
  2. Which surfaces need a price in initial HTML for SEO/no-JS, versus purely campaign landing pages where client-side fetch is acceptable?
  3. What is our authoritative server-side pricing source (internal service, Stripe Prices, Paddle), and does it already expose a typed payload we can put behind an interface?
  4. Do we ship Alpine today (Livewire 3), and does our CSP/Vite setup permit a script-injection helper, or do we need a bundled entry point?
  5. What request volume does per-visitor client-side fetching generate, and does it bypass our CDN/cache entirely?
  6. Does marketing value campaign velocity — shipping a promo page without an engineering deploy — enough to fund a reusable internal version?
  7. Who owns server-side re-validation of expiry and eligibility at cart/checkout, and is that enforced today?

Integration Approach

Stack fit

Strong fit for the shape, conditional fit for the package. Laravel 10–13 support, PHP 7.4+ history, Blade + Alpine components that cost nothing to evaluate if we are already on Livewire 3. Wherever we run Vue/React/Inertia, the front-end half is not reusable and only the server-side client pattern transfers.

Migration path

There is no meaningful migration path away from this package — that is the core objection. It has no provider abstraction; swapping in our own API means rewriting the class. We should therefore never reach a state where migration is required:

  1. Week 1 — Spike (2 days engineering + review). Build an internal price client behind an interface, backed by our own pricing source, with caching and a typed price DTO. Add a Blade helper that registers Alpine components and a countdown. Deploy to one promotional page.
  2. Week 1–2 — Measure. A/B countdown vs. none, bundle framing vs. unit framing. Success criteria: measurable conversion delta, no regression in checkout integrity.
  3. Week 2 — Decide. If lift is real, harden the internal version (caching, fallback, observability) and standardise it for promo pages. If not, we spent two days and learned something.
  4. Never composer require the package into a production service.

Compatibility

Composer/PHP/Laravel constraints are satisfied by any modern stack. The real compatibility questions are operational: CSP and the asset pipeline for scripts(), presence of Alpine, and whether the chosen pricing source returns regional/localized values — the Alpine components inherit whatever the API returns, so per-region display needs no extra front-end work, provided a server-side source backs it.

Sequencing

Interface and DTO first (so the source is swappable), then the server-rendered price in initial HTML, then the Alpine enhancement and countdown, then measurement. Building the client component first inverts the dependency and bakes in the upstream package's core mistake.

Operational Impact

Maintenance

As a dependency: near-zero code to maintain but non-trivial risk to carry — single maintainer, a cadence driven by Laravel version bumps, an undocumented upstream contract, and no dependents to surface breakage early. We would be the only affected party and would not be consulted. Built internally: ~50–100 lines to own, plus an interface, cache, and DTO — well within one team's capacity and straightforward to test.

Support

Upstream support is best-effort from a vendor using the package on its own sites. No SLA, no deprecation policy, no channel for a third-party consumer to raise an issue that gets prioritised. Internal ownership is the only defensible support model for a value displayed on a page we sell from.

Scaling

Two distinct load profiles. Server-side, each call is a synchronous outbound request on the render path — so it needs a cache (short TTL per purchasable/region) and a circuit breaker, otherwise page latency and availability inherit the upstream's. Client-side, every visitor issues their own fetch: that traffic comes from end-user browsers, not our servers, so it bypasses our CDN and shared cache entirely, scales linearly with sessions, and is subject to per-user rate limiting and ad-blockers. Neither profile is addressed by the package.

Failure modes

Upstream 5xx or timeout → missing price, or an exception on the render path if uncaught. Schema drift → silently rendered blanks or wrong numbers. Alpine not loaded or blocked by CSP → price never appears. Stale CDN/proxy cache → price disagreeing with checkout at the moment of purchase. Countdown expiry on a client clock → urgency shown on an offer that has already ended (or dismissed on one still live). The common thread is that every failure is silent and visual rather than an error we would alert on; the only reliable detector is the checkout total disagreeing with the page.

Ramp-up

Trivial in code terms — one method, one helper — which is precisely the trap: a half-day to integrate, and then an indefinite tail of undocumented-contract risk. Budget the ramp-up against the internal pattern instead: roughly two days for a spike plus a short review with whoever owns pricing and checkout integrity. The deliverable worth keeping is the interface, the cached DTO, and the server-rendered fallback — not the dependency.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels