AstroBaaS

Operations & platform

Dynamic Product Badges

Paid pluginsize Splanned, not built

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 AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

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 ../../AI-GUIDE.md for how to work on this repository.