Skip to content
Open
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
21 changes: 21 additions & 0 deletions app/llms-full.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ import {
SITE_DESCRIPTION,
STACK,
statusBlock,
TRY_HEADLINE,
TRY_LEAD,
TRY_NOTES,
} from "@/lib/copy";
import { FAQ_ITEMS } from "@/lib/faq";
import { getLegalDoc, LEGAL_SLUGS, legalUrl } from "@/lib/legal";
import { DOCS_ORIGIN, EMAIL, links, SITE_URL } from "@/lib/links";
import { MODELS, formatSize, pullCommand } from "@/lib/models";

// The whole origin as one plain-text document, so an agent grounding on deCDN
// fetches this instead of stripping HTML from the homepage, the blog index,
Expand Down Expand Up @@ -149,6 +153,13 @@ const compareTable = [
}),
].join("\n");

const tryWindows = `On Windows, in PowerShell: \`${pullCommand("b3:<hash>", "windows")}\``;

const tryModels = MODELS.map(
(m) =>
`- ${m.name} (${formatSize(m.bytes)}, ${m.license}): \`${pullCommand(m.hash)}\``,
).join("\n");

const methodSteps = METHOD_STEPS.map(
(step) =>
`#### ${step.n} ${assertHeadingText(step.word, `method ${step.n} word`)}\n\n${step.body}`,
Expand Down Expand Up @@ -205,6 +216,16 @@ ${HERO_LEAD}

${figureList(HERO_FIGURES)}

${TRY_HEADLINE}

${TRY_LEAD}

${tryModels}

${tryWindows}

${TRY_NOTES.join(" ")}

### Side by side

${COMPARE_HEADLINE.join(" ")}
Expand Down
3 changes: 3 additions & 0 deletions components/site/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Figure } from "@/components/ui/Figure";
import { Frame } from "@/components/ui/Frame";
import { SectionHeader } from "@/components/ui/SectionHeader";
import { HeroTerminal } from "@/components/site/HeroTerminal";
import { TryIt } from "@/components/site/TryIt";

