← All posts

The Product Catalog Isn't Just a Landing Page Problem

When you’re building a developer platform with multiple products, the product catalog — the list of what you offer, how it’s displayed, and what’s live vs. coming soon — is a UI concern on the surface and a data model concern underneath.

We started with the product catalog hard-coded on the landing page. That worked for a few weeks, until we needed the same data in three different places: the marketing site’s navigation, the developer console’s product switcher, and the billing system’s subscription UI. At that point, hard-coding the same list in three places became a maintenance problem, and we designed a proper product catalog.

This post describes the data model, the API, and some product decisions we made along the way.

The Initial List

When we designed the catalog, we were thinking about what developer tools we’d eventually build. The initial brainstorm produced 18 products:

Shipped (3): Config, Flags, Logging.

Planned but removed after reflection: Cache (commoditized — every cloud has this), Email (send email is a solved problem with Resend and Postmark; no differentiation), Messaging (pub/sub — extremely crowded space, hard to compete with Kafka and NATS).

Coming soon (15): Analytics, Auth, Billing, CMS, Data, Functions, Jobs, Metrics, Queue, Search, Storage, Telemetry, Testing, Webhooks, Workflows.

The removal of Cache, Email, and Messaging came from asking: “Would a developer choose smplkit over the category leader?” For Cache, the answer is Upstash or Redis Cloud. For Email, the answer is Resend. For Messaging, the answer is Kafka for high-volume and NATS for everything else. We’d be competing with products that have years of head start and zero differentiation angle.

The products we kept have a common thread: they benefit from centralized control across services. Config, Flags, and Logging give you visibility into what’s happening across your whole fleet from one console, with SDKs that work consistently in every language. The same logic applies to the planned additions: distributed tracing (Telemetry), metrics aggregation (Metrics), workflow coordination (Workflows) — these are all better centralized.

The Data Model

Each product is an entity with:

class Product:
    id: str           # Slug identifier: "config", "flags", "logging"
    name: str         # Display name: "Smpl Config"
    tagline: str      # One-line description for navigation
    description: str  # Longer description for product pages
    status: str       # "active", "coming-soon"
    icon_url: str     # URL to the product's SVG icon
    page_url: str     # URL to the product's marketing/console page
    order: int        # Display order in navigation and grids

The status field drives rendering: active products show “Try the live demo” CTAs; coming-soon products show “Notify me when available” forms. The API only returns products visible to a given caller — the marketing site gets all products, but the developer console’s product switcher only shows active products for the account’s subscription.

The API

The product catalog is served by the app service at /api/v1/products. It’s a read-only endpoint — products are not managed through the customer-facing API, only through the admin console.

The response structure follows JSON:API. Each product is a resource with the fields above. The icon_url is an absolute URL to assets served from the marketing site’s CDN.

The developer console’s navigation, the marketing site’s navigation flyout, and the pricing page all read from this endpoint. When we update a product’s tagline or add a new coming-soon product, it propagates everywhere without a coordinated deploy.

This was the original motivation for making the catalog an API rather than a static list: avoiding the coordinated deploy problem. The marketing site deploys independently from the developer console. If the product list is hard-coded in both, adding a product requires two deploys, coordinated. If the product list is an API, one data change updates everything.

The Coming-Soon Experience

Coming-soon products need special care. They should be visible enough that customers know what’s on the roadmap (this builds confidence, generates leads, and lets us gauge interest) but not so prominent that they distract from active products.

Our approach: coming-soon products appear in the navigation flyout and the homepage grid with a distinct visual treatment (greyed out, with a “Coming soon” badge) and a notification form. When a customer clicks “Notify me” on a coming-soon product, we add them to a list for that product. When the product ships, we email that list.

The notification list doubles as a demand signal. Before committing to building a product, we can look at the notification list and see real signal: 400 people have asked to be notified about Smpl Auth; 12 people have asked about Smpl CMS. Those numbers inform prioritization.

The Governance Question

The product catalog has a governance implication: adding a product to the list implies a commitment to build and support it. Customers who sign up for notifications expect to eventually receive them.

We’re careful about what goes in the catalog for this reason. “Coming soon” is a promise, even if it’s not a dated one. Products that are speculative (we’re thinking about it) don’t make the list; products that are committed (we’re building it) do.

The current coming-soon list reflects products we’ve designed (some with full ADRs) and are building in sequence. The ordering roughly reflects our build priority, though we don’t publish a public roadmap with dates.

What We’d Revisit

Localized product descriptions. As we expand to non-English markets, the product catalog needs localized content. The current data model doesn’t support this. Adding internationalization to the catalog is a well-understood problem, but we’ve deferred it until we have users who need it.

Dynamic feature availability. The catalog tells you what products exist but doesn’t currently surface which features within a product are available at which subscription tier. This lives in the comparison tables on product pages. Tying it to the catalog data model — so “flag targeting rules require Pro” is data, not hardcoded in the comparison table component — would make it easier to maintain.

Version history for the catalog. When did we add Telemetry to the catalog? When did we remove Cache? This information is in git history but not in the catalog data itself. A changelog for catalog changes would be useful for customer communications.

smplkit’s product catalog is served as an API by the app service, consumed by the marketing site and developer console. Active products (Config, Flags, Logging) are in production; fifteen coming-soon products reflect committed roadmap items.