diff --git a/packages/www/script/pagefind.ts b/packages/www/script/pagefind.ts
index 88bb8676bb8..008a502f148 100644
--- a/packages/www/script/pagefind.ts
+++ b/packages/www/script/pagefind.ts
@@ -1,5 +1,8 @@
+import { cp } from "node:fs/promises"
import config from "../astro.config"
const base = config.base?.replace(/\/$/, "") ?? ""
+const docs = `dist/client${base}/docs`
-await Bun.$`pagefind --site ${`dist/client${base}/docs`}`
+await cp(`dist/client${base}/docs-index`, docs, { recursive: true })
+await Bun.$`pagefind --site ${docs}`
diff --git a/packages/www/script/prepare-cloudflare.ts b/packages/www/script/prepare-cloudflare.ts
index 164e96afd30..8d08e230945 100644
--- a/packages/www/script/prepare-cloudflare.ts
+++ b/packages/www/script/prepare-cloudflare.ts
@@ -1,10 +1,21 @@
-export {}
+import { rm } from "node:fs/promises"
+import path from "node:path"
+import astro from "../astro.config"
-const path = "dist/server/wrangler.json"
-const config = await Bun.file(path).json()
+const base = astro.base?.replace(/\/$/, "") ?? ""
+const snapshots = `dist/client${base}/docs-index`
+
+await Promise.all(
+ (await Array.fromAsync(new Bun.Glob("**/*.html").scan({ cwd: snapshots }))).map((file) =>
+ rm(path.join(`dist/client${base}/docs`, file)),
+ ),
+)
+await rm(snapshots, { recursive: true })
+
+const config = await Bun.file("dist/server/wrangler.json").json()
delete config.kv_namespaces
delete config.images
delete config.previews
-await Bun.write(path, JSON.stringify(config))
+await Bun.write("dist/server/wrangler.json", JSON.stringify(config))
diff --git a/packages/www/src/docs/components/DocsPage.astro b/packages/www/src/docs/components/DocsPage.astro
new file mode 100644
index 00000000000..d8401b98cbb
--- /dev/null
+++ b/packages/www/src/docs/components/DocsPage.astro
@@ -0,0 +1,25 @@
+---
+import { render, type CollectionEntry } from "astro:content"
+import Callout from "./Callout.astro"
+import Card from "./Card.astro"
+import CardGroup from "./CardGroup.astro"
+import CodeBlock from "./CodeBlock.astro"
+import DocsLayout from "../layouts/DocsLayout.astro"
+
+interface Props {
+ entry: CollectionEntry<"docs">
+}
+
+const entry = Astro.props.entry
+const rendered = await render(entry)
+---
+
+
+
+
diff --git a/packages/www/src/pages/docs-index/[...slug].astro b/packages/www/src/pages/docs-index/[...slug].astro
new file mode 100644
index 00000000000..75e76648ce0
--- /dev/null
+++ b/packages/www/src/pages/docs-index/[...slug].astro
@@ -0,0 +1,21 @@
+---
+import { getCollection, type CollectionEntry } from "astro:content"
+import DocsPage from "../../docs/components/DocsPage.astro"
+
+interface Props {
+ entry: CollectionEntry<"docs">
+}
+
+export async function getStaticPaths() {
+ return (await getCollection("docs")).map((entry) => ({
+ params: {
+ slug: entry.id === "index" ? undefined : entry.id.replace(/\/index$/, ""),
+ },
+ props: { entry },
+ }))
+}
+
+export const prerender = true
+---
+
+
diff --git a/packages/www/src/pages/docs/[...slug].astro b/packages/www/src/pages/docs/[...slug].astro
index 089d1128c17..fb59d343835 100644
--- a/packages/www/src/pages/docs/[...slug].astro
+++ b/packages/www/src/pages/docs/[...slug].astro
@@ -1,36 +1,26 @@
---
-import { getCollection, render, type CollectionEntry } from "astro:content"
-import Callout from "../../docs/components/Callout.astro"
-import Card from "../../docs/components/Card.astro"
-import CardGroup from "../../docs/components/CardGroup.astro"
-import CodeBlock from "../../docs/components/CodeBlock.astro"
-import DocsLayout from "../../docs/layouts/DocsLayout.astro"
+import { getEntry } from "astro:content"
+import DocsPage from "../../docs/components/DocsPage.astro"
-interface Props {
- entry: CollectionEntry<"docs">
+export const prerender = false
+
+const slug = Astro.params.slug || "index"
+const entry = (await getEntry("docs", slug)) ?? (await getEntry("docs", `${slug}/index`))
+if (!entry) return new Response("Not found", { status: 404, headers: { "Cache-Control": "no-store" } })
+
+const headers = {
+ "Cache-Control": "public, max-age=300, stale-while-revalidate=3600",
+ Vary: "Accept",
}
-export async function getStaticPaths() {
- return (await getCollection("docs")).map((entry) => ({
- params: {
- slug: entry.id === "index" ? undefined : entry.id.replace(/\/index$/, ""),
- },
- props: { entry },
- }))
+const accept = Astro.request.headers.get("accept") ?? ""
+if (accept.includes("text/markdown") || accept.includes("text/x-markdown")) {
+ return new Response(`# ${entry.data.title}\n\n${entry.body ?? ""}`, {
+ headers: { ...headers, "Content-Type": "text/markdown; charset=utf-8" },
+ })
}
-export const prerender = true
-
-const entry = Astro.props.entry
-const rendered = await render(entry)
+Object.entries(headers).forEach(([name, value]) => Astro.response.headers.set(name, value))
---
-
-
-
+
diff --git a/packages/www/src/pages/install.astro b/packages/www/src/pages/install.astro
index 67c1e6c595e..865f38ed9a6 100644
--- a/packages/www/src/pages/install.astro
+++ b/packages/www/src/pages/install.astro
@@ -1,5 +1,13 @@
---
export const prerender = false
-return fetch("https://raw.githubusercontent.com/anomalyco/opencode/v2/install")
+const response = await fetch("https://raw.githubusercontent.com/anomalyco/opencode/v2/install")
+const headers = new Headers(response.headers)
+headers.set("Cache-Control", "no-store")
+
+return new Response(response.body, {
+ status: response.status,
+ statusText: response.statusText,
+ headers,
+})
---
diff --git a/packages/www/wrangler.jsonc b/packages/www/wrangler.jsonc
index 6bfc1b85b8f..5c3da434fb2 100644
--- a/packages/www/wrangler.jsonc
+++ b/packages/www/wrangler.jsonc
@@ -4,6 +4,9 @@
"compatibility_date": "2026-07-25",
"workers_dev": false,
"preview_urls": false,
+ "cache": {
+ "enabled": true,
+ },
"assets": {
"binding": "ASSETS",
"directory": "./dist/client",