diff --git a/app/docs-raw/[...slug]/route.dev.ts b/app/docs-raw/[...slug]/route.dev.ts
new file mode 100644
index 0000000..8153e92
--- /dev/null
+++ b/app/docs-raw/[...slug]/route.dev.ts
@@ -0,0 +1,21 @@
+import { getDoc } from "@/lib/docs"
+import { parseDocSlug } from "@/lib/docs-config"
+
+// In production, .md files are served as static files written by scripts/copy-docs-md.ts.
+// This route only runs in dev (output: "export" is not set in dev).
+export const dynamic = "force-dynamic"
+
+export async function GET(
+ _request: Request,
+ { params }: { params: Promise<{ slug: string[] }> }
+) {
+ const { slug } = await params
+ const { version, docSlug } = parseDocSlug(slug)
+ const doc = getDoc(version, docSlug)
+
+ if (!doc) return new Response("Not found", { status: 404 })
+
+ return new Response(doc.content, {
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
+ })
+}
diff --git a/app/docs/[...slug]/page.tsx b/app/docs/[...slug]/page.tsx
index 1d536c7..d1e89ad 100644
--- a/app/docs/[...slug]/page.tsx
+++ b/app/docs/[...slug]/page.tsx
@@ -104,7 +104,7 @@ export default async function DocPage({ params }: PageProps) {
{/* Table of Contents - right sidebar */}
{headings.length > 0 && (
)}
diff --git a/components/table-of-contents.tsx b/components/table-of-contents.tsx
index 4475bfa..555911d 100644
--- a/components/table-of-contents.tsx
+++ b/components/table-of-contents.tsx
@@ -2,6 +2,7 @@
import { useEffect, useState } from "react"
import { cn } from "@/lib/utils"
+import { CopyIcon, CheckIcon } from "lucide-react"
interface TocEntry {
depth: number
@@ -9,8 +10,22 @@ interface TocEntry {
id: string
}
-export function TableOfContents({ headings }: { headings: TocEntry[] }) {
+export function TableOfContents({
+ headings,
+ rawContent,
+}: {
+ headings: TocEntry[]
+ rawContent?: string
+}) {
const [activeId, setActiveId] = useState("")
+ const [copied, setCopied] = useState(false)
+
+ async function copyMarkdown() {
+ if (!rawContent) return
+ await navigator.clipboard.writeText(rawContent)
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ }
useEffect(() => {
if (headings.length === 0) return
@@ -46,6 +61,19 @@ export function TableOfContents({ headings }: { headings: TocEntry[] }) {
return (