← All posts

The products we decided not to build

A product catalog looks like a landing page problem — a list of what you offer, rendered nicely. Underneath it’s a data model, and everything in that data model is a commitment. The interesting part of ours is what we crossed off.

The list, and the knife

The initial brainstorm for the smplkit catalog produced three shipped products — Config, Flags, Logging — plus fifteen we committed to as coming soon: Analytics, Auth, Billing, CMS, Data, Functions, Jobs, Metrics, Queue, Search, Storage, Telemetry, Testing, Webhooks, and Workflows.

And three that made the brainstorm but not the catalog. Cache, Email, and Messaging all got cut after we asked one question: “Would a developer choose smplkit over the category leader?” For Cache, the honest answer is Upstash or Redis Cloud. For Email, it’s Resend — sending email is a solved problem, and Postmark solved it too. For Messaging, it’s Kafka for high volume and NATS for everything else. In each case we’d be entering a crowded category against products with years of head start and zero differentiation angle on our side. So they went.

The products we kept share a common thread: they benefit from centralized control across services. Config, Flags, and Logging give you visibility into your whole fleet from one console, with SDKs that behave identically in every language. The same logic holds for the planned additions — distributed tracing, metrics aggregation, and workflow coordination are all better centralized. The cut products had no such angle — only a category leader to lose to.

”Coming soon” is a promise

Putting a product in the catalog has a governance implication: it’s a commitment to build and support it. Customers who sign up for a notification expect to eventually receive one. “Coming soon” is a promise, even if it’s not a dated one.

So the bar for the list: products we’re thinking about don’t appear; products we’re building do. The current coming-soon list reflects products we’ve actually designed — some with full ADRs — queued in rough build order, though we don’t publish a dated public roadmap.

The notify-me list is a prioritization tool

Coming-soon products appear in the navigation flyout and the homepage grid, greyed out with a badge and a “Notify me” form. Click it and you’re on the list for that product; when it ships, that list gets the email.

The same list is a demand signal pointed back at us. The day four hundred people have asked to be notified about Smpl Auth and twelve about Smpl CMS, the prioritization meeting runs itself. Interest you’d otherwise guess at becomes a number you can sort by.

The plumbing

The catalog started as a hard-coded list on the landing page, which worked until the same data was needed in three places: the marketing site’s navigation, the developer console’s product switcher, and the billing system’s subscription UI. Hard-coding one list in three codebases is a maintenance problem with a familiar shape, so the catalog became data with an API in front of it.

Each product is an entity:

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 app service serves this at /api/v1/products — read-only, JSON:API format, managed through the admin console rather than the customer-facing API. The status field drives rendering (active products get live CTAs, coming-soon products get the notify form), and the endpoint only returns what a given caller should see: the marketing site gets everything, the console’s product switcher gets the active products for the account’s subscription.

The payoff is the absence of coordinated deploys. The marketing site and the developer console ship independently; when the product list is data behind an API, adding a product or fixing a tagline is one change that propagates everywhere, instead of two deploys that have to land together.

What we’d revisit

Localized descriptions. The data model has no internationalization story; deferred until we have users who need one.

Tier availability as data. The catalog says which products exist but not which features come with which subscription tier — that lives in comparison-table components on the product pages. Moving it into catalog data would make “flag targeting rules require Pro” a fact you edit rather than a component you maintain.

A changelog for the catalog itself. When did Telemetry join the list? When did Cache leave? Git knows, the catalog doesn’t. A changelog for catalog changes would be useful for customer communications.