Staaarter

Billing Add On Marketplace

A marketplace-style list for browsing optional add-ons like extra storage, security, or support. Each row shows a category icon, description, and price, with the action button switching between Add, Manage, and a disabled Pending state depending on the add-on's status. Renders entirely on the server since nothing in it needs client-side interactivity.

By Staaarter Team
Billing
Updated May 26, 2026
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its badge, button dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/billing-add-on-marketplace.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/billing/billing15.tsx instead.

Usage

The file also exports billing15Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Billing15, billing15Demo } from "@/components/blocks/billing/billing15";

export default function Page() {
  return <Billing15 {...billing15Demo} />;
}

Props

PropTypeDefaultDescription
headingstring"Add-on marketplace"Heading above the list.
descriptionstringnoneOptional supporting sentence under the heading.
addOnsMarketplaceAddOn[]noneAdd-ons rendered as rows, in the order given.
addLabelstring"Add"Button label for add-ons with status "available".
manageLabelstring"Manage"Button label for add-ons with status "active" or "pending".
classNamestringnoneExtra classes for the outer wrapper.

Types

type AddOnCategory = "storage" | "security" | "analytics" | "support" | "compute";

interface MarketplaceAddOn {
  id: string;
  name: string;
  description: string;
  price: string;
  category: AddOnCategory;
  status?: "available" | "active" | "pending";
  href?: string;
}

Behavior notes

  • Category is a fixed 5-value union mapped to a Lucide icon in CATEGORY_ICONS; add a new category by extending both the type and that map.
  • status defaults to "available" when omitted, showing an Add button. "active" swaps in an Active badge and a Manage button, and "pending" shows a Pending badge with a disabled Manage button.
  • Add and Manage render as next/link via the Button component's render prop, so href can point straight at a real route without any client-side handler.
  • The component holds no internal state and needs no "use client" directive, so it can render with real account data straight from a server component.

Frequently asked questions