Skip to content

Commit 535bf75

Browse files
sktbrdclaude
andcommitted
feat(pitch): crew speech balloons on /morpheus, live product embeds on /base
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 860d5eb commit 535bf75

7 files changed

Lines changed: 107 additions & 3 deletions

File tree

messages/en/base.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@
3838
"farcaster": "Farcaster mini-app integration — the auction and stake flows run inside the feed.",
3939
"mobile": "Mobile-first: every DAO feature works on a phone."
4040
},
41-
"culture": "What Gnars brings to Base is an audience crypto doesn't reach on its own: skate, BMX, and surf culture, funding real riders and real videos through a DAO that actually executes onchain."
41+
"culture": "What Gnars brings to Base is an audience crypto doesn't reach on its own: skate, BMX, and surf culture, funding real riders and real videos through a DAO that actually executes onchain.",
42+
"liveTitle": "Don't take our word for it — this is the live product",
43+
"liveDesc": "The sections below aren't screenshots. They're the same live components the site runs in production — auction, governance, swap, and rider staking."
4244
}

messages/en/stake.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
"unlocked": "unlocked",
2828
"next": "next up",
2929
"upcoming": "on the ladder"
30+
},
31+
"crew": {
32+
"title": "The crew breaks it down",
33+
"vlad": "We run a Builder subnet on Morpheus. Stake MOR behind the crew — every coin funds what Gnars ships next on decentralized AI.",
34+
"r4to": "Morpheus also powers the sponsorship vaults: back a rider on /stake with stETH or USDC and the yield lands in MOR — principal unlocks 7 days after your last stake.",
35+
"yan": "The $gnars airdrop is locked. Every milestone the community stakes past unlocks the next bucket — early stakers set the pace.",
36+
"pamtech": "And every milestone ships real Morpheus marketing from our side: the Gnars TV ad at 10k, edits, swag, IRL activations."
3037
}
3138
},
3239
"title": "Stake or Die",

messages/pt-br/base.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@
3838
"farcaster": "Integração de mini-app do Farcaster — os fluxos de leilão e stake rodam dentro do feed.",
3939
"mobile": "Mobile-first: toda funcionalidade da DAO funciona no celular."
4040
},
41-
"culture": "O que a Gnars traz pra Base é uma audiência que a cripto não alcança sozinha: a cultura do skate, BMX e surf, financiando riders e vídeos de verdade através de uma DAO que executa onchain de fato."
41+
"culture": "O que a Gnars traz pra Base é uma audiência que a cripto não alcança sozinha: a cultura do skate, BMX e surf, financiando riders e vídeos de verdade através de uma DAO que executa onchain de fato.",
42+
"liveTitle": "Não precisa acreditar — isto abaixo é o produto ao vivo",
43+
"liveDesc": "As seções abaixo não são screenshots. São os mesmos componentes que o site roda em produção — leilão, governança, swap e staking de riders."
4244
}

messages/pt-br/stake.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
"unlocked": "destravado",
2828
"next": "próximo",
2929
"upcoming": "na escada"
30+
},
31+
"crew": {
32+
"title": "A crew explica",
33+
"vlad": "A gente roda uma subnet Builder na Morpheus. Faça stake de MOR atrás da crew — cada moeda financia o que a Gnars entrega em IA descentralizada.",
34+
"r4to": "A Morpheus também move os vaults de patrocínio: apoie um rider na /stake com stETH ou USDC e o rendimento chega em MOR — o principal libera 7 dias depois do último stake.",
35+
"yan": "O airdrop de $gnars está travado. Cada marco que a comunidade cruza destrava o próximo bucket — quem staka cedo dita o ritmo.",
36+
"pamtech": "E cada marco entrega marketing de verdade da Morpheus do nosso lado: o anúncio na Gnars TV aos 10 mil, edits, swag, ativações IRL."
3037
}
3138
},
3239
"title": "Stake or Die",

src/app/[locale]/base/page.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { Metadata } from "next";
22
import { getTranslations, setRequestLocale } from "next-intl/server";
3-
import { BasePageContent } from "@/components/base/BasePageContent";
3+
import { BasePageContent, BaseUnderHood } from "@/components/base/BasePageContent";
4+
import { GovSection } from "@/components/newhome/GovSection";
5+
import { StakeSection } from "@/components/newhome/StakeSection";
6+
import { SwapSection } from "@/components/newhome/SwapSection";
47

