Different Hunger

Documentation

Badge

The "Built by 0 Hour Studio" footer signature — on every build by default.

Badge · "Built by 0 Hour Studio"

The signature that ships in the footer of every site and prototype we build and host — our "Made in Webflow." A traffic driver and backlink engine. On by default — hidden after a paid upgrade.

Hover either badge to trigger the glow — this is the real component, live:

The mark is our wireframe sphere + glyph. Default state is plain black/white; on hover / click / focus the glowing logo crossfades in. Type is Blanc — "Built by" Ultralight, "0 HOUR STUDIO" Bold. Square card whose fill matches the logo so there's no visible image box.

Use it

One source of truth: ~/0-hr/components/built-by-badge/. Import the gate, never copy-paste the markup.

import { BadgeGate } from "@/components/built-by-badge";

// dark footer
<BadgeGate client="lateral" variant="dark" />

// light footer
<BadgeGate client="mcm" variant="light" />
PropValuesNotes
client"mcm" · "dh" · "lateral"Per-site slug → ?ref=<client>. This is the attribution key — see Tracking. Required.
variant"dark" · "light"dark = light mark/text for dark footers · light = for light footers.
markSizepx (default 30)Mark size.

The link resolves to:

https://0hr.app/studio/showcase?ref=<client>&utm_source=client_site&utm_medium=badge

The & is a literal ampersand — never &amp; or any escaped variant (a prior build corrupted this and broke tracking). The component builds the URL via string concat to guarantee it. (Destination is temporarily the Studio showcase; reverts to 0hourstudio.com later.)

Tracking — where the clicks land

The ?ref= param was carried correctly from day one, but for months nothing read it: the showcase page dropped the query string, fired no event, and the portal had no GTM or pixel ID in production. Badge referrals were uncountable, not zero. As of 2026-09-09 the landing is instrumented:

EventFires when
showcase_viewA badge visitor lands on /studio/showcase
showcase_cta_clickThey click "Get Your Custom Roadmap" (placement: sidebar | footer)

Both carry ref, utm_source, utm_medium and utm_campaign straight off the URL, so referral volume is attributable per client install — and the view→CTA pair gives you a conversion rate, not just a hit count.

Events go out through the one track() in lib/analytics/track.ts (dataLayer + gtag + Meta), and — critically — to the first-party sink at POST /api/track, which writes them to the existing play ledger. No new table. Third-party tags are routinely ad-blocked; the same-origin sink is the number to trust, and it will read higher than Meta.

play.source     = "showcase"
play.type       = "page_view"      // play_type_check is a CHECK constraint —
play.data.event = "showcase_view"  // the real event name lives in data.event
play.data.ref   = "mcm"            // which client's badge sent them
play.brand_id   = <the 0hr brand>  // the showcase is 0HR's own surface, so views
                                   // roll up to 0HR, not to the referring client

Count referrals from one install:

select data->>'event' as event, count(*)
from play
where source = 'showcase' and data->>'ref' = 'mcm'
group by 1;

The event name is the contract. /api/track drops anything not on its allow-list — that is exactly how the first version of this wrote nothing at all. Adding an event means adding it in both lib/analytics/track.ts and the ALLOWED set in app/api/track/route.ts.

Removal lock — standing policy

The badge ships on every install and prototype by default. It comes out only when a client has cleared their full balance and owns the build outright.

To remove it for a project:

  1. Set OHS_BADGE_LOCKED = false (or pass locked={false} to <BadgeGate>).
  2. In the same commit, state the reason — e.g. "ohs-badge: unlock for mcm — POC paid in full, ownership transferred 2026-06-01."

While OHS_BADGE_LOCKED is true, the badge renders. Flipping it to false is the explicit, auditable act that authorizes removal.

Every instance — where the badge actually is

Verified 2026-09-09. Tracked means a click on that badge writes a badge_click row; see Tracking.

#InstanceSlugWhere it rendersTracked
1MCM Private Carebrands/mcm/site/app/components/Footer.tsxmcmGlobal footer → mcmprivatecare.com, every page✅ Live
2/os/badge demoapps/docs/.../BuiltByBadgeDemo.tsxdemoThis page, both variants✅ Live (tagged docs_demo so doc traffic never inflates a client's count)
3Different Hungerbrands/dh/site/app/components/Footer.tsxdhGlobal footer, dh-site Vercel URL only — no custom domain yet✅ Code ready, not on a public domain
4Canonical sourcecomponents/built-by-badge/Not a deployment. BuiltByBadge.tsx · track.ts · index.tsx (BadgeGate)

Not tracked — the fix list

InstanceProblemFix
Lateral — live sitelateralfulfillment.com carries no badge at all. A shipped client site earning zero referrals.Add <BadgeGate client="lateral" variant="…" /> to the footer.
brands/lateral/site/_export/*.html (5 files: index, about, presales, pricing, resources)Stale local export of an older, different badge — gradient pill reading "Made by 0 Hour Studio", pointing at 0hourstudio.com. Its href is corrupted: the ampersands were mangled into </body>amp;, so the params are junk. Not deployed — the live site is served from elsewhere.Replace with the canonical component; don't patch the export.
apps/showcase/badge-preview.htmlOld preview, same pre-showcase 0hourstudio.com destination, no beacon.Repoint or delete.
components/built-by-badge/_b · _r · _sq · _tight · _v .htmlStatic screenshot mock-ups used to render the PNG marks. Not deployed, no beacon needed.Leave as is.

The corrupted-ampersand case is the one to learn from. It is exactly what the string-concat rule above exists to prevent, and it is invisible until someone reads the raw href — the badge still looks and clicks fine.

See it in the wild

Scroll to the footer and hover the badge to trigger the glow: mcmprivatecare.com — the only badge on a public client domain today.

Badge destination (where every badge points): 0hr.app/studio/showcase

Rollout: Lateral, Beezys and the starter template are still outstanding — see the fix list above.