Different Hunger

Reference

Gated Access CTA

Free preview, gated code. Visitors get their one best-fit offer, or the whole ladder when we know nothing about them.

Gated Access CTA

0HR Studio · Conversion · Gated Access CTAstable

Show references for free and gate the code behind an upgrade. The gate never shows a generic sales page. It renders only the offer cards from /invest, picked per visitor from the blueprint.

The component

Live, exactly as a visitor sees it. Links open in a new tab; the pay switch works.

Visitor we know nothing about → the whole ladder
Known visitor (agency persona) → one best-fit offer

In context — Preview | Code

Click Code. Every link inside the widget opens in a new tab, and the Paid Upfront / Split Pay switch is live.

Try it as a known visitor: agency · brand · freelancer.

Who sees what

VisitorCode tab shows
Studio owner (signed in)The real source for that variant
Nothing knownThe whole ladder: Accelerator · Automator · Operator
Persona knownThat persona's entry offer only
Meets a higher offer's qualifiersThe highest offer they fully qualify for
Already owns an offerThe next offer up (Advisor only after a sprint)
DisqualifiedFree option — [PLACEHOLDER] until decided

Decided server-side by apps/portal/lib/offers/best-fit.ts, which reads the Different Hunger blueprint (personas · persona→offer links · offer qualifiers · disqualifiers) on every request. Change the blueprint and every gate moves with it. Prices, features and buttons come from the same buildPlans as /invest, so they never drift.

Use it

1 · Put a Preview | Code pair on a docs page

<PreviewCode component="reels" variant="thirds-card-mcm">
  {/* anything free: video, image, live preview */}
</PreviewCode>

?persona= on the docs URL is passed through to the gate.

2 · Gate a new component family

  1. Generate a server-only module of its variants: { [variant]: { name, brand, status, files: [{ path, code }] } } — copy apps/portal/scripts/sync-reel-code.mjs.
  2. Register it in apps/portal/lib/gated-code/registry.ts:
export const CODE_REGISTRY = {
  reels: REEL_CODE,
  // yourComponent: YOUR_CODE,
};
  1. The gate is live at /os/code/<component>/<variant>. No new route.

3 · Show the offer panel anywhere else

import { GatedAccessCTA } from "@/app/os/code/upgrade-panel";
import { loadOfferEconomics } from "@/lib/offers/blueprint-economics";
import { bestFit } from "@/lib/offers/best-fit";

const [econ, fit] = await Promise.all([loadOfferEconomics(), bestFit({ persona })]);
<GatedAccessCTA econ={econ} offerKey={fit.mode === "one" ? fit.offer : null} />

Embed treatment — locked

Every widget framed inside another surface follows this, no exceptions:

RuleHow
Content only — no header, footer or titleroute listed in apps/portal/lib/non-conversion.ts
Fits the frame side by side, no swipeapp/os/code/zoom-fit.tsx scales the desktop layout down; swipe row only under 560px
Frame hugs the content, zero inner scrollapp/os/code/frame-height.tsx posts content height; the host frame listens
Every link opens in a new tabframe-height.tsx intercepts clicks when framed
Controls actually worke.g. the pay switch holds state

Files

FileRole
apps/portal/app/os/code/[component]/[variant]/page.tsxThe gate: owner → code, everyone else → offers
apps/portal/app/os/code/upgrade-panel.tsxGatedAccessCTA — the offer cards
apps/portal/lib/offers/best-fit.tsOne offer per visitor, from the blueprint
apps/portal/lib/gated-code/registry.tsWhich component families are gated
apps/portal/app/os/code/frame-height.tsx · zoom-fit.tsxLocked embed treatment
apps/docs/packages/template/app/components/docs/mdx/preview-code.tsxDocs Preview