Skip to content

Commit b4dabf3

Browse files
committed
Add manifesto page to marketing site
- New /manifesto route with editorial layout, chapter numbers, callouts, and monospace prompt block for Databunny examples - Link footer Company section and include sitemap entry
1 parent 4d6b4d3 commit b4dabf3

File tree

8 files changed

+373
-1
lines changed

8 files changed

+373
-1
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { ManifestoBlock } from "./manifesto-data";
2+
3+
export function ManifestoBlocks({
4+
blocks,
5+
}: {
6+
blocks: readonly ManifestoBlock[];
7+
}) {
8+
return (
9+
<div className="space-y-6">
10+
{blocks.map((block, i) => {
11+
if (block.type === "callout") {
12+
return (
13+
<p
14+
className="text-balance font-medium text-foreground text-xl leading-snug sm:text-2xl"
15+
key={`${i}-callout`}
16+
>
17+
{block.text}
18+
</p>
19+
);
20+
}
21+
22+
if (block.type === "prompts") {
23+
return (
24+
<div
25+
className="space-y-2 rounded border border-border bg-card/40 p-4 sm:p-5"
26+
key={`${i}-prompts`}
27+
>
28+
{block.items.map((line, j) => (
29+
<p
30+
className="font-mono text-foreground/80 text-sm leading-relaxed"
31+
key={`${i}-pr-${j}`}
32+
>
33+
<span
34+
aria-hidden="true"
35+
className="mr-2 select-none text-muted-foreground/50"
36+
>
37+
&gt;
38+
</span>
39+
{line}
40+
</p>
41+
))}
42+
</div>
43+
);
44+
}
45+
46+
return (
47+
<p
48+
className="text-pretty text-foreground/80 leading-relaxed sm:text-lg"
49+
key={`${i}-p`}
50+
>
51+
{block.text}
52+
</p>
53+
);
54+
})}
55+
</div>
56+
);
57+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { ManifestoChapter } from "./manifesto-data";
2+
import { ManifestoBlocks } from "./manifesto-blocks";
3+
4+
export function ManifestoChapter({
5+
chapter,
6+
}: {
7+
chapter: ManifestoChapter;
8+
}) {
9+
return (
10+
<section
11+
aria-labelledby={`${chapter.id}-heading`}
12+
className="border-border border-t"
13+
id={chapter.id}
14+
>
15+
<div className="mx-auto max-w-3xl px-4 py-12 sm:px-6 sm:py-16 lg:px-8 lg:py-20">
16+
<div className="mb-8">
17+
<span
18+
aria-hidden="true"
19+
className="mb-3 block font-mono text-muted-foreground/40 text-sm tabular-nums"
20+
>
21+
{chapter.number}
22+
</span>
23+
<h2
24+
className="text-balance font-semibold text-2xl sm:text-3xl lg:text-4xl"
25+
id={`${chapter.id}-heading`}
26+
>
27+
{chapter.title}
28+
</h2>
29+
</div>
30+
<ManifestoBlocks blocks={chapter.blocks} />
31+
</div>
32+
</section>
33+
);
34+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
export type ManifestoBlock =
2+
| { type: "paragraph"; text: string }
3+
| { type: "callout"; text: string }
4+
| { type: "prompts"; items: readonly string[] };
5+
6+
export type ManifestoChapterId =
7+
| "analytics-is-broken"
8+
| "context-is-everything"
9+
| "privacy-is-the-default"
10+
| "ask-your-data"
11+
| "build-for-builders";
12+
13+
export type ManifestoChapter = {
14+
id: ManifestoChapterId;
15+
number: string;
16+
title: string;
17+
blocks: readonly ManifestoBlock[];
18+
};
19+
20+
export const manifestoIntro = {
21+
title: "The Databuddy Manifesto",
22+
lead: [
23+
"I built Databuddy because I was tired of pretending the analytics industry wasn't broken. Every tool I used was either spying on my users, drowning me in dashboards I'd never read, or charging me enterprise prices to answer questions a five-year-old could phrase better.",
24+
"So I stopped waiting for someone to fix it. Here's what I believe.",
25+
],
26+
} as const;
27+
28+
export const manifestoSections: readonly ManifestoChapter[] = [
29+
{
30+
id: "analytics-is-broken",
31+
number: "01",
32+
title: "Analytics Is Broken",
33+
blocks: [
34+
{
35+
type: "paragraph",
36+
text: "Google Analytics violated GDPR so many times that entire countries banned it. Then they replaced it with GA4, which somehow made everything worse. Amplitude costs more than most startups' entire cloud bill. PostHog ships a script heavier than some landing pages.",
37+
},
38+
{
39+
type: "paragraph",
40+
text: "And what do you get for all of it? Dashboards. Hundreds of dashboards nobody opens after the first week.",
41+
},
42+
{
43+
type: "paragraph",
44+
text: "The industry optimized for complexity because complexity justifies pricing tiers. More features, more seats, more events, more money. Nobody stopped to ask whether any of it actually helped you make a better product.",
45+
},
46+
{
47+
type: "callout",
48+
text: "If your tool needs a certification program, it's not a tool. It's a tax.",
49+
},
50+
],
51+
},
52+
{
53+
id: "context-is-everything",
54+
number: "02",
55+
title: "Context Is Everything",
56+
blocks: [
57+
{
58+
type: "paragraph",
59+
text: "Here's the dirty secret about privacy-focused analytics: most of them just show you numbers.",
60+
},
61+
{
62+
type: "paragraph",
63+
text: "Page views. Bounce rates. Referrers. Clean, private, and completely useless on their own.",
64+
},
65+
{
66+
type: "paragraph",
67+
text: "Knowing 500 people signed up yesterday tells you nothing. Knowing that 400 came from a Hacker News post, 60% hit an error on onboarding, and only 12 activated a core feature? That tells you exactly where to spend your morning.",
68+
},
69+
{
70+
type: "paragraph",
71+
text: "Raw data is not insight. Context is. That means connecting web analytics to product analytics to errors to performance, all in one place, so you can trace a user\u2019s journey from first click to \u201Caha\u201D moment without duct-taping four tools together.",
72+
},
73+
{
74+
type: "paragraph",
75+
text: "Every privacy tool out there got the first part right: stop tracking people. But they stopped too early. They gave you the numbers and left you to figure out the story yourself.",
76+
},
77+
{
78+
type: "callout",
79+
text: "I\u2019m building the tool that tells you the story.",
80+
},
81+
],
82+
},
83+
{
84+
id: "privacy-is-the-default",
85+
number: "03",
86+
title: "Privacy Is the Default, Not the Feature",
87+
blocks: [
88+
{
89+
type: "paragraph",
90+
text: "Some companies put \u201Cprivacy-first\u201D in their tagline and charge you extra for it. Others use it as a marketing angle while still fingerprinting your users behind the scenes.",
91+
},
92+
{
93+
type: "callout",
94+
text: "Privacy isn\u2019t a feature. It\u2019s the bare minimum.",
95+
},
96+
{
97+
type: "paragraph",
98+
text: "Databuddy\u2019s tracking script is 30KB. No cookies. No fingerprints. No personal identifiers. No consent banners scaring away 30\u201340% of your visitors before they even see your product. You install it, and it works. Your users never know it\u2019s there, because it never asks them for anything.",
99+
},
100+
{
101+
type: "paragraph",
102+
text: "This isn\u2019t a tradeoff. You don\u2019t lose insights by respecting people. You lose insights by making half your visitors click away from a cookie popup.",
103+
},
104+
],
105+
},
106+
{
107+
id: "ask-your-data",
108+
number: "04",
109+
title: "Ask Your Data Questions, Not Your Dashboard",
110+
blocks: [
111+
{
112+
type: "callout",
113+
text: "The best analytics UI is a conversation.",
114+
},
115+
{
116+
type: "paragraph",
117+
text: "I don\u2019t think you should need to learn a query builder, memorize filter syntax, or drag widgets around a canvas to understand your own product. You should just ask.",
118+
},
119+
{
120+
type: "prompts",
121+
items: [
122+
"How many users signed up yesterday?",
123+
"Show me errors from production in the last hour.",
124+
"Which feature has the highest drop-off after onboarding?",
125+
],
126+
},
127+
{
128+
type: "paragraph",
129+
text: "Databunny, the AI agent inside Databuddy, answers in seconds. It builds the charts. It writes the reports. It emails you the things you should care about before you even think to ask.",
130+
},
131+
{
132+
type: "paragraph",
133+
text: "The future of analytics isn\u2019t more dashboards. It\u2019s fewer. It\u2019s an agent that knows your data well enough to surface what matters and shut up about what doesn\u2019t.",
134+
},
135+
],
136+
},
137+
{
138+
id: "build-for-builders",
139+
number: "05",
140+
title: "Build for Builders",
141+
blocks: [
142+
{
143+
type: "paragraph",
144+
text: "Databuddy is for the founder who checks analytics between deploys. The engineer who wants to know if the feature they shipped last night actually moved a number. The two-person team that doesn\u2019t have a \u201Cdata person\u201D and shouldn\u2019t need one.",
145+
},
146+
{
147+
type: "paragraph",
148+
text: "I\u2019m not building for enterprises with 50-person data teams. I\u2019m building for the people who are actually making things, and who need their tools to stay out of the way while they do it.",
149+
},
150+
{
151+
type: "callout",
152+
text: "One script. One platform. The full picture.",
153+
},
154+
{
155+
type: "paragraph",
156+
text: "That\u2019s it. That\u2019s Databuddy.",
157+
},
158+
],
159+
},
160+
] as const;
161+
162+
export const manifestoSignature = {
163+
name: "Issa Nassar",
164+
role: "Founder",
165+
company: "Databuddy Analytics",
166+
} as const;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { manifestoIntro } from "./manifesto-data";
2+
3+
export function ManifestoHero() {
4+
return (
5+
<section className="relative w-full pt-16 pb-12 sm:pt-20 sm:pb-16 lg:pt-28 lg:pb-20">
6+
<div className="mx-auto w-full max-w-3xl px-4 sm:px-6 lg:px-8">
7+
<h1 className="mb-10 text-balance text-center font-semibold text-3xl leading-tight tracking-tight sm:text-4xl md:text-5xl lg:text-6xl">
8+
{manifestoIntro.title}
9+
</h1>
10+
<div className="space-y-5">
11+
{manifestoIntro.lead.map((paragraph, i) => (
12+
<p
13+
className="text-pretty text-foreground/80 leading-relaxed sm:text-lg"
14+
key={`lead-${i}`}
15+
>
16+
{paragraph}
17+
</p>
18+
))}
19+
</div>
20+
</div>
21+
</section>
22+
);
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { manifestoSignature } from "./manifesto-data";
2+
3+
export function ManifestoSignature() {
4+
return (
5+
<div className="mx-auto max-w-3xl px-4 py-12 sm:px-6 sm:py-16 lg:px-8 lg:py-20">
6+
<div className="space-y-1">
7+
<p className="font-medium text-foreground text-lg">
8+
{manifestoSignature.name}
9+
</p>
10+
<p className="text-muted-foreground text-sm">
11+
{manifestoSignature.role}, {manifestoSignature.company}
12+
</p>
13+
</div>
14+
</div>
15+
);
16+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { Metadata } from "next";
2+
import { Footer } from "@/components/footer";
3+
import Section from "@/components/landing/section";
4+
import { Spotlight } from "@/components/landing/spotlight";
5+
import { StructuredData } from "@/components/structured-data";
6+
import { ManifestoChapter } from "./manifesto-chapter";
7+
import { manifestoSections } from "./manifesto-data";
8+
import { ManifestoHero } from "./manifesto-hero";
9+
import { ManifestoSignature } from "./manifesto-signature";
10+
11+
const title = "The Databuddy Manifesto | Databuddy";
12+
const description =
13+
"Why we built Databuddy: analytics that respects users, connects context, and answers in plain language — without enterprise bloat or cookie theater.";
14+
const url = "https://www.databuddy.cc/manifesto";
15+
16+
export const metadata: Metadata = {
17+
title,
18+
description,
19+
alternates: {
20+
canonical: url,
21+
},
22+
openGraph: {
23+
title,
24+
description,
25+
url,
26+
images: ["/og-image.png"],
27+
},
28+
};
29+
30+
export default function ManifestoPage() {
31+
return (
32+
<div className="overflow-hidden">
33+
<StructuredData
34+
page={{
35+
title,
36+
description,
37+
url,
38+
}}
39+
/>
40+
<Spotlight transform="translateX(-60%) translateY(-50%)" />
41+
42+
<Section className="overflow-hidden" customPaddings id="manifesto-hero">
43+
<ManifestoHero />
44+
</Section>
45+
46+
{manifestoSections.map((chapter) => (
47+
<ManifestoChapter chapter={chapter} key={chapter.id} />
48+
))}
49+
50+
<section className="border-border border-t">
51+
<ManifestoSignature />
52+
</section>
53+
54+
<div className="w-full">
55+
<div className="mx-auto h-px max-w-6xl bg-linear-to-r from-transparent via-border/30 to-transparent" />
56+
</div>
57+
58+
<Footer />
59+
60+
<div className="w-full">
61+
<div className="mx-auto h-px max-w-6xl bg-linear-to-r from-transparent via-border/30 to-transparent" />
62+
</div>
63+
</div>
64+
);
65+
}

apps/docs/components/footer.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ export function Footer() {
108108
Blog
109109
</Link>
110110
</li>
111+
<li>
112+
<Link
113+
className="text-muted-foreground hover:text-foreground"
114+
href="/manifesto"
115+
>
116+
Manifesto
117+
</Link>
118+
</li>
111119
<li>
112120
<Link
113121
className="text-muted-foreground hover:text-foreground"

0 commit comments

Comments
 (0)