Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { links, SITE_URL, INDEXABLE } from "@/lib/links";
import { Chrome } from "@/components/site/Chrome";
import { Footer } from "@/components/site/Footer";
import { ScrollReveal } from "@/components/site/ScrollReveal";
import { FAQ_ITEMS } from "@/lib/faq";
import "./globals.css";

const geistSans = Geist({
Expand Down Expand Up @@ -47,15 +48,18 @@ export const viewport: Viewport = {

const ORG_ID = `${SITE_URL}#organization`;
const SITE_ID = `${SITE_URL}#website`;
const SERVICE_ID = `${SITE_URL}#service`;
const FAQ_ID = `${SITE_URL}#faq`;

const organizationSchema = {
"@context": "https://schema.org",
"@type": "Organization",
"@id": ORG_ID,
name: "deCDN",
url: SITE_URL,
logo: `${SITE_URL}icon.svg`,
description: DESCRIPTION,
logo: `${SITE_URL}d_logo.png`,
description:
"Organization developing deCDN, a peer-to-peer content delivery network with per-megabyte settlement in USDC.",
sameAs: [links.github, links.x],
};

Expand All @@ -69,6 +73,29 @@ const websiteSchema = {
publisher: { "@id": ORG_ID },
};

const serviceSchema = {
"@context": "https://schema.org",
"@type": "Service",
"@id": SERVICE_ID,
name: "deCDN",
url: SITE_URL,
serviceType: "Content Delivery Network",
provider: { "@id": ORG_ID },
areaServed: "Worldwide",
description: DESCRIPTION,
};

const faqSchema = {
"@context": "https://schema.org",
"@type": "FAQPage",
"@id": FAQ_ID,
mainEntity: FAQ_ITEMS.map(({ q, a }) => ({
"@type": "Question",
name: q,
acceptedAnswer: { "@type": "Answer", text: a },
})),
};

// Inline JSON in <script> must escape `<` so a stray `</script>` in any field
// can't close the tag and create an XSS sink. < decodes back to `<` in
// every JSON parser, so structured-data consumers are unaffected.
Expand All @@ -86,13 +113,15 @@ export default function RootLayout({
className={`${geistSans.variable} h-full motion-safe:scroll-smooth`}
>
<head>
{[organizationSchema, websiteSchema].map((schema) => (
<script
key={schema["@id"]}
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: safeJSONLD(schema) }}
/>
))}
{[organizationSchema, websiteSchema, serviceSchema, faqSchema].map(
(schema) => (
<script
key={schema["@id"]}
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: safeJSONLD(schema) }}
/>
),
)}
</head>
<body className="min-h-full">
<Chrome />
Expand Down
34 changes: 4 additions & 30 deletions components/site/Faq.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FaqItem } from "@/components/ui/FaqItem";
import { Frame } from "@/components/ui/Frame";
import { SectionHeader } from "@/components/ui/SectionHeader";
import { FAQ_ITEMS } from "@/lib/faq";

