# AI & agent access (/docs/agents)
Docs published with docs.dev aren't just a website — they're a corpus that AI
assistants and coding agents can consume directly. Everything on this page
ships with every site, no configuration required.
## Ask AI [#ask-ai]
Every docs site includes an **Ask AI** assistant — the floating button in the
bottom-right corner of any docs page. It answers questions using only your
documentation, streams its answers, and links to the pages it used.
Like [AI writing in the editor](/docs/ai), the assistant runs on
[Workers AI](https://developers.cloudflare.com/workers-ai/) in **your**
Cloudflare account: no API keys, no per-seat AI pricing, no message quotas
imposed by us. If the deployment has the `AI` binding (the default
`wrangler.jsonc` does), the assistant is live; without it, the button simply
doesn't render.
Site owners can optionally enable [Ask AI insights](/docs/configuration#bindings-wranglerjsonc):
questions are then logged **anonymously** — the question text, the page it
was asked from, and a timestamp; never IPs, accounts, or identifiers — to
the site's own database, pruned after 90 days, so the team can see what the
docs failed to answer. Without that binding, nothing is stored.
## Markdown for every page [#markdown-for-every-page]
Append `.md` to any docs URL to get the page as raw markdown — the convention
agents already expect:
```bash
curl https://your-site.example/docs/getting-started.md
```
Every page also has a **copy as markdown** button and view options for opening
the page directly in AI tools.
## llms.txt [#llmstxt]
Two standard index files are generated from your content on every build:
* `/llms.txt` — an index of all pages with descriptions, linking to the
markdown version of each page.
* `/llms-full.txt` — the entire docs corpus concatenated as one markdown
document, for tools that want everything in a single fetch.
## MCP server [#mcp-server]
Every site serves a [Model Context Protocol](https://modelcontextprotocol.io)
endpoint at `/mcp`, so MCP clients can search and read your docs during a
conversation or coding session. For Claude Code:
```bash
claude mcp add --transport http my-docs https://your-site.example/mcp
```
Or in any client that accepts JSON configuration:
```json
{
"mcpServers": {
"my-docs": { "url": "https://your-site.example/mcp" }
}
}
```
The server exposes three tools:
| Tool | What it does |
| ------------- | ------------------------------------------------------------ |
| `search_docs` | Search pages by keyword; returns titles, URLs, and snippets. |
| `read_page` | Fetch one page as markdown by its URL or path. |
| `list_pages` | List every page with its title and description. |
No authentication is required — the MCP server exposes exactly what the
public site already serves.
# AI writing & images (/docs/ai)
The editor can draft documentation and generate images for you. Both run on
[Workers AI](https://developers.cloudflare.com/workers-ai/) — meaning they
execute on **your** Cloudflare account, are billed to you (the free tier goes
a long way for docs), and require no API keys from anyone. It works the
moment your site deploys.
## Writing with AI [#writing-with-ai]
In the editor, **Generate with AI** drafts content from a prompt, aware of
the page you're on (title and surrounding context), and returns Markdown that
drops straight into your blocks — headings, code fences, lists intact. You
review and edit before anything is published; AI output is a draft like any
other.
### Grounding with web search (optional) [#grounding-with-web-search-optional]
For topics that benefit from current sources, generation can ground itself
with a web search first and cite what it found. Enable it by setting one
secret — either provider works:
```bash
wrangler secret put TAVILY_API_KEY # tavily.com
# or
wrangler secret put BRAVE_API_KEY # brave.com/search/api
```
Without a key, generation still works — it just skips the search step.
## Image generation [#image-generation]
**Generate image** turns a prompt into an illustration you can place like any
uploaded image — including as a figure that prose flows around, exactly like
this one. Generated images ride the same pipeline as uploads: they save into
your draft, publish as a git commit to `public/uploads/`, and are served as
static assets by your own site.
## Choosing models [#choosing-models]
Sensible defaults ship out of the box, overridable with two variables in
`wrangler.jsonc`:
| Variable | Default |
| ---------------- | ------------------------------------------ |
| `AI_TEXT_MODEL` | `@cf/meta/llama-3.3-70b-instruct-fp8-fast` |
| `AI_IMAGE_MODEL` | `@cf/black-forest-labs/flux-1-schnell` |
Any text or image model in the
[Workers AI catalog](https://developers.cloudflare.com/workers-ai/models/)
works.
Your prompts and your docs never route through a third party's metering
proxy, there's no per-seat AI fee, and rate limits are yours alone. It's
the same principle as the rest of docs.dev: the tool is ours, the
infrastructure is yours.
# Why docs.dev + Claude Code (/docs/claude-code)
Most docs platforms make agents second-class citizens: content lives in a
database behind a proprietary API, so an agent needs a custom integration
before it can change a word. docs.dev inverts that. Your documentation is
**MDX files in your own GitHub repository** — the exact medium Claude Code is
best at working in. No plugin, no connector, no export step. `cd` into the
repo, run `claude`, and ask for what you want.
```bash
cd your-docs-repo
claude
# > document the new webhooks API — endpoint list is in src/routes/webhooks.ts
```
## The repo ships agent-ready [#the-repo-ships-agent-ready]
Every docs.dev site is created with the guardrails an agent needs already in
place:
* **`CLAUDE.md` teaches the conventions.** Where pages live, the required
frontmatter, how URLs derive from file paths, how the sidebar is ordered,
and which commands verify a change. Claude reads it on session start, so
"add a quickstart page" works on day one — no prompt engineering required.
* **A `/new-page` skill does the chore correctly.** Creating a page isn't
just writing a file: it's a valid slug, frontmatter, a `meta.json` entry,
and a passing type check. The skill encodes all of it, so every generated
page lands consistent with the rest of the site.
* **Verification is one command.** `pnpm types:check` validates frontmatter
and MDX across the whole site. Claude runs it before pushing, which means
broken pages get caught in the session — not in production.
## Publishing is just `git push` [#publishing-is-just-git-push]
There is no "sync" step between what Claude writes and what readers see.
Pages are files, publishing is a commit, and pushing to the default branch
triggers your own Cloudflare CI. A typical request — *"document the new
rate-limit headers"* — ends with the change live in about a minute, with a
real commit in your history that you can review, revert, or cherry-pick like
any code change.
Want a human in the loop? Ask Claude to open a pull request instead, and
review the docs the way you review code.
## Draft first, publish from the editor [#draft-first-publish-from-the-editor]
For reviewers who'd rather see a rendered page than a diff, there's a second
human-in-the-loop path: the repo ships a `/draft-page` skill that writes
Claude's page into the same shared-drafts store the
[on-page editor](/docs/editing) uses, instead of committing it to the
content directory.
```bash
# > /draft-page Webhooks retry behavior — but I want to review before it ships
```
Nothing deploys. Instead, anyone signed in to the editor sees the draft
overlaid on the live site at its future URL — authored by "Claude Code",
rendered exactly as it will ship. They can polish the wording in place and
click **Publish** to promote it (a git commit, like any other publish), or
discard it. AI writes, a human previews and touches up, then promotes —
with no CMS between them, just a git branch.
### Or review any branch, no skill required [#or-review-any-branch-no-skill-required]
If Claude (or a teammate) simply pushed docs pages to a **branch**, you
don't need the drafts handshake at all. In the editor sidebar, open
**Branches…**, pick the branch, and every docs page it adds or changes is
listed. **Review** loads a page into the editor as a draft: preview it
rendered, edit it in place, and publish it to the live site — all without
leaving the docs. The branch itself is never modified; close its pull
request whenever you're done with it.
## Agents and humans never fight [#agents-and-humans-never-fight]
The editor, your teammates, and Claude Code all converge on the same source
of truth: whatever lands on the default branch is what deploys. Editor
publishes are commits; agent edits are commits. There's no CMS state to drift
out of sync with the repo, and no lock an agent can trip over.
Because the repo is the only source of truth, you can mix workflows
freely: a writer polishes a page in the on-page editor while Claude Code
drafts three new API pages in a branch. Git merges it; nothing gets lost.
## Things people actually ask for [#things-people-actually-ask-for]
These are all one-line requests in a docs.dev repo:
* *"Add a troubleshooting page for common deploy errors and link it from
getting started."*
* *"Our SDK renamed `client.connect()` to `client.open()` — update every
code sample that uses it."*
* *"Read `src/routes/billing.ts` and write reference docs for each
endpoint."*
* *"Restructure the sidebar so the API reference comes last."*
Because docs and code can live side by side, the last-mile problem of
documentation — keeping it true to the code — becomes a request Claude can
verify against the source itself.
## Beyond the terminal [#beyond-the-terminal]
The same properties that make the repo good for Claude Code make it good for
every agent surface: Claude Code on the web, GitHub Actions that file
docs PRs when APIs change, or scheduled sessions that audit pages for
staleness. Anything that can make a git commit can maintain your docs.
Ready to try it? [Get started](/docs/getting-started), then point Claude
Code at the repo — or see [Editing](/docs/editing) for how agent edits and
the on-page editor fit together.
# Configuration reference (/docs/configuration)
Configuration lives in two places: non-secret **vars** in `wrangler.jsonc`
(committed to your repo), and **secrets** set with `wrangler secret put NAME`
(or in your Worker's dashboard under Settings → Variables and Secrets). For
local development, put secrets in a `.dev.vars` file (never committed).
## Variables (`wrangler.jsonc` → `vars`) [#variables-wranglerjsonc--vars]
| Variable | Purpose |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GITHUB_OWNER` / `GITHUB_REPO` / `GITHUB_BRANCH` | Where the editor publishes — point these at **your** repo and default branch. |
| `DOCSDEV_SITE_ID` | Enables [team sign-in](/docs/team). When set, it's the only sign-in method. Empty = standalone mode. |
| `DOCSDEV_ISSUER` | The docs.dev service origin (leave the default unless self-hosting the service). |
| `AI_TEXT_MODEL` / `AI_IMAGE_MODEL` | Override the [Workers AI models](/docs/ai) used by the editor. |
| `HOME_REDIRECT_TO_DOCS` | Set to `"true"` to skip the landing page — `/` redirects straight to `/docs`. Offered as an option when you first deploy with the Deploy to Cloudflare button; change it later in `wrangler.jsonc` (applies on the next push) or in the dashboard (applies immediately). |
## Secrets [#secrets]
| Secret | Needed for |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `GITHUB_PAT` | Publishing from PIN/docs.dev sessions and the shared-drafts store. Fine-grained token, `contents: read/write` on the docs repo. |
| `ADMIN_PIN` + `ADMIN_SECRET` | [PIN sign-in](/docs/standalone-auth#pin-sign-in). Both required; no defaults — editing stays disabled without them. |
| `GITHUB_APP_CLIENT_ID` + `GITHUB_APP_CLIENT_SECRET` | [GitHub sign-in](/docs/standalone-auth#github-sign-in). |
| `TAVILY_API_KEY` *or* `BRAVE_API_KEY` | Optional [web-search grounding](/docs/ai#grounding-with-web-search-optional) for AI writing. |
## Bindings (`wrangler.jsonc`) [#bindings-wranglerjsonc]
| Binding | Purpose |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AI` (Workers AI) | [AI writing & images](/docs/ai) in the editor and the reader-facing [Ask AI assistant](/docs/agents#ask-ai). Included by default; remove it and both features hide themselves. |
| `INSIGHTS` (D1, optional) | [Ask AI insights](/docs/agents#ask-ai) — logs reader questions anonymously so admins can see what the docs couldn't answer. Off until you create the database and uncomment the block: |
```bash
npx wrangler d1 create docsdev-insights
# paste the returned id into the d1_databases block in wrangler.jsonc
```
## Sign-in precedence [#sign-in-precedence]
1. **`DOCSDEV_SITE_ID` set** → docs.dev team sign-in only. PIN and GitHub
sign-in are disabled, so stale credentials can't bypass team membership.
2. **Otherwise** → whichever of GitHub sign-in and PIN you've configured
(both is fine). Nothing configured = editing disabled, docs still served.
## Commands [#commands]
```bash
pnpm dev # local dev server
pnpm types:check # frontmatter + type validation — run before pushing
pnpm cf:preview # build and run the real Worker locally
pnpm cf:deploy # manual deploy (normally unnecessary — pushing deploys)
```
## CI (Workers Builds) [#ci-workers-builds]
The one-click deploy configures these automatically; if you're setting up CI
by hand, use:
* **Build command:** `npx opennextjs-cloudflare build`
* **Deploy command:** `npx wrangler deploy`
# Editing (/docs/editing)
## The editor is the page [#the-editor-is-the-page]
There's no separate "editor view" that approximates your site. Hit
**Edit page** on any page (or pick one from `/admin`) and the page itself
becomes editable — same typography, same layout engine, same flowing prose.
What you see while editing is exactly what readers get, including text
reflowing live around figures as you drag or resize them.
Blocks can be inserted, reordered, and deleted in place: prose, code blocks
(with editable tabs), callouts, cards, images, and Spread figures that prose
flows around — like this one. Hover the left margin for the insert rail, drag
a block to reorder it, and every change reflows the page exactly as readers
will see it.
## Drafts are shared [#drafts-are-shared]
Edits autosave as drafts — instantly to your browser, and (debounced) to a
shared store the rest of your team sees. A teammate opening the same page
picks up your draft, with the author shown, and conflicting edits are caught
rather than silently overwritten.
Shared drafts live in a dedicated `docsdev-drafts` branch of your own repo —
no extra infrastructure, and your drafts are as private as your repository.
## Publishing is a commit [#publishing-is-a-commit]
**Publish** commits the page (and any uploaded images) to your repo via the
GitHub API, and your push-to-deploy CI takes it from there — changes are live
in about a minute. Depending on how you signed in:
* **GitHub sign-in:** the commit is authored by *you* — real attribution in
your git history.
* **docs.dev or PIN sign-in:** the commit uses the site's `GITHUB_PAT`
server credential.
Because published pages are just MDX in git, everything you already do with
code applies to docs: branches, pull requests, reviews, reverts.
## Theming from the sidebar [#theming-from-the-sidebar]
Admins get a **Theme…** entry at the bottom of the sidebar. Pick a preset
accent or dial in a custom color, and the whole site updates instantly —
links, buttons, figure accents, editor chrome, even the draft you're in the
middle of editing — so you can judge the color in context, not in a settings
page. The preview is local to you until you hit **Publish**, which commits
`src/app/theme.css` to your repo like any other edit; push-to-deploy CI
rebuilds the site with the new accent for everyone.
## API reference from your OpenAPI spec [#api-reference-from-your-openapi-spec]
Admins also get an **API specs…** entry in the sidebar. Upload an OpenAPI
document (JSON) and it's committed to `openapi/` in your repo; the next
build generates a full API reference from it under `/docs/api-reference` —
one page per operation, grouped by tag, each with an interactive
playground. Re-upload under the same name to update it, or remove it to
retire the section. Multiple specs each get their own section.
Prefer git? Drop the file into `openapi/` and push — the upload button and
the commit are the same thing. Never edit the generated pages by hand; they
are rebuilt from the spec on every deploy.
## See what readers ask [#see-what-readers-ask]
With [Ask AI insights enabled](/docs/configuration#bindings-wranglerjsonc),
the **Questions…** sidebar entry shows what readers asked the assistant —
most recent first, with an **Unanswered** filter surfacing the questions the
docs couldn't answer. That list is effectively your writing backlog: each
unanswered question is a page (or paragraph) readers already tried to find.
Logging is anonymous — question, page, and time; no reader identity — and
entries expire after 90 days.
## Editing with Claude Code [#editing-with-claude-code]
The repo is agent-ready: `CLAUDE.md` teaches the conventions (where pages
live, frontmatter, nav, how to verify) and ships a `/new-page` skill. Typical
session:
```bash
cd your-docs-repo
claude
# > document the new webhooks API — endpoint list is in src/routes/webhooks.ts
```
Claude writes the pages, registers them in the nav, runs `pnpm types:check`,
and pushes. The push deploys. For content that needs a human eye first, ask it
to open a pull request instead.
The editor and the repo never fight: the repo is the only source of truth.
Editor publishes are commits; agent and human edits are commits. Whatever
lands on the default branch is what deploys.
# Getting started (/docs/getting-started)
## Deploy in one click [#deploy-in-one-click]
Click **Deploy to Cloudflare** on the
[docs.dev template](https://github.com/keyboard-dev/docs.dev). Cloudflare will:
1. **Clone the template into your GitHub account** — the repo is yours from
the first second.
2. **Build and deploy it to your Cloudflare account**, live at
`..workers.dev`.
3. **Wire up push-to-deploy CI** (Workers Builds): every push to your repo's
default branch rebuilds and redeploys the site automatically.
No Cloudflare account? The deploy flow creates one — the free tier is more
than enough for a docs site.
The site you just deployed contains docs.dev's own documentation as working
example pages. Replace it with your own — every page is an MDX file in
`content/docs/`.
## Choose how editors sign in [#choose-how-editors-sign-in]
A fresh deployment has editing **disabled** — there are no default
credentials, on purpose. Pick one:
* **[Team sign-in](/docs/team)** (recommended): editors sign in with their
docs.dev account; you control membership centrally.
* **[Standalone](/docs/standalone-auth)**: GitHub sign-in (anyone with push
access to the repo) and/or a PIN — no docs.dev account involved.
Either way, `/admin` on your site is the way in.
## Make your first edit [#make-your-first-edit]
1. Open any page on your site and hit **Edit page** (or go to `/admin` and
pick one):
2. Edit right on the page — the layout you see is the layout readers get.
3. **Publish.** That's a git commit to your repo, and your CI redeploys the
site. Live in about a minute.
Prefer files? Every page is `content/docs/.mdx` with two lines of
frontmatter:
```mdx
---
title: Page title
description: One-sentence summary shown in navigation and search.
---
## Start headings at H2
The H1 comes from the title.
```
Sidebar order lives in `content/docs/meta.json`. Images go in
`public/uploads/` and are referenced as `/uploads/name.png`.
## Or let an agent do it [#or-let-an-agent-do-it]
The repo ships a `CLAUDE.md` documenting all of the conventions above, plus a
`/new-page` skill. Point [Claude Code](https://claude.com/claude-code) at your
clone and ask for what you want:
```bash
git clone https://github.com//
cd
claude
# > add a quickstart page for our API and put it after getting-started
```
Claude writes the MDX, updates the nav, runs the checks, and pushes — and the
push deploys.
## Local development [#local-development]
```bash
pnpm install
pnpm dev # http://localhost:3000
pnpm types:check # validates MDX frontmatter + types — run before pushing
pnpm cf:preview # run the real Cloudflare Worker locally
```
## Custom domain [#custom-domain]
Your site is a Cloudflare Worker, so custom domains are first-class: in the
Cloudflare dashboard, open your Worker → **Settings → Domains & Routes** →
add your domain. If you use [team sign-in](/docs/team), update your site's
registered redirect URI to the new domain afterwards.
# Welcome to docs.dev (/docs)
docs.dev is a documentation platform built on a bet most docs tools won't make: **you should own everything.** Your docs live in your GitHub repository, your site runs on your Cloudflare account, and if you stop using docs.dev tomorrow, your site keeps working. What we add on top is the part you actually want from a docs product: a beautiful reading experience, an editor your whole team can use, and sign-in that stays out of your way!!!!
## What makes it different [#what-makes-it-different]
**A reading experience, not a wall of blocks.** Prose flows around figures, code, and shapes — like the paragraph you are reading right now — powered by the [pretext](https://github.com/chenglou/pretext) layout engine. Every run of text is measured with canvas arithmetic and placed as real, selectable, indexable DOM text on **both** sides of a figure at once, which CSS floats and CSS Shapes cannot express. Resize the window and the words re-measure and re-break against the live column width. [See it live on the home page](/).
* **Your repo is the source of truth.** Every page is an MDX file. Publishing from the editor is a git commit. Your history, your pull requests, your rollbacks.
* **Your infrastructure.** One click deploys to *your* Cloudflare account with CI wired up. AI features run on Workers AI — also yours. There is no hosting bill from us and no lock-in to escape later.
* **Built for agents.** The repo ships a `CLAUDE.md` and skills, so pointing Claude Code at your docs works on day one: "add a quickstart page" is a one-line request.
## Start here [#start-here]
## How it fits together [#how-it-fits-together]
Your site is a Next.js app (Fumadocs + the pretext engine) deployed to
Cloudflare Workers from your own repository. Everything the editor does —
sign-in, drafts, publishing, AI generation — goes through your site's own
same-origin API, documented in the [API reference](/docs/api-reference).
The optional docs.dev service adds one thing: [team sign-in](/docs/team),
so editors authenticate with their docs.dev account instead of shared
credentials. It's a sign-in check, not a dependency — your published site
never needs us to serve a single page.
# Standalone sign-in (/docs/standalone-auth)
Don't want another account? Your site's editor also works fully standalone,
with two methods you can enable independently. (If you later set up
[team sign-in](/docs/team), it takes over as the only method.)
## GitHub sign-in [#github-sign-in]
Editors sign in with GitHub; authorization is **push access to your docs
repo** — if someone can push, they can edit, and their publishes are
committed *as them* in git history.
Set it up once:
1. Create a **GitHub App** (Settings → Developer settings → GitHub Apps) with
the callback URL:
```
https:///api/auth/github/callback
```
2. Enable **"Request user authorization (OAuth) during installation"** and
install the app on your docs repo.
3. Set two secrets on your Worker:
```bash
wrangler secret put GITHUB_APP_CLIENT_ID
wrangler secret put GITHUB_APP_CLIENT_SECRET
```
That's it — `/admin` now shows **Sign in with GitHub**.
## PIN sign-in [#pin-sign-in]
The lightweight option for solo sites and local development: one shared PIN.
### Set the PIN [#set-the-pin]
Set two secrets on your Worker — you'll be prompted for each value:
```bash
wrangler secret put ADMIN_PIN # the PIN editors type at /admin
wrangler secret put ADMIN_SECRET # long random string that seals session cookies
```
Pick any PIN you like; for the sealing key, generate something strong:
```bash
openssl rand -base64 32
```
Both are required — there is **no default PIN**. This template is public
code, so a baked-in fallback would be a published constant, not a secret; an
unconfigured deployment simply has editing disabled until you set these.
Once set, visit `/admin` (or the **Edit page** button on any page after
signing in) and enter the PIN. Sessions last 8 hours.
### Local development [#local-development]
Secrets aren't available to `pnpm dev`, so put them in a `.dev.vars` file at
the repo root (it's gitignored — never commit it):
```bash title=".dev.vars"
ADMIN_PIN=1234
ADMIN_SECRET=any-long-random-string-for-local-work
```
### Rotating [#rotating]
* **Change the PIN:** run `wrangler secret put ADMIN_PIN` again. Existing
sessions stay valid until they expire (8 hours); only new sign-ins need
the new PIN.
* **Sign everyone out now:** rotate `ADMIN_SECRET`. Session cookies are
sealed with it, so changing it invalidates every session immediately.
GitHub sign-in for anything with more than one editor — real identity, per
person revocation, commit attribution. PIN for a personal site or a quick
demo. Both at once is fine: the sign-in screen offers whatever is
configured.
## Publishing credential [#publishing-credential]
Publishes from GitHub-signed-in editors use their own token. PIN sessions
(and the shared-drafts store) need a server credential:
```bash
wrangler secret put GITHUB_PAT # fine-grained token, contents: read/write on the docs repo
```
# Team sign-in (/docs/team)
Team sign-in connects your site's editor to a docs.dev team: editors sign in
with their own docs.dev account (GitHub identity), and only people you've
invited can get in. No shared PINs, no per-person GitHub repo access to
manage — invite someone once and they can edit; remove them once and they
can't.
## Set it up [#set-it-up]
1. **Create your account** at your docs.dev dashboard — sign in with GitHub.
Your team is created automatically.
2. **Register your site**: add its name and its sign-in callback URL —
exactly your deployed site's origin plus `/api/admin/sso/callback`, e.g.
```
https://docs.example.com/api/admin/sso/callback
```
You get back a **Site ID**.
3. **Configure your site**: in your repo's `wrangler.jsonc`, set
```jsonc
"DOCSDEV_SITE_ID": "site_…" // from the dashboard
```
Commit and push — your CI redeploys with team sign-in enabled.
4. **Invite your team** from the dashboard by email. Invitees accept, sign in
with GitHub, and can immediately use your site's `/admin`.
## Roles [#roles]
* **Admin** (the team owner): manages members and registered sites, and can
edit.
* **Editor** (everyone you invite): can edit and publish.
## The security model [#the-security-model]
Team sign-in is a standard OAuth 2.0 authorization-code flow with PKCE, and
it's deliberately strict:
* **Exact-match redirect whitelist.** Sign-ins can only ever be sent back to
the callback URL registered for your site — exact string match, HTTPS only,
no wildcards. A look-alike domain can't borrow your sign-in.
* **Membership is checked centrally** before a sign-in completes. Someone who
isn't on your team gets a clear "ask an admin to invite you," never a
session.
* **No secrets on your site.** The flow uses PKCE, and your site verifies
sessions against docs.dev's published public keys (JWKS). Nothing
confidential ships in your repo or your Worker.
* **Sessions are short-lived** signed tokens carrying the editor's identity
and role — which is also how draft attribution works.
When `DOCSDEV_SITE_ID` is set, it is the only way in: the PIN and GitHub
sign-in paths are disabled so a leftover credential can't bypass your team's
membership list.
## What stays yours [#what-stays-yours]
Your published site never depends on docs.dev to serve a page — the sign-in
check happens only when an editor signs in. If docs.dev is unreachable,
readers notice nothing, and already-signed-in editors keep working until
their session expires. And if you ever leave, remove one variable and switch
to [standalone sign-in](/docs/standalone-auth) — everything else keeps
working.
# API Reference (/docs/api-reference)
{/* Generated by scripts/generate-api-docs.mjs — edit the spec in openapi/, not this file. */}
The API behind the in-site editor: sessions, shared drafts, page management, publishing, and AI generation. Every route lives on the same origin as the docs site and authenticates with the sealed `docsdev_admin` session cookie set at sign-in.
## Auth [#auth]
Sign in with a PIN or GitHub, inspect the session, sign out.
## Drafts [#drafts]
Shared drafts visible to every editor, with a last-writer conflict guard.
## Pages [#pages]
List and delete documentation pages.
## Publish [#publish]
Commit a page (and its uploaded assets) to GitHub.
## AI [#ai]
Workers AI documentation writing and image generation.
# Check AI availability (/docs/api-reference/ai/aiAvailability)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Generate documentation or an image (/docs/api-reference/ai/aiGenerate)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Delete a draft (/docs/api-reference/drafts/deleteDraft)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Read a draft, or list all drafts (/docs/api-reference/drafts/getDrafts)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Save a draft (/docs/api-reference/drafts/saveDraft)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Delete a page (/docs/api-reference/pages/deletePage)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List published pages (/docs/api-reference/pages/listPages)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Inspect the current session (/docs/api-reference/auth/getSession)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Sign in with GitHub (/docs/api-reference/auth/loginWithGitHub)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Sign in with a PIN (/docs/api-reference/auth/loginWithPin)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Sign out (/docs/api-reference/auth/logout)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Publish a page (/docs/api-reference/publish/publishPage)
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}