AstroBaaS

Operations & platform

Dynamic Product Badges

Paid pluginsize Sidea, not a commitment

Indicative price, not an offer: EUR 100-200/year or EUR 250 one-off

Generated from docs/plan/paid/dynamic-product-badges/PLAN.md in the project's planning notes, which are not part of the public repository. Nothing described below is implemented — it is the written plan for it.

An idea, not a commitment. It has a written plan but no place in the build order and no date. What is committed.

Static product images don’t convey promotions or inventory status. This feature adds dynamic badges (New, Sale, Low Stock, Bestseller) with rule-based activation, displayed as image overlays or in product cards.

The problem

My product cards are static. I want to show ‘New’, ‘On Sale’, ‘Last 3 left’ badges automatically based on product data, without editing images manually.

What it does

  • Badge types: predefined (New, Sale, Low Stock, Bestseller, Popular) and custom text badges
  • Badge rules: trigger badge based on product state (sale_price < regular_price, stock < 10, created_at < 30 days ago, sold > 100 in last 30 days)
  • Visual config: badge color, position (top-left, top-right, center), text/label, optional icon
  • Admin UI: toggle each badge type on/off, configure rules and visuals
  • Storefront: badges render as image overlays on product cards and detail pages
  • API: badge list for product (returns active badges for that product)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Animated badges (GIF/video overlays) — static images only
  • Customer-visible badge customization — admin controls visuals; customer sees result
  • Badge analytics (which badges drive clicks) — display only, no interaction tracking

Data model

New entity: Badge {id, name, type, enabled, rules (JSON: field + operator + value), visual_config (color, position, label), created_at}. Example: {type: ‘sale’, rules: {sale_price: ’<’, regular_price}, label: ‘Sale’, color: ‘red’, position: ‘top-right’}.

API

  • GET /api/products/:id/badges — return active badges for product (public)
  • POST /api/badges — create badge (admin only)
  • PATCH /api/badges/:id — update badge config (admin only)
  • DELETE /api/badges/:id — delete badge (admin only)

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Badge manager: list of badge types (New, Sale, Low Stock, Bestseller). Toggle on/off. Edit: configure rules (if sale_price < regular_price, show Sale badge), visual (color: red, position: top-left, label: ‘Sale’), preview badge on sample product card.

The seam — why this is paid

Core owns the badge model and storefront rendering logic. Paid layer owns advanced analytics and targeting (show badge only for specific customer segments, A/B test badge text).

Paid marketing feature. Core provides basic product info; dynamic badges with rule-based automation is a paid marketing tool.

Dependencies

  • Product entity with sale_price, created_at, stock fields (already shipped)
  • Sales/order history for bestseller calculation

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Badge ‘Sale’ is created with rule: sale_price < regular_price
  • Product with regular_price €50, sale_price €40 gets the Sale badge automatically
  • Badge is rendered on product card as image overlay (position: top-right, color: red, text: ‘Sale’)
  • Badge ‘Low Stock’ is created with rule: stock < 10
  • Product with stock=5 gets Low Stock badge; stock=10 does not
  • Badge is disabled; all products stop showing that badge (no cache invalidation needed; check on render)

Risks

Badge rules must be evaluated efficiently; querying ‘sold > 100 in last 30 days’ on every product list query could be slow (index on sale timestamps or pre-compute bestseller flag). Rule evaluation can be wrong if product data is stale. Badge clutter (too many badges) reduces impact; restrict to 2–3 simultaneous badges per product.

Commercial context

Suggested priceEUR 100-200/year or EUR 250 one-off
Rival anchorMirasvit Advanced Product Labels

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and CONTRIBUTING.md for how to work on this repository.