export function Faq() {
return (
Expand All @@ -18,36 +19,9 @@ export function Faq() {
</h2>

<dl className="flex flex-col divide-y divide-current/20">
<FaqItem
delay={0}
q="How is it 90% cheaper?"
a="Legacy CDNs provision for peak traffic and amortise that cost across long contracts, so a popular release gets expensive fast. deCDN is demand-shaped: supply forms around traffic, nodes cache what's hot, and bandwidth gets reused across many pulls. Cost per gigabyte collapses as regional demand concentrates — the opposite of how fixed-provisioning CDNs behave. Target price today: ~$0.01/GB, one cent, per actual gigabyte delivered."
/>
<FaqItem
delay={80}
q="How is byte-level integrity enforced?"
a="Every blob is BLAKE3-addressed, so the hash the client is asking for is the same hash they'll be checking on the way in. Verification happens chunk-by-chunk, in flight — mismatched bytes are dropped and the next peer on the list is asked instead. Peers that send garbage lose staked TOKEN via a non-custodial Merkle proof. There is no central arbiter; the math is the arbiter."
/>
<FaqItem
delay={160}
q="Can content be gated or taken down?"
a="Both. For gating: upload ciphertext instead of plaintext — nodes cache the encrypted blob without ever seeing inside, and your app holds the keys, handing them to clients over a separate authenticated channel. Subscription, paywall, whatever logic fits. For takedown: governance can flag specific BLAKE3 hashes as non-servable, and nodes that keep serving them past a short compliance window lose staked TOKEN — slashing is on-chain, not a human call. Both the key gate and the flag list are auditable; compliance runs end-to-end, from origin onboarding to peer-level slashing, governance-owned and auditable throughout."
/>
<FaqItem
delay={240}
q="Why does the network need a token?"
a="TOKEN secures the network — operators stake it to participate, and they lose it if they misbehave. Payments, though, happen in USDC, because operators want stable currency they can pay power bills with. Twenty percent of protocol fees flow into a Balancer V3 80/20 TOKEN/USDC buyback, tying token demand to network throughput."
/>
<FaqItem
delay={320}
q="Can publishers pay on behalf of users?"
a="Yes. Account abstraction lets a publisher fund a payment channel for their audience, so users pull content with no wallet and no subscription — same free-to-download experience as a public mirror, except the publisher pays peers per megabyte instead of one cloud's egress bill. Default flow is client-pays; publisher-pays is the flag you flip when you want to ship widely without per-user payment friction."
/>
<FaqItem
delay={400}
q="Does this work well for AI models?"
a="Yes — AI is where deCDN's primitives compound. Clients pull large weights from several peers in parallel and saturate their own uplink instead of a single origin's. BLAKE3 chunk addressing lets teams grab one quantisation variant or a single layer without downloading the full checkpoint. And when a model drops and every region pulls it at once, the mesh warms around the demand instead of choking at a central bucket."
/>
{FAQ_ITEMS.map((item, i) => (
<FaqItem key={item.q} delay={i * 80} q={item.q} a={item.a} />
))}
</dl>
</div>
</Frame>
Expand Down
26 changes: 26 additions & 0 deletions lib/faq.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const FAQ_ITEMS = [
{
q: "How is it 90% cheaper?",
a: "Legacy CDNs provision for peak traffic and amortise that cost across long contracts, so a popular release gets expensive fast. deCDN is demand-shaped: supply forms around traffic, nodes cache what's hot, and bandwidth gets reused across many pulls. Cost per gigabyte collapses as regional demand concentrates — the opposite of how fixed-provisioning CDNs behave. Target price today: ~$0.01/GB, one cent, per actual gigabyte delivered.",
},
{
q: "How is byte-level integrity enforced?",
a: "Every blob is BLAKE3-addressed, so the hash the client is asking for is the same hash they'll be checking on the way in. Verification happens chunk-by-chunk, in flight — mismatched bytes are dropped and the next peer on the list is asked instead. Peers that send garbage lose staked TOKEN via a non-custodial Merkle proof. There is no central arbiter; the math is the arbiter.",
},
{
q: "Can content be gated or taken down?",
a: "Both. For gating: upload ciphertext instead of plaintext — nodes cache the encrypted blob without ever seeing inside, and your app holds the keys, handing them to clients over a separate authenticated channel. Subscription, paywall, whatever logic fits. For takedown: governance can flag specific BLAKE3 hashes as non-servable, and nodes that keep serving them past a short compliance window lose staked TOKEN — slashing is on-chain, not a human call. Both the key gate and the flag list are auditable; compliance runs end-to-end, from origin onboarding to peer-level slashing, governance-owned and auditable throughout.",
},
{
q: "Why does the network need a token?",
a: "TOKEN secures the network — operators stake it to participate, and they lose it if they misbehave. Payments, though, happen in USDC, because operators want stable currency they can pay power bills with. Twenty percent of protocol fees flow into a Balancer V3 80/20 TOKEN/USDC buyback, tying token demand to network throughput.",
},
{
q: "Can publishers pay on behalf of users?",
a: "Yes. Account abstraction lets a publisher fund a payment channel for their audience, so users pull content with no wallet and no subscription — same free-to-download experience as a public mirror, except the publisher pays peers per megabyte instead of one cloud's egress bill. Default flow is client-pays; publisher-pays is the flag you flip when you want to ship widely without per-user payment friction.",
},
{
q: "Does this work well for AI models?",
a: "Yes — AI is where deCDN's primitives compound. Clients pull large weights from several peers in parallel and saturate their own uplink instead of a single origin's. BLAKE3 chunk addressing lets teams grab one quantisation variant or a single layer without downloading the full checkpoint. And when a model drops and every region pulls it at once, the mesh warms around the demand instead of choking at a central bucket.",
},
] as const;
Loading