feat: flatten routes and merge marketing and onboarding directories
This commit is contained in:
333
design-templates/VIBN (2)/journey.jsx
Normal file
333
design-templates/VIBN (2)/journey.jsx
Normal file
@@ -0,0 +1,333 @@
|
||||
// The Journey — 4 steps from idea → first 100 customers. A visual marker shows
|
||||
// where most tools stop. Each step shows a tiny "demo" snippet of what Vibn does.
|
||||
|
||||
const JOURNEY_STEPS = [
|
||||
{
|
||||
num: "01",
|
||||
title: "You describe it.",
|
||||
sub: "The AI builds it.",
|
||||
body: "Talk to it like you'd talk to a friend who codes. It builds the screens, the buttons, the logic — whatever your idea needs.",
|
||||
demo: "describe",
|
||||
},
|
||||
{
|
||||
num: "02",
|
||||
title: "It goes live.",
|
||||
sub: "The AI puts it online.",
|
||||
body: "Logins, saving your stuff, hosting — handled. You get a live link from minute one. Share it. Show your friends. It just works.",
|
||||
demo: "live",
|
||||
},
|
||||
{
|
||||
num: "03",
|
||||
title: "It gets seen.",
|
||||
sub: "The AI markets it.",
|
||||
body: "Posts, emails, social — written, scheduled, and shipped on autopilot. The tone matches your brand because you trained it talking to your AI.",
|
||||
demo: "seen",
|
||||
},
|
||||
{
|
||||
num: "04",
|
||||
title: "It gets customers.",
|
||||
sub: "Your first 100.",
|
||||
body: "Through our Google partnership, Vibn helps the right people find your product when they're searching for what you built.",
|
||||
demo: "customers",
|
||||
},
|
||||
];
|
||||
|
||||
function Journey() {
|
||||
return (
|
||||
<section className="section journey" id="how">
|
||||
<style>{`
|
||||
.journey { padding-block: clamp(80px, 11vh, 140px); }
|
||||
.journey-head { text-align: center; max-width: 820px; margin: 0 auto 64px; }
|
||||
.journey-title {
|
||||
font-size: clamp(36px, 4.8vw, 64px);
|
||||
font-weight: 500; letter-spacing: -0.025em; line-height: 1.02;
|
||||
text-wrap: balance;
|
||||
}
|
||||
.journey-title .accent { color: var(--accent); }
|
||||
.journey-sub {
|
||||
margin-top: 20px;
|
||||
color: var(--fg-mute); font-size: 17px;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.journey-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px;
|
||||
position: relative;
|
||||
}
|
||||
@media (max-width: 1080px) { .journey-grid { grid-template-columns: repeat(2, 1fr); } }
|
||||
@media (max-width: 640px) { .journey-grid { grid-template-columns: 1fr; } }
|
||||
|
||||
.step {
|
||||
position: relative;
|
||||
padding: 24px 24px 0;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(180deg, oklch(0.20 0.009 60 / 0.55), oklch(0.17 0.008 60 / 0.55));
|
||||
border: 1px solid var(--hairline);
|
||||
display: flex; flex-direction: column;
|
||||
min-height: 380px;
|
||||
overflow: hidden;
|
||||
isolation: isolate;
|
||||
}
|
||||
.step::before {
|
||||
/* Top accent line that varies by step */
|
||||
content: "";
|
||||
position: absolute; top: 0; left: 0; right: 0; height: 1px;
|
||||
background: linear-gradient(90deg, transparent, var(--accent) 50%, transparent);
|
||||
opacity: 0;
|
||||
}
|
||||
.step.active::before { opacity: .7; }
|
||||
.step.stopped {
|
||||
opacity: 0.46;
|
||||
}
|
||||
.step.stopped::after {
|
||||
content: "";
|
||||
position: absolute; inset: 0;
|
||||
background: linear-gradient(180deg, transparent 40%, oklch(0.155 0.008 60 / 0.6));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.step-num {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: var(--fg-faint);
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
.step-title {
|
||||
margin-top: 12px;
|
||||
font-size: 22px; font-weight: 500;
|
||||
letter-spacing: -0.018em;
|
||||
}
|
||||
.step-sub {
|
||||
margin-top: 4px;
|
||||
color: var(--accent);
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.step.stopped .step-sub { color: var(--fg-mute); }
|
||||
.step-body {
|
||||
margin-top: 12px;
|
||||
color: var(--fg-dim);
|
||||
font-size: 14px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
.step-demo {
|
||||
margin-top: auto;
|
||||
margin-inline: -24px; margin-bottom: 0;
|
||||
padding: 16px 18px;
|
||||
border-top: 1px solid var(--hairline);
|
||||
background: oklch(0.16 0.008 60 / 0.6);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px; line-height: 1.55;
|
||||
color: var(--fg-dim);
|
||||
min-height: 116px;
|
||||
display: flex; flex-direction: column;
|
||||
gap: 7px;
|
||||
}
|
||||
|
||||
/* Visual marker: where other tools stop */
|
||||
.stop-marker {
|
||||
position: absolute;
|
||||
left: calc(50% - 8px);
|
||||
top: 0; bottom: 0;
|
||||
width: 16px;
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
@media (max-width: 1080px) { .stop-marker { display: none; } }
|
||||
.stop-marker .line {
|
||||
flex: 1; width: 1px;
|
||||
background: repeating-linear-gradient(180deg, var(--accent) 0 6px, transparent 6px 12px);
|
||||
opacity: .7;
|
||||
}
|
||||
.stop-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
background: var(--bg);
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid oklch(0.74 0.175 35 / 0.5);
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 0 24px var(--accent-glow);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Demo blocks */
|
||||
.demo-row { display: flex; gap: 8px; align-items: flex-start; }
|
||||
.demo-tag {
|
||||
font-family: var(--font-mono); font-size: 10px;
|
||||
padding: 1px 6px; border-radius: 4px;
|
||||
color: var(--fg-faint);
|
||||
background: oklch(0.22 0.01 60);
|
||||
letter-spacing: 0.04em;
|
||||
flex-shrink: 0;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.demo-tag.you { color: oklch(0.85 0.06 250); background: oklch(0.28 0.04 250); }
|
||||
.demo-tag.ai { color: var(--accent); background: oklch(0.35 0.10 35 / 0.4); }
|
||||
.demo-line { color: var(--fg-dim); }
|
||||
.demo-ok { color: var(--ok); }
|
||||
.demo-host {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
color: var(--fg-dim);
|
||||
}
|
||||
.demo-host i {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--ok);
|
||||
box-shadow: 0 0 6px oklch(0.78 0.16 155 / 0.6);
|
||||
}
|
||||
.demo-progress {
|
||||
height: 4px; border-radius: 999px;
|
||||
background: oklch(0.25 0.01 60);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.demo-progress span {
|
||||
position: absolute; inset: 0;
|
||||
background: var(--accent);
|
||||
width: 64%;
|
||||
box-shadow: 0 0 8px var(--accent-glow);
|
||||
}
|
||||
.demo-customer {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
}
|
||||
.demo-customer .av {
|
||||
width: 16px; height: 16px; border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.demo-num {
|
||||
font-family: var(--font-mono); font-size: 22px;
|
||||
color: var(--accent);
|
||||
letter-spacing: -0.02em;
|
||||
font-weight: 500;
|
||||
}
|
||||
.demo-num small {
|
||||
color: var(--fg-mute); font-size: 11px;
|
||||
font-weight: 400;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.journey-foot {
|
||||
margin-top: 48px;
|
||||
text-align: center;
|
||||
color: var(--fg-mute);
|
||||
font-size: 15px;
|
||||
text-wrap: balance;
|
||||
}
|
||||
.journey-foot b {
|
||||
color: var(--fg);
|
||||
font-weight: 500;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className="wrap">
|
||||
<div className="journey-head">
|
||||
<Eyebrow>The journey</Eyebrow>
|
||||
<h2 className="journey-title" style={{ marginTop: 18 }}>
|
||||
From idea to first 100 customers.
|
||||
<br/><span className="accent">In one chat.</span>
|
||||
</h2>
|
||||
<p className="journey-sub">
|
||||
Other tools take you to step two and wave goodbye. Vibn keeps building with you.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="journey-grid">
|
||||
{/* "Where everyone else stops" marker, sits over the gap between cards 2 and 3 */}
|
||||
<div className="stop-marker" style={{ left: "calc(50% - 1px)" }}>
|
||||
<div className="line" />
|
||||
<span className="stop-label">↑ Where every other tool stops</span>
|
||||
<div className="line" />
|
||||
</div>
|
||||
|
||||
{JOURNEY_STEPS.map((step, i) => (
|
||||
<StepCard key={step.num} step={step} stopped={i >= 2} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="journey-foot">
|
||||
<b>One tool. One chat.</b> From "wouldn't it be cool if…" to <b>real customers paying you money.</b>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function StepCard({ step, stopped }) {
|
||||
return (
|
||||
<div className={`step${stopped ? "" : " active"}`}>
|
||||
<div>
|
||||
<div className="step-num">{step.num}</div>
|
||||
<h3 className="step-title">{step.title}</h3>
|
||||
<div className="step-sub">{step.sub}</div>
|
||||
<p className="step-body">{step.body}</p>
|
||||
</div>
|
||||
<StepDemo demo={step.demo} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StepDemo({ demo }) {
|
||||
if (demo === "describe") {
|
||||
return (
|
||||
<div className="step-demo">
|
||||
<div className="demo-row"><span className="demo-tag you">YOU</span><span className="demo-line">build a booking site for my dog grooming biz</span></div>
|
||||
<div className="demo-row"><span className="demo-tag ai">VIBN</span><span className="demo-line">on it — designing screens…</span></div>
|
||||
<div className="demo-row" style={{ alignItems: "center" }}>
|
||||
<span className="demo-tag ai">VIBN</span>
|
||||
<span className="demo-ok">✓ booking flow ready</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (demo === "live") {
|
||||
return (
|
||||
<div className="step-demo">
|
||||
<div className="demo-row" style={{ alignItems: "center" }}>
|
||||
<span className="demo-tag ai">VIBN</span>
|
||||
<span className="demo-line">put it online</span>
|
||||
</div>
|
||||
<div className="demo-progress"><span /></div>
|
||||
<div className="demo-row" style={{ alignItems: "center", marginTop: 2 }}>
|
||||
<span className="demo-host"><i /> pawsandposh.vibn.app</span>
|
||||
</div>
|
||||
<div className="demo-row"><span className="demo-ok">✓ logins · ✓ saving · ✓ live</span></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (demo === "seen") {
|
||||
return (
|
||||
<div className="step-demo">
|
||||
<div className="demo-row"><span className="demo-tag ai">VIBN</span><span className="demo-line">draft a launch post for Instagram + email blast</span></div>
|
||||
<div className="demo-row" style={{ color: "var(--fg-faint)" }}>↳ scheduled for Tue 9:00 AM</div>
|
||||
<div className="demo-row" style={{ color: "var(--fg-faint)" }}>↳ scheduled for Thu 6:00 PM</div>
|
||||
<div className="demo-row"><span className="demo-ok">✓ 3 channels on autopilot</span></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (demo === "customers") {
|
||||
return (
|
||||
<div className="step-demo">
|
||||
<div className="demo-row" style={{ alignItems: "center" }}>
|
||||
<span className="demo-num">+47<small>this week</small></span>
|
||||
</div>
|
||||
<div className="demo-customer">
|
||||
<span className="av" style={{ background: "oklch(0.55 0.14 35)" }} />
|
||||
<span className="av" style={{ background: "oklch(0.55 0.14 260)" }} />
|
||||
<span className="av" style={{ background: "oklch(0.55 0.14 155)" }} />
|
||||
<span className="av" style={{ background: "oklch(0.55 0.14 80)" }} />
|
||||
<span style={{ color: "var(--fg-mute)" }}>found you via Google</span>
|
||||
</div>
|
||||
<div className="demo-row"><span className="demo-ok">✓ tracking toward 100</span></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Object.assign(window, { Journey });
|
||||
Reference in New Issue
Block a user