import type { ReactNode } from "react"; import { Link } from "react-router-dom"; /** Landing page feature tour: one full section per feature, alternating sides, each with a small * product visual that animates when the section arrives (the parent adds .arrived via Landing's observer). */ type Feature = { id: string; eyebrow: string; title: string; body: string; points: string[]; visual: ReactNode; }; function ChatVisual() { return (
What have I written about pricing?
Searching for pric(e|ing)|paid tier Reading On Pricing, lines 12 to 20

You raised prices twice and the paid tier doubled 1, because readers took the work more seriously2.

[1] On Pricing · lines 12 to 14 The paid tier doubled after I raised the price to ten dollars.
); } function MapVisual() { const nodes = [ { x: 50, y: 48, r: 14, label: "Pricing" }, { x: 22, y: 30, r: 9, label: "Habits" }, { x: 78, y: 26, r: 10, label: "Audience" }, { x: 30, y: 76, r: 8, label: "Craft" }, { x: 74, y: 74, r: 11, label: "Paid tier" }, ]; const edges = [ [0, 1], [0, 2], [0, 4], [1, 3], [2, 4], ]; return (
); } function AudioVisual() { return (

ASo the big idea is that price is a signal.

BAnd she has the numbers: the paid tier doubled.

); } function VideoVisual() { return (
9:16 I doubled my price.
16:9 Why price is a signal
1:1
); } function KitVisual() { const cards = [ ["X thread", "I doubled my price. My paid tier doubled too."], ["LinkedIn", "Most writers underprice. I did for two years."], ["Notes", "Price is a signal. Readers told me so."], ["Bluesky", "Raised my price to $10. Paid went up."], ]; return (
{cards.map(([label, body], i) => (
{label}

{body}

))}
); } function VoiceVisual() { const sliders = [ ["Stability", 62], ["Similarity", 80], ["Style", 28], ] as const; return (
Your voice

Warm, direct, short paragraphs. Opens with a number. Never uses jargon.

{sliders.map(([label, v], i) => (
{label}
))}
Recording take 2 · 1:24
); } function PadVisual() { const lit = [2, 5, 9, 12, 16, 19]; return (
{Array.from({ length: 21 }).map((_, i) => ( {i + 1} ))}
X LinkedIn Bluesky Notes reminder
); } const FEATURES: Feature[] = [ { id: "research", eyebrow: "Research notebook", title: "Ask your archive anything. It answers with receipts.", body: "Notestack reads your posts the way a careful researcher would: it searches, opens the right post, and cites the exact lines. If you never wrote it, it tells you so instead of guessing.", points: ["Every sentence links to the lines it came from", "Chats are saved per notebook", "Summaries of whole notebooks, cited"], visual: , }, { id: "map", eyebrow: "Topic map", title: "See the constellations in your writing.", body: "Every post is tagged with what it is really about, then linked to the topics it travels with. Zoom through years of work and spin any topic into a notebook.", points: ["Topics merge automatically as you publish", "Spot the themes you keep coming back to", "One click from a topic to a notebook"], visual: , }, { id: "audio", eyebrow: "Audio overview", title: "Two hosts talk through your ideas.", body: "Turn a post or a whole notebook into a natural conversation, voiced by ElevenLabs. Pick from a library of commercial voices, or clone your own with consent.", points: ["Deep dive, brief or debate formats", "Every line grounded in your posts", "Your cloned voice as host, if you want"], visual: , }, { id: "video", eyebrow: "Video studio", title: "Narrated videos from one post, edited scene by scene.", body: "Pick a post or paste a link, choose a template, style and voice, and Notestack writes the script, narrates it and builds the scenes. Edit any scene and watch the live preview update, then render an MP4.", points: ["Landscape for YouTube, vertical for Reels and TikTok", "Templates, stock footage, captions and 16 languages", "Square audiograms from any audio overview"], visual: , }, { id: "kit", eyebrow: "Launch Kit", title: "One post becomes a launch on every platform.", body: "Hooks, an X thread, a LinkedIn post, Substack Notes, a Bluesky thread, an SEO pack, a carousel and quote cards, all written in your voice from claims the post actually makes.", points: ["Edit anything, copy in one click", "Character counts per platform", "Quote cards rendered and ready"], visual: , }, { id: "voice", eyebrow: "Voice profile", title: "Sounds like you, on the page and out loud.", body: "Notestack learns your tone from your own posts, so drafts read like you wrote them. For audio, tune two hosts or record a couple of minutes to clone your voice.", points: ["Editable writing voice", "Commercially licensed voice library", "Consented cloning you can revoke anytime"], visual: , }, { id: "pad", eyebrow: "Launchpad", title: "Schedule the countdown. We handle liftoff.", body: "Plan every post on one calendar. Notestack publishes to X, LinkedIn and Bluesky on time, emails you Substack Notes to paste, and tracks the clicks that follow.", points: ["Auto posting with connected accounts", "Tracked links and engagement", "Resurface evergreen posts when they matter"], visual: , }, ]; export default function FeatureShowcase() { return (
{FEATURES.map((f, i) => (

{String(i + 1).padStart(2, "0")} {f.eyebrow}

{f.title}

{f.body}

    {f.points.map((p) => (
  • {p}
  • ))}
{i === FEATURES.length - 1 && ( Start Exploring )}
{f.visual}
))}
); }