AAOA.studio · Case Study · Web · Next.js · Convex
A link-in-bio platform built on an anti-greed foundation: the price drops the more people pay. Not a clone, a villain seeking vengeance for the death of a loved one.
Ch01
Bento.me was a link-in-bio tool built around a bento-grid layout, a flexible canvas of cards for links, social profiles, media, and whatever else a person wanted to surface. It was good. It had an audience that liked it. Then Linktree acquired it, and shortly after, shut it down. The loss was personal: the studio's own bento profile was among the casualties, hastily exported as a screenshot the week the shutdown email arrived.
The obvious response is to build a clone. Fill the gap, serve the displaced users, run on standard SaaS pricing. That is the sensible business decision. Bhann is not that. Bhann is the other response: build the replacement with a structural principle that makes it constitutionally incapable of doing what Linktree did.
Not a clone. A villain seeking vengeance for the death of a loved one, and its weapon is the pricing model.
Linktree Pro costs €54 a year ($4.50 a month). That price does not change based on how many people use Linktree. The more subscribers they have, the more revenue they extract, full stop. This is the standard model: grow subscribers, grow revenue, the two are proportional, the company keeps the difference between cost and price forever.
Bhann inverts the relationship. Subscriber growth lowers the price, for everyone, including the people already subscribed. The product still has to sustain itself but any margin beyond that goes back to the people paying for it. The platform cannot become a machine for extracting value from a captive user base because it is structurally prohibited from doing so.
Ch02
The pricing model has 21 tiers. Tier 1, Pioneer, is for the first 99 paying subscribers: €30 per year. When the platform reaches 100 subscribers, the price drops to €26 for everyone and the tier becomes Founder. At 500 subscribers, €22. At 1,000, €19. Free accounts do not move the staircase; only paying subscribers count. The descent continues in decreasing steps until the floor: €6 per year at one million subscribers. The staircase lived as a spreadsheet for a month before any code was written, and the steps were redrawn a dozen times before they stopped moving.
Three properties make this model interesting. First, everyone always pays the current market price or less, never more. When a new tier is reached, all subscribers move to the lower price. Second, when you subscribe, your tier index is locked: if you joined at €30 and the price drops to €19, you renew at €19, not €30. Third, the lock only ever improves. If you somehow locked at a higher tier index than the current market, you pay the current lower market price at renewal.
The staircase is implemented in convex/pricing.ts. A single stats table tracks the live paying subscriber count; free accounts never touch it. On every subscription event, the current tier index is looked up and stored on the user record as lockedTierIndex. At renewal, the system takes the minimum of locked and current market price, the user always wins any tie.
// At subscription time: lock to current tier index. // HIGHER index = LOWER price (better for user). // Keep existing lock if it's already better. const newLockedTierIndex = user.lockedTierIndex !== undefined ? Math.max(user.lockedTierIndex, currentTierIndex) : currentTierIndex; // At renewal: pay whichever is lower, locked or current market. const actualAnnualPrice = Math.min(lockedAnnualPrice, marketAnnualPrice);
There is also a lifetime option at €163.57, a one-time payment, no renewals, no subscriptions. The amount is not round, it is what the model's NPV calculation suggested was fair given projected infrastructure costs and the floor price trajectory, basically projected user cost for the next 10 years, after that they cost me money.
Linktree does things Bhann cannot, social scheduling, a large partner ecosystem. The comparison is not a claim that Bhann beats Linktree across every dimension. It is that for a creator who only needs a link-in-bio page, which is most of them, Bhann starts at €30 versus €54, and the gap widens every time a new subscriber joins.
Ch03
The profile editor is a drag-and-drop bento grid built on react-grid-layout. Cards can be any size, placed anywhere, and styled individually. Desktop and mobile layouts are stored independently, the same cards, different positions, so a profile can be genuinely optimised for both form factors rather than one being a collapsed version of the other.
The card system supports 67+ distinct types. Social platform links, embedded media, commerce integrations (Gumroad, Ko-fi, Patreon, Stripe), professional portfolio cards (GitHub, Dribbble, Figma, Behance, Calendly), interactive toys (a tone matrix sequencer, an etch-a-sketch, an analogue clock), and a full-length case study card with block content edited in a Tiptap rich text editor. The tone matrix sequencer was built in a single evening, mostly as a joke, and then refused to be cut, it remains one of the most fun interactive cards. The set is large enough to cover almost any creator's real use case while keeping the interface coherent.
Public profiles are server-rendered and edge-cached using Next.js ISR with a 60-second revalidation window. The first request after a cold edge miss hits the Convex backend; every subsequent request within the minute is served from Cloudflare's edge network without touching the database. Profile edits appear within 60 seconds without a redeploy.
// ISR: revalidate every 60 seconds. // First request misses cache → hits Convex → caches at edge. // Subsequent requests served from Cloudflare in <100ms TTFB. export const revalidate = 60; // Edge runtime for sub-100ms cold starts on Cloudflare. export const runtime = "edge"; // LLM-friendly profile data embedded in server-rendered HTML. // AI agents can read public profiles without client-side JS. const llmProfile = generateLLMProfile(profile);
Themes are configurable at the profile level: background (solid, gradient, image, pattern), heading and body fonts, card border radius, spacing, and a full set of colour tokens. Individual cards can also override their own background and text colour. A card theme registry maps named themes to CSS variable sets, applied at runtime via a ThemeStyleInjector component that does not require re-rendering the grid.
The 67+ card types are a component library in the traditional sense: each card has defined variants, a token-based theming contract, and strict separation between layout structure and visual presentation. The ThemeStyleInjector applies CSS variable sets at the card level without touching the grid layout, so a profile's visual language can change entirely without a single DOM reflow. The same token architecture governs profile-level themes and per-card overrides, the same way semantic design tokens govern both global and local scope in a mature design system. It is what makes 67 card types feel like one coherent editor rather than 67 separate design problems.
Ch04
The anti-greed foundation only works if it is verifiable. A platform that claims to lower prices as it grows, but does not show you whether it is actually growing, is just a marketing pitch. The staircase only descends if the subscriber count actually climbs, so the climb has to be public: Bhann publishes its financials in real time.
The transparency page shows live MRR, total users, paying users, monthly infrastructure costs, initial build spend (€1,365.17), current balance, and a sustainability gauge, the ratio of income to expenses. The data comes directly from the Convex backend and refreshes in real time. Anyone can see whether the platform is covering its costs before they decide to subscribe.
Analytics are built into every published profile: views, unique visitors, card clicks, top countries, referrers, and device breakdown. Data is stored in a single consolidated record per profile, not one row per event, updated incrementally on each view or click. This keeps query costs proportional to the number of profiles, not the number of events, which matters at scale on a platform where infrastructure cost is part of the pricing argument.
Coda
126 users. €80 in three months. By any standard growth metric, this is a failed launch. The honest assessment is that a structurally sound product in a crowded category, without a marketing strategy, is invisible, and visibility was never part of the plan.
What the numbers do not invalidate: the model works. The staircase pricing is implemented, auditable, and live. The transparency page shows real figures in real time. The founder badges are locked to join order in the database and cannot be revised. The platform does exactly what it claimed it would do, and nothing it could not maintain, the same integrity call that kept the social scheduler out of scope. The problem was not the idea, it was that ideas do not distribute themselves.
The lesson is about sequencing. A novel pricing model is a story that needs to be told, loudly, repeatedly, to the right audience. Building the model and assuming the story would spread on its own was the mistake. The platform will stay live as long as it is personally useful, and as a proof that decremental pricing is not theoretical. If the marketing ever arrives, the product is ready.
Bhann was built with Cursor and Claude Code throughout. The decremental pricing model, the bento editor's drag-and-drop layout logic, the ISR caching layer, the Stripe webhook and tier lock system, implemented in four months at the pace these tools make possible for a lean, designer-led team. The architecture decisions were never AI's to make: whether the pricing model was structurally sound, what the 67 card types should be and how they should compose, why the transparency page mattered to the anti-greed argument. Without LLMs as an implementation partner, a designer without a CS degree does not ship a full-stack Next.js + Convex platform. With them, it took four months.
Try Bhann