{
  "markdown": "# Booklet\n\n**Publish clean, readable pages from Markdown — by hand, by script, or by your AI assistant.**\n\n[![License: MIT](https://img.shields.io/github/license/AshwinSathian/booklet)](LICENSE)\n[![npm version](https://img.shields.io/npm/v/booklet-cli?label=booklet-cli)](https://www.npmjs.com/package/booklet-cli)\n[![npm downloads](https://img.shields.io/npm/dw/booklet-cli)](https://www.npmjs.com/package/booklet-cli)\n[![CI](https://img.shields.io/github/actions/workflow/status/AshwinSathian/booklet/ci.yml?branch=main&label=CI)](https://github.com/AshwinSathian/booklet/actions/workflows/ci.yml)\n\nPaste Markdown into the editor, preview it live, and share a polished read-only URL in one click — or skip the editor and publish the same way from a CI pipeline, a script, or an AI assistant like Claude. Sign in for pages that never expire, version history, analytics, custom slugs, password protection, collections, and a full REST API.\n\nWhat makes Booklet more than an editor is the surface around it: a REST API, an npm-published CLI, a GitHub Action for publishing docs in CI, and a standalone MCP server so AI assistants like Claude can publish and manage pages directly. Markdown-to-shareable-page tools are common; shipping the same functionality as an API, a CLI, a CI action, and an MCP server on top of it is the part that isn't.\n\n**Live:** [booklet.ashwinsathian.com](https://booklet.ashwinsathian.com) · **API docs:** [/api-docs](https://booklet.ashwinsathian.com/api-docs) · **MCP setup:** [/mcp-setup](https://booklet.ashwinsathian.com/mcp-setup)\n\n---\n\n## Quick start\n\n```bash\nnpm install -g booklet-cli\nbooklet login                            # opens your browser to authorize\nbooklet publish README.md --open         # publish this file, open it in your browser\n```\n\nThat's it: you get back a permanent, shareable URL. No account needed to try the editor itself; sign in only when you want pages that never expire, an API key, or the CLI.\n\n---\n\n## Features\n\n- **Editor**: live preview (120 ms debounce), unlimited local drafts with autosave, import/export\n- **Share pages**: clean read-only URLs, table of contents, reading time, dark/light mode\n- **Embeds**: `<iframe>` embed codes for any page via `/p/:id/embed`\n- **Export**: PDF, Markdown, HTML fragment\n- **LaTeX / KaTeX**: inline `$...$` and display `$$...$$` math blocks\n- **Mermaid diagrams**: fenced code blocks with `mermaid` language tag\n- **Version history**: every publish is snapshotted; browse and restore past versions\n- **Analytics**: per-page view counts, scroll depth, referrers\n- **Collections**: group pages into a named collection with a shared URL\n- **Password protection**: require a password to view any page\n- **Custom slugs**: set a human-readable URL like `/p/my-release-notes`\n- **Team Spaces**: invite collaborators, publish to shared `/t/:slug` spaces\n- **Webhooks**: HTTP callbacks on `page.published` and `page.updated` events\n- **REST API**: publish, update, list, and delete pages programmatically\n- **CLI**: publish Markdown from your terminal (`npx booklet-cli`)\n- **GitHub Action**: publish docs in CI via [`AshwinSathian/publish-to-booklet`](https://github.com/AshwinSathian/publish-to-booklet)\n- **MCP server**: expose the API to AI assistants (Claude, Cursor, etc.) via the Model Context Protocol\n<!-- VS Code extension: built, not yet on the Marketplace; re-add once AshwinSathian.booklet-vscode is published -->\n- **Frontmatter**: YAML frontmatter sets title, slug, visibility, tags, author, date\n\n---\n\n## CLI\n\n```bash\nnpm install -g booklet-cli\n\nbooklet login                          # save your API key\nbooklet publish README.md              # publish a file\nbooklet publish README.md --watch      # watch + auto-republish on save\nbooklet publish - < NOTES.md           # from stdin\nbooklet pages list                     # list your pages\n```\n\nSee [packages/cli/README.md](packages/cli/README.md) for full docs (all flags, CI/non-interactive auth via `--key` or `BOOKLET_API_KEY`, `pages open`, etc.).\n\n---\n\n## REST API\n\nAll endpoints are under `/api/v1/` and authenticated with `Authorization: Bearer <bklt_...>`.\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/api/v1/publish` | Create a new page |\n| `GET` | `/api/v1/pages` | List your pages |\n| `GET` | `/api/v1/pages/:id` | Read a page's metadata and raw content |\n| `PATCH` | `/api/v1/pages/:id` | Update content, slug, or visibility |\n| `DELETE` | `/api/v1/pages/:id` | Delete a page |\n| `GET` | `/api/v1/keys` | List API keys |\n| `POST` | `/api/v1/keys` | Create an API key |\n| `DELETE` | `/api/v1/keys/:id` | Revoke an API key |\n\n**Publish example:**\n\n```bash\ncurl -X POST https://booklet-api.ashwinsathian.com/api/v1/publish \\\n  -H \"Authorization: Bearer bklt_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"raw\": \"# Hello\\n\\nThis is my page.\"}'\n```\n\n`booklet-api.ashwinsathian.com` is a dedicated hostname for the API surface (same app/process as the main site, just scoped; see `docs/OPERATIONS.md`). `booklet.ashwinsathian.com` serves `/api/v1/*` too, so either works.\n\nFull endpoint reference with request/response shapes: [booklet.ashwinsathian.com/api-docs](https://booklet.ashwinsathian.com/api-docs).\n\n---\n\n## MCP Server\n\nA plain Node process (`mcp-server/`) that exposes Booklet's API to AI assistants supporting the [Model Context Protocol](https://modelcontextprotocol.io), run under PM2 alongside the main app, not a Cloudflare Worker (that was the original design, changed when the rest of the app moved off Cloudflare Workers; see `docs/OPERATIONS.md`).\n\n**Endpoint:** `https://booklet-mcp.ashwinsathian.com/mcp`\n**Auth:** `Authorization: Bearer <bklt_...>` header (same API keys as the REST API)\n**Tools:** `publish_page`, `update_page`, `get_page`, `list_pages`, `delete_page`\n**Resources:** published pages are also exposed as browsable/readable MCP resources (`booklet://pages/:id`)\n**Prompts:** five pre-built document templates the assistant can fill in and publish directly — `incident_report`, `adr` (Architecture Decision Record), `release_notes`, `rfc`, and `runbook`\n\nPoint any MCP-compatible client at the endpoint above with your API key in the `Authorization` header. [booklet.ashwinsathian.com/mcp-setup](https://booklet.ashwinsathian.com/mcp-setup) has copy-paste config for Claude Desktop, Claude.ai, Cursor, Windsurf, VS Code, and Zed.\n\nTo run the server itself locally:\n\n```bash\ncd mcp-server && npm run dev\n```\n\n---\n\n## Tech stack\n\n| Layer | Technology |\n|-------|-----------|\n| Framework | Next.js 16 (App Router) |\n| Language | TypeScript 5 (strict) |\n| Styling | Tailwind CSS v4 |\n| Auth | In-house (email + password, argon2id, DB-backed sessions) |\n| Database | Self-hosted MongoDB (pages, users, API keys, webhooks, rendered documents) |\n| Deployment | PM2 process on a Mac behind a Cloudflare Tunnel (Cloudflare Workers/OpenNext was built, shipped, then deliberately rolled back 2026-05-25; see `docs/OPERATIONS.md`) |\n| Markdown | unified + remark-parse + remark-gfm + remark-math |\n| Math | KaTeX |\n| Diagrams | Mermaid |\n| Analytics | Google Analytics 4 |\n\n---\n\n## Local development\n\n### Prerequisites\n\n- Node.js 20+\n- MongoDB connection string (a local `mongod`, or any self-hosted/managed instance)\n\n### Install & run\n\n```bash\nnpm install\nnpm run dev        # Next.js dev server at http://localhost:3000\n```\n\n### Environment variables\n\nCreate `.env.local`:\n\n```env\nNEXT_PUBLIC_SITE_URL=http://localhost:3000\nNEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX\nMONGODB_URI=mongodb://localhost:27017/booklet\n\n# Required: dedicated secret that signs/verifies team-invite JWT tokens.\n# Must be its own random value; there is no fallback, and invite creation\n# and joining fail closed if this is unset. Generate with: openssl rand -base64 32\nINVITE_JWT_SECRET=<random-secret>\n```\n\nSee `.env.example` for the full list of required secrets (session auth, API keys, page-unlock tokens, etc.). Each documents its own generation command and fail-closed behavior.\n\n### Deploy\n\n```bash\nnpm run deploy     # rebuilds and restarts the PM2-managed app + MCP server (scripts/redeploy.sh)\n```\n\n---\n\n## Project structure\n\n```\nsrc/\n  app/\n    app/            # Editor (client)\n    p/[id]/         # Share page + embed\n    my-pages/       # Dashboard: pages, API keys, webhooks, collections\n    api/v1/         # REST API\n    explore/        # Public page directory\n    templates/      # Template landing pages\n  components/\n    blocks/         # BlockRenderer + InlineRenderer (custom AST renderer)\n    share/          # TOC, export, embed, reading progress, analytics beacon\n    ui/             # Design system components\n  lib/\n    blocks.ts       # Block/Inline type definitions\n    parse.ts        # Markdown → Block[] (unified pipeline)\n    db/             # MongoDB helpers\n    storage.ts      # Document content storage (MongoDB)\n    quota.ts        # Feature flags\n    frontmatter.ts  # YAML frontmatter parser (js-yaml)\npackages/           # npm workspaces; one root lockfile covers all of these\n  shared/           # booklet-api-client: shared /api/v1 schemas + client\n  cli/              # booklet-cli npm package\n  vscode/           # VS Code extension: publish from editor\nmcp-server/         # MCP server (plain Node process, run under PM2)\n.github/\n  workflows/        # ci.yml, publish-cli.yml, publish-shared.yml, publish-vscode.yml\n  examples/         # publish-to-booklet.yml, use in your own repo\n```\n\n---\n\n## GitHub Actions\n\n### CI\n\nEvery push/PR to `main` runs lint, typecheck (root app + each workspace package), a production build, and the unit test suite against a real MongoDB service container. See [.github/workflows/ci.yml](.github/workflows/ci.yml).\n\n### Auto-publish to npm\n\nPush to `main` with a bumped version in `packages/cli/package.json` or `packages/shared/package.json` → automatically publishes `booklet-cli` or `booklet-api-client` to npm.\n\nRequired secret: `NPM_TOKEN` (Granular Access Token with publish + 2FA bypass).\n\n### Publish docs to Booklet from your repo\n\nTwo ways: the [`AshwinSathian/publish-to-booklet`](https://github.com/AshwinSathian/publish-to-booklet) GitHub Action, or `booklet-cli` via `npx`. See [.github/examples/publish-to-booklet.yml](.github/examples/publish-to-booklet.yml) for both — copy it into your own repo's `.github/workflows/`, add a `BOOKLET_API_KEY` secret, and it publishes on every release.\n",
  "bytes": 10399,
  "sha": "53b03fed536195bc8baaa64e86101f79c7195847ae5689125dd364200b0a1135",
  "repo_slug": "ashwinsathian/booklet",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ashwinsathian_booklet_99e0f541/readme"
}