diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4a3942..e555dc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,73 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Added — web / marketing page v2 — 2026-04-19
+
+- **New marketing page at `/`.** Terminal-hero with `pnpm dlx create-helpbase`
+ typing into a shadcn-framed Terminal (via `@magicui/terminal`), click-to-copy
+ primary CTA, `See the live demo →` secondary CTA. Announces OSS + live today.
+- **Dual-front comparator.** A vertical table compares Helpbase against two
+ real status-quos side by side: rolling your own Next.js help center vs. a
+ hosted docs SaaS. Checks the ownership, MCP, llms.txt, cost, and "maintained
+ without you" rows.
+- **How-it-works strip.** Scaffold → Preview → Deploy, 3 steps with
+ illustrations, mapped to the real CLI flow.
+- **AI-native bento.** Five-cell grid explaining the MCP server, llms.txt,
+ structured agent output, `helpbase sync` (code-grounded doc diffs), and the
+ hosted tier escape hatch.
+- **Demo cross-link.** A section that points visitors at `demo.helpbase.dev`
+ with a `curl /llms.txt` teaser of the structured agent output.
+- **Pricing — open-core, three tiers.** Self-host (free, MIT), Hosted free
+ (one site on `{slug}.helpbase.dev`, hosted MCP included), and Hosted Pro
+ (coming soon — custom domain, team roles, analytics, priority support).
+- **Grouped FAQ.** General / Hosted tier / MCP & AI, 9 questions covering OSS
+ vs hosted, ownership, MCP, and migration.
+- **Real footer.** GitHub, Docs, Pricing, Privacy, newsletter form. Named the
+ built-on stack in the copyright line.
+
+### Added — web / analytics
+
+- **Supabase-native page analytics.** New `public.marketing_events` table
+ (insert-only for anon via RLS, service-role read only). New `track` edge
+ function validates an event allowlist, caps metadata at 2 KB, and derives a
+ session hash as `sha256(ip|ua|yyyy-mm-dd)` without storing raw PII.
+- **Client helper `apps/web/lib/analytics.ts`.** `track(event, metadata)` uses
+ `keepalive: true` fetch and swallows every failure so analytics can never
+ break the page.
+
+### Added — `@workspace/ui`
+
+- **`CopyButton` primitive.** Wraps the button with `navigator.clipboard`
+ plus an `execCommand("copy")` fallback for older Safari / non-secure
+ contexts. Exposes an `onCopy` callback and a `data-copy-state` attribute
+ (`idle` / `copied` / `error`) for consumers.
+
+### Changed — web / header
+
+- **Killed placeholder nav.** The shadcn template left behind ten fake links
+ (`Automation`, `Scalability`, `Marketplace`, `Guides`, `Partnerships`, etc.)
+ and a `Continue` button pointing nowhere. Replaced with real helpbase nav:
+ Docs, Pricing (anchor), GitHub. Right-side: `Sign in` + `Deploy now`.
+
+### Security
+
+- **`cf-connecting-ip` precedence in edge analytics.** The `track` function
+ now prefers Cloudflare's authoritative IP header over the client-spoofable
+ `x-forwarded-for`, closing a trivial session-hash forgery.
+- **Scoped Cloudinary allowlist in `next.config.mjs`.** Added pathname
+ constraint `/dohqjvu9k/**` so arbitrary Cloudinary content cannot be
+ proxied through `/_next/image`.
+
+### For contributors
+
+- **Shadcn add, from `apps/web`.** Registry lives in
+ `apps/web/components.json`, not the repo root. Document in your workflow:
+ `cd apps/web && pnpm dlx shadcn@latest add @tailark-pro/...`.
+- **Test coverage + 26.** Net-new tests: `apps/web/test/analytics.test.ts`
+ (7), `apps/web/test/copy-button.test.tsx` (8), and
+ `apps/web/test/track-edge-handler.test.ts` (12). Handler refactored out of
+ the Deno `Deno.serve` entry so vitest can exercise it directly.
+
## [create-helpbase 0.5.0] — 2026-04-19
### Changed
diff --git a/apps/web/app/(main)/docs/page.tsx b/apps/web/app/(main)/docs/page.tsx
index dbc3552..59ecc27 100644
--- a/apps/web/app/(main)/docs/page.tsx
+++ b/apps/web/app/(main)/docs/page.tsx
@@ -73,10 +73,10 @@ export default async function HomePage() {
- The AI-native knowledge layer, as code you own.
+ The docs your AI tools can read.
- Helpbase ships MCP, llms.txt, and codebase-grounded doc sync as primitives that run in your repo. Open source, self-hostable, built on shadcn/ui + Next.js.
+ Helpbase includes an MCP server, an llms.txt, and a doc-sync tool that reads your source code. Open source, self-hostable, built on shadcn/ui + Next.js.
{/* Search bar in hero */}
diff --git a/apps/web/app/(marketing)/page.tsx b/apps/web/app/(marketing)/page.tsx
index 0ad1c53..d8ee01e 100644
--- a/apps/web/app/(marketing)/page.tsx
+++ b/apps/web/app/(marketing)/page.tsx
@@ -1,5 +1,42 @@
-import HeroSection from "@/components/hero-section"
+import dynamic from "next/dynamic"
+
+import { Header } from "@/components/header"
+import { Hero } from "@/components/marketing/hero"
+import Comparator from "@/components/comparator-7"
+import FooterSection from "@/components/footer"
+
+// Below-fold sections load via next/dynamic so their JS code-splits out
+// of the first-paint bundle. SSR stays on — the HTML ships pre-rendered;
+// only client hydration defers.
+const HowItWorks = dynamic(() => import("@/components/how-it-works-3"))
+const FeaturesOwnIt = dynamic(() => import("@/components/features-1"))
+const AiNativeBento = dynamic(() => import("@/components/bento-2"))
+const DemoCrossLink = dynamic(() =>
+ import("@/components/marketing/demo-cross-link").then((m) => ({
+ default: m.DemoCrossLink,
+ })),
+)
+const Pricing = dynamic(() => import("@/components/pricing"))
+const FAQs = dynamic(() => import("@/components/faqs-3"))
export default function LandingPage() {
- return
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )
}
diff --git a/apps/web/components.json b/apps/web/components.json
index ca9a735..5a5b823 100644
--- a/apps/web/components.json
+++ b/apps/web/components.json
@@ -26,6 +26,7 @@
"headers": {
"Authorization": "Bearer ${TAILARK_API_KEY}"
}
- }
+ },
+ "@magicui": "https://magicui.design/r/{name}.json"
}
}
diff --git a/apps/web/components/bento-2.tsx b/apps/web/components/bento-2.tsx
new file mode 100644
index 0000000..6479dbd
--- /dev/null
+++ b/apps/web/components/bento-2.tsx
@@ -0,0 +1,109 @@
+import { AgentTasksIllustration } from "@/components/illustrations/agent-tasks"
+import { ModelsIllustration } from "@/components/illustrations/models"
+import { Card } from '@/components/ui/card'
+import { UptimeIllustration } from "@/components/illustrations/uptime"
+import { DocumentAnalysisIllustration } from "@/components/illustrations/document-analysis"
+
+export default function AiNativeBento() {
+ return (
+
+
+
+
+ Claude and Cursor can read your docs. Day one.
+
+
+ Every helpbase site includes an MCP server and an llms.txt. Claude, Cursor, and ChatGPT can answer from your real docs the moment you deploy. You don't pay us for this later.
+
+
+
+
+
+
+
+
+
+
MCP server, built in
+
+ Every helpbase site runs a Model Context Protocol endpoint. Point Claude Code or Cursor at the URL and they answer from your real docs instead of guessing.
+
+
+
+
+
+
+
+
+
+
llms.txt, always fresh
+
+ A fresh /llms.txt on every build. It's the manifest AI agents already look for. You don't have to remember to write it.
+
+
+
+
+
+
+
+
+
+
Structured agent output
+
+ The MCP server exposes your content as typed tool calls: list articles, read a specific slug, search. No scraping, no guesswork.
+
+
+
+
+
+
+
+
+
Docs that stay in sync with code
+
+ helpbase sync reads your source and proposes MDX edits based on the actual functions and types. You review, you merge. AI assists, it does not author.
+
+
+
+
+
+
+
+
+
Hosted tier, if you want it
+
+ helpbase deploy pushes the same app to {'{'}slug{'}'}.helpbase.dev. No servers to manage. Hosted MCP at scale, custom domain, team roles, analytics when you upgrade.
+
+ Build your own in Next.js and burn a weekend. Pay a hosted docs SaaS and get locked in. Helpbase is the third option: free as open source, paid only when you want us to host it.
+
+
+ )
+}
+
+const Indicator = ({ checked = false }: { checked?: boolean }) => {
+ return (
+
+ {checked ? : '✗'}
+
+ )
+}
+
+const CheckIcon = () => {
+ return (
+
+ )
+}
diff --git a/apps/web/components/const.ts b/apps/web/components/const.ts
new file mode 100644
index 0000000..3857414
--- /dev/null
+++ b/apps/web/components/const.ts
@@ -0,0 +1,6 @@
+const MESCHAC_AVATAR = 'https://avatars.githubusercontent.com/u/47919550?v=4'
+const BERNARD_AVATAR = 'https://avatars.githubusercontent.com/u/31113941?v=4'
+const THEO_AVATAR = 'https://avatars.githubusercontent.com/u/68236786?v=4'
+const GLODIE_AVATAR = 'https://avatars.githubusercontent.com/u/99137927?v=4'
+
+export { BERNARD_AVATAR, GLODIE_AVATAR, THEO_AVATAR, MESCHAC_AVATAR }
\ No newline at end of file
diff --git a/apps/web/components/faqs-3.tsx b/apps/web/components/faqs-3.tsx
new file mode 100644
index 0000000..94b375d
--- /dev/null
+++ b/apps/web/components/faqs-3.tsx
@@ -0,0 +1,138 @@
+import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'
+import Link from 'next/link'
+
+const faqItems = [
+ {
+ group: 'General',
+ items: [
+ {
+ id: 'gen-1',
+ question: 'Is helpbase open source?',
+ answer: 'Yes, MIT-licensed on GitHub. The CLI writes a real Next.js app straight into your repo. Every file is yours to edit, commit, fork, and deploy anywhere.',
+ },
+ {
+ id: 'gen-2',
+ question: 'How is this different from a hosted docs SaaS?',
+ answer: 'You own every file. Your docs are code in your git history, not rows in someone else\'s database. MCP and llms.txt are free and built in, not a Pro-tier add-on.',
+ },
+ {
+ id: 'gen-3',
+ question: 'What framework does it use?',
+ answer: 'Next.js 14 App Router + shadcn/ui + MDX. A standard stack, nothing proprietary. If you already build with Next.js, you already know it.',
+ },
+ ],
+ },
+ {
+ group: 'Hosted tier',
+ items: [
+ {
+ id: 'host-1',
+ question: 'Can I migrate off the hosted tier?',
+ answer: 'Yes. The hosted tier runs the exact same MDX + config that create-helpbase put in your repo. Clone your repo, deploy the Next.js app anywhere, done. We built it so you can leave.',
+ },
+ {
+ id: 'host-2',
+ question: 'What is on the free hosted tier vs Pro?',
+ answer: 'Hosted free gets you one site at {slug}.helpbase.dev with a hosted MCP endpoint we run, edge caching, and SSL. Pro adds custom domain, team members and roles, analytics, higher MCP rate limits, and priority support.',
+ },
+ {
+ id: 'host-3',
+ question: 'Where is data stored on the hosted tier?',
+ answer: 'Supabase (Postgres + edge functions), plus Vercel edge runtime for serving content and the MCP endpoint. Your MDX source is always in your own git repo, the hosted tier just serves a build of it.',
+ },
+ ],
+ },
+ {
+ group: 'MCP & AI',
+ items: [
+ {
+ id: 'mcp-1',
+ question: 'Does the MCP server work with Claude Code and Cursor?',
+ answer: 'Yes, over standard Model Context Protocol. The CLI prints the URL. Point your editor at it. Autocomplete and chat answer from your real docs from that moment on.',
+ },
+ {
+ id: 'mcp-2',
+ question: 'What do you mean by AI built in?',
+ answer: 'Every site includes an llms.txt and an MCP server by default. The MCP exposes typed tool calls for list, read, and search. No scraping, no lock-in, no Pro-tier upsell.',
+ },
+ {
+ id: 'mcp-3',
+ question: 'Do I need an AI key to use it?',
+ answer: 'No. The install CLI does not call external AI APIs. Optional features like helpbase sync (which proposes doc edits from code changes) use your own provider keys.',
+ },
+ ],
+ },
+]
+
+export default function FAQs() {
+ return (
+
+
+
+
+
+ FAQs
+
+
The questions founders ask before running the install.
+
+ Still stuck? Open an issue on{' '}
+
+ GitHub
+
+ .
+
+ Still stuck? Open an issue on{' '}
+
+ GitHub
+
+ .
+
+
+
+ )
+}
diff --git a/apps/web/components/features-1.tsx b/apps/web/components/features-1.tsx
new file mode 100644
index 0000000..96055e7
--- /dev/null
+++ b/apps/web/components/features-1.tsx
@@ -0,0 +1,47 @@
+import { FlowIllustration } from "@/components/illustrations/flow"
+import { MdxSourcePreview } from "@/components/illustrations/mdx-source-preview"
+
+export default function FeaturesOwnIt() {
+ return (
+
+
+
+
+ Every file is yours, from the first commit.
+
+
+ Helpbase doesn't store your content anywhere. The CLI writes a Next.js app straight into your git history. Every edit is a commit. Every file is yours.
+
+
+
+
+
+
MDX all the way down
+
+ Every article is a plain .mdx file in help-center/content. Import React components, version control every change, diff in PR review.
+
+
+
+
+
+
+
+
+
Zero vendor runtime
+
+ No hosted CMS, no editorial database, no cloud to migrate off if we disappear. Deploy the same repo anywhere that runs Next.js.
+
- )
-}
\ No newline at end of file
diff --git a/apps/web/components/hero-section.tsx b/apps/web/components/hero-section.tsx
deleted file mode 100644
index e56f88c..0000000
--- a/apps/web/components/hero-section.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import React from 'react'
-import { Header } from "@/components/header"
-import { Button } from '@/components/ui/button'
-import Link from 'next/link'
-import { ProductIllustration } from "@/components/ui/illustrations/product-illustration"
-import { LogoCloud } from "@/components/logo-cloud"
-import Image from 'next/image'
-import { ChevronRight } from 'lucide-react'
-
-export default function HeroSection() {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
New
-
- Open source, live today
-
-
-
-
-
-
-
Docs your AI agent can actually use.
-
-
Helpbase turns your repo into an AI-native knowledge layer. One command gives you an MCP server, an llms.txt, and a Next.js help center generated from your code. You own every file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- )
-}
\ No newline at end of file
diff --git a/apps/web/components/how-it-works-3.tsx b/apps/web/components/how-it-works-3.tsx
new file mode 100644
index 0000000..60be0fb
--- /dev/null
+++ b/apps/web/components/how-it-works-3.tsx
@@ -0,0 +1,78 @@
+import { cn } from '@workspace/ui/lib/utils'
+import { InstallCommandPreview } from "@/components/illustrations/install-command-preview"
+import { PreviewUrlCard } from "@/components/illustrations/preview-url-card"
+import { WorkflowIllustration } from "@/components/illustrations/workflow"
+
+const steps = [
+ {
+ title: "Install",
+ body: "Run pnpm dlx create-helpbase in your repo. You get a Next.js app with shadcn/ui, MDX content, an MCP server, and an llms.txt. Every file is yours.",
+ visual: ,
+ },
+ {
+ title: "Preview",
+ body: "pnpm dev runs it locally. helpbase deploy --preview pushes a draft to a shareable URL without touching your production site.",
+ visual: ,
+ },
+ {
+ title: "Deploy",
+ body: "Push to helpbase.dev with one command, or deploy the same files to Vercel, Fly, or your own server. Same content, same MCP endpoint, your choice of host.",
+ visual: ,
+ },
+]
+
+export default function HowItWorks() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ From zero to live in three commands.
+
+
+ No hosted CMS. No lock-in. Your docs are plain MDX files in your git history from day one.
+
- )
-}
\ No newline at end of file
diff --git a/apps/web/components/logo.tsx b/apps/web/components/logo.tsx
new file mode 100644
index 0000000..3d192b2
--- /dev/null
+++ b/apps/web/components/logo.tsx
@@ -0,0 +1,69 @@
+import { cn } from '@workspace/ui/lib/utils'
+
+export const Logo = ({ className, uniColor }: { className?: string; uniColor?: boolean }) => {
+ return (
+
+ )
+}
+
+export const LogoIcon = ({ className, uniColor }: { className?: string; uniColor?: boolean }) => {
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/apps/web/components/map.tsx b/apps/web/components/map.tsx
new file mode 100644
index 0000000..de2fbbd
--- /dev/null
+++ b/apps/web/components/map.tsx
@@ -0,0 +1,31 @@
+'use client'
+import DottedMap from 'dotted-map'
+
+const map = new DottedMap({ height: 55, grid: 'vertical' })
+
+const points = map.getPoints()
+
+const svgOptions = {
+ backgroundColor: 'var(--color-background)',
+ color: 'currentColor',
+ radius: 0.15,
+}
+
+export const Map = () => {
+ const viewBox = `0 0 120 60`
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/apps/web/components/marketing/demo-cross-link.tsx b/apps/web/components/marketing/demo-cross-link.tsx
new file mode 100644
index 0000000..5c982a7
--- /dev/null
+++ b/apps/web/components/marketing/demo-cross-link.tsx
@@ -0,0 +1,87 @@
+"use client"
+
+import Link from "next/link"
+
+import { Button } from "@/components/ui/button"
+import { track } from "@/lib/analytics"
+
+export function DemoCrossLink() {
+ return (
+
+
+
+
+
+
+ See a real helpbase site. Running right now.
+
+
+ demo.helpbase.dev is a live helpbase site with real MDX
+ content, a working MCP server, and an llms.txt you can curl.
+ Point Claude Code or Cursor at{" "}
+
+ demo.helpbase.dev/api/mcp
+ {" "}
+ and watch it answer from the docs.
+
+
+
+
+
+
+
+
+
+
+ $ curl
+ demo.helpbase.dev/llms.txt
+
+
# Helpbase demo docs
+
+ Docs: https://demo.helpbase.dev/docs
+
+
+ MCP: https://demo.helpbase.dev/api/mcp
+
+
## Articles
+
- getting-started
+
- mcp-integration
+
- deploy-preview
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/web/components/marketing/hero.tsx b/apps/web/components/marketing/hero.tsx
new file mode 100644
index 0000000..1a7a639
--- /dev/null
+++ b/apps/web/components/marketing/hero.tsx
@@ -0,0 +1,147 @@
+"use client"
+
+import Link from "next/link"
+import { Check, Copy, Terminal as TerminalIcon } from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import {
+ AnimatedSpan,
+ Terminal,
+ TypingAnimation,
+} from "@/components/ui/terminal"
+import { CopyButton } from "@workspace/ui/components/copy-button"
+import { track } from "@/lib/analytics"
+
+const INSTALL_COMMAND = "pnpm dlx create-helpbase"
+
+export function Hero() {
+ return (
+
+
+ {/* Announcement pill */}
+
+
+
+ New
+
+
+ Open source, shipped today
+
+ →
+
+
+
+
+
+
+
+
+ Half your docs readers are AI agents now.
+ {" "}
+ Helpbase is the help center built for them.
+
+
+
+ Every helpbase site includes an MCP server and an{" "}
+ llms.txt, so Claude and Cursor answer from your real docs. One command drops a full Next.js site into your git history. Host it yourself, or deploy with us.
+