Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6ed79ee
Migrate docs from Mintlify to fumadocs (Next.js, self-hosted)
masnwilliams Jul 21, 2026
9f94fda
Pin Vercel framework preset to Next.js
masnwilliams Jul 22, 2026
4d67246
Default docs assistant to Haiku
masnwilliams Jul 22, 2026
2a8ff17
Address Bugbot review findings
masnwilliams Jul 22, 2026
a5659c1
Match production docs look: notebook layout, logo wordmark
masnwilliams Jul 22, 2026
2219ac8
Sidebar links: text-only hover/active states like navbar links
masnwilliams Jul 22, 2026
9ba98c9
Sidebar folder toggles: same text-only hover as page links
masnwilliams Jul 22, 2026
a1c1731
Pointer cursor on sidebar folder toggles
masnwilliams Jul 22, 2026
d21485a
Match Mintlify homepage and page chrome; disable overscroll
masnwilliams Jul 22, 2026
3b528d5
Group API reference endpoints by tag, like prod
masnwilliams Jul 22, 2026
d0371d9
Render title and description on API reference pages
masnwilliams Jul 22, 2026
3422937
Render API responses with a status-code dropdown
masnwilliams Jul 22, 2026
175b328
Fix AI chat: pass system prompt via instructions option
masnwilliams Jul 22, 2026
f97c250
API sidebar method badges + plain status dropdown
masnwilliams Jul 22, 2026
3a16eee
Drop role labels in AI chat; user turn as a bubble
masnwilliams Jul 22, 2026
87fa555
Address bugbot findings: code tabs, input casing, open-in URL
masnwilliams Jul 22, 2026
72441ee
Harden /api/chat: BotID + rate limiting
masnwilliams Jul 22, 2026
b51b764
BotID Deep Analysis + Vercel Firewall rate limiting
masnwilliams Jul 22, 2026
95c5171
Add Braintrust chat telemetry + input-size guard
masnwilliams Jul 22, 2026
79ea2cc
Group chat turns into one Braintrust trace per conversation
masnwilliams Jul 22, 2026
b9da61d
Tag chat retries in Braintrust
masnwilliams Jul 22, 2026
240ffc7
Enable fumadocs ImageZoom for content images
masnwilliams Jul 22, 2026
0ddfd42
Raise chat input-size cap so real conversations aren't rejected
masnwilliams Jul 22, 2026
e74151f
Soften API method badges to subtle tints
masnwilliams Jul 22, 2026
23385a9
Fix bugbot findings across the docs app
masnwilliams Jul 22, 2026
3fe509e
Merge origin/main into hypeship/fumadocs-migration
masnwilliams Jul 22, 2026
2971558
Address bugbot: robust chat size cap + skip external stubs in index
masnwilliams Jul 23, 2026
1a81b29
Merge origin/main into hypeship/fumadocs-migration
masnwilliams Jul 23, 2026
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
32 changes: 25 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
*/.DS_Store
# deps
/node_modules

# generated content
.source

# test & build
/coverage
/.next/
/out/
/build
*.tsbuildinfo

# misc
.DS_Store
.env
*.pem
/.pnp
.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*