58
// The pitch page for Base ecosystem programs (Base Batches): everything Gnars
69
// runs on Base, with links to the live surfaces. See BasePageContent.
@@ -46,6 +49,13 @@ export default async function BasePage({ params }: { params: Promise<{ locale: s
4649
return (
4750
<div className="py-10">
4851
<BasePageContent />
52+
{/* The proof: live production sections, not screenshots. GovSection is
53+
the daily auction + recent proposals + activity feed; SwapSection is
54+
the working 0x swap widget; StakeSection is the rider roster. */}
55+
<GovSection />
56+
<SwapSection />
57+
<StakeSection />
58+
<BaseUnderHood />
4959
</div>
5060
);
5161
}

src/components/base/BasePageContent.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,23 @@ export function BasePageContent() {
8585
</ul>
8686
</section>
8787

88+
{/* Handoff line into the LIVE embeds the page composes after this
89+
component (GovSection, SwapSection, StakeSection — real production
90+
sections, not screenshots). */}
91+
<section className="pt-2 text-center">
92+
<h2 className="text-2xl font-black tracking-tight sm:text-3xl">{t("liveTitle")}</h2>
93+
<p className={`mx-auto mt-2 max-w-2xl text-sm ${MUTED}`}>{t("liveDesc")}</p>
94+
</section>
95+
</div>
96+
);
97+
}
98+
99+
/** The plumbing + culture pitch, rendered by the page AFTER the live embeds. */
100+
export function BaseUnderHood() {
101+
const t = useTranslations("base");
102+
103+
return (
104+
<div className="mx-auto w-full max-w-5xl px-4 sm:px-6">
88105
{/* The Base-native plumbing — the part reviewers actually ask about */}
89106
<section className={`${CARD} ${CARD_PAD}`}>
90107
<h2 className="text-lg font-bold tracking-tight">{t("underHoodTitle")}</h2>

src/components/stake/MorpheusPageContent.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
Shirt,
2626
Tv,
2727
} from "lucide-react";
28+
import { CHARACTERS } from "@/components/stake/CharacterSelector";
2829
import { GnarsStakeDialog } from "@/components/stake/GnarsStakeDialog";
2930
import { RoadmapSection } from "@/components/stake/RoadmapSection";
3031
import { CARD, CARD_PAD, GOLD, GOLD_CTA, GOLD_INK, MUTED } from "@/components/stake/stake-ui";
@@ -38,6 +39,11 @@ import { cn } from "@/lib/utils";
3839
// One icon per flywheel step and per milestone rung. Data-keyed (not positional)
3940
// so a ladder edit in stake-milestones.ts can't silently shift every icon.
4041
const STEP_ICONS = { step1: HandCoins, step2: Gift, step3: Megaphone } as const;
42+
// The four riders who narrate the page, one Morpheus topic each. Heads are
43+
// cropped from the /stake cut-outs with the roster's own face zoom data, so a
44+
// new cut-out automatically works here too.
45+
const CREW = ["vlad", "r4to", "yan", "pamtech"] as const;
46+
4147
const RUNG_ICONS: Record<string, typeof Tv> = {
4248
"10k": Tv,
4349
"15k": Flag,
@@ -50,6 +56,7 @@ const RUNG_ICONS: Record<string, typeof Tv> = {
5056
export function MorpheusPageContent() {
5157
const t = useTranslations("stake.morpheusPage");
5258
const tSub = useTranslations("stake.page.subnet");
59+
const tChar = useTranslations("stake.characters");
5360
const locale = useLocale();
5461
const [stakeOpen, setStakeOpen] = useState(false);
5562
const { totalStaked } = useGnarsSubnet();
@@ -181,6 +188,58 @@ export function MorpheusPageContent() {
181188
</ul>
182189
</section>
183190

191+
{/* The crew explains it, fighting-game style: rider heads from the /stake
192+
cut-outs + speech balloons. This is also where the Morpheus-powered
193+
SPONSORSHIP VAULTS get their mention — the subnet sections above are
194+
about MOR, this bubble routes people to the rider side. */}
195+
<section className={`${CARD} ${CARD_PAD} sm:p-8`}>
196+
<h2 className="text-lg font-bold tracking-tight">{t("crew.title")}</h2>
197+
<div className="mt-5 flex flex-col gap-5">
198+
{CREW.map((id, i) => {
199+
const c = CHARACTERS.find((x) => x.id === id);
200+
if (!c) return null;
201+
const flipped = i % 2 === 1;
202+
return (
203+
<div
204+
key={id}
205+
className={cn("flex items-start gap-3 sm:gap-4", flipped && "flex-row-reverse")}
206+
>
207+
<div className="flex w-16 shrink-0 flex-col items-center gap-1.5 sm:w-20">
208+
<div
209+
aria-hidden
210+
className={cn("h-16 w-16 rounded-full bg-muted ring-2 sm:h-20 sm:w-20", c.ring)}
211+
style={{
212+
backgroundImage: `url("${c.image}")`,
213+
backgroundSize: c.face.size,
214+
backgroundPosition: c.face.pos,
215+
backgroundRepeat: "no-repeat",
216+
}}
217+
/>
218+
<span className="text-[10px] font-bold uppercase tracking-wider">
219+
{tChar(`${id}.name`)}
220+
</span>
221+
</div>
222+
<div
223+
className={cn(
224+
"relative max-w-xl rounded-2xl border border-border/60 bg-card px-4 py-3 text-sm leading-relaxed shadow-sm",
225+
flipped ? "mr-1.5" : "ml-1.5",
226+
)}
227+
>
228+
<span
229+
aria-hidden
230+
className={cn(
231+
"absolute top-7 h-3 w-3 rotate-45 border-border/60 bg-card",
232+
flipped ? "-right-1.5 border-t border-r" : "-left-1.5 border-b border-l",
233+
)}
234+
/>
235+
{t(`crew.${id}`)}
236+
</div>
237+
</div>
238+
);
239+
})}
240+
</div>
241+
</section>
242+
184243
{/* Custody facts — every line verified against the contract */}
185244
<section className={`${CARD} ${CARD_PAD}`}>
186245
<h2 className="text-lg font-bold tracking-tight">{t("facts.title")}</h2>

0 commit comments

Comments
 (0)