A decentralized delivery layer for bytes at scale. Anyone can serve bytes; clients pay per megabyte in USDC.
This is the source for the deCDN marketing site and blog.
Next.js 16 (App Router) · React 19 · Tailwind CSS v4 · TypeScript · pnpm. Static export, deployed to Cloudflare Pages.
pnpm install # required (not npm/yarn) — husky hooks shell out to `pnpm exec`
pnpm dev # dev server on :3000
pnpm build # static export → ./out
pnpm test# vitest run
pnpm typecheck # tsc --noEmit
pnpm lint # eslint (flat config)
pnpm format # prettier --write .app/— App Router entry (layout.tsx,page.tsx,globals.css) plus the blog routes (blog/,blog/[slug]/), thelegal/[doc]route, the sitemap/robots handlers, thellms.txt/llms-full.txthandlers, and file-convention metadata assets.components/site/— page sections composed byapp/page.tsx(Hero, Compare, Method, Faq, Contact, …) plus chrome (Chrome,Footer,ScrollReveal, …).components/ui/— low-level primitives (Frame, SectionHeader, Prose, Figure, …).lib/— shared helpers (links.ts,copy.ts,blog.ts,faq.ts,legal.ts,jsonld.tsx,schema.ts, …). The site's prose and its displayed values live inlib/copy.tsas plain data — the comparison table maps over it and thellms-full.txtmirror serialises it, so anything inlined in a component drifts from the mirror.test-utils/— test-only helpers for walking the element tree a server component returns.scripts/—check-out.mjs, postbuild assertions run against./outbypnpm build.content/blog/— MDX posts loaded bylib/blog.tsand rendered byapp/blog/[slug]/page.tsx.content/legal/— MDX for the legal pages (privacy,terms,disclaimer), loaded bylib/legal.tsand rendered byapp/legal/[doc]/page.tsx.docs/— Mintlify source fordocs.decdn.org. Built and deployed independently ofpnpm build; not part of the static export and not imported from the website code.- Path alias:
@/*maps to the project root (e.g.@/lib/links, not@/src/...).
- Static export only.
next.config.tssetsoutput: "export"; the build emits./out. No SSR, ISR, middleware, or Image Optimization API. Route handlers (app/robots.txt/route.ts,app/sitemap.xml/route.ts,app/sitemap-pages.xml/route.ts,app/llms.txt/route.ts,app/llms-full.txt/route.ts) must bedynamic = "force-static"and GET-only; the dotted segment is what makes them emit real files rather than<path>/index.html.robots.txtis a hand-written route handler rather than the Nextapp/robots.tsmetadata file, so it can emit the non-standardContent-Signal:directive (per contentsignals.org). trailingSlash: true. Every route emits<path>/index.html. Internal links and hand-built URLs (sitemap entries, JSON-LD@ids) should expect a trailing slash — seeSITE_URLandBLOG_URLinlib/links.ts.- Tailwind v4. Theme tokens live in
app/globals.cssunder@theme inline { … }— there is notailwind.config.*. - Conventional commits enforced.
commitlintruns in thecommit-msghusky hook; non-conforming messages are rejected. metadataBaseis live.lib/links.tssiteis the real origin andINDEXABLEistrue. Anything anchored on this origin — OG and canonical (viametadataBase); JSON-LD and the sitemap/robots emitters (viaSITE_URL) — ships to production. Adding a non-blog page means appending an entry toapp/sitemap-pages.xml/route.ts; blog posts are auto-derived fromcontent/blog/, while legal pages are driven by the closedLEGAL_SLUGSlist inlib/legal.ts(add both the MDX file undercontent/legal/and a slug there). FlippingINDEXABLEflips<meta name="robots">only;robots.txtand the sitemap stay unconditional by design (rationale inlib/links.ts).- Machine-readable surfaces.
/llms.txtis a curated index of this origin and/llms-full.txtis every page as one plain-text document; both derive their page entries fromlistPosts(),LEGAL_SLUGS,lib/faq.tsandlib/copy.ts, are listed inapp/sitemap-pages.xml/route.ts, and are advertised throughalternates.typesinapp/layout.tsxand aLink:header inpublic/_headers.scripts/check-out.mjsresolves every advertised same-origin URL againstout/after a build. The protocol documentation has its own pair ondocs.decdn.org, served by Mintlify.
Cloudflare Pages serves the out/ directory produced by pnpm build.
See AGENTS.md for the full ruleset (CLAUDE.md is a one-line include of it).