node_modules/
venv
__pycache__/**
test.py
./kernel/**
# others
.env
.env*.local
.vercel
next-env.d.ts
Comment thread
cursor[bot] marked this conversation as resolved.
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

## Cursor Cloud specific instructions

This is a Mintlify documentation site (no `package.json`). The only service is the docs preview server.
This is a fumadocs (Next.js) documentation site. Content lives in `content/docs/` as MDX.

- **Run the docs site:** `mintlify dev` (serves on `http://localhost:3000` by default; auto-increments if the port is busy)
- **Lint/build:** Mintlify handles rendering; there's no separate lint or build step. Validate by running `mintlify dev` and checking pages load.
- **Config:** `docs.json` is the main Mintlify config (navigation, theme, OpenAPI spec URL, redirects).
- **Run the docs site:** `bun dev` (serves on `http://localhost:3000`)
- **Lint/build:** `bun run build` compiles every page; `bun run lint` runs Biome. Validate changes with a build.
- **Config:** `docs.json` remains the navigation source of truth (tabs/groups/redirects); `lib/tree.ts` converts it to the sidebar at build time. Mintlify components (`<Info>`, `<CodeGroup>`, `<Steps>`, ...) still work — they're aliased in `components/mdx.tsx`.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ When you add Go examples:
To run the docs locally, you can use the following command:

```bash
mintlify dev
bun install
bun dev
```

## Contributing
Expand Down
84 changes: 84 additions & 0 deletions app/(docs)/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle,
MarkdownCopyButton,
} from "fumadocs-ui/layouts/notebook/page";
import { createRelativeLink } from "fumadocs-ui/mdx";
import type { Metadata } from "next";
import { notFound, redirect } from "next/navigation";
import { getMDXComponents } from "@/components/mdx";
import { OpenInDropdown } from "@/components/page-actions";
import { SocialFooter } from "@/components/social-footer";
import { getPageImage, getPageMarkdownUrl, source } from "@/lib/source";
import { getEyebrow } from "@/lib/tree";

export default async function Page(props: PageProps<"/[[...slug]]">) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
// Mintlify url: frontmatter marks a page as an external sidebar link
if (page.data.url) redirect(page.data.url);

const MDX = page.data.body;
const markdownUrl = getPageMarkdownUrl(page).url;
const eyebrow = getEyebrow(params.slug ?? []);
// Mintlify's mode: wide widens the content column and drops the TOC
const full = page.data.full || page.data.mode === "wide";

return (
<DocsPage
toc={page.data.toc}
full={full}
breadcrumb={{ enabled: false }}
footer={{ children: <SocialFooter /> }}
>
{eyebrow ? (
<span className="-mb-4 text-sm font-semibold text-fd-primary">
{eyebrow}
</span>
) : null}
<DocsTitle className="text-3xl tracking-tight sm:text-4xl">
{page.data.title}
</DocsTitle>
<DocsDescription className="mb-0">
{page.data.description}
</DocsDescription>
<div className="flex flex-row gap-2 items-center border-b pb-6">
<MarkdownCopyButton markdownUrl={markdownUrl}>
Copy page
</MarkdownCopyButton>
<OpenInDropdown />
</div>
<DocsBody>
<MDX
components={getMDXComponents({
// this allows you to link to other pages with relative file paths
a: createRelativeLink(source, page),
})}
/>
</DocsBody>
</DocsPage>
);
Comment thread
cursor[bot] marked this conversation as resolved.
}

export async function generateStaticParams() {
return source.generateParams();
}

export async function generateMetadata(
props: PageProps<"/[[...slug]]">,
): Promise<Metadata> {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();

return {
title: page.data.title,
description: page.data.description,
openGraph: {
images: getPageImage(page).url,
},
Comment thread
cursor[bot] marked this conversation as resolved.
};
}
49 changes: 49 additions & 0 deletions app/(docs)/api-reference/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle,
} from "fumadocs-ui/layouts/notebook/page";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { OpenAPIPage } from "@/components/api-page";
import { SocialFooter } from "@/components/social-footer";
import { apiSource } from "@/lib/source";

export default async function Page(
props: PageProps<"/api-reference/[[...slug]]">,
) {
const params = await props.params;
const page = apiSource.getPage(params.slug);
if (!page) notFound();

return (
<DocsPage toc={page.data.toc} footer={{ children: <SocialFooter /> }}>
<DocsTitle className="text-3xl tracking-tight sm:text-4xl">
{page.data.title}
</DocsTitle>
{page.data.description ? (
<DocsDescription className="mb-0">
{page.data.description}
</DocsDescription>
) : null}
<DocsBody>
<OpenAPIPage {...page.data.getOpenAPIPageProps()} />
</DocsBody>
</DocsPage>
);
}

export function generateStaticParams() {
return apiSource.generateParams();
}

export async function generateMetadata(
props: PageProps<"/api-reference/[[...slug]]">,
): Promise<Metadata> {
const params = await props.params;
const page = apiSource.getPage(params.slug);
if (!page) notFound();

return { title: page.data.title, description: page.data.description };
}
35 changes: 35 additions & 0 deletions app/(docs)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { buttonVariants } from "fumadocs-ui/components/ui/button";
import { DocsLayout } from "fumadocs-ui/layouts/notebook";
import { MessageCircleIcon } from "lucide-react";
import {
AISearch,
AISearchPanel,
AISearchTrigger,
} from "@/components/ai/search";
import { cn } from "@/lib/cn";
import { baseOptions } from "@/lib/layout.shared";
import { buildTree } from "@/lib/tree";

export default function Layout({ children }: LayoutProps<"/">) {
return (
<DocsLayout tree={buildTree()} tabMode="navbar" {...baseOptions()}>
<AISearch>
<AISearchPanel />
<AISearchTrigger
position="float"
className={cn(
buttonVariants({
variant: "secondary",
className: "text-fd-muted-foreground rounded-2xl",
}),
)}
>
<MessageCircleIcon className="size-4.5" />
Ask AI
</AISearchTrigger>
</AISearch>

{children}
</DocsLayout>
);
}
Loading
Loading