export function Hero() {
return (
Expand Down Expand Up @@ -74,6 +75,8 @@ export function Hero() {
<HeroTerminal className="block w-full" />
</div>
</div>

<TryIt />
</Frame>
);
}
209 changes: 209 additions & 0 deletions components/site/TryIt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
"use client";

import { useRef, useState, useSyncExternalStore } from "react";
import { highlightBrand } from "@/components/ui/brand";
import { Figure } from "@/components/ui/Figure";
import { TRY_HEADLINE, TRY_LEAD, TRY_NOTES } from "@/lib/copy";
import {
MODELS,
PLATFORMS,
type Platform,
detectPlatform,
formatSize,
pullCommand,
} from "@/lib/models";

const COPIED_MS = 2000;

// The visitor's OS never changes while the page is open, so there is nothing
// to subscribe to.
const subscribeNever = () => () => {};

function clientPlatform(): Platform {
const nav = navigator as Navigator & {
userAgentData?: { platform?: string };
};
return detectPlatform(nav.userAgentData?.platform || navigator.userAgent);
}

// The static export renders the POSIX line for everyone; a Windows visitor
// gets PowerShell once the page hydrates.
const serverPlatform = (): Platform => "unix";

/**
* The hero's closing block: pick a seeded model, copy the one line that pulls
* it. Unlike HeroTerminal above it, this panel is real and not aria-hidden:
* the command is the product's actual install-and-download line.
*/
export function TryIt() {
const [id, setId] = useState(MODELS[0]?.id ?? "");
const detected = useSyncExternalStore(
subscribeNever,
clientPlatform,
serverPlatform,
);
const [chosen, setPlatform] = useState<Platform | null>(null);
const platform = chosen ?? detected;
const [copied, setCopied] = useState(false);
const codeRef = useRef<HTMLElement>(null);

const model = MODELS.find((m) => m.id === id) ?? MODELS[0];
const shell = PLATFORMS.find((p) => p.id === platform) ?? PLATFORMS[0];
if (!model || !shell) return null;
const command = pullCommand(model.hash, platform);

function flashCopied() {
setCopied(true);
window.setTimeout(() => setCopied(false), COPIED_MS);
}

// Selects the command, then tries the legacy copy path. Where even that is
// blocked, the command is left selected for the visitor to copy by hand.
function selectAndCopy() {
const code = codeRef.current;
const selection = window.getSelection();
if (!code || !selection) return;
const range = document.createRange();
range.selectNodeContents(code);
selection.removeAllRanges();
selection.addRange(range);
if (document.execCommand("copy")) flashCopied();
}

async function copy() {
try {
await navigator.clipboard.writeText(command);
flashCopied();
} catch {
selectAndCopy();
}
}

return (
<div
id="try"
data-reveal
className="mt-16 flex scroll-mt-[var(--nav-h)] flex-col gap-8 @4xl:mt-24"
>
<span aria-hidden className="rule opacity-50" />

<div className="flex flex-col gap-6">
<h2
id="try-h"
className="hug text-h3 leading-[0.95] font-semibold tracking-[-0.03em]"
>
{TRY_HEADLINE}
</h2>
<p className="max-w-[64ch] text-body leading-[1.65]">
{highlightBrand(TRY_LEAD)}
</p>
</div>

<div className="grid gap-10 @4xl:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)] @4xl:items-start @4xl:gap-12">
<div className="flex flex-col gap-8">
<label className="flex flex-col gap-3">
<span className="meta opacity-60">model</span>
<span className="relative">
<select
value={model.id}
onChange={(e) => {
setId(e.target.value);
setCopied(false);
}}
className="w-full cursor-pointer appearance-none truncate border-b border-current bg-transparent pr-8 pb-2 text-[clamp(1.25rem,2.2vw,1.75rem)] font-semibold tracking-[-0.02em] focus-visible:outline-2 focus-visible:outline-offset-4"
>
{MODELS.map((m) => (
<option key={m.id} value={m.id}>
{m.name}
</option>
))}
</select>
<span
aria-hidden
className="pointer-events-none absolute right-1 bottom-3 text-body opacity-60"
>
▾
</span>
</span>
</label>

<div className="grid grid-cols-2 gap-y-4">
<Figure label="size" value={formatSize(model.bytes)} />
<Figure label="license" value={model.license} />
<div className="col-span-2 flex flex-col gap-1">
<span className="meta opacity-60">source</span>
<a
className="self-start text-body font-medium tracking-[-0.01em] break-all underline decoration-1 underline-offset-4 hover:decoration-whisper"
href={`https://huggingface.co/${model.repo}`}
target="_blank"
rel="noopener noreferrer"
>
{model.repo}
</a>
</div>
</div>
</div>

<div className="terminal flex flex-col">
<div className="terminal-head">
<span className="terminal-dot" />
<span className="terminal-dot" />
<span className="terminal-dot" />
<span className="terminal-label">{shell.shell}</span>
<span
role="group"
aria-label="operating system"
className="ml-auto flex gap-4"
>
{PLATFORMS.map((p) => (
<button
key={p.id}
type="button"
aria-pressed={p.id === platform}
onClick={() => {
setPlatform(p.id);
setCopied(false);
}}
className={`cursor-pointer border-b pb-[1px] text-[10px] font-medium tracking-[0.14em] uppercase ${
p.id === platform
? "border-current opacity-100"
: "border-transparent opacity-45 hover:opacity-80"
}`}
>
{p.label}
</button>
))}
</span>
</div>

<pre className="m-0 px-[18px] pt-[18px] pb-4 font-[inherit] break-all whitespace-pre-wrap">
<span className="prompt select-none">{shell.prompt} </span>
<code ref={codeRef}>{command}</code>
</pre>

<div className="flex items-center justify-between gap-6 px-[18px] pb-[18px]">
<span className="dim text-[11px] tracking-[0.08em]">
testnet · sponsored · no wallet
</span>
<button
type="button"
onClick={copy}
className="meta cursor-pointer border-b border-current pb-[2px] hover:border-whisper"
aria-live="polite"
>
{copied ? "copied ✓" : "copy"}
</button>
</div>

<ul className="flex flex-col gap-1 border-t border-dashed border-current/30 px-[18px] py-4 text-[12px] opacity-70">
{TRY_NOTES.map((note) => (
<li key={note}>
<span className="dim">#</span> {note}
</li>
))}
</ul>
</div>
</div>
</div>
);
}
12 changes: 12 additions & 0 deletions lib/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ export const HERO_FIGURES = [
{ label: "gas overhead", value: "<1%" },
] as const satisfies readonly FigureCopy[];

/** The try-it block at the foot of the hero. */
export const TRY_HEADLINE = "try it: pull a real model.";

export const TRY_LEAD =
"pick a model we seeded on the testnet and paste the line into a terminal on macos or linux, or into powershell on windows. it installs deCDN, opens one captcha in your browser, then pulls the model from the network and checks every byte against its blake3 hash. the testnet sponsor pays for the transfer, so there is no wallet, no token, and no sign-up.";

/** The short notes under the command. */
export const TRY_NOTES = [
"files land in the current directory. add -o <dir> to change it.",
"interrupted? run the same line again to resume.",
] as const;

export const COMPARE_HEADLINE = [
"information scaled.",
"supply didn't.",
Expand Down
3 changes: 3 additions & 0 deletions lib/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export const links = {
litepaper: "/decdn_litepaper.pdf",
presskit: "/presskit/decdn-presskit.zip",
docs: "https://docs.decdn.org/overview/introduction",
// Served by sponsord; each installs decdn + decdn-sponsored.
installer: "https://up.decdn.org/decdn.sh",
installerPs1: "https://up.decdn.org/decdn.ps1",
blog: "/blog/",
contact: `mailto:${EMAIL}`,
privacy: "/legal/privacy/",
Expand Down
62 changes: 62 additions & 0 deletions lib/models.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { describe, expect, it } from "vitest";
import {
HASH_RE,
MODELS,
detectPlatform,
formatSize,
pullCommand,
} from "@/lib/models";

describe("launch catalogue", () => {
it("offers at least one model", () => {
expect(MODELS.length).toBeGreaterThan(0);
});

it("carries a well-formed b3 hash for every model", () => {
for (const model of MODELS) {
expect(model.hash, model.id).toMatch(HASH_RE);
}
});

it("has unique ids and hashes", () => {
expect(new Set(MODELS.map((m) => m.id)).size).toBe(MODELS.length);
expect(new Set(MODELS.map((m) => m.hash)).size).toBe(MODELS.length);
});
});

describe("pullCommand", () => {
it("installs and pulls by hash in one line", () => {
const hash = `b3:${"ab".repeat(32)}`;
expect(pullCommand(hash)).toBe(
`curl -fsSL https://up.decdn.org/decdn.sh | sh -s -- pull ${hash}`,
);
});

it("installs and pulls from PowerShell on Windows", () => {
const hash = `b3:${"ab".repeat(32)}`;
expect(pullCommand(hash, "windows")).toBe(
`irm https://up.decdn.org/decdn.ps1 | iex; decdn-sponsored pull ${hash}`,
);
});
});

describe("detectPlatform", () => {
it("picks PowerShell only for Windows", () => {
expect(detectPlatform("Windows")).toBe("windows");
expect(detectPlatform("Win32")).toBe("windows");
expect(
detectPlatform("Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/130"),
).toBe("windows");
expect(detectPlatform("macOS")).toBe("unix");
expect(detectPlatform("MacIntel")).toBe("unix");
expect(detectPlatform("Linux x86_64")).toBe("unix");
expect(detectPlatform("Darwin")).toBe("unix");
});
});

describe("formatSize", () => {
it("renders decimal gigabytes to one place", () => {
expect(formatSize(28_995_469_846)).toBe("29.0 GB");
expect(formatSize(550_000_000)).toBe("0.6 GB");
});
});
Loading
Loading