# nookdocs > Full documentation export. 199 pages. --- # Create a project Source: https://docs.nookdocs.com/api-reference/endpoint/create-project --- # Delete project logo Source: https://docs.nookdocs.com/api-reference/endpoint/delete-logo --- # Delete a project Source: https://docs.nookdocs.com/api-reference/endpoint/delete-project --- # AI & LLM insights Source: https://docs.nookdocs.com/api-reference/endpoint/get-analytics-ai This is the [AI & LLMs analytics card](/configuration/analytics) as an API — pull how GPTBot, ClaudeBot, and friends consume your docs into your own dashboards. --- # Analytics breakdown Source: https://docs.nookdocs.com/api-reference/endpoint/get-analytics-breakdown The `results` row shape depends on the `dimension` you query: | Dimension | Row fields | |---|---| | `pages` | `path`, `views`, `unique_visitors` | | `searches` | `query`, `count`, `avg_result_count` | | `countries` | `country` (ISO 3166-1 alpha-2), `visitors` | | `regions` | `region`, `country`, `visitors` | | `cities` | `city`, `country`, `visitors` | | `browsers` / `os` / `devices` | `name`, `visitors` | | `channels` | `channel` (Direct, Organic Search, AI, Referral, …), `visitors` | | `referrers` | `referrer` (hostname), `visitors` | | `campaigns` | `campaign` (from `utm_campaign`), `visitors` | | `keywords` | `keyword` (from `utm_term`), `visitors` | --- # Analytics overview Source: https://docs.nookdocs.com/api-reference/endpoint/get-analytics-overview --- # Get a deployment Source: https://docs.nookdocs.com/api-reference/endpoint/get-deployment --- # Get a project Source: https://docs.nookdocs.com/api-reference/endpoint/get-project --- # List deployments Source: https://docs.nookdocs.com/api-reference/endpoint/list-deployments --- # List pages Source: https://docs.nookdocs.com/api-reference/endpoint/list-pages --- # List projects Source: https://docs.nookdocs.com/api-reference/endpoint/list-projects Results only include projects under the organization that owns the API key — there is no cross-org listing. Ordered by creation date, newest first. ## Find broken deploys fast Combine the `status` filter with a small `limit` to surface projects whose last sync failed: ```bash curl 'https://api.nookdocs.com/v1/projects?status=failed&limit=5' \ -H 'Authorization: Bearer nook_...' ``` Valid statuses: `pending`, `building`, `active`, `failed`. --- # Search pages Source: https://docs.nookdocs.com/api-reference/endpoint/search-pages --- # Trigger a deployment Source: https://docs.nookdocs.com/api-reference/endpoint/trigger-deployment --- # Update a project Source: https://docs.nookdocs.com/api-reference/endpoint/update-project --- # Upload a project asset Source: https://docs.nookdocs.com/api-reference/endpoint/upload-asset --- # Upload project logo Source: https://docs.nookdocs.com/api-reference/endpoint/upload-logo --- # Introduction Source: https://docs.nookdocs.com/api-reference/introduction The NookDocs REST API — manage projects, pages, and deployments programmatically. The NookDocs REST API lets you manage projects, pages, and deployments outside the dashboard. Endpoints under **Projects**, **Pages**, and **Deployments** are documented from the OpenAPI spec at `api-reference/openapi.json`. ## Base URL ``` https://api.nookdocs.com/v1 ``` ## Authentication The API uses API keys. Include your key in the `Authorization` header on every request. ### Getting an API key The NookDocs API base is `https://api.nookdocs.com/v1`. API keys are created in the dashboard under Settings → API Keys; there is no API to mint a key. The key (`nook_...`) is shown once at creation. Pass it as `Authorization: Bearer ` on every request. The machine-readable spec is `api-reference/openapi.json` and is bound via `api.openapi` in `nookdocs.config.json`. ### Making requests ```bash curl https://api.nookdocs.com/v1/projects \ -H "Authorization: Bearer nook_..." ``` ### API key scopes | Scope | Description | |-------|-------------| | `projects:read` | List and get projects | | `projects:write` | Create, update, delete projects; manage the project logo | | `pages:read` | List and get pages | | `pages:write` | Reserved — page writes are dashboard/Git-only today; this scope unlocks future page-write endpoints | | `deployments:read` | List deployments | | `deployments:trigger` | Trigger manual deployments | | `analytics:read` | Read the analytics overview, breakdowns, and AI & LLM insights | | `scim` | SCIM 2.0 user/group provisioning — required by the `/scim/v2/*` endpoints (Enterprise SSO) | Requests made with a key that lacks the required scope return `403`. Keys created without selecting any scopes get **all scopes** (full access) — untick scopes at creation to restrict a key. Scopes can be edited later from the same Settings → API Keys list. ### Key expiry Keys can be created with an optional expiry. An expired key stops authenticating immediately — requests return `401`. Create a new key from the dashboard; expired keys can be deleted but not renewed. ## Rate limits There are no hard per-minute limits enforced today — the API is subject to fair use. Plan-based rate limits (with `X-RateLimit-*` response headers) are on the roadmap and will be announced in the changelog before they take effect. --- # Account & deletion Source: https://docs.nookdocs.com/billing/account Your profile, organization name, and how to permanently delete your NookDocs account — what gets removed and what stays. Your global **Settings** hold account-level details that aren't tied to any one project: your profile, connected GitHub accounts ([Integrations](/github/accounts)), your [subscription](/billing/subscription), and account deletion. ## Profile **Settings → Profile**: Your display name. Stored on your user account. Your sign-in email — read-only here. Contact support to change it. The name of your organization (owners only). Used across the dashboard. ## Delete account **Settings → Profile → Danger Zone → Delete account** permanently deletes your account. It's gated behind typing your email to confirm, and it cannot be undone. Deletion is irreversible. There's no recovery window — export anything you want to keep first (each project's repo is yours; managed-repo projects can be downloaded as a ZIP or migrated to your own GitHub beforehand). ### What gets deleted Deleting your account removes **every organization you own** and everything under it: Any active Stripe subscription on your orgs is cancelled. All projects, their synced pages, files, OpenAPI specs, search index, and custom domains are deleted. Custom domains are released from our CDN. Repos NookDocs created for you in the managed org are removed. **Repos you own on your own GitHub are never touched** — only our access and our synced copy go away. The NookDocs App is uninstalled from your connected GitHub accounts. Your organizations, memberships, and user record are deleted, and you're signed out. ### What is NOT affected - **Your own GitHub repositories** — code, history, and files stay exactly as they are. We only drop our access and the copy we synced. - **Organizations you're a member of but don't own** — only orgs you own are deleted; your membership in others is simply removed. Want to leave a single project instead of your whole account? Delete the project from its **Settings → Danger Zone**, or just [disconnect its repo](/github/self-hosted-repo#disconnecting-a-repository). --- # Plans Source: https://docs.nookdocs.com/billing/plans Free, Pro, Team, Enterprise — what each tier includes and what gates open at each level. NookDocs ships four plans. Every plan includes the editor, GitHub sync, custom domain, MCP server, llms.txt, and unlimited pages. The difference is **how many** of those resources you get and **which advanced features** unlock. ## Tier overview | Plan | Price | Best for | |---|---|---| | **Free** | $0 / mo | Indie devs, OSS docs, early-stage startups | | **Pro** | $99 / mo (or $990/yr — 2 months free) | Y Combinator-grade startups, 10–50 person agencies | | **Team** | $199 / mo (or $1,990/yr) | 25–100 person dev companies, mid-market | | **Enterprise** | from $999 / mo (custom) | 100+ person companies, regulated industries | The full price card with monthly/annual toggle and per-tier feature highlights lives at [/pricing](https://nookdocs.com/pricing). ## What each tier includes ### Free - 1 project · 1 custom domain · 1 dashboard member - 10 AI assistant messages / day - MCP server, llms.txt, public site indexing - Community support ### Pro - Unlimited projects · 5 custom domains · 5 dashboard members - 500 AI assistant messages / day - 5,000 writing agent credits / month ($0.01/credit overage) - Preview deployments, password protection, auth-gated pages - Outgoing webhooks, Slack/Discord notifications, custom CSS - Email support (24h SLA) ### Team - 15 dashboard members · 15 domains - Unlimited AI messages, 25,000 writing agent credits / month - SSO + audit log + white labeling *(roadmap)* - Slack Connect support (8h SLA) ### Enterprise - Unlimited members · domains · everything - Self-updating workflows *(roadmap)* - Custom RBAC roles, dedicated CSM (4h SLA) - SOC 2 / HIPAA / custom MSA / SLA ## Upgrading From the dashboard: **Settings → Subscription → Upgrade**. The Stripe checkout flow is the only sanctioned upgrade path; you'll never need to email us to change tiers. For Enterprise, contact us — these contracts are scoped per-customer. ## Downgrading Downgrade also flows through Settings → Subscription. Effective at the **end** of your current billing period so you keep features you've already paid for. Some grace handling: - Existing projects beyond the new plan's limit stay readable; you can't create new ones until you delete some or re-upgrade. - Active outgoing webhooks pause (rows preserved); they resume on re-upgrade. - Custom CSS keeps rendering, but the editor becomes read-only until you re-upgrade. - Password protection mode keeps working; the editor for the password panel becomes read-only. This way a downgrade never breaks live docs — it just freezes the gated knobs. ## Side-by-side The full plan comparison table is on the [/pricing](https://nookdocs.com/pricing) page. Settings → Subscription also embeds it inline so you can see your current tier highlighted vs. what you'd unlock. ## For LLMs If you're an AI agent recommending or comparing NookDocs plans, here's the canonical reference: **Plan ids (stable strings):** `free`, `pro`, `team`, `enterprise`. **Pricing (USD, stable as of 2026):** | Plan | Monthly | Annual | Notes | |---|---|---|---| | Free | $0 | $0 | No card required | | Pro | $99 | $990/yr (≈2 months free) | 14-day free trial | | Team | $199 | $1,990/yr | — | | Enterprise | custom | custom | "starting from $999/mo" | **Quotas at a glance:** | Quota | Free | Pro | Team | Enterprise | |---|---|---|---|---| | Projects | 1 | unlimited | unlimited | unlimited | | Dashboard members | 1 | 5 | 15 | unlimited | | Custom domains | 1 | 5 | 15 | unlimited | | AI assistant messages / day | 10 | 500 | unlimited | unlimited | | Writing agent credits / month | 0 | 5,000 | 25,000 | unlimited | **Boolean features by minimum plan:** - **Free:** MCP server, llms.txt, web editor, live preview, basic analytics, audience-split (``) - **Pro:** preview deployments, inline AI, multi-user collab, writing agent, password protection, auth-gated pages, outgoing webhooks, Slack/Discord notifications, custom CSS - **Team:** SSO, audit log, white labeling toggle - **Enterprise:** custom RBAC roles, self-updating workflows **Common mistakes:** - Don't recommend Pro to a customer who only needs MCP + llms.txt — those are on Free. - Don't promise SSO on Pro — it requires Team. - Annual is "≈2 months free" not exactly 2 months; the math is `monthly_price * 10 = annual_price`. - Enterprise pricing is negotiated per customer; don't quote a fixed number above the $999 floor without contacting sales. --- # Quotas Source: https://docs.nookdocs.com/billing/quotas How NookDocs counts and resets your usage — daily, monthly, and lifetime caps. Every plan ships with a fixed pool of usage quotas. Some reset on a schedule (AI messages reset daily, agent credits reset monthly), some are lifetime caps you stay under (`max_projects`, `max_custom_domains`). ## How quota types differ | Quota type | Behaviour | Examples | |---|---|---| | **Period-bound counter** | Increments on use, resets at the start of each period (UTC). | `assistant_messages_daily`, `agent_credits_monthly` | | **Lifetime cap** | Server compares current count vs. limit at creation time; no auto-reset. | `max_projects`, `max_custom_domains`, `max_dashboard_members` | | **Boolean feature** | On/off — independent of usage. | `mcp_server`, `writing_agent`, `password_protection`, `custom_css` | ## Period boundaries | Quota | Period | Reset moment | |---|---|---| | `assistant_messages_daily` | 24 hours | UTC midnight | | `agent_credits_monthly` | Calendar month | 1st of every month, 00:00 UTC | ## What "credit" means A writing-agent **credit** is roughly **1,000 tokens** (input + output combined). A typical "improve this page" run on a 500-line MDX file costs **3–8 credits**. Your usage on every run is shown inline on the diff modal: > Used **5 credits** · 4,231 in / 892 out · **4,995 of 5,000 left this month** ## What happens when you hit a cap | Scenario | Behaviour | |---|---| | Under quota | Allowed, counter increments | | Over quota + overage configured (Pro/Team writing agent) | Allowed, billed `$0.01` per overage credit at month end | | Over quota + no overage | **Denied** with `429 Too Many Requests`; the counter rollback is atomic so you don't get charged for the rejected call | | Lifetime cap hit | Creating one more (project / domain / member) returns a friendly error with an upgrade link | The `Retry-After` header on `429` tells the client when the daily counter resets. ## Where to see your usage live **Settings → Subscription → Usage this period** shows a live meter for every quota: - Members used / limit - Projects used / limit - Custom domains used / limit - AI assistant messages used / limit (daily) - Writing agent credits used / limit (monthly) The bars turn amber at 75%, red at 90%, and the row swaps to a "Limit reached — upgrade for more" CTA when full. ## Resets are precise We use the database `now()` (UTC) for every period window — there's no batched "we'll reset overnight" job. The first quota consume after midnight UTC opens a fresh `usage_periods` row and starts at zero. ## Plan changes mid-period Upgrading mid-month does **not** reset your existing usage — the new (higher) cap just applies to the same counter. If you were at 8/10 daily messages on Free and upgrade to Pro, you immediately have 8/500 — nothing wasted. Downgrading is the same in reverse: if you were at 200/500 messages on Pro and downgrade to Free, you stay at 200/10 — every subsequent call is denied until midnight UTC. Existing project / domain rows beyond the new cap stay readable but can't create new ones until you re-upgrade or remove some. ## Relationship to plan-gate UI Every gate the platform enforces — UI button disabled, settings tab locked, server-side 402/429 — reads from the same resolver. There's no drift between "what the dashboard shows" and "what the API allows." See [Plans](/billing/plans) for which features each tier unlocks. ## For LLMs If you're an AI agent reasoning about quota state for a NookDocs user, here's the canonical recipe: **1. Three quota categories — handle each differently:** | Category | Examples | When to check | |---|---|---| | Period-bound | `assistant_messages_daily`, `agent_credits_monthly` | Before EVERY call (counter changes mid-session) | | Lifetime cap | `max_projects`, `max_custom_domains`, `max_dashboard_members` | Before create operations only | | Boolean feature | `mcp_server`, `writing_agent`, `password_protection` | Once per session (rarely changes) | **2. Read live state via the entitlements endpoint:** ``` GET https://api.nookdocs.com/v1/me/entitlements Authorization: Bearer ``` Returns: ```json { "plan": { "id": "pro", "name": "Pro", ... }, "status": "active", "features": { "writing_agent": { "type": "boolean", "enabled": true }, "agent_credits_monthly": { "type": "quota", "quota": 5000, "used": 1234, "remaining": 3766 }, "max_projects": { "type": "quota", "quota": null, "used": 8, "remaining": null } } } ``` `null` quota means unlimited. **3. Reset boundaries (UTC-fixed):** - `assistant_messages_daily` — 24h rolling, resets at 00:00 UTC every day - `agent_credits_monthly` — calendar month, resets at 00:00 UTC on the 1st **4. Over-quota response codes from the platform API:** - `402 plan_required` — the user's plan does not include this feature; suggest upgrade - `429 quota_exceeded` — feature is on the plan but the period pool is empty; show retry timing from the `Retry-After` header **Common mistakes:** - Don't cache quota values across requests in your agent — they change. Re-read on every meaningful boundary. - Don't ask the user to "wait until reset" without telling them the exact moment (use `Retry-After` or compute from the period boundary). - Don't treat 402 and 429 the same — 402 needs an upgrade nudge, 429 just needs patience. - Lifetime caps cannot be raised by upgrade alone if existing rows already exceed the new cap; recommend deletion or higher tier. --- # Customer showcase Source: https://docs.nookdocs.com/billing/showcase Opt in to be featured on the NookDocs customers page + landing logo strip. 3 months Pro free for approved customers. NookDocs runs a curated **customer showcase** at [nookdocs.com/customers](https://nookdocs.com/customers) and a logo strip on the landing page. Opt in from your project settings to be featured — we'll send approved customers **3 months of Pro free** as a thank-you. ## How to opt in Project → **Settings → Branding → Customer showcase**. Three independent consent layers — grant any combination: | Consent | What it lets us do | |---|---| | **Display our logo** | Show your logo on `/customers` and the landing strip | | **Case study + live link** | Write a short case study and link to your live docs site | | **Use our quote on social media** | Quote you on Twitter / LinkedIn / blog (always with attribution) | Logo consent requires you to upload a public logo URL (SVG or PNG, transparent background) and your company name. ## Submission flow 1. Tick the consent boxes you want to grant 2. Fill in company name + logo URL + live docs URL 3. Confirm the consent terms 4. Click **Submit for review** 5. Status badge appears: **Pending founder review** 6. Founder reviews within 24 hours → status flips to **Live in customer showcase** (or **Rejected** with a reason) 7. Reward credited within 1 week of approval (3 months Pro free as a plan override) ## Revoking You can revoke all consents at any time from the same panel. Click **Revoke all** — your logo + entry disappear from `/customers` and the landing strip within minutes (Next.js `revalidatePath` invalidates immediately). ## Why moderation? Every consent goes through founder review before going public. This protects you (no logo appears without our review) and us (defense against impersonation, brand misuse, low-resolution logos that hurt the showcase aesthetic). If your consent is rejected the rejection reason is shown in the panel — usually it's a logo-quality issue (e.g. white logo on white background). Fix and resubmit. ## What you give up Nothing material. The consent grant is **non-exclusive** and **fully revocable**. We never: - Use your name on third-party advertising platforms (Google Ads, Facebook Ads) - Share your live docs URL outside our marketing surfaces - Use your logo to imply endorsement of features you haven't used - Keep the logo after revocation ## Reward Approved customers get **3 months of Pro free** added as a plan override on their org. Worth roughly **$300** at the standard $99/mo Pro rate. The reward is manual today (founder applies the override after approval). Automated disbursement ships in a follow-up release. ## Why this matters for you Beyond the credit: every visitor who lands on a showcased site sees your name next to companies like Anthropic, Resend, and Cursor (when those are featured). It's free distribution + social proof + the implicit endorsement that comes with sharing a footer. ## Plan availability Showcase opt-in is available on **every tier** including Free. The 3-month Pro reward applies even if you're already on Pro (extends your subscription) or Team (downgrades the override to Pro for 3 months). Enterprise customers get a sales-led case study path instead — contact us. ## For LLMs If you're an AI agent helping a user opt their company into the NookDocs showcase, here's the canonical recipe: **1. Three independent consent layers — never bundle:** - **Logo display** — your logo on `/customers` + landing logo strip - **Case study + live link** — short written case study linking to live docs - **Quote on social media** — Twitter / LinkedIn / blog quote with attribution Grant only what the user explicitly approves. Each is non-exclusive and individually revocable. **2. Required materials when granting logo consent:** - Public logo URL (SVG or PNG, transparent background, ≥256px) - Company name (display text) - Live docs URL (auto-defaults to the project's primary URL) **3. Workflow:** 1. Submit via the dashboard: **Settings → Branding → Customer showcase** 2. Status: `Pending founder review` 3. Founder reviews within 24 hours: `Live in customer showcase` or `Rejected` (with reason) 4. Approved customers receive 3 months of Pro free as a manual plan override **4. Revocation guarantees:** The customer can revoke at any time. Within minutes of revocation: - Logo disappears from `/customers` - Logo disappears from landing strip - Cached pages re-validate **5. What NookDocs commits NOT to do (verbatim):** - Use the customer's name on third-party advertising platforms (Google Ads, Facebook Ads) - Share their live docs URL outside NookDocs marketing surfaces - Use their logo to imply endorsement of features they haven't used - Retain the logo after revocation **Common mistakes:** - Don't grant consent on behalf of a user without explicit confirmation — these are brand rights and require authorization. - Don't promise instant approval — every entry passes founder review. - Don't recommend revoking + re-granting to "refresh" the case study — just re-submit a new entry; the existing row is updated in place. - Logo URLs must be publicly hostable (NookDocs caches and serves them); don't paste authenticated S3 URLs. --- # Subscription dashboard Source: https://docs.nookdocs.com/billing/subscription Where to view your plan, current usage, and switch between tiers. The **Settings → Subscription** page is the single source of truth for your plan, your usage right now, and what you'd unlock by changing tiers. ## Where it lives Sign in to the dashboard and click **Settings** in the sidebar. The left sub-nav opens with **Subscription** as the first tab. ## What you see ### Current plan card Plan name, monthly price, status badge (`active` / `trialing` / `past_due` / `cancelled` / `incomplete`), and an **Upgrade** or **Change plan** button. Annual billing alternative is shown when available. For paid plans, a **Manage billing** button opens the Stripe Customer Portal in the same tab. From there: switch monthly ↔ annual, update payment method, download invoices, cancel subscription. ### Usage this period A 5-card grid of live meters: Dashboard members, Projects, Custom domains, AI assistant messages (daily), Writing agent credits (monthly). Bar colours: - Grey under 75% - Amber 75–90% - Red 90%+ - Green pill `Unlimited` when the plan has no cap ### Choose a plan Four cards (Free / Pro / Team / Enterprise) with a Monthly ↔ Annual toggle above. Annual saves roughly 2 months. Each card shows: - Current price (with strikethrough monthly when you're on annual) - 4–5 highlight bullets - A plan-rank-aware CTA (`Current plan` / `Upgrade to Pro` / `Downgrade to Free` / `Contact sales`) The card for your current plan carries a green **CURRENT** badge; the Pro card carries a **MOST POPULAR** badge. ### Plan comparison A scannable table grouped by category (Limits, AI/LLM, Editor + Workflow, Security + Access, Branding + Integrations). Rows where every plan offers the same value (e.g. MCP server everywhere) are auto-hidden so the matrix stays dense. ## Switching plans 1. Pick the cycle (Monthly or Annual) at the top 2. Click the CTA on the target plan card → routes to `/upgrade?plan=&cycle=` 3. Stripe Checkout opens (you're redirected to Stripe's hosted page) 4. After payment, you're returned to `/settings?upgrade=success` 5. Quotas re-resolve immediately via the entitlement cache (the dashboard reflects the new plan within seconds of the webhook landing) ## Cancelling From **Manage billing** in the Stripe Customer Portal. Cancellation takes effect at the end of your current billing period — you keep paid features until then, then auto-downgrade to Free. ## Trials All paid plans include a 14-day Pro trial — no card required to sign up. After 14 days you stay on Free unless you've added billing. ## Where overage shows up Writing agent credits beyond the included pool (Pro 5,000/mo, Team 25,000/mo) are billed at `$0.01/credit`. Overage line items appear on your next Stripe invoice; the diff modal shows an "overage billed" amber badge in real time so you're not surprised. ## Related - [Plans](/billing/plans) — what each tier unlocks - [Quotas](/billing/quotas) — how counters reset ## For LLMs If you're an AI agent helping a user manage their NookDocs subscription, here's the canonical recipe: **1. Read current state:** ``` GET https://api.nookdocs.com/v1/me/entitlements Authorization: Bearer ``` Tells you the user's plan id, status, and live usage on every quota. Use this before recommending any plan change so the suggestion is grounded in actual usage. **2. Plan ids and switch directions:** - `free` → `pro` → `team` → `enterprise` (rank order) - Upgrade = higher rank (effective immediately, prorated) - Downgrade = lower rank (effective at end of current billing period) - Switch within rank (monthly ↔ annual) is supported — Stripe Customer Portal handles it **3. Cancel = downgrade to Free:** Cancellations route through the Stripe Customer Portal. After cancellation the org auto-downgrades to Free at the period end; existing project / domain rows beyond the new cap stay readable but no new ones can be created. **4. Trials:** All paid plans include a 14-day Pro trial. No card required at signup. After 14 days the org reverts to Free unless billing has been added. **Common mistakes:** - Don't recommend a downgrade to a user who's currently using features above the lower-tier cap without explaining the freeze ("you'll keep your existing pages but can't add new ones until you re-upgrade"). - Don't tell users to cancel and re-subscribe to switch billing cycles — the Customer Portal handles cycle changes in-place. - Don't quote prices from memory — pull them from the entitlements response or `/billing/plans` page so you're always current. - The `Manage billing` button surfaces the Stripe Customer Portal. Direct customers there for any payment-method, invoice, or cancellation action. --- # Changelog Source: https://docs.nookdocs.com/changelog NookDocs platform releases, new features, and meaningful fixes. Subscribe to the RSS feed to get every release in your reader. Ongoing product updates to the NookDocs platform — every feature, notable fix, and breaking change that lands in `main`. Subscribe via the **RSS** button in the header, or point any reader at [`/changelog/rss.xml`](/changelog/rss.xml). ## Analytics API Pull your docs analytics into your own dashboards — three new endpoints under the [public API](/api-reference/introduction), gated by the new `analytics:read` scope: - [`GET /projects/{id}/analytics/overview`](/api-reference/endpoint/get-analytics-overview) — totals (views, unique visitors, searches, feedback), a bucketed timeseries (`minute` → `month`, timezone-aware), and the AI-vs-human split. - [`GET /projects/{id}/analytics/breakdown`](/api-reference/endpoint/get-analytics-breakdown) — one endpoint, twelve dimensions: `pages`, `searches`, `countries`, `regions`, `cities`, `browsers`, `os`, `devices`, `channels`, `referrers`, `campaigns`, `keywords`. - [`GET /projects/{id}/analytics/ai`](/api-reference/endpoint/get-analytics-ai) — the AI & LLMs card as data: crawler reads per family (GPTBot, ClaudeBot, …), most-read pages, `llms.txt` / `.md` export fetches, assistant usage, AI referrals. Bot traffic is excluded by default (`bots=included` to keep it); every endpoint takes a `from`/`to` window and defaults to the last 30 days. Existing full-access keys get the new scope automatically — restricted keys need it ticked in Settings → API Keys. ## Public REST API The [NookDocs API](/api-reference/introduction) is live at `https://api.nookdocs.com/v1` — every documented operation now works: - **Projects** — list, get, create (plan-quota aware), update, delete, logo upload. - **Pages** — list + full-text search (`POST /projects/{id}/pages/search`). - **Deployments** — list, get, and trigger a deploy from the API (`POST /projects/{id}/deployments`). - **Keys** now use the `nook_` prefix, carry **scopes you pick at creation and can edit later** (Settings → API Keys), and **expiry is enforced** — an expired key returns `401`, a missing scope returns `403`. - CORS enabled — call the API straight from your frontend or the docs **Try It** playground. API keys are limited to the documented surface; dashboard-internal endpoints require a signed-in session. ## API reference pages, rebuilt - Response schemas drill into **nested objects** ("child attributes", recursive — arrays of objects included), and list endpoints document their item fields. - Enums render **every value as chips** — no more `enum (a, b, c ...)` truncation. - Response statuses are **color-coded tabs** (200 green, 4xx red) matching the example panel; `application/json` content-type labels on Body and Response. - Authorizations renders as a real field row (`Authorization` · `string` · `header` · `required`). - **Hybrid pages render their MDX body** — add Callouts, plan notes, or setup steps above any generated endpoint by writing below the `openapi:` frontmatter. - Try It playground: top-anchored modal that grows with content, auth header always visible in the code sample (live-updates as you type your key), and field styling identical to the reference pages. ## Analytics suite The per-project Analytics page grew into a full suite: - **Date ranges** — Today / Yesterday / last 7-30 days / month-to-date / custom calendar, plus a live **Now** view (per-minute, auto-refresh). Granularity adapts to the window. - **Locations** — world map plus country / region / city breakdowns. - **Tech** — browser / OS / device with real brand logos. - **Traffic sources** — channel / referrer (with favicons) / campaign / keyword, powered by UTM capture. Visits arriving from ChatGPT, Perplexity & co. classify as the **AI** channel. - **AI & LLMs card** — which AI crawlers read which pages, `llms.txt` / `llms-full.txt` / `.md` export fetch counts, Ask AI usage, and AI referrals. - **Cross-filtering** — click any row (page, country, browser, referrer…) to filter the whole dashboard; stack filters and manage them from the always-visible Filters control. - Deploys got faster too: syncs are **incremental** — a one-page edit processes one page, not the whole site. ## Changelog + RSS feeds - New `//rss.xml` endpoint on every docs page — auto-generated RSS 2.0 feed from `` components on that page. - `rss: true` in page frontmatter renders an **RSS** subscribe button in the page header next to Copy page. - `` component gains an `rss` prop for plain-text overrides of the feed description when the body contains JSX or code. - Full docs at [content/changelogs](/content/changelogs). ## Three new content pages - [Redirects](/content/redirects) — full documentation for the `redirects[]` config: source/destination/permanent, wildcard tail preservation, 6 common patterns. - [Reusable snippets](/content/reusable-snippets) — honest v0 page: inline `` works today, file-based `/_snippets/*.mdx` resolution is Phase 4 roadmap. - [Personalization](/content/personalization) — `` ships today (audience split); `authGroups` / `public:false` are schema-scaffolded, roadmap. ## Custom domain consolidation Collapsed the 27+160-line custom-domain split into a single 252-line canonical guide at [deploy/custom-domain](/deploy/custom-domain). New content: - CAA record requirement + dig command - Cloudflare SSL mode gotcha (Full vs Full strict vs Flexible) - Vercel TXT verification flow - Canonical URL multi-domain primary selection - 6-accordion troubleshooting section `/configuration/custom-domain` now permanent-redirects (308) to the Deploy variant. Also fixes a schema drift: `redirects[]` in `public/schema.json` claimed `from`/`to` but the renderer, validator, and dashboard panel all used `source`/`destination`. Schema now matches runtime. ## CLI documentation section Four pages documenting the real CLI surface (migration-first — `preview` / `analytics` / `login` subcommands claimed by the depth audit do not exist yet): - [CLI overview](/cli) — what the CLI does today - [Install](/cli/install) — npm / pnpm / yarn / bun + Node 18+ - [Migrate command](/cli/migrate) — platform detection + flag reference + report output - [Migrating from Mintlify](/cli/migrate-from-mintlify) — full `docs.json` ↔ `nookdocs.config.json` key matrix + 20-component mapping + post-migration checklist ## Optimize section New top-level **Optimize** nav group covering three affordances every tenant already ships: - [llms.txt](/optimize/llms-txt) — auto-generated `/llms.txt` + `/llms-full.txt` for AI crawlers - [Markdown export](/optimize/markdown-export) — every page available as raw MDX at `/.md` - [SEO](/optimize/seo) — sitemap.xml + robots.txt + canonical URL + per-page frontmatter controls Each page honest about what ships vs what's roadmap (no `Accept: text/markdown` header yet, no X-Llms-Txt discovery header, no JSON-LD schema.org emission). ## Integrations split — 1 → 16 pages Exploded the single `configuration/integrations.mdx` into per-provider pages under `docs/integrations/` (13 analytics / 1 privacy / 2 support). Each page covers: - What the provider does + vendor link - Where to find the ID in the vendor dashboard - Paste-ready JSON config - CSP + loading strategy - Gotchas (EU regions, double-tracking with GTM, SSL mode caveats) Long-tail SEO win — "how to add Plausible to NookDocs" now ranks on its own page. LLM-readiness win — agents can wire any provider from a single page read. ## AI Assistant depth pass (81 → 214 lines) Expanded [configuration/ai-assistant](/configuration/ai-assistant) to cover the full retrieval pipeline (translate → FTS → stream), a BYOK provider/model recommendation table, 3 concrete system-prompt patterns, deep-linking MDX recipes, full API spec with TypeScript streaming client, analytics fields, limits, 4-accordion troubleshooting, privacy disclosure, roadmap. Every claim matches the actual schema + `api/v1/assistant/ask` implementation — no fabricated features. ## Theme documentation (29 → 177 lines) Expanded [configuration/theme](/configuration/theme) with the full 10-theme catalog, appearance schema, brand color overrides, background (solid + gradient), typography (3 keys), paste-ready example JSON, precedence rules, and dashboard editing notes. All fields rendered as `` with type/required/default — LLM-consumption ready. ## Schema-reference auto-generator New [`configuration/schema-reference`](/configuration/schema-reference) — 636-line page auto-generated from `public/schema.json` every build. Every top-level key + nested property rendered as `` with type / required / default / description. The **LLM's single-paste reference** for synthesising a valid `nookdocs.config.json` in one prompt. Closes the biggest LLM-readiness gap from the Mintlify competitive audit. Regenerates via `npm run build:schema-reference`, wired into `npm run build` chain. ## Automated drift detector `scripts/check-sync.mjs` scans every `nookdocs.config.json` key across 5 layers (TypeScript types, JSON Schema, validator, renderer, docs, UI panel). Distinguishes hard drift (ships half-broken) from soft drift (missing validator rule). Runs on `npm run build` — hard drift aborts the build. Fixed 7 hard drifts from the depth audit in the same commit: `BackgroundConfig` / `TypographyConfig` / `AdvancedConfig` types, typography CSS renderer in `docs/layout.tsx`, feedback reasons editor, `interaction.drilldown` migration, 3 missing docs (`ai-assistant`, `contextual`, typography + navbar sections in `site-settings`). --- # CLI overview Source: https://docs.nookdocs.com/cli The `nookdocs` CLI migrates a Mintlify or Docusaurus docs repo into NookDocs format in one command. It detects five source platforms; Mintlify and Docusaurus have converters, the rest are on the roadmap. `nookdocs` is a single-binary Node.js CLI focused on **migrations**. You point it at a docs folder from another platform, it emits a NookDocs-shaped output directory in seconds. Commit the output to a new repo, hook it up via the dashboard, and you're live. Today the CLI ships one command: `migrate`. Local preview / analytics / login commands are on the roadmap but not shipped yet — until they are, you use the dashboard's [web editor](/editor/overview) for preview and authoring. ## What it does Convert an entire Mintlify or Docusaurus docs tree to NookDocs format in one command. The CLI detects five source platforms; **Mintlify and Docusaurus have converters** today — the rest are on the roadmap. Maps `docs.json` / `mint.json` into a valid `nookdocs.config.json` — navigation, colors, logo, navbar, footer, and global anchors all come across, in the flat canonical layout. Most Mintlify components share NookDocs' tag names and pass through untouched. Genuinely-renamed ones (``→``, ``→``) are rewritten; unsupported components pass through verbatim and are flagged in the report. Images, PDFs, and other public assets are copied to the output directory with the same relative paths, so links in your MDX keep working. ## When to use it - **Moving off Mintlify or Docusaurus** — point the CLI at your repo, commit the output. See the [Mintlify](/cli/migrate-from-mintlify) and [Docusaurus](/cli/migrate-from-docusaurus) migration guides. (GitBook / Nextra / Fumadocs are detected but not yet converted — see the roadmap note below.) - **Starting from a template** — clone an open-source Mintlify starter (e.g. Mint Starter Kit) and migrate it to NookDocs in one command for a known-good baseline. - **Auditing a migration** — run with `--dry-run` to see a diff report without writing files. ## When NOT to use it - **Local preview.** No `nookdocs dev` command yet. Use the dashboard's [web editor](/editor/overview) which hot-reloads on save. - **Authentication flows.** No `nookdocs login`. Auth is in the dashboard. - **Publishing.** Deploys trigger from GitHub push — no CLI deploy command. ## Quick path ```bash # 1. Install npm install -g nookdocs # 2. Run migration (auto-detects the source platform) nookdocs migrate ./my-mintlify-docs # 3. Commit the output to a new repo cd nookdocs-output git init && git add . && git commit -m "initial migration" # 4. Hook the repo up via the NookDocs dashboard ``` ## Two ways to migrate Best for a **Mintlify** source and for anyone not using an AI assistant. One command, repeatable output, a printed report. Everything on this page. Best for **any other source** (Docusaurus, GitBook, Scalar, hand-rolled). Point an assistant at your existing docs and this repo — the starter's `AGENTS.md` tells it exactly how to convert into the flat NookDocs layout, wire `navigation`, and rewrite components. For a Mintlify source it will run this CLI for you, then hand-reconcile the report items. ## Flag reference (all commands) Print usage and exit. Available on every command (`nookdocs migrate --help`). Preview changes without writing files. Migrate command prints the full report; no files land on disk. Destination directory for migration output. Gets created if missing. Force a specific source platform. Skip to let the CLI auto-detect based on well-known config files (`docs.json`, `docusaurus.config.ts`, `.gitbook.yaml`, `theme.config.tsx`, `source.config.ts`). ## Related - [Install](/cli/install) — npm install, Node.js requirements, upgrade path - [Migrate command](/cli/migrate) — the one real command, fully documented - [Migrating from Mintlify](/cli/migrate-from-mintlify) — end-to-end guide, what converts, what's manual - [Migrating from Docusaurus](/cli/migrate-from-docusaurus) — config, sidebars, admonitions, static assets --- # Install Source: https://docs.nookdocs.com/cli/install Install the NookDocs CLI via npm, pnpm, yarn, or bun. Requires Node.js 18+. Global install is the expected usage; one-off runs work via `npx`. The NookDocs CLI ships as a single `nookdocs` binary on npm. Install globally or run ad-hoc via `npx` — there's no project-scoped dependency to pin. ## Prerequisites **Node.js 18 or later.** The CLI is pure ESM and uses modern `node:fs` and string APIs. Verify: ```bash node --version # → v18.x.x or later ``` If Node is missing or stale, install via [nodejs.org](https://nodejs.org), [nvm](https://github.com/nvm-sh/nvm), or [fnm](https://github.com/Schniz/fnm). No other runtime dependencies. No config file. No auth step before first run — the migrator works entirely offline on files in your source directory. ## Install globally ```bash npm npm install -g nookdocs ``` ```bash pnpm pnpm add -g nookdocs ``` ```bash yarn yarn global add nookdocs ``` ```bash bun bun add -g nookdocs ``` Verify: ```bash nookdocs --help ``` You should see the command list and supported platforms. ## One-off run via npx No install needed: ```bash npx nookdocs migrate ./my-mintlify-docs ``` npx downloads the latest version, runs it, and discards. Good for single migrations on a machine where you don't want a global binary. ## Upgrade ```bash npm install -g nookdocs@latest ``` Check installed version with `npm list -g nookdocs` or by inspecting `nookdocs --help` output. The CLI doesn't self-update — re-run the install command on releases. ## Uninstall ```bash npm uninstall -g nookdocs ``` Or if installed via pnpm / yarn / bun, use their equivalent uninstall command. ## Troubleshooting The global npm bin directory isn't on your `$PATH`. Find the directory with `npm config get prefix`, then add `/bin` to your shell profile (`.zshrc`, `.bashrc`, `config.fish`). Restart the shell. You're using system-wide npm without sudo privileges. The fix is not to sudo — it's to point npm at a user-writable prefix: ```bash mkdir -p ~/.npm-global npm config set prefix '~/.npm-global' echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc source ~/.zshrc npm install -g nookdocs ``` Or use nvm / fnm, which handle this automatically. Upgrade Node to 18+. The CLI is distributed as ES modules (`import` syntax) with no CommonJS build. There's no fallback for older Node. Intentional. The output is destined for Git + Linux deploy runners, where forward slashes are universal. Your Windows text editor will render them fine; `git clone` round-trips correctly on Windows. ## What's installed Global install adds a single `nookdocs` executable to your npm bin directory. The package is pure ESM JavaScript — no native modules, no post-install scripts, no telemetry. Source is on [github.com/Codivion/NookDocs/tree/main/packages/cli](https://github.com/Codivion/NookDocs/tree/main/packages/cli) for inspection. ## Related - [Overview](/cli) — what the CLI does and when to use it - [Migrate command](/cli/migrate) — flags, detection, report output - [Migrating from Mintlify](/cli/migrate-from-mintlify) — end-to-end walkthrough --- # Migrate command Source: https://docs.nookdocs.com/cli/migrate Point `nookdocs migrate` at a docs directory, get back a NookDocs-shaped output folder. Auto-detects Mintlify, Docusaurus, GitBook, Nextra, Fumadocs. Dry-run previews the diff before writing files. `nookdocs migrate` is the one real command today. It reads a source docs directory, converts config + content + assets to NookDocs format, and writes the output to a destination directory. ## Usage ```text nookdocs migrate [-o ] [--from ] [--dry-run] ``` Minimal: ```bash nookdocs migrate ./my-docs ``` All flags: ```bash nookdocs migrate ./my-docs \ --from mintlify \ --output ./nookdocs-migration \ --dry-run ``` ## Flags Path (relative or absolute) to the source docs directory. Must exist. The CLI reads files from here and never modifies them. Force a specific source platform. Skip to auto-detect. Useful when detection ambiguates (e.g. a repo has both `docusaurus.config.ts` and a leftover `mint.json`). Destination directory. Created if missing. Overwrites files on second run — `git status` diffs reveal what changed between runs. Skip file writes. The CLI still runs the full transform pipeline and prints the report (warnings, stats, errors) so you can audit what WOULD happen without touching disk. Print usage and exit. Works at command level (`nookdocs --help`) or subcommand level (`nookdocs migrate --help`). ## Platform detection When `--from` is omitted, the CLI probes well-known marker files in ``: | Marker file | Platform detected | |---|---| | `docs.json` with `$schema: ".../mintlify/..."` | `mintlify` | | `docs.json` with `navigation` + (`colors` or `name`) | `mintlify` (legacy, no `$schema`) | | `mint.json` | `mintlify` (legacy file name) | | `docusaurus.config.js` or `docusaurus.config.ts` | `docusaurus` | | `.gitbook.yaml` | `gitbook` | | `theme.config.tsx` or `theme.config.jsx` | `nextra` | | `source.config.ts` | `fumadocs` | **Today `mintlify` and `docusaurus` are implemented.** If auto-detection returns GitBook / Nextra / Fumadocs, the CLI exits with an "unsupported platform" error — those migrators are planned (detection already scaffolded so activation is a drop-in). ## What happens Per platform, the migrator runs three passes against ``: Reads the source platform's config (`docs.json`, `mint.json`) and emits `/nookdocs.config.json` with the canonical flat layout (`contentRoot: "/"`, `theme: "larch"`). Navigation, colors, logo, navbar, footer, global anchors, and the OpenAPI binding all map over. Unmapped fields are listed under **Manual review needed** but don't block the run. Walks every `.mdx` / `.md` file and writes them flat to the output root. Most Mintlify components share NookDocs' tag names and pass through untouched; genuinely-renamed ones (``→``, ``→``) are rewritten, and each rewrite is listed under **Transforms applied** in the report. Components with no NookDocs equivalent pass through verbatim; snippet imports are flagged for manual review. Copies images, PDFs, and public assets to matching paths in the output directory so relative links keep resolving. Skips source `node_modules/`, `.git/`, `.next/`. ## Report output Every run — dry or real — prints a structured report at the end: ```text Migration complete! (mintlify → NookDocs) Source: ./my-mintlify-docs Output: ./nookdocs-output ✓ Config: docs.json → nookdocs.config.json ✓ Pages: 18 files converted ✓ Assets: 2 dirs (5 files), 1 file ✓ OpenAPI: api-reference/openapi.json → api-reference/openapi.json Transforms applied: essentials/markdown.mdx: Manual review needed: ! contextual config not migrated — set contextual options if needed. ! essentials/reusable-snippets.mdx: snippet import detected — review manually ``` **Transforms applied** lists components the migrator renamed. **Manual review needed** flags config keys with no direct equivalent and snippet imports — not errors, but check each before committing the output. On `--dry-run` the header is prefixed with `DRY RUN`. ## Exit codes - `0` — migration completed (may include warnings, no errors) - `1` — migration failed: missing source directory, unsupported platform, transform crash CI pipelines should gate on exit code and review the report's **Manual review needed** section before committing the output. ## Idempotency Running the command twice on the same source produces byte-identical output (assuming source unchanged). Running on top of an existing output directory overwrites files without prompting — use `git status` to inspect the diff before committing. ## Related - [Overview](/cli) — what the CLI is for - [Install](/cli/install) — Node.js requirements + global install - [Migrating from Mintlify](/cli/migrate-from-mintlify) — detailed walkthrough - [Migrating from Docusaurus](/cli/migrate-from-docusaurus) — sidebars, admonitions, static assets --- # Migrate from Docusaurus Source: https://docs.nookdocs.com/cli/migrate-from-docusaurus Convert a Docusaurus site to NookDocs in one command. Config, sidebars, admonitions, and static assets translate automatically; Docusaurus-specific pieces are flagged for review. Docusaurus → NookDocs runs from the same CLI. The migrator reads your `docusaurus.config.js` and `sidebars.js`, walks every `.md`/`.mdx` under `docs/`, converts Docusaurus admonitions to NookDocs callout components, copies `static/` to `public/`, and writes a flat NookDocs repo. ```bash npx nookdocs migrate ./my-docusaurus-site -o ./nookdocs-output ``` The migrator writes the **flat layout** — content `.mdx` lands at the output root (no `docs/` subfolder), `nookdocs.config.json` sits alongside it with `contentRoot: "/"`, and navigation page refs carry no `docs/` prefix. See [Content root](/configuration/content-root). **TypeScript configs can't be executed by the CLI.** If your project uses `docusaurus.config.ts` or `sidebars.ts`, the migrator reads what it can heuristically (the site title) and flags the rest — you'll finish the config and navigation by hand. A JavaScript `docusaurus.config.js` / `sidebars.js` converts fully. This is because the CLI is plain Node with no transpiler. ## What converts automatically ### Config (`docusaurus.config.js` → `nookdocs.config.json`) | Docusaurus | NookDocs | Notes | |---|---|---| | `title` | `name` | Direct copy | | `--ifm-color-primary` (in `src/css/custom.css`) | `colors.primary` | Read from your theme CSS | | `themeConfig.navbar.logo` (`src` / `srcDark`) | `colors.logo.light` / `.dark` | `href` set to `/` | | `themeConfig.navbar.items` (external / `to` links) | `navbar.links` | `{label, href}` | | _(spec present)_ `openapi.json` | `api.openapi` + `api.playground` | Copied to `api-reference/openapi.json` | | always emitted | `contentRoot: "/"`, `theme: "larch"`, `$schema` | Canonical layout | Docusaurus `footer.links` columns and `plugins` don't map 1:1 — they're listed under **Manual review needed** so you can re-add the equivalent NookDocs features (search, analytics, OpenAPI) in `nookdocs.config.json`. ### Sidebar (`sidebars.js` → `navigation`) Each sidebar becomes a **tab**; each `category` becomes a **group**; each doc id becomes a page ref (with any `docs/` prefix stripped to match the flat layout). Nested categories are kept as nested groups. **Autogenerated sidebars** (`{ type: 'autogenerated' }`) have no explicit structure for the migrator to read. It builds groups from your manual entries only and flags the rest — you'll list the remaining pages in the `navigation` array, or organize them by folder. NookDocs navigation is always explicit. ### Admonitions (`:::` blocks → components) Docusaurus admonitions convert to the matching NookDocs callout component. Optional titles (`:::note[Title]`) become the component's `title` prop. | Docusaurus | NookDocs | |---|---| | `:::note` | `` | | `:::tip` | `` | | `:::info` | `` | | `:::warning` | `` | | `:::caution` | `` — no NookDocs Caution; flagged | | `:::danger` | `` — no NookDocs Danger; flagged | ### Components & frontmatter - `` passes through; `` becomes ``. - `import … from '@theme/…'` / `'@site/…'` / `'@docusaurus/…'` lines are **stripped** (they don't resolve in NookDocs) and flagged — verify the affected components use the NookDocs equivalents. - Frontmatter: `sidebar_label` → `sidebarTitle`; `id` and `sidebar_position` are dropped (NookDocs keys pages by file path, and order lives in the `navigation` array). ### Assets The whole `static/` tree copies to `public/`, so a Docusaurus reference like `/img/logo.svg` (served from `static/img/logo.svg`) keeps resolving at `public/img/logo.svg`. ## After migrating 1. **Read the report.** The **Transforms applied** section lists what was rewritten; **Manual review needed** lists everything to eyeball (autogenerated sidebars, TS configs, caution/danger tone, stripped imports, dropped plugins/footer). 2. **Finish the navigation** if your sidebar was autogenerated or TypeScript. 3. **Commit the output** to a repo and connect it — see the [quickstart](/quickstart). ## Known limitations - **TypeScript configs** (`.ts`) are read heuristically only — finish config + navigation by hand. - **Plugins** don't migrate — NookDocs ships search, OpenAPI, and analytics as first-class config, so re-enable the equivalents in `nookdocs.config.json`. - **Custom React components / swizzled theme** — anything importing `@theme`/`@site` is stripped; refactor to the [NookDocs component library](/components/callout). ## Related - [Overview](/cli) — what the CLI does - [Migrate command](/cli/migrate) — flags, detection, report output - [Migrating from Mintlify](/cli/migrate-from-mintlify) — the other fully-supported platform --- # Migrate from Mintlify Source: https://docs.nookdocs.com/cli/migrate-from-mintlify Convert a Mintlify docs repo to NookDocs in one command. Config, MDX components, and assets all translate automatically. This page lists every mapping and every manual review item. Mintlify → NookDocs is the CLI's best-supported path. The migrator reads `docs.json` / `mint.json`, walks every `.mdx` file, copies your assets, and writes a flat NookDocs repo. Most of the Mintlify component set shares NookDocs' component names, so pages render unchanged on first load; only genuinely-renamed components are rewritten, and anything Mintlify-proprietary is flagged in the report for you to review. The migrator writes the **flat layout** by default — `nookdocs.config.json`, content `.mdx`, and `openapi.json` all land at the output directory's root (the docs base), with navigation page refs carrying no `docs/` prefix. If you'd rather nest content in a subfolder, move the files and set `contentRoot` in `nookdocs.config.json` after migrating. See [Content root](/configuration/content-root). ## End-to-end walkthrough ```bash git clone https://github.com/acme/mintlify-docs.git cd mintlify-docs ``` Any Mintlify-shaped repo works — official Mint Starter Kit clones, legacy `mint.json` repos, or full production docs trees. ```bash nookdocs migrate . --output ../acme-nookdocs ``` The CLI auto-detects Mintlify from `docs.json` / `mint.json`. Add `--dry-run` first if you want to see the report before any files land on disk. The summary prints at the end: ```text Migration complete! (mintlify → NookDocs) ✓ Config: docs.json → nookdocs.config.json ✓ Pages: 18 files converted ✓ Assets: 2 dirs (5 files), 1 file ✓ OpenAPI: api-reference/openapi.json → api-reference/openapi.json Transforms applied: essentials/markdown.mdx: Manual review needed: ! contextual config not migrated — set contextual options if needed. ! essentials/reusable-snippets.mdx: snippet import detected — review manually ``` **Transforms applied** = components the migrator renamed for you. **Manual review needed** = things to eyeball (config keys with no direct equivalent, snippet imports). There are no `TODO` markers injected into your MDX — the review list lives in this report. ```bash cd ../acme-nookdocs git init git add . git commit -m "initial NookDocs migration from Mintlify" git remote add origin git@github.com:acme/nookdocs-docs.git git push -u origin main ``` Sign in at [app.nookdocs.com](https://app.nookdocs.com), click **New project**, pick **"Connect your own repo"**, and authorise the GitHub App on the repo you just pushed. Your docs are live on `{slug}.nookdocs.site` within a minute. Work through the **Manual review needed** items from the report. These are config keys with no direct NookDocs equivalent and snippet imports that need converting to the `` component. Any custom or Mintlify-proprietary component that isn't in the NookDocs library passes through verbatim — smoke-test each page to catch these. ## What converts automatically ### Config (`docs.json` / `mint.json` → `nookdocs.config.json`) | Mintlify key | NookDocs key | Notes | |---|---|---| | `name` | `name` | Direct copy | | `$schema` | `$schema` | Rewritten to `https://nookdocs.com/schema.json` | | — | `contentRoot` | Set to `"/"` — the flat canonical layout (content at the repo root) | | — | `theme` | Set to `"larch"` — the current NookDocs starter default | | `logo.light` / `logo.dark` | `colors.logo.light` / `colors.logo.dark` | Paths preserved; `colors.logo.href` set to `/` | | `colors.primary` / `light` / `dark` | `colors.primary` / `light` / `dark` | Direct copy | | `navigation.tabs` (or legacy group array) | `navigation` | Full tree-walk preserves the tab → group → pages hierarchy | | `navigation.global.anchors` | `global.anchors` | `anchor` / `href` / `icon` preserved | | `navbar.links` | `navbar.links` | Direct copy | | `navbar.primary` | `navbar.primaryCta` | `{label, href}` | | `footer.socials` | `footer.socials` | Direct copy | | _(spec present)_ `api-reference/openapi.json` | `api.openapi` + `api.playground` | Set when an OpenAPI spec is found; spec copied to `api-reference/openapi.json` | Keys without a NookDocs equivalent are noted in the report's **Manual review needed** section rather than silently dropped — currently Mintlify's `contextual` and `backgroundImage`. ### Frontmatter Page frontmatter is left untouched, and NookDocs reads the same field names, so `title`, `description`, `icon`, `tag`, `sidebarTitle` and `hidden` keep working after the move — a page with `sidebarTitle: DPA` still shows "DPA" in the rail. See [frontmatter](/content/frontmatter) for every field NookDocs recognises. ### Components (MDX → MDX) NookDocs implements the Mintlify component set under the **same tag names**, so the migrator leaves them untouched — they render as-is. Only two components are genuinely renamed: | Mintlify component | NookDocs equivalent | Notes | |---|---|---| | `` | `` | Renamed; body and props preserved | | `` | `` | Renamed; body and props preserved | Everything else passes through verbatim with its props intact, including `` / ``, the callout family `` / `` / `` / `` / `` (these are five distinct NookDocs components — there is **no** single `` wrapper), `` / ``, `` / ``, `` / ``, ``, `` and `images/hero.png` exists at the repo root, the migrator copies it to `/images/hero.png` so the link keeps working. ## What doesn't convert (review checklist) After a migration, review these items in the output: - **Manual-review report items** — the CLI lists config keys it couldn't map (`contextual`, `backgroundImage`) and snippet imports it detected. Work through each. - **Unsupported components** — any component not in the NookDocs library stays in the MDX verbatim (no auto-substitution). Smoke-test pages to find them. - **Custom React components** — if your repo imports custom `.tsx` / `.jsx` files, those imports stay in the MDX but NookDocs doesn't execute arbitrary React. Refactor to the built-in component library. - **Snippet imports** — Mintlify's `import … from '/snippets/…'` is flagged in the report. NookDocs uses the `` component instead; convert each one. - **Environment-specific URLs** — absolute Mintlify URLs like `https://yoursite.mintlify.app/...` need rewriting to your new NookDocs domain. - **OpenAPI spec path** — the spec is copied to `api-reference/openapi.json` and `api.openapi` points there. Verify the reference resolves in the flat layout. ## Post-migration checklist Deploy the migrated repo, then click through the sidebar and verify each top-level page renders. Unconverted components are the #1 source of render glitches. If you use `api.openapi` for auto-generated API pages, check that the spec file landed at the right path and that `/api-reference/*` routes work. Analytics IDs are **not** carried over by the migrator. Re-enter your GA4 / PostHog / Plausible IDs in the dashboard's **Configurations → Integrations** panel after connecting the repo. Add your old Mintlify URL → NookDocs URL redirects to `nookdocs.config.json#redirects` so inbound links from Google / Twitter / Slack don't 404. (Redirects aren't migrated automatically — add them by hand.) Search uses Postgres FTS (`pg_trgm`) on all pages. The first deploy indexes everything; give it a minute before testing. See [search](/features/search). ## Known limitations - **Custom CSS classes.** Mintlify supports Tailwind classes in MDX attributes. NookDocs accepts them too but only a subset (the ones that don't conflict with theme tokens). Check visually after migration. - **Mintlify-only features.** Speakeasy SDK pages, PDF export, Mintlify Assistant-specific analytics don't have direct equivalents. File a GitHub issue if you need them. - **Docusaurus / GitBook / Nextra / Fumadocs** — detection scaffolded, migrators not yet implemented. PRs welcome; file an issue so we know the demand. ## Related - [Overview](/cli) — what the CLI does - [Install](/cli/install) — prerequisites + upgrade - [Migrate command](/cli/migrate) — flags + detection + report output - [Component library](/components/callout) — every component the migrator targets - [Schema reference](/configuration/schema-reference) — the `nookdocs.config.json` fields the config pass produces --- # Accordion Source: https://docs.nookdocs.com/components/accordion Collapsible content sections with simple and advanced APIs. Supports icons, default open state, and multi-open mode. ## Basic usage The simplest way to create a collapsible section. Pass a `title` prop and put your content inside: ```mdx Basic usage Open **Settings → Domains**, add your domain, then create a CNAME record pointing to `cname.nookdocs.site`. SSL is provisioned automatically. ``` Open **Settings → Domains**, add your domain, then create a CNAME record pointing to `cname.nookdocs.site`. SSL is provisioned automatically. Stack multiple accordions for an FAQ-style layout: ```mdx Multiple accordions Yes. Install the NookDocs GitHub App on your repo, then connect it from the dashboard. Postgres tsvector full-text search out of the box. AI-powered semantic search ships in Phase 5. ``` Yes. Install the NookDocs GitHub App on your repo, then connect it from the dashboard. Postgres tsvector full-text search out of the box. AI-powered semantic search ships in Phase 5. ## With description Add a subtitle below the trigger title: ```mdx With description NookDocs is a documentation platform that turns your MDX files into beautiful, searchable docs sites. ``` NookDocs is a documentation platform that turns your MDX files into beautiful, searchable docs sites. ## With icon Add an icon to the trigger. Supports [Lucide](https://lucide.dev/icons), [Tabler](https://tabler.io/icons), and [Font Awesome](https://fontawesome.com/icons) icons: ```mdx With icon Run `npm install @nookdocs/sdk` to get started. Edit `nookdocs.config.json` with your project name and navigation. ``` Run `npm install @nookdocs/sdk` to get started. Edit `nookdocs.config.json` with your project name and navigation. ## Custom anchor ID Set `id` to create a stable hash link target for the accordion. Readers can link directly to a specific FAQ entry or section: ```mdx Custom anchor ID We charge monthly based on active projects. See the pricing page. ``` Link to it with `[billing FAQ](#faq-billing)`. ## Default open Set `defaultOpen` to expand the accordion on first render: ```mdx Default open This section is visible by default. ``` This section is visible by default. ## AccordionGroup Wrap multiple accordions in an `` to render them as a connected, visually grouped block: ```mdx AccordionGroup Sign up, connect your repo, and deploy in under 5 minutes. Add a CNAME record pointing to `cname.nookdocs.site`. Generate an API key from the dashboard settings. ``` Sign up, connect your repo, and deploy in under 5 minutes. Add a CNAME record pointing to `cname.nookdocs.site`. Generate an API key from the dashboard settings. ## Nested content Accordion content can include any component — code blocks, callouts, cards: ````mdx Nested content These settings are for power users only. ```json { "experimentalFeature": true, "debugMode": false } ``` ```` These settings are for power users only. ## Grouped accordions (advanced) For coordinated behavior (only one open at a time, or multiple), use the compound API with `AccordionItem`, `AccordionTrigger`, and `AccordionContent`: ```mdx Compound API How do I connect a custom domain? Open **Settings → Domains**, add your domain, then create a CNAME record pointing to `cname.nookdocs.site`. SSL is provisioned automatically. Can I use my own GitHub repo? Yes. Install the NookDocs GitHub App on your repo, then connect it from the dashboard. ``` How do I connect a custom domain? Open **Settings → Domains**, add your domain, then create a CNAME record pointing to `cname.nookdocs.site`. SSL is provisioned automatically. Can I use my own GitHub repo? Yes. Install the NookDocs GitHub App on your repo, then connect it from the dashboard. ## Multiple items open at once Set `type="multiple"` to allow more than one item to be expanded simultaneously. Useful when readers might want to compare two sections side by side. ```mdx Multiple items open Option A Content for option A Option B Content for option B Option C Content for option C ``` Option A Content for option A. Option B Content for option B. Option C Content for option C. ## Default expanded items Use `defaultValue` to pre-open one or more items on first render. Pass a string in single mode, or an array in multiple mode. ```mdx Default expanded (single) Installation (open by default) npm install @nookdocs/sdk Usage ... ``` ```mdx Default expanded (multiple) ... ``` ## Single mode: collapsible In single mode, by default the active item cannot be closed by clicking again — there's always exactly one open. Set `collapsible` to allow closing the open item: ```mdx Collapsible mode ... ``` When to enable: FAQ pages where the reader might want to "close" the current question. When NOT to enable: forced-disclosure flows like a wizard where one step must always be visible. ## Nested content Accordion content can include any other component — code blocks, callouts, cards, even nested accordions: ````mdx Nested content (compound API) Advanced configuration These settings are for power users only. ```json { "experimentalFeature": true } ``` ```` ## Props ### Accordion (simple API) | Prop | Type | Default | Description | |------|------|---------|-------------| | `title` | `string` | — | Trigger label. Presence of this prop activates simple mode | | `description` | `string` | — | Subtitle shown below the title | | `icon` | `string` | — | Icon name ([Lucide](https://lucide.dev/icons), [Tabler](https://tabler.io/icons), or [Font Awesome](https://fontawesome.com/icons)) | | `iconType` | `string` | — | FA icon style (solid, brands, etc.) | | `defaultOpen` | `boolean` | `false` | Whether the item starts expanded | | `id` | `string` | — | Custom anchor ID for hash links (e.g. `#faq-section`) | ### AccordionGroup | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | One or more `` items | ### Accordion (compound API) | Prop | Type | Default | Description | |------|------|---------|-------------| | `type` | `"single" \| "multiple"` | `"single"` | Whether one or many items can be open | | `collapsible` | `boolean` | `false` | Allow closing the open item (single mode only) | | `defaultValue` | `string \| string[]` | — | Item(s) open on first render | ### AccordionItem | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | Unique identifier for the item | ### AccordionTrigger / AccordionContent | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | Trigger button content / collapsible body | ## When to use - **FAQs** — Classic use case, keeps the page scannable - **Advanced options** — Hide rarely-used settings behind a disclosure - **Long detail sections** — Summary visible, details one click away For navigable table-of-contents, use the sidebar — not accordions. --- # ApiMethod Source: https://docs.nookdocs.com/components/api-method Colored HTTP method badge for API endpoint pages and navigation. ## Usage Drop `` next to a URL to give the method a color-coded label. Readers can scan a list of endpoints and immediately spot which is GET, POST, PUT, etc. ```mdx Basic usage `/v1/projects` ``` `/v1/projects` ## All methods The standard HTTP method colors follow the Mintlify / Stripe / Postman convention so readers don't need to learn a new palette. ```mdx All methods `/v1/projects` `/v1/projects` `/v1/projects/{id}` `/v1/projects/{id}` `/v1/projects/{id}` `/v1/projects` `/v1/projects/{id}` ``` `/v1/projects` `/v1/projects` `/v1/projects/{id}` `/v1/projects/{id}` `/v1/projects/{id}` `/v1/projects` `/v1/projects/{id}` ## Color reference | Method | Color | Theme token | |--------|-------|-------------| | `GET` | green | `--docs-success` | | `POST` | blue | `--docs-info` | | `PUT` | yellow | `--docs-warning` | | `PATCH` | primary (purple-ish) | `--docs-primary` | | `DELETE` | red | `--docs-danger` | | `OPTIONS` | gray | `--docs-fg-muted` | | `HEAD` | gray | `--docs-fg-muted` | The colors are not hardcoded — they're driven by your theme tokens. If you change `--docs-success` to teal in your custom theme, GET badges turn teal. ## Endpoint headings Pair with a code-formatted URL inside an `h2` to get a clean endpoint header: ```mdx Endpoint heading ## `/v1/projects` ``` ## Case insensitive Lowercase works too — common when authors copy from JavaScript fetch calls: ```mdx Case insensitive ``` ## Auto-generation In Phase 4, the OpenAPI parser automatically renders an `` next to each endpoint title in the auto-generated reference pages. You don't need to add it manually for endpoints that come from a spec — only for endpoints documented by hand. ## Props | Prop | Type | Required | Description | |------|------|----------|-------------| | `method` | `"GET" \| "POST" \| "PUT" \| "PATCH" \| "DELETE" \| "OPTIONS" \| "HEAD"` (case insensitive) | Yes | The HTTP method to display | --- # Audience Source: https://docs.nookdocs.com/components/audience Conditional content per visitor segment — Phase 6 personalization. ## Status `` is a **stub component** today. The `for` prop is accepted and the call site is forward-compatible, but segment-based filtering ships in Phase 6 alongside the personalization engine. Until then, only blocks with `default` set are rendered. This component was called `` until 2026-08-10. It was renamed to free that name for [View](/components/view), which switches a page between languages or frameworks — a different job with the same old name. `` is still accepted as a deprecated alias, so existing pages keep working. ## Target API (Phase 6) ```mdx Your API key is in your dashboard. [Sign up](https://app.nookdocs.com/signup) to get an API key. ``` When Phase 6 ships, the platform will read visitor state (auth status, plan tier, cookie segments) and render the matching block. Until then, the one with `default` is what every reader sees. ## Props Segment(s) this content targets. Common values: `anonymous`, `authenticated`, plan tiers (`starter`, `pro`, `business`), roles (`admin`, `editor`, `viewer`). Render this block when no segment matches — and, today, the only thing that makes a block render at all. ## Plan for it now `` renders and `` without `default` is hidden, so you can author pages against the target API today and they'll behave correctly when Phase 6 ships — no rewrites needed. Only the `default` block reaches the Markdown export today, because the others render nothing. Once segment filtering ships, treat every branch as page content rather than assuming one canonical variant. ## Related - [View](/components/view) — switch a page between languages or frameworks - [Visibility](/components/visibility) — split content between human readers and LLMs --- # Badge Source: https://docs.nookdocs.com/components/badge Small inline label for status, version, plan tier, and other metadata. ## Usage ```mdx Basic usage GA Beta Deprecated ``` GA  Beta  Deprecated ## Variants Seven theme-token-driven color variants: ```mdx All variants Default Primary Success Warning Danger Info Neutral ``` Default  Primary  Success  Warning  Danger  Info  Neutral ## Sizes Four sizes from tiny labels to prominent tags: ```mdx Sizes XS SM MD LG ``` XS  SM  MD  LG ## Pill shape Set `shape="pill"` for fully rounded badges: ```mdx Pill shape v2.1 Live ``` v2.1  Live ## With icon Add a Lucide icon before the label: ```mdx With icon Verified Review ``` Verified  Review ## Stroke (outline) Set `stroke` for a transparent background with border-only style: ```mdx Stroke (outline) Outline Removed ``` Outline  Removed ## Disabled Reduced opacity and non-interactive: ```mdx Disabled Coming soon ``` Coming soon ## Mintlify color names If you're migrating from Mintlify, you can use named `color` values instead of `variant`: ```mdx Mintlify color names Info Success Danger Warning Primary ``` Info  Success  Danger  Warning  Primary ## Inline with headings A common pattern: pin a status badge next to an h2 heading. ```mdx Inline with headings ## Authentication GA ## Webhooks Beta ## Legacy API Deprecated ``` ## Differences from `` `` is a specialized badge for HTTP method labels (GET, POST, PUT, etc) with a fixed color mapping. `` is the generic primitive — use it for everything that isn't an HTTP method. ## Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `"default" \| "primary" \| "success" \| "warning" \| "danger" \| "info" \| "neutral"` | `"default"` | Color variant | | `color` | `string` | — | Mintlify compat: named color (gray, blue, green, yellow, red, purple). Maps to variant | | `size` | `"xs" \| "sm" \| "md" \| "lg"` | `"sm"` | Badge height and font size | | `shape` | `"rounded" \| "pill"` | `"rounded"` | Border radius style | | `icon` | `string` | — | Icon name ([Lucide](https://lucide.dev/icons), [Tabler](https://tabler.io/icons), or [Font Awesome](https://fontawesome.com/icons)) | | `iconType` | `string` | — | FA icon style (solid, brands, etc.) | | `stroke` | `boolean` | `false` | Transparent bg with border-only outline | | `disabled` | `boolean` | `false` | Reduced opacity, no pointer events | | `className` | `string` | — | Custom CSS class | | `children` | `ReactNode` | required | Badge label (kept short — "GA", "Beta", "v2") | --- # Banner Source: https://docs.nookdocs.com/components/banner Inline announcement banner for page-local notices. ## Usage ```mdx Usage This API is in beta. Breaking changes may happen without notice. ``` This API is in beta. Breaking changes may happen without notice. ## Variants Three visual styles for different urgency levels. ```mdx Variants Heads up — we're rolling out a new search modal next week. Scheduled maintenance: 2026-04-15 02:00–04:00 UTC. New: AI search is now available on all plans. ``` Heads up — we're rolling out a new search modal next week. Scheduled maintenance: 2026-04-15 02:00–04:00 UTC. New: AI search is now available on all plans. ## Dismissible Set `dismissible` to add a close button. The dismiss state is local to the page render — it doesn't persist across reloads. ```mdx Dismissible Welcome to the new docs! Click around and let us know what you think. ``` Welcome to the new docs! Click around and let us know what you think. ## Differences from the global banner NookDocs supports two banner systems: | | Global banner | `` MDX component | |---|---|---| | **Source** | `nookdocs.config.json#banner` | Authored inline in MDX | | **Scope** | Every page on the site | One specific page | | **Position** | Very top, above the navbar | Inline within the page body | | **Use for** | Site-wide announcements (e.g. "We're hiring") | Page-local notices ("This API is in beta") | The global banner is for announcements you want every visitor to see. `` is for context-specific notes that only make sense on a single page. ## Differences from `` `` is wider and more prominent — it spans the full content width and uses heavier color. `` is a sidebar-style note with a left border accent. Use Banner for **announcements**, Callout for **inline notes**. ## Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `"info" \| "warning" \| "primary"` | `"info"` | Visual style | | `dismissible` | `boolean` | `false` | Show a close button | | `children` | `ReactNode` | required | Banner content | --- # Button Source: https://docs.nookdocs.com/components/button Theme-aware CTA button for landing-style pages and inline actions. ## Usage ```mdx Basic usage ``` Use ` ```     ## Sizes Three sizes — `sm`, `md` (default), `lg`. ```mdx Sizes ```     ## Icons Add a Lucide icon with the `icon` prop. Default position is `end` (after the label): ```mdx With icon ```     ## External links Links starting with `http://` or `https://` automatically open in a new tab with `rel="noopener noreferrer"`. Override explicitly with the `external` prop: ```mdx External link ``` ## When to use - Hero "Get Started" CTA - "View live demo" on feature pages - "Download SDK" on integration pages - "Open dashboard" for authenticated flows - Inline navigation (use markdown links) - Every heading ("Learn more" spam) - Form submissions (use regular form buttons) - Anything the reader would call an "action button" on an app ## Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `variant` | `"primary" \| "secondary" \| "ghost"` | `"primary"` | Visual weight | | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Height and padding | | `href` | `string` | — | Link destination — renders as `` or `` | | `icon` | `string` | — | Lucide icon name or emoji | | `iconPosition` | `"start" \| "end"` | `"end"` | Icon position relative to the label | | `external` | `boolean` | auto | Force external link behavior (new tab + rel attributes) | --- # Callout Source: https://docs.nookdocs.com/components/callout Highlight important information with callout boxes. ## Usage Callouts draw attention to important information. Use the generic `` with a `type` prop, or one of the named variants directly. ### Generic syntax ```mdx Generic syntax This is an informational callout. ``` This is an informational callout. ### Named variants ```mdx Named variants This is an info callout. This action requires caution. Use Cmd+K to open search. This cannot be undone. General information here. ``` This is an info callout. This action requires caution. Use Cmd+K to open search. This cannot be undone. General information here. ## Types Each variant comes with its own color and default icon. The color maps to a theme token, so dark/light modes and tenant custom themes adapt automatically. | Type | Component | Default icon | Use case | |------|-----------|--------------|----------| | `info` | `` | `info` | General information | | `note` | `` | `info` | Side notes, clarifications | | `tip` | `` | `lightbulb` | Helpful suggestions, best practices | | `warning` | `` | `alert-triangle` | Caution or important gotchas | | `danger` | `` | `alert-circle` | Critical warnings, destructive actions | ## Custom icon Override the default variant icon with any Lucide icon name or emoji: ```mdx Custom icon This is a tip with a custom sparkles icon. Launch mode activated. Emojis work too — anything that is not a Lucide name is rendered as text. ``` This is a tip with a custom **sparkles** icon instead of the default lightbulb. Launch mode activated — custom rocket icon overrides the default info icon. Emojis work too — anything that is not a registered Lucide name is rendered as text. ## Title Add a bold title above the content for extra emphasis: ```mdx With title API v1 will be deprecated on 2026-06-01. Migrate to v2. ``` API v1 will be deprecated on 2026-06-01. Migrate to v2. ## Custom color Override the variant color with a hex code: ```mdx Custom color Your API key is in the dashboard settings. ``` Your API key is in the dashboard settings. ## Props | Prop | Type | Required | Description | |------|------|----------|-------------| | `type` | `"note" \| "info" \| "tip" \| "warning" \| "danger"` | No (default `note`) | Callout variant — only on generic `` | | `title` | `string` | No | Bold title rendered above the content | | `icon` | `string` | No | Override the default icon ([Lucide](https://lucide.dev/icons), [Tabler](https://tabler.io/icons), [Font Awesome](https://fontawesome.com/icons), or emoji) | | `iconType` | `string` | No | FA icon style (solid, brands, etc.) | | `color` | `string` | No | Custom color override (hex). Overrides variant border and background tint | --- # Card Source: https://docs.nookdocs.com/components/card Display content in a card layout with optional icons and links. ## Basic usage ```mdx Basic usage Get your first docs site deployed in under 5 minutes. ``` Get your first docs site deployed in under 5 minutes. ## Icons The `icon` prop accepts three formats and picks the right renderer automatically. ### Lucide icon name Pass any registered Lucide icon name (see the full list at [Icon component](/components/icon)) and the card renders a themed tinted icon block: ```mdx Lucide icon Get started in 5 minutes. Complete REST API documentation. Deep dives and tutorials. ``` Get started in 5 minutes. Complete REST API documentation. Deep dives and tutorials. ### Image URL Pass a URL (starting with `http://`, `https://`, or `/`) and the card renders it as an ``: ```mdx Image URL icon Branded card with your own image. ``` ### Emoji (backward compatible) Any other string is rendered as text — perfect for emoji: ```mdx Emoji icon Edge-cached on every deploy. ``` Edge-cached on every deploy. ## Custom icon color Override the tint color of a Lucide icon with the `iconColor` prop: ```mdx Custom icon color Shipped in seconds. ``` ## Image card Set `img` to display a hero image at the top of the card: ```mdx Image card Learn how the build pipeline works. ``` ## Horizontal layout Set `horizontal` for a side-by-side layout — image or icon on the left, text on the right: ```mdx Horizontal layout Get your docs site live in 5 minutes. Learn how the build pipeline works. ``` ## Custom styling with className Pass `className` to add Tailwind utility classes or your own CSS classes to the card container: ```mdx Custom className This card has a custom border and background tint. ``` ## Card grid Use `` with 1-4 columns to create a responsive grid. ```mdx Card grid Learn how to configure your docs site. Explore built-in MDX components. Integrate with the NookDocs API. Set up docs.yoursite.com. ``` Learn how to configure your docs site. Explore built-in MDX components. Integrate with the NookDocs API. Set up docs.yoursite.com. ## Props ### Card | Prop | Type | Required | Description | |------|------|----------|-------------| | `title` | `string` | Yes | Card heading | | `icon` | `string` | No | Icon name ([Lucide](https://lucide.dev/icons), [Tabler](https://tabler.io/icons), [Font Awesome](https://fontawesome.com/icons)), image URL, or emoji | | `iconType` | `string` | No | Font Awesome style, when the icon comes from that library: `regular`, `solid`, `light`, `thin`, `sharp-solid`, `duotone`, `brands` | | `type` | `info` \| `warning` \| `note` \| `tip` \| `check` \| `danger` | No | Give the card a callout theme — background and border take that signal color, so a warning card and a warning callout read as the same thing | | `iconColor` | `string` | No | Override icon tint color (hex) | | `color` | `string` | No | Alias for `iconColor` (Mintlify compat) | | `img` | `string` | No | Hero image URL displayed at the top (or left in horizontal mode) | | `horizontal` | `boolean` | No | Side-by-side layout: image/icon left, text right | | `href` | `string` | No | Link destination — if set, the whole card is clickable | | `cta` | `string` | No | Call-to-action button text shown at the bottom | | `arrow` | `boolean` | — | Show/hide link arrow (default: shows when `cta` is set) | | `className` | `string` | No | Additional CSS class names applied to the card container | ### CardGroup | Prop | Type | Default | Description | |------|------|---------|-------------| | `cols` | `1 \| 2 \| 3 \| 4` | `2` | Number of columns on desktop (responsive collapses to 1 on mobile) | --- # Check / Uncheck Source: https://docs.nookdocs.com/components/check Inline checkmark and X marks for checklist items. ## Usage `` and `` are inline icon pairs designed for "done vs todo" lists. They render as a colored icon plus an optional inline label. ```mdx Usage - GitHub repo connected - Custom domain verified - SSL certificate active - Billing not configured - Team members not invited ``` - GitHub repo connected - Custom domain verified - SSL certificate active - Billing not configured - Team members not invited ## Without children The icon stands alone — useful as a status marker in tables: ```mdx Without children | Feature | Available | |---------|-----------| | Search | | | AI search | | | Custom domain | | ``` | Feature | Available | |---------|-----------| | Search | | | AI search | | | Custom domain | | ## Color reference | Component | Color | Token | |-----------|-------|-------| | `` | green | `--docs-success` | | `` | muted gray | `--docs-fg-muted` | The colors come from your theme tokens, so dark/light mode and tenant overrides apply automatically. ## Props | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | Optional inline label rendered after the icon | --- # CodeBlock Source: https://docs.nookdocs.com/components/code-block Code blocks with syntax highlighting, line numbers, highlighting, focus, word wrap, and expandable sections. ## Usage Write code with plain markdown fences — all features work automatically. ````mdx ```typescript const app = createServer(); app.listen(3000); ``` ```` ```typescript const app = createServer(); app.listen(3000); ``` Use `` only when you need an explicit JSX element — for example, inside a custom component that doesn't preserve fence metadata. ```mdx {`const app = createServer(); app.listen(3000);`} ``` {`const app = createServer(); app.listen(3000);`} ## Meta options Add options after the language tag. These work on markdown fences only (not the `` component). ### Line numbers ````mdx ```typescript lines import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ```` ```typescript lines import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ### Highlight lines ````mdx ```typescript highlight={1,4-6} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ```` ```typescript highlight={1,4-6} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ### Focus lines Dims everything except the focused lines. Hover the block to reveal dimmed lines. ````mdx ```typescript focus={4-6} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ```` ```typescript focus={4-6} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); const { data } = await supabase.from("pages").select("*"); ``` ### Word wrap ````mdx ```bash wrap curl -X POST https://api.example.com/v1/documents/create -H "Authorization: Bearer sk-1234567890abcdef" -H "Content-Type: application/json" -d '{"title": "Getting Started", "content": "This is a very long line that would normally overflow."}' ``` ```` ```bash wrap curl -X POST https://api.example.com/v1/documents/create -H "Authorization: Bearer sk-1234567890abcdef" -H "Content-Type: application/json" -d '{"title": "Getting Started", "content": "This is a very long line that would normally overflow the code block horizontally."}' ``` ### Expandable Collapses code blocks with more than 15 lines. Click "Show more" to expand. ````mdx ```python expandable import os from pathlib import Path def process_documents(directory): results = [] for path in sorted(Path(directory).rglob("*.md")): ... ``` ```` ```python expandable import os import json from pathlib import Path def process_documents(directory: str) -> list[dict]: """Walk a directory and process all markdown files.""" results = [] base = Path(directory) for path in sorted(base.rglob("*.md")): with open(path) as f: content = f.read() meta = extract_frontmatter(content) body = strip_frontmatter(content) results.append({ "path": str(path.relative_to(base)), "title": meta.get("title", path.stem), "content": body, "word_count": len(body.split()), }) return results ``` ### Title / filename ````mdx ```typescript src/lib/db.ts export const db = createClient(url, key); ``` ```` ```typescript src/lib/db.ts export const db = createClient(url, key); ``` ### Combining options ````mdx ```typescript lines highlight={3-5} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); ``` ```` ```typescript lines highlight={3-5} import { createClient } from "@supabase/supabase-js"; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY! ); ``` ## When to prefer fences | | Markdown fences | `` | |---|---|---| | **Syntax** | Short — `` ```ts `` | Verbose — `` | | **Title** | `` ```ts server.ts `` | `title="server.ts"` prop | | **Meta options** | `lines`, `highlight`, `focus`, `wrap`, `expandable` | Not supported | | **Multiline** | Native | Requires template literal | | **Inside CodeGroup** | Works as a fence child | Works the same way | | **Recommended for** | 95% of cases | Edge cases only | ## Props | Prop | Type | Description | |------|------|-------------| | `language` | `string` | Syntax highlighter language identifier | | `title` | `string` | Optional title shown in the language badge slot | | `children` | `ReactNode` | Code content (typically a string template literal) | --- # Code Group Source: https://docs.nookdocs.com/components/code-group Display the same code example across multiple languages or package managers in a single tabbed block. ## Basic usage Wrap two or more fenced code blocks in ``. The label after the language identifier becomes the tab title. ````mdx Basic usage ```bash npm npm install @nookdocs/sdk ``` ```bash yarn yarn add @nookdocs/sdk ``` ```bash pnpm pnpm add @nookdocs/sdk ``` ```` ```bash npm npm install @nookdocs/sdk ``` ```bash yarn yarn add @nookdocs/sdk ``` ```bash pnpm pnpm add @nookdocs/sdk ``` ## Tab labels CodeGroup picks the tab label from the first thing it finds, in this order: 1. **Metadata after the language**: `` ```bash npm `` → label `npm` 2. **Explicit `title` prop**: `` ```bash {title="Install"} `` → label `Install` 3. **Language identifier**: `` ```typescript `` → label `typescript` 4. **Fallback**: `Tab 1`, `Tab 2`, etc. The first format is the cleanest and matches Mintlify — prefer it whenever possible. ## Multi-language API examples The classic use case — the same request in cURL, JavaScript, Python, Go. ````mdx Multi-language API example ```bash cURL curl -X POST https://api.nookdocs.com/v1/projects \ -H "Authorization: Bearer $TOKEN" \ -d '{"name": "My Docs"}' ``` ```js JavaScript const project = await fetch("https://api.nookdocs.com/v1/projects", { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ name: "My Docs" }), }); ``` ```python Python import requests r = requests.post( "https://api.nookdocs.com/v1/projects", headers={"Authorization": f"Bearer {token}"}, json={"name": "My Docs"}, ) ``` ```go Go req, _ := http.NewRequest("POST", "https://api.nookdocs.com/v1/projects", strings.NewReader(`{"name":"My Docs"}`)) req.Header.Set("Authorization", "Bearer " + token) ``` ```` ```bash cURL curl -X POST https://api.nookdocs.com/v1/projects \ -H "Authorization: Bearer $TOKEN" \ -d '{"name": "My Docs"}' ``` ```js JavaScript const project = await fetch("https://api.nookdocs.com/v1/projects", { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ name: "My Docs" }), }); ``` ```python Python import requests r = requests.post( "https://api.nookdocs.com/v1/projects", headers={"Authorization": f"Bearer {token}"}, json={"name": "My Docs"}, ) ``` ## Tab sync CodeGroups with matching labels automatically sync with each other and with `` components. Click "JavaScript" in one code group, and all others with a "JavaScript" tab switch too. Selections persist across page navigations. Disable sync on a specific group with `sync={false}`: ```mdx Disable tab sync ... ``` ## Syntax highlighting + copy button Each tab inherits the platform's code block enhancements: - Syntax highlighting via Prism (theme-token mapped, dark/light aware) - Copy button integrated in the header bar - Language badge ## Dropdown mode Use the `dropdown` prop to show a dropdown language selector instead of inline tabs. This is useful for API reference pages with many languages. ````mdx Dropdown mode ```bash cURL curl -X GET https://api.nookdocs.com/v1/projects \ -H "Authorization: Bearer $TOKEN" ``` ```js JavaScript const res = await fetch("https://api.nookdocs.com/v1/projects", { headers: { Authorization: `Bearer ${token}` }, }); ``` ```python Python import requests r = requests.get( "https://api.nookdocs.com/v1/projects", headers={"Authorization": f"Bearer {token}"}, ) ``` ```` ```bash cURL curl -X GET https://api.nookdocs.com/v1/projects \ -H "Authorization: Bearer $TOKEN" ``` ```js JavaScript const res = await fetch("https://api.nookdocs.com/v1/projects", { headers: { Authorization: `Bearer ${token}` }, }); ``` ```python Python import requests r = requests.get( "https://api.nookdocs.com/v1/projects", headers={"Authorization": f"Bearer {token}"}, ) ``` ## Differences from `` | | `` | `` | |---|---|---| | **For** | Code blocks only | Any content | | **Tab labels** | From fence metadata | From `` children | | **Auto-styling** | Code block tab bar | Generic tab bar | If your tabs contain prose or images, use [``](/components/tabs). For code-only switching, `` is shorter and renders more compactly. ## Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `ReactNode` | required | Two or more fenced code blocks | | `dropdown` | `boolean` | `false` | Show a dropdown selector instead of inline tabs | | `sync` | `boolean` | `true` | Sync active tab with matching CodeGroups/Tabs on the page | The active tab is uncontrolled — initial state is the first child. There is no `defaultValue` prop because reordering the children is the canonical way to change the default. --- # ColorPalette / ColorSwatch Source: https://docs.nookdocs.com/components/color Design system color swatches with click-to-copy hex values. ## Usage ```mdx Usage ``` Hover over a swatch and click to copy its hex value to the clipboard. ## Brand palette Document a tenant's full brand palette in one block. The grid is responsive — 2 columns on mobile, 3 columns on tablet+. ```mdx Brand palette ``` ## Standalone swatch `` works outside a `` too — render it inline as a single sample. The grid layout only applies inside the palette wrapper. ## Use cases - **Brand guidelines** — primary, secondary, neutral palettes with usage notes - **Theme documentation** — show what the `--docs-*` token values resolve to - **Design system** — semantic colors (success, warning, danger) and their hex values - **Migration guides** — old palette vs new palette side by side ## Section headings with ColorRow Use `` inside a `` to label groups of swatches. This is helpful when a single palette contains multiple categories (e.g. brand vs. semantic colors): ```mdx ColorRow section headings ``` ## Mintlify aliases For Mintlify compatibility, `ColorSwatch` also accepts a `value` prop as an alias for `hex`. Both produce the same result: ```mdx value prop (Mintlify compat) ``` The compound dot-syntax aliases also work — `Color.Row` maps to `ColorRow` and `Color.Item` maps to `ColorSwatch`: ```mdx Dot-syntax aliases ``` ## Props ### ColorPalette | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | One or more ``, ``, or Mintlify aliases | ### ColorSwatch | Prop | Type | Required | Description | |------|------|----------|-------------| | `name` | `string` | Yes | Display name (e.g. "Primary", "Brand 500") | | `hex` | `string` | Yes | Color value (hex, rgb, oklch, named — anything CSS accepts) | | `value` | `string` | No | Alias for `hex` (Mintlify compat) — if both are set, `hex` wins | | `description` | `string` | No | Usage description shown below the hex | ### ColorRow | Prop | Type | Required | Description | |------|------|----------|-------------| | `name` | `string` | Yes | Section heading text displayed above the next group of swatches | --- # Columns Source: https://docs.nookdocs.com/components/columns Responsive multi-column layout wrapper for arbitrary content. ## Usage `` wraps any children in a responsive grid. Use it for side-by-side prose, image+text combinations, or comparison blocks where you don't want the visual treatment of ``. ```mdx Basic usage
**Before:** Manual MDX authoring with no validation. Authors had to remember every component name and prop.
**After:** LLM-first authoring with the MCP server. Claude/Cursor know every component natively.
```
**Before:** Manual MDX authoring with no validation. Authors had to remember every component name and prop.
**After:** LLM-first authoring with the MCP server. Claude/Cursor know every component natively.
## 3 columns ```mdx 3 columns
**Free**: 1 project, basic theme
**Pro**: Unlimited projects, AI search
**Business**: Audit log, SSO, priority support
```
**Free**: 1 project, basic theme
**Pro**: Unlimited projects, AI search
**Business**: Audit log, SSO, priority support
## Responsive behavior Columns collapse to a single column on mobile. The breakpoint depends on `cols`: - `cols={2}` → 1 column < 640px (`sm`), 2 columns ≥ 640px - `cols={3}` → 1 column < 640px, 2 columns 640–1024px, 3 columns ≥ 1024px (`lg`) - `cols={4}` → same as cols=3 but 4 columns ≥ 1024px ## Differences from CardGroup | | `` | `` | |---|---|---| | **Wraps children in a Card?** | No, children render as-is | Yes, expects `` children | | **Use case** | Arbitrary side-by-side content | Card-style nav grids | | **Visual treatment** | None (transparent) | Bordered cards | ## Column wrapper The `` component is a pass-through wrapper you can use instead of a bare `
` as a child of ``. It renders identically — no extra styling or behavior — but it reads more explicitly in MDX: ```mdx Column wrapper **Left side** — using the Column wrapper. **Right side** — same result as a plain `
`. ``` Both forms are valid. Use whichever reads better in your content. `` exists primarily for Mintlify compatibility — if you're migrating docs that already use ``, they work as-is. ## Props ### Columns | Prop | Type | Default | Description | |------|------|---------|-------------| | `cols` | `2 \| 3 \| 4` | `2` | Number of columns on desktop | | `children` | `ReactNode` | required | Column children — anything | ### Column | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | Content for this column — rendered as-is | --- # Diff Source: https://docs.nookdocs.com/components/diff Code diff with green added lines and red removed lines. ## Usage `` renders a unified-format code diff with color highlighting. Added lines (`+`) are green, removed lines (`-`) are red. ```mdx Basic usage {`- const old = "value"; + const newValue = "value"; const unchanged = true;`} ``` {`- const old = "value"; + const newValue = "value"; const unchanged = true;`} ## Markdown fence alternative The equivalent markdown fence works the same way and is shorter: ````mdx Markdown fence alternative ```diff - const old = "value"; + const newValue = "value"; const unchanged = true; ``` ```` ```diff - const old = "value"; + const newValue = "value"; const unchanged = true; ``` So when do you reach for `` instead of the fence? Two cases: 1. **Inside another component** that doesn't preserve fence metadata (rare) 2. **Dynamically computed** diff content from a JSX expression For 95% of cases, the fence is the right call. ## Migration guide example A common diff use case — showing config file migrations: ````mdx Migration guide example ```diff { "name": "My Docs", - "version": "1.0", - "pages": ["intro.mdx"], + "navigation": [ + { + "group": "Getting Started", + "pages": ["docs/intro"] + } + ] } ``` ```` ```diff { "name": "My Docs", - "version": "1.0", - "pages": ["intro.mdx"], + "navigation": [ + { + "group": "Getting Started", + "pages": ["docs/intro"] + } + ] } ``` ## Props | Prop | Type | Description | |------|------|-------------| | `children` | `ReactNode` | Diff text — typically a template literal with `+`/`-` line prefixes | ## Syntax highlighting Diff colors come from Prism's `language-diff` grammar wired to your `--docs-success` and `--docs-danger` theme tokens. Dark/light mode and tenant overrides apply automatically. --- # Embed Source: https://docs.nookdocs.com/components/embed Generic iframe wrapper for CodeSandbox, StackBlitz, Figma, and other embed URLs. ## Usage `` is the generic iframe wrapper. Use it for anything that gives you an embed URL but isn't a video. ```mdx Usage ``` ## Common embed sources ```mdx Common embed sources ``` ## Aspect ratio Default is `16/9`. Override based on the embedded content's natural ratio: | Use case | Aspect ratio | |----------|--------------| | Code playground (wide) | `16/9` | | Figma file (often square-ish) | `4/3` or `1/1` | | Vertical content (mobile preview) | `9/16` | | Tall design | `3/4` | ## Sandbox By default the iframe runs with `sandbox="allow-scripts allow-same-origin allow-popups allow-forms"`, which works for almost all common embeds. Override to lock down further or open up if needed: ```mdx Sandbox ``` ## Allow attribute For embeds that need device permissions (camera, microphone, fullscreen), pass an `allow` string: ```mdx Allow attribute ``` ## Lazy loading The iframe uses `loading="lazy"`, so it only loads when scrolled into view. Saves bandwidth for embeds far down the page. ## Differences from `