Compare commits

..

320 Commits

Author SHA1 Message Date
Nolann Biron 1cfc0c1f99 changeset 2026-08-14 14:32:43 +02:00
Nolann Biron 6ca03e53b4 Attribute markdown and ask events to their space
`page_markdown_request` and the `ask_question` the middleware emits for `?ask=`
carried only a displayContext, so they were stored with an empty spaceId and an
unparseable siteSpaceId. Any space- or section-scoped query dropped them, and the
markdown traffic of a space read as zero.

Reuse the location the middleware already builds, as `rss_request` does. The
llms branches keep theirs: llms.txt spans every section and site-space, so a
single spaceId would attribute a site-wide document to one of them.

`ask_question` also gains the goal, which was parsed off the query string to be
encoded in the rewrite and then dropped from the event.

The pageId the TODO asked for is not in the URL, and resolving it in the
middleware costs a request per document served; it is left to the API to return
alongside the space.
2026-08-14 14:32:36 +02:00
Nolann B. 0f994016f4 Update OpenAPI customer test URL (#4498) 2026-08-13 18:43:33 +02:00
Nolann B. 419094b79d Stop every DOM change from restyling the whole document (#4492) 2026-08-13 17:18:48 +02:00
Greg Bergé 95d23775ce Migrate repository to Oxlint and Oxfmt (#4497) 2026-08-13 13:18:42 +00:00
spastorelli aa98859560 Detect and pass visitor type for site resolution (#4490) 2026-08-13 14:33:10 +02:00
Tomek ea19801cfa feat: add greeting customization to AI chat (#4483) 2026-08-13 11:17:26 +00:00
Peter White 13059b843c Fix Docs Embed being stuck on the Search tab (RND-12435) (#4496) 2026-08-13 06:57:13 +00:00
Johan Preynat 3db14ad950 Fix search result links for page matches (RND-11916) (#4488) 2026-08-12 17:43:57 +02:00
Nolann B. 5fac9e37ee Move the OpenAPI package from react-aria to Base UI (#4473) 2026-08-12 14:53:09 +02:00
Nolann B. 1424c566a0 Load the OpenAPI renderer only on pages that use it (#4472) 2026-08-12 14:53:09 +02:00
conico974 65f99eafe5 Reduce bundle size on the server (#4464) 2026-08-12 13:22:51 +02:00
Tomek 7594a334d8 Show image thumbnails for file attachments (#4486)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-11 13:09:16 +02:00
conico974 827e4f9856 Fix variant switcher URL for non-default variants (#4487) 2026-08-11 13:09:14 +02:00
Peter White a9a1a609c5 Fix sticky search results when switching the search filter RND-12265 (#4485) 2026-08-11 10:15:36 +02:00
conico974 61405a3036 feat: add CSS browser compatibility check for pull requests (#4478) 2026-08-07 15:44:52 +02:00
conico974 634a24ff03 Fix text visibility issues on pages with background covers in Firefox and iOS Safari (#4477) 2026-08-07 12:46:26 +02:00
Nolann B. 2ccd43ee5e Lazy-load the Mermaid code block (#4468) 2026-08-06 08:59:03 +02:00
Nolann B. cd506e3f79 Split the Shiki highlighter from the plain token helpers (#4467) 2026-08-06 08:59:02 +02:00
Brett Jephson a6644074cb Fix: select no longer stored in url (#4466)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 11:59:56 +01:00
conico974 4be043d96e Add support for visitor token revalidation without redirection (#4463) 2026-08-05 09:50:26 +02:00
Brett Jephson 673f4b6076 RND-11832: button with select slug action (#4462) 2026-08-04 14:12:13 +01:00
Brett Jephson d0a63bab91 Tab - reinstate scroll hash (#4458)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 14:42:30 +02:00
conico974 ca9a1dd396 Block crawler from using ask endpoint (#4457) 2026-08-03 11:47:17 +02:00
claude[bot] 996d7ec021 Scroll to in-page heading even when the URL hash is unchanged (RND-12290) (#4454)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Tomek Gargula <tomasz@gitbook.com>
2026-07-31 10:36:37 +02:00
Brett Jephson f9ad9b5356 RND-11830: select store URL param (#4439)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 16:05:36 +01:00
Nolann B. 332089eca9 Don't forward cookies through the OpenAPI Scalar proxy (#4451) 2026-07-30 10:06:17 +02:00
Zeno Kapitein 6ac4cf4b76 Align card and column breakpoints (#4449) 2026-07-29 12:13:25 +00:00
Zeno Kapitein 5c74eef602 Make the table search empty state more prominent (#4418)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 16:13:02 +02:00
Zeno Kapitein 1ee1853995 Add an assistant tool to rate its own previous response (#4425)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 16:10:41 +02:00
Tomek fa9c9b38b7 Force software rendering in Playwright for consistent images (#4444)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-27 14:01:55 +00:00
conico974 b4d9c6b95e Fix BUILD_VERSION assignment to ensure fallback to current timestamp (#4445) 2026-07-27 15:47:54 +02:00
Tomek 588964279e Remove search value from URL on unfocus (#4443)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 10:46:02 +00:00
Nolann B. a80d41200a Run the OpenAPI Scalar proxy on GitBook's origin (#4440) 2026-07-24 18:36:27 +02:00
Nolann B. ccb9d7bda4 Submit sendFeedback MCP tool findings through submitSiteAgentFeedback (#4437) 2026-07-24 10:34:50 +02:00
Nolann B. 14562e9e5b Serve noindex on internal search/assistant URLs (?q= / ?ask=) (#4433) 2026-07-23 15:00:13 +02:00
spastorelli 580d186ddd Clean up old forward resume authorize to sites oauth server (#4436) 2026-07-23 14:08:56 +02:00
Tomek 038008c853 Fix heading anchor links on touch devices (#4435)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-23 11:56:21 +00:00
conico974 8c890522ed Patch next for dev, and fix issue in dev with inline icon (#4432) 2026-07-22 16:00:36 +02:00
conico974 e9558a6df7 Revert "Simplify search query handling to in-memory storage only (#4419)" (#4431) 2026-07-22 14:53:29 +02:00
Brett Jephson b5f3c1416a RND-11857: Prompt block with default expanded options (#4429) 2026-07-22 13:33:06 +01:00
conico974 b9d383bed3 Bump dependencies for @opennextjs/aws, @opennextjs/cloudflare, and next to latest versions (#4430) 2026-07-22 11:01:17 +02:00
spastorelli b6e7f2d2db Render the Site OAuth consent screen from the server's signed marker (#4428) 2026-07-22 09:59:30 +02:00
Tomek 94ef1769ec Simplify search query handling to in-memory storage only (#4419)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-22 07:54:50 +00:00
Zeno Kapitein ae9367dafe Only show the assistant activity heading when there's activity to reveal (#4424)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 14:47:58 +02:00
Zeno Kapitein cef18701be Add an assistant tool to submit page feedback (#4408)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 13:25:14 +02:00
Zeno Kapitein bf674a47d9 Add supporting context to AI tool confirmation dialogs (#4422)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 11:45:51 +02:00
conico974 1eb763f9c5 Implement API token cookie handling with chunking support (#4421) 2026-07-20 15:38:07 +02:00
Nolann B. db176ba0ea Add "On this page" on models page (#4417) 2026-07-20 13:17:02 +02:00
Nolann B. 03bbacf319 Add missing link reference to OpenAPI models (#4416) 2026-07-20 12:53:28 +02:00
Tomek 484cc11627 Fix ScrollContainer scroll buttons not reflecting overflow immediately (#4414)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-20 08:47:04 +00:00
spastorelli 0dee4155a2 Add consent flow env vars to next config (#4413) 2026-07-17 15:16:46 +00:00
spastorelli 4d7c01587e Add Sites OAuth consent screen (#4405) 2026-07-17 15:58:27 +02:00
Greg Bergé 6083a88845 Expose the current page context to integration block webframes (#4411)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 12:06:38 +02:00
Nolann B. bf6a7af72b Defer search index loading until search is opened (#4407) 2026-07-16 21:53:24 +02:00
Utku Ufuk 703e654a37 Split the default-scope site search into two parallel API requests (#4395) 2026-07-16 15:23:30 +03:00
conico974 1b571aeaa9 Fix scroll behavior for navigation (#4406) 2026-07-16 14:21:01 +02:00
Zeno Kapitein c41cf9c12a Add cover image background mode and mask (#4213)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:02:53 +02:00
Zeno Kapitein 3d376845d7 Add a carousel layout for cards blocks (#4393)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 16:17:00 +02:00
Nolann B. bcd4d4e980 Remove MCP test that recorded real feedback in production (#4399) 2026-07-15 10:42:20 +02:00
Addison 88b1919a45 Add centered GitBook logo to README (#4401)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 17:31:04 +09:00
Steven H cf94386c16 fix an issue where certain keywords could cause an exception when rendering emojis (#4397) 2026-07-14 19:08:09 +00:00
Zeno Kapitein e77bf32d51 Update customer e2e test URL after redirect (#4398)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 18:24:14 +00:00
Zeno Kapitein a69a307de2 Take a near-neutral extreme tint as the exact site background (#4392) 2026-07-13 20:37:08 +02:00
Zeno Kapitein 39156ee9c3 Support button sizes in the button block (#4394)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 20:03:52 +02:00
spastorelli 47ac3e2c81 Only advertise OAuth PRM doc for the auth MCP endpoint on non-VA sites (#4387) 2026-07-10 15:24:33 +02:00
Zeno Kapitein e73b182925 Declare embed standalone bundle as a Turbo build output (RND-11876) (#4386)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-10 13:51:48 +02:00
claude[bot] a9a52fee72 RND-11356: remove redundant GBO best-section re-selection (#4375)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-07-10 13:25:26 +02:00
Greg Bergé cb92754575 Add a navigate action to integration block webframes (#4362)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 11:24:33 +02:00
Zeno Kapitein 49d35aa026 Let visitors type a follow-up while the Assistant is answering (RND-11789) (#4377)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-09 21:00:01 +02:00
Nolann B. 98b2df42ef Add sendFeedback MCP tool for reporting documentation findings (#4384)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-09 15:17:32 +02:00
Zeno Kapitein 6cf4278f14 Only show "Back to [space]" for table-of-contents cross-space links (#4381)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 14:32:11 +02:00
Zeno Kapitein 86c44299eb docs(agents): discourage multi-line block comments (#4382)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-09 14:16:26 +02:00
claude[bot] 89c4a0f808 feat(mcp): add askQuestion tool to the site MCP server (#4372)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-07-09 13:11:05 +02:00
Nolann B. 8e9a49de1a Separate prompt block actions (#4379) 2026-07-08 16:11:26 +02:00
Zeno Kapitein 4e9071d1b5 Fix docs embed navigateToPage for cross-space/section deep links (#4374)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 11:02:49 +02:00
Nolann B. 597fe34d3b Sync responses selector with the Responses collapsibles (#4376) 2026-07-08 09:08:21 +02:00
claude[bot] e14609cb3e fix(theme): resolve system theme before first paint to avoid dark/light flash (RND-11643) (#4373)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-07 20:10:02 +02:00
Zeno Kapitein 57f3077006 Keep the page outline and Ask button in view while scrolling API reference pages (#4371)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:10:55 +02:00
conico974 e24632c80b Integrate GitBook image resizing service and remove cdn-cgi mode (#4285) 2026-07-07 16:21:32 +02:00
Zeno Kapitein ad3399b42e Refine the per-paragraph ask button (shorter tooltip, hide inside cards) (#4365)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 19:27:04 +02:00
Brett Jephson f3408ed495 A11y fix: table structure (#4368) 2026-07-06 16:58:23 +01:00
Brett Jephson 8676ad19e2 RND-11788: hide unlabelled button from screen readers (#4369) 2026-07-06 16:58:02 +01:00
Samy Pessé 3a31100efe Version Packages (#4335)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-06 12:52:44 +00:00
Greg Bergé 3fedaaa08c Install eval-estree-expression from npm instead of a GitHub commit (#4367)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 12:31:54 +00:00
Nolann B. bcea23e886 Handle nullable expressed via anyOf/oneOf with a null member (#4366) 2026-07-06 12:33:02 +02:00
Zeno Kapitein fdea8f1c47 Show section, variant & section groups in page breadcrumbs (#4357)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 11:49:47 +02:00
Zeno Kapitein 139b897521 Improve language selector on mobile (#4361) 2026-07-06 11:03:39 +02:00
Greg Bergé 37c2dd8819 Fix flaky customer screenshots caused by the cookie banner (#4363)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 22:06:20 +02:00
Zeno Kapitein 62ca6d3ce5 Show a "Back to [space]" shortcut when a link leads to another space (#4358)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 12:36:07 +02:00
Nolann B. 6102413d6b Reuse shared AI mode helpers across AI actions and UI (#4355) 2026-07-02 23:19:07 +02:00
Zeno Kapitein eaef259a80 Refresh e2e customer list (#4360)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 19:34:09 +02:00
Zeno Kapitein 578a3a829b Fix section tab dropdowns clipping their contents during animation (#4356)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 12:06:41 +00:00
Zeno Kapitein c923c654bd Fix centered paragraphs shifting left with the paragraph ask button (#4354)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 12:19:24 +02:00
Nolann B. 65fd3cc101 Gate AI features server-actions (#4353) 2026-07-02 11:37:03 +02:00
Zeno Kapitein bb30db105d Add a margin button to ask the assistant about a paragraph (#4328) 2026-07-02 08:34:49 +02:00
Nolann B. 6146f8e183 Reduce oversized searchDocumentation MCP responses (#4352) 2026-07-01 18:00:02 +02:00
Nolann B. 7e55cd5e4c Add "Available in MCP" badge for OpenAPI operations (#4350) 2026-07-01 17:38:04 +02:00
conico974 cb2dfa76af Keep first 3 remote results pinned at the top (#4349) 2026-06-30 13:47:04 +02:00
Viktor Renkema 77efd449ae Allow quickly viewing which pages have changed in a CR/revision (#4348) 2026-06-30 12:49:31 +02:00
Zeno Kapitein af259fbe86 Scrap recommended questions from Search e2e test (#4351) 2026-06-30 12:29:21 +02:00
conico974 2b31b0213c Refactor error handling and remove unused caching logic (#4345) 2026-06-30 08:16:23 +02:00
Nolann B. f60afe1b25 Add missing MCP annotations (#4347) 2026-06-29 10:15:57 +02:00
Nolann B. b7c3b847e8 Prevent insights tracking failures from breaking MCP tool requests (#4346) 2026-06-27 09:31:20 +02:00
Zeno Kapitein 2fa65e6949 Support per-table search override (#4340)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 10:46:47 +02:00
Nolann B. c76b4fdccc Fix OpenAPI sticky preview column overflowing onto the next operation (#4341) 2026-06-25 15:10:26 +02:00
Zeno Kapitein 9f651339f0 Redesign the 404 page with related-page suggestions and a search input (#4338)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 12:30:42 +02:00
Zeno Kapitein 5ce3b1e578 Turn off search on cards (for now) (#4339) 2026-06-24 11:26:14 +02:00
Nolann B. d172684b88 Some small OpenAPI design tweaks (#4337) 2026-06-23 21:20:28 +02:00
conico974 937c8b8eb2 Remove 'remote' from cache usage in specific functions (#4312) 2026-06-23 17:59:43 +02:00
Zeno Kapitein 36dbdb48cc Support agent goal query param for markdownAsk (#4324)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:47:51 +02:00
Zeno Kapitein 2dc76a2c3c Fix empty grouped section dropdown in embedded sites (#4334)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 09:47:15 +02:00
Samy Pessé 0edc378c57 Version Packages (#4306)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-23 00:10:23 +02:00
Zeno Kapitein 2eb313194a Remove old PageAction checks (#4333) 2026-06-22 17:12:35 +02:00
Brett Jephson 882dfcda83 Tidy relating to prompt (#4332) 2026-06-22 15:48:58 +02:00
Brett Jephson 3ff88ba22f Adds the prompt block (#4329) 2026-06-22 11:53:25 +01:00
Nolann B. 51bd768042 Make the AI Assistant panel resizable (#4330) 2026-06-20 21:41:59 +02:00
spastorelli daadd91eba Fix NextLink prefetch side effect on unsigned claims persistance (#4325) 2026-06-19 11:39:12 +02:00
Nolann B. f4469b2df3 Support OpenAPI one-operation-per-page mode (#4314) 2026-06-19 10:35:09 +02:00
Nolann B. 91b325ca08 Add AI chat reference button on text selection (#4326) 2026-06-19 10:18:07 +02:00
Nolann B. 1616028426 Align code block action buttons vertically with the block (#4327) 2026-06-19 10:03:37 +02:00
Nolann B. 6c15d8314a Update OpenAPI border radius (#4323) 2026-06-18 23:25:19 +02:00
Zeno Kapitein 6c967c9bcc Add search and filters to table blocks (#4322)
Co-authored-by: utkuufuk <utkuufuk@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 10:41:40 +02:00
Johan Preynat c44d822fe1 Trust cookieless integration content host for WebFrames (#4321)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 18:08:25 +02:00
Zeno Kapitein af3cda1c53 Fix wide content overflowing hint blocks (#4320)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:32:53 +02:00
Tomek a0ad403a91 Stabilize Playwright Chrome text rendering across platforms (#4318) 2026-06-17 09:21:16 +00:00
Zeno Kapitein 0ca49523a2 Remove external link button from link tooltip hover card (#4316)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:52:02 +02:00
Zeno Kapitein 76550415ac Fix ⌘-C opening the Assistant on Dvorak keyboard layouts (#4311)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 10:51:20 +02:00
Nolann B. 509389c7e5 Update @gitbook/api to latest version (#4315) 2026-06-16 14:30:10 +02:00
Nolann B. 88b94b5d36 Handle circular oneOf with discriminator and allOf in OpenAPI schemas (#4070) 2026-06-16 13:34:17 +02:00
Greg Bergé 251630c49f Use page actions items list for ordering and default action (#4302)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 15:19:20 +02:00
Zeno Kapitein acf2719d06 Stabilize AI Assistant visual regression tests (#4305)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 14:19:56 +02:00
Zeno Kapitein ddba8031ec Reference the current page when opening the Assistant (#4308)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:35:15 +02:00
Zeno Kapitein 72a1596ae8 Fix AI assistant forms overflowing the chat panel (#4309)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 17:22:57 +02:00
Nolann B. 5b36c59061 Fix PDF export failing on API Reference pages (#4307) 2026-06-12 13:43:38 +00:00
Zeno Kapitein 77c717c251 Group an assistant turn's tool calls into a single expandable (#4303)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 15:26:27 +02:00
Samy Pessé 60310b4c83 Version Packages (#4278)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-12 14:55:55 +02:00
conico974 6eabaecbad Implement getVariables method for expression evaluation (#4304) 2026-06-12 14:26:17 +02:00
Zeno Kapitein 423bbd06d9 Create Claude launch.json (#4301) 2026-06-12 12:52:24 +02:00
conico974 36f19c8018 Add LLMs directive for documentation links (#4300) 2026-06-12 12:09:25 +02:00
Zeno Kapitein 2ecbdd8f62 add navigateToPage assistant tool (#4299)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 11:57:55 +02:00
Nolann B. c727cc8b9d Fix inflated visitor counts from unstable anonymous visitorId (#4293) 2026-06-12 00:52:59 +02:00
Zeno Kapitein 2c729d461e Rework Assistant “based on your context” popover wording (#4298) 2026-06-11 22:19:32 +02:00
Tomek d83ea4ce14 chore(a11y): increase width of the collapse/expand arrow in menu items (#4297) 2026-06-11 14:02:38 +00:00
spastorelli bac8608e78 Add support for passing visitor claims to integration webframes (#4291) 2026-06-11 09:52:26 +02:00
Greg Bergé 7a1236a3a5 Fix search results linking to page instead of section anchor (#4295)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:23:59 +00:00
Zeno Kapitein ed80bd9e7a Add recent search (and chat) queries (#4225) 2026-06-10 18:45:07 +02:00
Zeno Kapitein 7036b67307 Fix window.GitBook.registerAssistant is being called twice (#4296) 2026-06-10 15:54:38 +00:00
Zeno Kapitein 6bd522b322 Update site section tabs with better column calc and animations (#4252) 2026-06-10 17:35:38 +02:00
Zeno Kapitein 74fc3f74d7 Fix: Submit feedback confirmation does not auto close (#4240) 2026-06-10 17:35:29 +02:00
conico974 3e384c679e Add suggested follow-up questions to AI answer markdown response (#4284) 2026-06-10 17:29:08 +02:00
Greg Bergé f1fa1061db Upgrade bun.lock (#4294) 2026-06-10 17:09:10 +02:00
Addison 4f754a73a3 Add information about GitBook to page markdown (#4292) 2026-06-09 19:53:07 +02:00
conico974 62d6d28888 Fix context handling in resolveContentRef for page resolution issues (#4290) 2026-06-09 15:10:03 +02:00
conico974 fd73a9912b Fix caching strategy for icon fetching (#4289) 2026-06-08 13:46:32 +02:00
Johan Preynat 595435ac4a Ensure local search matches remote filter when there are no sections (#4287) 2026-06-04 19:14:54 +02:00
Addison aa9d41a1b6 Update footer for llms (#4286) 2026-06-04 16:19:02 +02:00
conico974 30089b404c Adjust caching strategy for icon fetching based on runtime environment (#4283)
Co-authored-by: Steven H <steven@gitbook.io>
2026-06-02 12:00:38 +02:00
Nolann B. 92b68560e1 Add Ask AI in CodeBlock (#4220) 2026-06-02 00:40:54 +02:00
Nolann B. f158064817 Match OpenAPI operation paths regardless of trailing slash (#4282) 2026-05-29 12:16:24 +02:00
Greg Bergé 2885a137f8 Fix heading anchor alignment with heading text and translate its accessibility label (#4281) 2026-05-29 09:38:47 +02:00
spastorelli 0ffb74a6f8 Fix issue where MCP POST requests with expired tokens returns 307 instead of 401 (#4280) 2026-05-28 16:35:12 +02:00
Nolann B. b116a0a2a4 Fix OpenAPI code sample box not scrolling on initial load (#4279) 2026-05-28 12:04:32 +02:00
Greg Bergé b9bb535d52 Full screen view for Mermaid diagrams (#4275)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 09:17:21 +02:00
Samy Pessé 257ca09a5e Version Packages (#4263)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tomek Gargula <tomasz@gitbook.com>
2026-05-28 07:12:45 +00:00
Tomek f405fffa06 feat: add support for icons in tabs (#4277) 2026-05-27 15:22:25 +00:00
Tomek 16a54b6bb9 Improve accessibility in published docs (#4276) 2026-05-27 12:40:25 +00:00
Greg Bergé 526a928420 Fix annotation hover interaction when card has a target link (#4274) 2026-05-27 12:02:20 +02:00
conico974 c201abab5f Don't display agents instructions for page action (#4272) 2026-05-27 10:41:53 +02:00
Greg Bergé 3697dfefed Add page actions layout visibility (#4270) 2026-05-22 12:37:37 +02:00
spastorelli 287203d197 Show MCP page actions for VA & adaptive sites (#4268) 2026-05-22 08:47:13 +02:00
conico974 0b38f6c93b Update regional cache settings (#4267) 2026-05-20 14:25:59 +02:00
conico974 8ce64f4862 Remove remote from use cache (#4259) 2026-05-20 14:12:51 +02:00
Greg Bergé 127ef54b0f Add updates tag filtering (#4265) 2026-05-20 12:42:51 +02:00
Greg Bergé 67f31aaa7a Always allow LLMs to read the content (#4264) 2026-05-20 09:39:35 +02:00
Greg Bergé 51fef84d39 Fix logo size variations (#4266) 2026-05-19 20:55:45 +02:00
Greg Bergé 0c577a00de Allow CORS for the same root domain (#4262)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:41:07 +02:00
Samy Pessé 8b6dc6dbbd Version Packages (#4255)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-05-19 13:24:41 +02:00
Antoine Coutellier 2e7ba40a25 feat: support integrations inside reusable content blocks (#4250) 2026-05-19 11:29:02 +02:00
Greg Bergé b70b8fd2ca Fix llms.txt not including all content (#4260) 2026-05-18 21:33:07 +02:00
Greg Bergé a9ba996953 Fix left/right aligment of images with caption (#4261) 2026-05-18 21:32:22 +02:00
Brett Jephson 47c8ccba6f Fix: clipping of FA icons (#4257) 2026-05-18 15:09:41 +01:00
conico974 e9842feeef Bump Next.js to version 16.2.6 and fix oom on dev (#4258) 2026-05-18 11:12:47 +02:00
Greg Bergé f4b4fe15c1 Add missing translations (#4254) 2026-05-16 07:16:49 +02:00
Greg Bergé 06b9fd542a Do not add target blank on mailto (#4256) 2026-05-15 20:43:39 +02:00
Taran Vohra 76077f9f6d Fix publish workflow (#4245) 2026-05-15 10:51:43 +02:00
Greg Bergé 7b65f7c0d5 Update iframely embed URL (#4253) 2026-05-14 19:04:34 +02:00
Greg Bergé 37a9453917 Allow to copy in embed (#4251) 2026-05-13 04:49:14 +00:00
Viktor Renkema d994875bea Support code block // [!code -- or ++] notation (#4248) 2026-05-12 15:39:21 +02:00
Claire Chabas a9b5521f3a Fix anchor URL resolution (#4249) 2026-05-11 16:02:20 +02:00
Greg Bergé 91fadb08ed Fix turbo burning Mac CPU (#4247) 2026-05-11 11:36:23 +00:00
Samy Pessé b55605f25e Version Packages (#4199)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-05-08 13:00:03 +00:00
Addison 6ba5e54d19 add isComposing to search (#4244) 2026-05-08 18:47:20 +09:00
Samy Pessé 56aeb19e49 Fix events tracked from the middleware missing some properties (#4242) 2026-05-07 23:15:34 +02:00
conico974 ebab8188f6 Bump @opennextjs/aws and @opennextjs/cloudflare versions (#4243) 2026-05-07 17:01:05 +02:00
Zeno Kapitein 8064c95267 Fix publish workflow npm upgrade in Bun repo (#4239) 2026-05-07 09:36:14 +02:00
conico974 2cef2e02c8 Bump Next.js version to 16.2.5 (#4241) 2026-05-06 22:02:10 +02:00
conico974 8bfced2e0d Add negotiator for markdown acceptance in middleware (#4238)
Co-authored-by: Copilot <copilot@github.com>
2026-05-06 14:59:38 +02:00
conico974 61ee4e3637 Add tests for markdown serving based on user agents (#4227) 2026-05-06 13:52:09 +02:00
Greg Bergé 927aa89213 Add "Go to home" button on 404 page (#4236) 2026-05-05 13:12:12 +00:00
Greg Bergé f29d1e2f16 Round images when site customization border style is rounded (#4237) 2026-05-05 14:50:24 +02:00
conico974 3a9efb8aed bust revision page markdown (#4235) 2026-05-05 14:39:34 +02:00
conico974 f71ab8426c Bust page document data cache (#4234) 2026-05-04 16:15:27 +02:00
conico974 a3d1558f99 Disable regional cache for debugging purposes (#4233) 2026-05-04 14:03:29 +02:00
conico974 ca53869e2d Reduce cache TTL for regional cache and log cache debug (#4232) 2026-05-04 13:32:36 +02:00
conico974 33598e665b Add logging for cache retrieval in GitbookIncrementalCache (#4231) 2026-05-04 11:47:47 +02:00
Samy Pessé 9045ba5248 Remove progressive rollout for markdown stable links (#4230) 2026-05-01 21:56:28 +02:00
Rodrigo Castro 7061fc2223 Fix hidden pages in sitemap exports (#4216) 2026-04-30 14:04:37 +01:00
Samy Pessé 0c9e3952b7 Increase rollout of markdown stable links to 50% (#4228) 2026-04-30 11:37:37 +02:00
Samy Pessé 4b78672135 Fix links to other site-spaces / sections in llms.txt (#4222) 2026-04-30 08:43:32 +02:00
conico974 10289e4881 Revert search worker changes and add error handling (#4226)
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 21:59:05 +02:00
conico974 8b6a6df1d6 Move search into a web worker (#4223)
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 18:42:44 +02:00
conico974 83df84ac28 Improve markdown serving logic (#4224)
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 18:28:45 +02:00
Greg Bergé 5e5075a137 Make Mermaid controls shown only on hover (#4221) 2026-04-29 17:13:31 +02:00
Greg Bergé 90c1f68e19 Speed up Mermaid rendering (#4219) 2026-04-29 15:40:24 +02:00
Zeno Kapitein 0e10124626 Adapt max logo height (#4218) 2026-04-28 14:59:45 +02:00
Zeno Kapitein 01e1c2ae6a Add space between ask button and content (#4217) 2026-04-28 14:59:14 +02:00
Zeno Kapitein 65558cfbb1 Redesign search results (#4198)
Co-authored-by: Nicolas Dorseuil <nicolas@gitbook.io>
2026-04-28 14:49:46 +02:00
conico974 10d894ce19 Integrate local search functionality (#4078)
Co-authored-by: Copilot <copilot@github.com>
2026-04-28 14:14:47 +02:00
Samy Pessé d1a2958212 Pass visitor session to streamAskQuestion (#4211) 2026-04-24 21:07:46 +02:00
Viktor Renkema 894b6adc4c Support marks colors for text and background (#4212) 2026-04-24 17:23:10 +02:00
Nolann B. b3b819f8e5 Disable MCP server when MCP page action is off (#4210) 2026-04-23 18:01:43 +02:00
spastorelli 2b98af0cc0 Fix not found pages showing duplicate trademark badges (#4209) 2026-04-23 16:31:40 +01:00
Samy Pessé 54a56ed772 Remove rollout for agent ask (#4208) 2026-04-23 14:48:06 +02:00
Samy Pessé 071627d4f0 Improve the footer for agent to query the docs (#4206) 2026-04-22 22:56:28 +02:00
Samy Pessé 7595706b92 Allow AI agents to ask questions using ?ask= (#4205) 2026-04-22 08:43:57 +02:00
conico974 be080248b1 Block search indexation in deployment configuration (#4203) 2026-04-20 16:22:34 +02:00
Samy Pessé d3d51507e5 Add "Content-Signal" to robots.txt (#4202) 2026-04-20 14:14:59 +02:00
Addison a17ab65a6d Show variants in fully hidden sections (#4201) 2026-04-20 16:41:24 +09:00
Zeno Kapitein e3aca9e4f6 Fix embeddable search links (#4196) 2026-04-18 00:43:07 +02:00
spastorelli 045f603849 Add ~gitbook/auth/logout endpoint in GBO (#4195) 2026-04-16 22:40:56 +02:00
Greg Bergé b2854500a1 Allow to scroll to top of the page (#4194) 2026-04-16 16:20:50 +02:00
Samy Pessé ead88591c2 Version Packages (#4193)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-16 14:19:37 +02:00
Peter White aa1fc246e2 Add support for sticky first column in tables (#4188) 2026-04-16 10:33:15 +00:00
Samy Pessé e792cffeb3 Version Packages (#4178)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-04-15 19:07:34 +02:00
Zeno Kapitein 119e3bc369 Refine Assistant phase UI (#4187) 2026-04-15 18:29:58 +02:00
Greg Bergé 823e7d5c4b Fix tags appearing on top of page even if disabled (#4192) 2026-04-15 18:26:06 +02:00
Claire Chabas f5f659e7fc Display updates blocks headings in page outline (#4167) 2026-04-15 16:20:51 +02:00
Brett Jephson 723e579958 Fix: whitespace of Expandable in Column (#4190) 2026-04-15 14:07:20 +01:00
conico974 f27901c453 Update deployment ID logic for environment-specific prefixes (#4191) 2026-04-15 14:52:44 +02:00
Zeno Kapitein 789c2fab60 Adjust empty TOC logic and layout (#4189) 2026-04-15 14:04:13 +02:00
conico974 3fa727c80b Migrate to Next 16 (#4162) 2026-04-15 13:20:25 +02:00
Zeno Kapitein 88c38fa505 Add Search tab to Docs Embed, refactor search into an embeddable frame (#4185) 2026-04-15 12:09:59 +02:00
Claire Chabas bda9fe2d76 Make ToC groups collapsible and other styles fixes/improvements (#4177) 2026-04-14 19:41:51 +02:00
Nolann B. 2bdade3b57 Fix HTML lang attribute not reflecting language variants (#4186) 2026-04-14 13:14:39 +02:00
Zeno Kapitein 8d2a95b168 Docs Embed: Better support light/dark mode overrides (#4181) 2026-04-14 10:50:05 +02:00
Taran Vohra 68c842bd4c Translations dropdown should show language spaces that best matches the current space title (#4184) 2026-04-14 13:11:55 +05:30
Nolann B. ecb4292551 Fix llms.txt and llms-full.txt language variants filtering (#4179) 2026-04-13 21:53:42 +02:00
Zeno Kapitein 7fd381c0b1 Hide empty sidebar on OpenAPI pages (#4180) 2026-04-13 20:29:57 +02:00
Zeno Kapitein 709964fe3e Rework page layout (#4013) 2026-04-13 14:48:24 +02:00
Samy Pessé afc7a38bef Version Packages (#4163)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-13 14:16:46 +02:00
Greg Bergé bbcfd72a6d Fix toolbar design (#4175) 2026-04-13 11:10:34 +00:00
spastorelli 8242f18b8a Extend gitbook/expr std lib with some additional methods (#4173)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2026-04-13 10:19:52 +00:00
Samy Pessé 4f7fba08df Prepare for step.content to be optional (#4174) 2026-04-13 11:47:21 +02:00
conico974 f17e292ba4 Refactor test setup for improved mock restoration (#4176) 2026-04-13 11:23:54 +02:00
Greg Bergé 6e1074ec4d Reduce search debounce (#4170) 2026-04-09 17:43:14 +02:00
Nolann B. c5e5857623 Exclude language variants from llms.txt and llms-full.txt (#4165) 2026-04-08 14:30:31 +02:00
Nolann B. 11df1fd395 Fix MCP getPage tool returning page not found (#4166) 2026-04-08 14:28:39 +02:00
spastorelli 569d4046be Expose a ~gitbook/mcp/auth endpoint for non-VA adaptive content sites (#4155) 2026-04-07 12:50:39 +02:00
Samy Pessé 50653abd08 Improve AI agent detection and readability by outputting 200 for page not found (#4164) 2026-04-04 12:35:43 +02:00
Greg Bergé 84082225af Respect locale to format date in update block (#4160) 2026-04-03 15:36:12 +00:00
Nolann B. 7d882cef5f Fix HTML lang attribute not reflecting site language variants (#4161) 2026-04-03 17:31:37 +02:00
Zeno Kapitein 126d4b78b6 Improve Assistant form controls, i18n, and UX (#4159) 2026-04-03 09:47:19 +02:00
Nolann B. e8224bad6c Support system as a default theme mode (#4151) 2026-04-01 00:39:34 +02:00
Samy Pessé 6063437513 Version Packages (#4158)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-01 00:22:45 +02:00
Nolann B. ab17ff47b0 Update missing CustomIconName (#4157) 2026-04-01 00:09:06 +02:00
Samy Pessé d97b404c7a Version Packages (#4156)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-31 21:14:44 +02:00
Nolann B. 3c141f0231 Bump fontawesome to 7.2.0 (#4154) 2026-03-31 20:38:12 +02:00
Samy Pessé e3d391e01b Version Packages (#4102)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-31 17:01:13 +02:00
Nolann B. 62cfec874a Setup AGENTS.md and CLAUDE.md (#4147) 2026-03-31 16:38:28 +02:00
Nolann B. ccd21e4943 Update fontawesome-pro to 1.0.23 (#4153) 2026-03-31 16:37:13 +02:00
conico974 696d9d0d01 Update vercel dependency to version 50.37.3 (#4152) 2026-03-31 12:07:00 +02:00
Nolann B. b77c4fc5b9 Add getPage MCP tool (#4148) 2026-03-31 11:01:51 +02:00
Zeno Kapitein 7e1ea48080 Revise AI Chat e2e tests (#4150) 2026-03-30 17:58:35 +02:00
Nolann B. b5d6f2e908 Fix translation quality across 11 locales (#4146) 2026-03-30 13:17:03 +02:00
Nolann B. 832b44f0ac Use site-level path for MCP URL instead of space-level path (#4149) 2026-03-30 13:09:25 +02:00
Nolann B. 4909044831 Add Claude Code and Codex connect actions (#4145) 2026-03-30 09:55:45 +02:00
Nolann B. 4ed84c209a Localize announcement message (#4144) 2026-03-30 09:47:17 +02:00
Nolann B. ca01888fe2 Localize footer links title (#4143) 2026-03-30 09:46:37 +02:00
Nolann B. 6855c05781 Localize header link titles (#4142) 2026-03-30 09:46:20 +02:00
Nolann B. ab867eb69c Add top-level locale field to GitBookBaseContext (#4140) 2026-03-27 18:16:19 +01:00
Samy Pessé deabce98ae Sort results by score to mix records and pages (#4077) 2026-03-27 15:25:09 +01:00
Samy Pessé f884477a65 Associate questions asked in the embeddable assistant to the proper channel (#4141) 2026-03-27 15:07:42 +01:00
Nolann B. c56b569a05 Support expand-all options for OpenAPI (#4116) 2026-03-25 23:53:51 +01:00
Peter White 1ba412ff6c Fix OneTrust issue for customer E2E test (#4137) 2026-03-25 17:37:43 +01:00
Peter White 7c2823cd26 Fix full width header alignment (#4138) 2026-03-25 17:01:22 +01:00
Peter White 16bfafe32b Add option to sticky header row in tables (#4134) 2026-03-25 14:04:35 +01:00
Zeno Kapitein da648cabd8 Fix regressions in Assistant UX (#4136) 2026-03-24 18:49:44 +01:00
spastorelli a36e437580 Add login button to not found page for adaptive content site with configured fallback/login URL (#4133) 2026-03-23 16:25:03 +01:00
Samy Pessé d5dd5e7ba1 Include site.id in UTM utm_content for Trademark link (#4135) 2026-03-23 14:08:29 +01:00
Nolann B. c4a2604b4d Fix PDF export crash when page contains an OpenAPI block (#4128) 2026-03-20 11:15:19 +01:00
Nolann B. 7f4e644733 Small OpenAPI improvements (#4131) 2026-03-20 11:15:03 +01:00
Nolann B. 5d3f78b112 Fix flaky internal tests (#4132) 2026-03-20 10:50:20 +01:00
Nolann B. 60bcf43304 Fix allOf merging for annotation-only schemas (#4118) 2026-03-20 10:03:56 +01:00
Samy Pessé b40465e7b7 Fix normalization of URL causing invalid redirections. (#4130) 2026-03-19 19:27:00 +01:00
Samy Pessé 3151864f81 Track events from the proper server URL (#4129) 2026-03-19 18:55:26 +01:00
Greg Bergé 80803c92f2 Fix code block styling (#4127) 2026-03-19 16:07:03 +01:00
Samy Pessé 31e77d4e17 Track events for markdown page views, llms.txt, RSS, MCP connections (#4110) 2026-03-18 17:37:58 +01:00
Taran Vohra 8e5a2aa6e6 pan and zoom controls for mermaid block (#4125) 2026-03-18 20:32:16 +05:30
Taran Vohra fe6f6420e3 Cleanup and remove old preview format using /url/preview (#4117) 2026-03-18 17:50:12 +05:30
Nolann B. aff6285eb9 Deep-merge schema properties in OpenAPISchema (#4124) 2026-03-18 13:09:04 +01:00
conico974 5f132bc979 Add try-catch for error handling and improve logging (#4123) 2026-03-17 17:42:34 +01:00
Nolann B. 4297de3571 Add localizedTitle support for site title (#4115) 2026-03-17 12:17:41 +01:00
Nolann B. 6455f2e3ff Fix parent schema metadata lost during oneOf/anyOf allOf flattening (#4119) 2026-03-17 10:31:12 +01:00
Nolann B. dee52fa80a Fix schema title display stripping spaces (#4120) 2026-03-17 10:27:56 +01:00
spastorelli 4ac29817a2 Expose a ~gitbook/auth/login URL to handle redirection to upstream auth with current location passed (#4113) 2026-03-16 16:00:31 +01:00
spastorelli f09ca60930 Fix crash for PDF route when the page include an Ask AI button (#4121) 2026-03-16 15:41:16 +01:00
Greg Bergé a7c0f7251b Allow <br> in OpenAPI descriptions (#4112) 2026-03-13 11:51:50 +01:00
Greg Bergé efc6117665 Fix code block layout (#4108) 2026-03-13 10:24:18 +01:00
Taran Vohra 6c613d0df3 Fix auth redirects with the new preview URL (#4111) 2026-03-13 13:52:09 +05:30
Taran Vohra 45d32b5084 Site Preview URLs (#4096) 2026-03-12 20:27:59 +05:30
conico974 0f62a629b4 Handle unexpected errors in getExposableError (#4109) 2026-03-12 15:54:01 +01:00
Peter White 7ab63516bd Import site redirect patterns from @gitbook/api (#4107) 2026-03-12 10:06:33 +00:00
Nolann B. 9dd2db6678 Support x-gitbook-token-placeholder as TryIt prefill fallback for basic auth (#4105) 2026-03-11 20:35:13 +01:00
Nolann B. 4787b7e910 Use localized titles/descriptions for site entities (#4106) 2026-03-11 18:25:18 +01:00
Taran Vohra be02e33ada Fix an issue where source path containing special characters were not getting resolved to a site redirect (#4104) 2026-03-11 21:33:42 +05:30
Zeno Kapitein 3ce7e529f7 Fix Variant dropdown not showing in GitBook embed (#4100) 2026-03-11 13:57:13 +01:00
Samy Pessé 0f162a45a7 Version Packages (#4082)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Zeno Kapitein <zeno@gitbook.io>
2026-03-11 12:56:28 +00:00
Steven H 02ba0ef601 Disable Workers Observability (#4099) 2026-03-11 11:02:44 +00:00
Nolann B. bdc6cd9aba Use OpenAPI publicURL as Scalar specUrl (#4093) 2026-03-11 11:21:14 +01:00
834 changed files with 39324 additions and 10265 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"@gitbook/embed": minor
---
Support `assistantName` property to override Assistant name
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Scroll to an in-page heading even when the URL hash is unchanged (e.g. clicking the same anchor again).
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Force software rendering (SwiftShader) in Playwright Chromium to eliminate image downscaling drift between GPU-equipped local runs and headless CI runs in Argos screenshots.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add an assistant tool to rate its own previous response when the user reacts to it.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add an assistant tool to submit feedback about the current page on behalf of the user.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Assistant: you can now send follow-up questions while an answer is still being written. Each one appears as your own message with a "Queued" badge (hover for when it will send, × to cancel), and they're sent automatically one at a time as each answer completes.
-5
View File
@@ -1,5 +0,0 @@
---
"gitbook": patch
---
Add backward compatibility for OpenAPI spec content URL
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": minor
---
Add a carousel layout option to cards blocks, rendering them as a horizontally-scrolling, scroll-snapping row instead of a wrapping grid.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Assistant: the "Explored briefly" activity heading no longer appears when there's nothing to show. It now renders only when the answer is preceded by a real preamble or one or more tool calls, so a simple answer with an empty reasoning step no longer surfaces an empty collapsible.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the docs embed `navigateToPage` API on multi-space sites. Deep-linking to a page in a different space/section (e.g. `navigateToPage('/help-center/integrations')`) previously 404'd because the section base was not placed before `~gitbook/embed/page`. The target is now resolved to its space server-side, so pages in any space resolve correctly. The input accepts the page path, an absolute path, or the full published URL.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix switching from the Search tab to the Docs or Assistant tab in the embed doing nothing.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add configurable default visibility to Prompt block
@@ -0,0 +1,6 @@
---
"@gitbook/colors": patch
"gitbook": patch
---
A near-white tint color (e.g. a warm `#F5F3EF`) is now taken as the exact page background, mirroring the existing behavior for near-black tints. The tint's exact lightness, hue and chroma are preserved, and the color is anchored to whichever scale step the active theme renders as the background — so it matches exactly on `muted` (which uses the second step) as well as `clean`. This applies only to near-neutral tints that are light enough to read as a background; saturated or merely light-ish colors keep their normal accent scale. The `bold` theme is unaffected: it already uses the tint for the header and stays intentionally two-tone.
+7
View File
@@ -0,0 +1,7 @@
---
"gitbook": patch
---
Introduce client-side content selection (`select`): a site-wide, recency-ordered list of selected slugs, persisted in localStorage and shareable via `?select=`, applied to `<html>` before first paint so the right variant renders with no flash. All variants stay server-rendered, so pages are byte-identical for every visitor (no cache impact).
Tabs now use it: switching a tab activates its slug, and every tab group offering that slug follows, across pages. Tabs no longer write to the URL fragment (`#` returns to anchors only); deep-links into a tab still activate and scroll to it.
@@ -1,6 +1,7 @@
---
"@gitbook/openapi-parser": patch
"@gitbook/react-openapi": patch
"gitbook": patch
---
Support x-enable-proxy at operation level
Add missing link reference to OpenAPI models
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Update the URL hash when a tab is selected, so a copied link scrolls back to that tab
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add cover image background mode and masks
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Button blocks now respect the `size` option, so you can render small, medium, or large buttons.
+7
View File
@@ -0,0 +1,7 @@
---
"@gitbook/browser-types": patch
"@gitbook/embed": patch
"gitbook": patch
---
Add an optional `context` property (string, up to 512 characters) to the `confirmation` of custom AI tools, shown above the confirmation dialog to help the user understand what they are approving or rejecting. The `confirmation` can now also be a function that receives the AI-provided input and returns the confirmation, so the context can be derived dynamically from the arguments the tool is about to run with. Available both to integrations (`GitBookIntegrationTool`) and to embed consumers (`GitBookToolDefinition`).
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Lazy-load the Mermaid code block so pages that have code blocks but no diagram no longer ship its rendering dependencies.
+8
View File
@@ -0,0 +1,8 @@
---
"@gitbook/react-openapi": major
"gitbook": patch
---
Lazy load the Scalar API client modal and stop preloading the Scalar runtime. The modal is now code-split into its own chunk, fetched in parallel with the runtime only when a reader clicks "Test it", and a spinner is shown on the button until the client opens.
Breaking: the package no longer ships the modal in its main entry — consumers must serve the emitted `ScalarApiModal` chunk and use a bundler that supports dynamic `import()`, and the Scalar runtime is no longer preloaded on page load. The internal `preloadScalarRuntime` helper is removed.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Attribute the markdown and ask events tracked from the middleware to their space, and record the goal passed alongside a question.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": minor
---
Add an `askQuestion` tool to the site MCP server. Alongside `searchDocumentation` and `getPage`, MCP clients can now ask a natural-language question and get a synthesized answer with links to the source pages, powered by the same AI search backend as the site's "ask a question" experience. The tool accepts an optional `goal` param so calling agents can attach the intent they're trying to accomplish, which tailors the answer and is tracked in analytics. The tool is only exposed on sites that have AI enabled.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Submit `sendFeedback` MCP tool findings through the dedicated `submitSiteAgentFeedback` API endpoint. The `pageUrl` is now required and an optional `goal` can be provided.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Persist content selection (tabs and other `select` blocks) in localStorage only, dropping the `?select=` query parameter from the URL. A tab click still writes the tab's hash, so a copied URL lands on that tab and reactivates it on load.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Serve `X-Robots-Tag: noindex` on internal search/assistant URLs (`?q=` / `?ask=`) and stop disallowing them in robots.txt, so Google can crawl the directive and drop them from the index instead of reporting "Indexed, though blocked by robots.txt".
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the variant switcher linking to the wrong URL for non-default variants of the default section
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add an "On this page" table of contents on OpenAPI models pages. Each model in a grouped/multi-model "Models" section is now listed as its own section, matching operations and webhooks.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Improve cookie handling in the OpenAPI "Test it" request proxy.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Serve the OpenAPI "Test it" request proxy from GitBook's own domain.
@@ -0,0 +1,6 @@
---
"gitbook": patch
"@gitbook/react-openapi": minor
---
Keep the OpenAPI renderer out of the initial bundle of pages that have no OpenAPI block, by building its context on the client behind a dynamic boundary.
-5
View File
@@ -1,5 +0,0 @@
---
"gitbook": patch
---
Refactor embeddable context to merge local & site properties in one unified way
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix text disappearing in Firefox and iOS Safari on pages with a background cover
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Remove GBO's redundant re-selection of the best-scoring search section. The search API now returns a single highest-scoring section per page (and orders sections highest-score-first), so GBO no longer needs its own `getBestScoredResult` helper to pick the best section for the search and MCP previews. No user-visible change.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Sync the API reference responses selector with the "Responses" collapsibles, and keep the selected response in sync across every operation on the page (like the code sample language selector). Selecting a status code now expands the matching response section and applies to all operations at once.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix a light/dark flash on published sites configured to respect the system default (no theme toggle). Such sites forced the `system` theme, but `next-themes`' pre-paint script applies a forced value verbatim without resolving `prefers-color-scheme`, so the page painted light and only switched to dark after hydration. We now leave the theme unforced when the default is `system` (only concrete light/dark themes are forced), letting `next-themes`' existing pre-paint script resolve the system preference before first paint.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add a `sendFeedback` MCP tool so AI agents can report documentation findings (outdated / incoherent / gap / other) as `agent_feedback` insights events. The tool only accepts finding categories, so it never records positive feedback.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Separate the prompt block actions into a primary "Open in" dropdown and a secondary "Copy prompt" button, instead of a single combined button group, and align the block's design with the expandable block (bordered frame, left disclosure chevron, and subtle elevation when expanded).
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the docs embed widget shipping a stale script: declare the embed package's `standalone/` bundle as a Turbo build output. Because it wasn't declared, changes confined to the standalone widget (which compiles to `standalone/` but not `dist/`) didn't invalidate the downstream `generate` cache that copies it into the app, so the deployed widget could lag the source — e.g. the `clipboard-write` permission on the widget iframe never reached production, breaking the copy button in the Assistant embed.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix ScrollContainer scroll buttons not reflecting content overflow immediately or after dynamic content changes (e.g. search results).
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep the last search query visible after closing search, and restore it when reopening, without breaking navigation when clicking a search result.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Link page-level search matches to the top of the page while preserving section anchors for section matches.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep Shiki out of the initial page bundle by splitting the highlighter from the plain-text token helpers, so client code no longer pulls the engine and language bundles in through a shared import.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Refine the per-paragraph AI ask button: shorten its tooltip to "Ask" (from "Ask <assistant> about this"), and hide it inside cards where it would otherwise be clipped by the card's overflow.
-6
View File
@@ -1,6 +0,0 @@
---
"@gitbook/react-openapi": patch
"gitbook": patch
---
Move ~scalar/proxy route to site route group
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Split the default-scope site search into two parallel API requests — one restricted to the current site space and one for the other site spaces — rendering each result set as soon as its response arrives. All results are ranked together by score, with the current site space scores boosted.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep the "On this page" and "Ask" buttons pinned below the header while scrolling on desktop API reference pages, so the page outline stays reachable throughout long operations.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Hide unfocusable unlabelled button from screen readers
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Only show the "Back to [space]" shortcut for cross-space links in the table of contents, not for in-content text links or other ways of reaching another space.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Show image thumbnails, including SVG previews, for file attachments on published sites.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Make the table search "no results" empty state more prominent with vertical spacing so it no longer blends into the content below.
-6
View File
@@ -1,6 +0,0 @@
---
"@gitbook/react-openapi": patch
"gitbook": patch
---
Add token verification on OpenAPI proxy
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix heading anchor links being unreachable on touch devices by adding a tap-to-reveal state. The anchor icon now appears after the heading text without wrapping onto an orphan line while retaining its existing desktop placement. Use `pointerup` for the dismiss listener to fix unreliable dismissal on iOS Safari, and enlarge the anchor's touch tap target to a square 24px area (meeting the WCAG 2.5.8 minimum) so the icon stays centered instead of overflowing shorter headings' line height.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix search results from a previous scope staying stuck on top of the new results when switching the search filter.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Support localized custom AI Assistant greeting subtitles.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
a11y screen reader fixes
+6
View File
@@ -0,0 +1,6 @@
---
"@gitbook/react-contentkit": patch
"gitbook": patch
---
Let integration block webframes navigate the reader to another page in the site by posting a `@webframe.navigate` action with a `path` (and optional `anchor`). Resolved client-side against the site base path, so navigation stays in-site and drives the standard navigation progress bar.
+6
View File
@@ -0,0 +1,6 @@
---
"@gitbook/react-contentkit": patch
"gitbook": patch
---
Expose the current page (`id`, `path`, `title`) to integration block webframes through the client-only webframe `state.page`, alongside adaptive visitor claims.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix an issue where certain keywords could cause an exception when rendering emojis
-5
View File
@@ -1,5 +0,0 @@
---
"gitbook": patch
---
Add support for localized site section titles
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add the `select` action to InlineButton. Clicking the button activates its slug, so any block containing that slug switches to it.
+12
View File
@@ -0,0 +1,12 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "🚀 Dev server",
"runtimeExecutable": "sh",
"runtimeArgs": ["-c", "bun install && bun dev"],
"port": 3000,
"autoPort": false
}
]
}
+10
View File
@@ -0,0 +1,10 @@
# Stop editors from looking for .editorconfig files in parent directories.
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
max_line_length = 100
+4 -1
View File
@@ -76,7 +76,10 @@ bun dev
```
Additional development commands:
- `bun format`: Format the code using Biome
- `bun lint`: Lint the code using Oxlint
- `bun lint:fix`: Automatically fix lint issues using Oxlint
- `bun format`: Format the code using Oxfmt
- `bun format:check`: Check formatting without changing files
- `bun typecheck`: Run TypeScript type checking
- `bun unit`: Run unit tests
- `bun e2e`: Run end-to-end tests
@@ -1,83 +1,83 @@
name: Gradual Deploy to Cloudflare
description: Use gradual deployment to deploy to Cloudflare. This action will upload the middleware and server versions to Cloudflare and kept them bound together
inputs:
apiToken:
description: 'Cloudflare API token'
required: true
accountId:
description: 'Cloudflare account ID'
required: true
environment:
description: 'Cloudflare environment to deploy to (staging, production, preview)'
required: true
middlewareVersionId:
description: 'Middleware version ID to deploy'
required: true
serverVersionId:
description: 'Server version ID to deploy'
required: true
apiToken:
description: 'Cloudflare API token'
required: true
accountId:
description: 'Cloudflare account ID'
required: true
environment:
description: 'Cloudflare environment to deploy to (staging, production, preview)'
required: true
middlewareVersionId:
description: 'Middleware version ID to deploy'
required: true
serverVersionId:
description: 'Server version ID to deploy'
required: true
outputs:
deployment-url:
description: "Deployment URL"
value: ${{ steps.deploy_middleware.outputs.deployment-url }}
deployment-url:
description: 'Deployment URL'
value: ${{ steps.deploy_middleware.outputs.deployment-url }}
runs:
using: 'composite'
steps:
- id: wrangler_status
name: Check wrangler deployment status
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: deployments status --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
using: 'composite'
steps:
- id: wrangler_status
name: Check wrangler deployment status
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: deployments status --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
# This step is used to get the version ID that is currently deployed to Cloudflare.
- id: extract_current_version
name: Extract current version
shell: bash
run: |
version_id=$(echo "${{ steps.wrangler_status.outputs.command-output }}" | grep -A 3 "(100%)" | grep -oP '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
echo "version_id=$version_id" >> $GITHUB_OUTPUT
# This step is used to get the version ID that is currently deployed to Cloudflare.
- id: extract_current_version
name: Extract current version
shell: bash
run: |
version_id=$(echo "${{ steps.wrangler_status.outputs.command-output }}" | grep -A 3 "(100%)" | grep -oP '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
echo "version_id=$version_id" >> $GITHUB_OUTPUT
- id: deploy_server
name: Deploy server to Cloudflare at 0%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ steps.extract_current_version.outputs.version_id }}@100% ${{ inputs.serverVersionId }}@0% -y --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
- id: deploy_server
name: Deploy server to Cloudflare at 0%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ steps.extract_current_version.outputs.version_id }}@100% ${{ inputs.serverVersionId }}@0% -y --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
# Since we use version overrides headers, we can directly deploy the middleware to 100%.
- id: deploy_middleware
name: Deploy middleware to Cloudflare at 100%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ inputs.middlewareVersionId }}@100% -y --config ./packages/gitbook/openNext/customWorkers/middlewareWrangler.jsonc
# Since we use version overrides headers, we can directly deploy the middleware to 100%.
- id: deploy_middleware
name: Deploy middleware to Cloudflare at 100%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ inputs.middlewareVersionId }}@100% -y --config ./packages/gitbook/openNext/customWorkers/middlewareWrangler.jsonc
- name: Deploy server to Cloudflare at 100%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ inputs.serverVersionId }}@100% -y --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
- name: Deploy server to Cloudflare at 100%
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ inputs.apiToken }}
accountId: ${{ inputs.accountId }}
workingDirectory: ./
wranglerVersion: '4.43.0'
environment: ${{ inputs.environment }}
command: versions deploy ${{ inputs.serverVersionId }}@100% -y --config ./packages/gitbook/openNext/customWorkers/defaultWrangler.jsonc
- name: Outputs
shell: bash
env:
DEPLOYMENT_URL: ${{ steps.deploy_middleware.outputs.deployment-url }}
run: |
echo "URL: ${{ steps.deploy_middleware.outputs.deployment-url }}"
- name: Outputs
shell: bash
env:
DEPLOYMENT_URL: ${{ steps.deploy_middleware.outputs.deployment-url }}
run: |
echo "URL: ${{ steps.deploy_middleware.outputs.deployment-url }}"
+52 -48
View File
@@ -1,34 +1,34 @@
name: 'Deploy cloudflare'
description: 'Deploy GitBook to Cloudflare'
inputs:
opItem:
description: '1Password item to load secrets from'
required: true
opServiceAccount:
description: '1Password service account token'
required: true
apiToken:
description: 'Cloudflare API token'
required: true
accountId:
description: 'Cloudflare account ID'
required: true
environment:
description: 'Cloudflare environment to deploy to (staging, production, preview)'
required: true
deploy:
description: 'Deploy as main version for all traffic instead of uploading versions'
required: true
commitTag:
description: 'Commit branch to associate with the deployment'
required: true
commitMessage:
description: 'Commit message to associate with the deployment'
required: true
opItem:
description: '1Password item to load secrets from'
required: true
opServiceAccount:
description: '1Password service account token'
required: true
apiToken:
description: 'Cloudflare API token'
required: true
accountId:
description: 'Cloudflare account ID'
required: true
environment:
description: 'Cloudflare environment to deploy to (staging, production, preview)'
required: true
deploy:
description: 'Deploy as main version for all traffic instead of uploading versions'
required: true
commitTag:
description: 'Commit branch to associate with the deployment'
required: true
commitMessage:
description: 'Commit message to associate with the deployment'
required: true
outputs:
deployment-url:
description: "Deployment URL"
value: ${{ steps.upload_middleware.outputs.deployment-url }}
description: 'Deployment URL'
value: ${{ steps.upload_middleware.outputs.deployment-url }}
runs:
using: 'composite'
steps:
@@ -42,28 +42,33 @@ runs:
- name: Load secret
uses: 1password/load-secrets-action@v2
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.opServiceAccount }}
GITBOOK_URL: ${{ inputs.opItem }}/GITBOOK_URL
GITBOOK_ICONS_URL: ${{ inputs.opItem }}/GITBOOK_ICONS_URL
GITBOOK_ICONS_TOKEN: ${{ inputs.opItem }}/GITBOOK_ICONS_TOKEN
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ inputs.opItem }}/NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
GITBOOK_SECRET: ${{ inputs.opItem }}/GITBOOK_SECRET
GITBOOK_APP_URL: ${{ inputs.opItem }}/GITBOOK_APP_URL
GITBOOK_API_URL: ${{ inputs.opItem }}/GITBOOK_API_URL
GITBOOK_API_PUBLIC_URL: ${{ inputs.opItem }}/GITBOOK_API_PUBLIC_URL
GITBOOK_API_TOKEN: ${{ inputs.opItem }}/GITBOOK_API_TOKEN
GITBOOK_OAUTH_SERVER_URL: ${{ inputs.opItem }}/GITBOOK_OAUTH_SERVER_URL
GITBOOK_PREVIEW_BASE_URL: ${{ inputs.opItem }}/GITBOOK_PREVIEW_BASE_URL
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.opServiceAccount }}
GITBOOK_URL: ${{ inputs.opItem }}/GITBOOK_URL
GITBOOK_ICONS_URL: ${{ inputs.opItem }}/GITBOOK_ICONS_URL
GITBOOK_ICONS_TOKEN: ${{ inputs.opItem }}/GITBOOK_ICONS_TOKEN
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ inputs.opItem }}/NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
GITBOOK_SECRET: ${{ inputs.opItem }}/GITBOOK_SECRET
GITBOOK_APP_URL: ${{ inputs.opItem }}/GITBOOK_APP_URL
GITBOOK_API_URL: ${{ inputs.opItem }}/GITBOOK_API_URL
GITBOOK_API_PUBLIC_URL: ${{ inputs.opItem }}/GITBOOK_API_PUBLIC_URL
GITBOOK_API_TOKEN: ${{ inputs.opItem }}/GITBOOK_API_TOKEN
GITBOOK_OAUTH_SERVER_URL: ${{ inputs.opItem }}/GITBOOK_OAUTH_SERVER_URL
GITBOOK_SITE_OAUTH_SIGNING_SECRET: ${{ inputs.opItem }}/GITBOOK_SITE_OAUTH_SIGNING_SECRET
GITBOOK_PREVIEW_BASE_URL: ${{ inputs.opItem }}/GITBOOK_PREVIEW_BASE_URL
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
GITBOOK_INTEGRATIONS_CONTENT_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_CONTENT_HOST
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL_2
GITBOOK_IMAGE_RESIZE_SALT: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SALT
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
- name: Build worker
run: bun run turbo build:cloudflare
env:
GITBOOK_RUNTIME: cloudflare
GITBOOK_RUNTIME: cloudflare
GITBOOK_BLOCK_SEARCH_INDEXATION: ${{ inputs.environment == 'preview' && 'true' || '' }}
GITBOOK_ALLOW_CUSTOMIZATION_OVERRIDE: ${{ inputs.environment == 'preview' && 'true' || '' }}
shell: bash
- name: Upload the DO worker
@@ -130,11 +135,10 @@ runs:
middlewareVersionId: ${{ steps.extract_middleware_version_id.outputs.version_id }}
deploy: ${{ inputs.deploy }}
- name: Outputs
shell: bash
env:
DEPLOYMENT_URL: ${{ steps.upload_middleware.outputs.deployment-url }}
DEPLOYMENT_URL: ${{ steps.upload_middleware.outputs.deployment-url }}
run: |
echo "URL: ${{ steps.upload_middleware.outputs.deployment-url }}"
echo "Output server: ${{ steps.upload_server.outputs.command-output }}"
echo "Output server: ${{ steps.upload_server.outputs.command-output }}"
+63 -45
View File
@@ -1,28 +1,31 @@
name: 'Deploy vercel'
description: 'Deploy GitBook to Vercel'
inputs:
vercelOrg:
description: 'Vercel organization'
required: true
vercelProject:
description: 'Vercel project'
required: true
vercelToken:
description: 'Vercel token'
required: true
opItem:
description: '1Password item to load secrets from'
required: true
opServiceAccount:
description: '1Password service account token'
required: true
environment:
description: 'Environment to deploy to'
required: true
vercelOrg:
description: 'Vercel organization'
required: true
vercelProject:
description: 'Vercel project'
required: true
vercelToken:
description: 'Vercel token'
required: true
opItem:
description: '1Password item to load secrets from'
required: true
opServiceAccount:
description: '1Password service account token'
required: true
environment:
description: 'Environment to deploy to'
required: true
headSha:
description: 'Git ref to deploy, used for the deploymentId'
required: false
outputs:
deployment-url:
description: "Deployment URL"
value: ${{ steps.deploy.outputs.deployment-url }}
description: 'Deployment URL'
value: ${{ steps.deploy.outputs.deployment-url }}
runs:
using: 'composite'
steps:
@@ -37,35 +40,51 @@ runs:
run: bun run vercel pull --yes --environment=${{ inputs.environment }} --token=${{ inputs.vercelToken }}
shell: bash
env:
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
- name: Load secret
uses: 1password/load-secrets-action@v2
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.opServiceAccount }}
GITBOOK_URL: ${{ inputs.opItem }}/GITBOOK_URL
GITBOOK_ICONS_URL: ${{ inputs.opItem }}/GITBOOK_ICONS_URL
GITBOOK_ICONS_TOKEN: ${{ inputs.opItem }}/GITBOOK_ICONS_TOKEN
GITBOOK_SECRET: ${{ inputs.opItem }}/GITBOOK_SECRET
GITBOOK_APP_URL: ${{ inputs.opItem }}/GITBOOK_APP_URL
GITBOOK_API_URL: ${{ inputs.opItem }}/GITBOOK_API_URL
GITBOOK_API_PUBLIC_URL: ${{ inputs.opItem }}/GITBOOK_API_PUBLIC_URL
GITBOOK_API_TOKEN: ${{ inputs.opItem }}/GITBOOK_API_TOKEN
GITBOOK_OAUTH_SERVER_URL: ${{ inputs.opItem }}/GITBOOK_OAUTH_SERVER_URL
GITBOOK_PREVIEW_BASE_URL: ${{ inputs.opItem }}/GITBOOK_PREVIEW_BASE_URL
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
OP_SERVICE_ACCOUNT_TOKEN: ${{ inputs.opServiceAccount }}
GITBOOK_URL: ${{ inputs.opItem }}/GITBOOK_URL
GITBOOK_ICONS_URL: ${{ inputs.opItem }}/GITBOOK_ICONS_URL
GITBOOK_ICONS_TOKEN: ${{ inputs.opItem }}/GITBOOK_ICONS_TOKEN
GITBOOK_SECRET: ${{ inputs.opItem }}/GITBOOK_SECRET
GITBOOK_APP_URL: ${{ inputs.opItem }}/GITBOOK_APP_URL
GITBOOK_API_URL: ${{ inputs.opItem }}/GITBOOK_API_URL
GITBOOK_API_PUBLIC_URL: ${{ inputs.opItem }}/GITBOOK_API_PUBLIC_URL
GITBOOK_API_TOKEN: ${{ inputs.opItem }}/GITBOOK_API_TOKEN
GITBOOK_OAUTH_SERVER_URL: ${{ inputs.opItem }}/GITBOOK_OAUTH_SERVER_URL
GITBOOK_SITE_OAUTH_SIGNING_SECRET: ${{ inputs.opItem }}/GITBOOK_SITE_OAUTH_SIGNING_SECRET
GITBOOK_PREVIEW_BASE_URL: ${{ inputs.opItem }}/GITBOOK_PREVIEW_BASE_URL
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
GITBOOK_INTEGRATIONS_CONTENT_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_CONTENT_HOST
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL_2
GITBOOK_IMAGE_RESIZE_SALT: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SALT
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
- name: Inject build env vars
if: ${{ inputs.environment == 'preview' }}
shell: bash
run: |
HEAD_SHA=$(git rev-parse HEAD)
echo "resolved HEAD_SHA: $HEAD_SHA"
echo "GITBOOK_HEAD_SHA=$HEAD_SHA" >> .vercel/.env.${{ inputs.environment }}.local
echo "GITBOOK_RUNTIME=vercel" >> .vercel/.env.${{ inputs.environment }}.local
echo "GITBOOK_BLOCK_SEARCH_INDEXATION=true" >> .vercel/.env.${{ inputs.environment }}.local
echo "GITBOOK_ALLOW_CUSTOMIZATION_OVERRIDE=true" >> .vercel/.env.${{ inputs.environment }}.local
echo "--- .vercel/.env.${{ inputs.environment }}.local after inject ---"
cat .vercel/.env.${{ inputs.environment }}.local
- name: Build Project Artifacts
run: bun run vercel build --target=${{ inputs.environment }} --token=${{ inputs.vercelToken }}
shell: bash
env:
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
GITBOOK_RUNTIME: vercel
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
GITBOOK_RUNTIME: vercel
GITBOOK_HEAD_SHA: ${{ inputs.headSha }}
- name: Deploy Project Artifacts to Vercel
id: deploy
shell: bash
@@ -73,10 +92,9 @@ runs:
DEPLOYMENT_URL=$(bun run vercel deploy --prebuilt --target=${{ inputs.environment }} --token=${{ inputs.vercelToken }})
echo "deployment-url=$DEPLOYMENT_URL" >> "$GITHUB_OUTPUT"
env:
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
- name: Outputs
shell: bash
run: |
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
+14
View File
@@ -20,6 +20,20 @@ jobs:
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- run: bun format:check
lint:
runs-on: ubuntu-latest
name: Lint
timeout-minutes: 6
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Bun
uses: ./.github/composite/setup-bun
- name: Install dependencies
run: bun install --frozen-lockfile
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- run: bun lint
test:
runs-on: ubuntu-latest
name: Test
@@ -0,0 +1,35 @@
name: CSS browser compatibility
on:
pull_request_target:
types: [opened, reopened, synchronize]
permissions:
contents: read
issues: write
pull-requests: read
concurrency:
group: css-browser-compatibility-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
check:
name: Check newly added CSS declarations
runs-on: ubuntu-latest
timeout-minutes: 6
steps:
# pull_request_target checks out the trusted base branch by default. Never use the PR ref here.
- name: Checkout trusted checker
uses: actions/checkout@v4
- name: Setup Bun
uses: ./.github/composite/setup-bun
- name: Install dependencies
run: bun install --frozen-lockfile
env:
PUPPETEER_SKIP_DOWNLOAD: 1
- name: Check CSS browser compatibility
working-directory: packages/gitbook
run: bun run check:css-browser-compatibility
env:
GITHUB_TOKEN: ${{ github.token }}
+60 -16
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.fork }}
environment:
name: preview-approval
name: preview-approval
steps:
- name: Approval gate
run: echo "Preview deployment approved."
@@ -21,8 +21,8 @@ jobs:
needs: approval
if: ${{ always() && (needs.approval.result == 'success' || needs.approval.result == 'skipped') }}
environment:
name: 2v-preview
url: ${{ steps.deploy.outputs.deployment-url }}
name: 2v-preview
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
deployment-url: ${{ steps.deploy.outputs.deployment-url }}
steps:
@@ -40,14 +40,15 @@ jobs:
vercelToken: ${{ secrets.VERCEL_TOKEN }}
opItem: op://gitbook-open/2v-preview
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
headSha: ${{ github.event.pull_request.head.sha || github.sha }}
deploy-v2-cloudflare:
name: Deploy v2 to Cloudflare Worker (preview)
runs-on: ubuntu-latest
needs: approval
if: ${{ always() && (needs.approval.result == 'success' || needs.approval.result == 'skipped') }}
environment:
name: 2c-preview
url: ${{ steps.deploy.outputs.deployment-url }}
name: 2c-preview
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
deployment-url: ${{ steps.deploy.outputs.deployment-url || steps.extract-worker-id.outputs.worker-url }}
steps:
@@ -71,10 +72,10 @@ jobs:
id: extract-worker-id
if: ${{ !steps.deploy.outputs.deployment-url }}
run: |
if [[ "${{ steps.deploy.outputs.command-output }}" =~ Worker\ Version\ ID:\ ([0-9a-f]{8})-([0-9a-f-]+) ]]; then
WORKER_ID_FIRST_PART="${BASH_REMATCH[1]}"
echo "worker-url=https://${WORKER_ID_FIRST_PART}-gitbook-open-v2-preview.gitbook.workers.dev/" >> $GITHUB_OUTPUT
fi
if [[ "${{ steps.deploy.outputs.command-output }}" =~ Worker\ Version\ ID:\ ([0-9a-f]{8})-([0-9a-f-]+) ]]; then
WORKER_ID_FIRST_PART="${BASH_REMATCH[1]}"
echo "worker-url=https://${WORKER_ID_FIRST_PART}-gitbook-open-v2-preview.gitbook.workers.dev/" >> $GITHUB_OUTPUT
fi
- name: Outputs
run: |
echo "URL: ${{ steps.deploy.outputs.deployment-url || steps.extract-worker-id.outputs.worker-url }}"
@@ -136,7 +137,6 @@ jobs:
env:
BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}
SITE_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/url/
SITE_PREVIEW_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/preview/
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_BUILD_NAME: v2-vercel
visual-testing-v2-cloudflare:
@@ -161,7 +161,6 @@ jobs:
env:
BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}
SITE_BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}/url/
SITE_PREVIEW_BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}/preview/
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_BUILD_NAME: v2-cloudflare
visual-testing-customers-v2:
@@ -169,7 +168,7 @@ jobs:
name: Visual Testing Customers v2
needs: deploy-v2-vercel
if: ${{ always() && needs.deploy-v2-vercel.result == 'success' }}
timeout-minutes: 15
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -186,15 +185,62 @@ jobs:
env:
BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}
SITE_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/url/
SITE_PREVIEW_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/preview/
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_BUILD_NAME: customers-v2-vercel
# Style recalc depends on the client bundle, not the host, so this runs here only and
# not in the Cloudflare job. Kept out of `e2e-customers`, which is a visual suite.
- name: Run style invalidation tests
if: always()
working-directory: packages/gitbook
run: bun run e2e-style-perf
env:
BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}
SITE_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/url/
# Runs on failure too: a blown style budget is exactly when the numbers are worth seeing.
- name: Build style invalidation report
if: always() && github.event_name != 'push'
id: style-perf
working-directory: packages/gitbook
run: |
rows=$(cat test-results/style-perf.md 2>/dev/null || true)
if [ -z "$rows" ]; then exit 0; fi
{
echo 'body<<STYLE_PERF_EOF'
echo '### Style invalidation on a large API reference'
echo
echo 'Elements restyled by opening one popup on [the Snyk API reference](https://docs.snyk.io/snyk-api/reference/apps). A share near or above 100% means the insertion restyles the whole document.'
echo
echo '| interaction | restyled | page | share | budget | |'
echo '| --- | ---: | ---: | ---: | ---: | :-: |'
echo "$rows"
echo 'STYLE_PERF_EOF'
} >> "$GITHUB_OUTPUT"
- name: Find style invalidation comment
if: always() && github.event_name != 'push' && steps.style-perf.outputs.body != ''
uses: peter-evans/find-comment@v3
id: fc-style-perf
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
body-includes: 'Style invalidation on a large API reference'
- name: Create or update style invalidation comment
if: always() && github.event_name != 'push' && steps.style-perf.outputs.body != ''
uses: peter-evans/create-or-update-comment@v4
with:
comment-id: ${{ steps.fc-style-perf.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: ${{ steps.style-perf.outputs.body }}
edit-mode: replace
visual-testing-customers-v2-cloudflare:
runs-on: ubuntu-latest
name: Visual Testing Customers v2 (Cloudflare)
needs: deploy-v2-cloudflare
if: ${{ always() && needs.deploy-v2-cloudflare.result == 'success' }}
timeout-minutes: 15
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -211,7 +257,6 @@ jobs:
env:
BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}
SITE_BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}/url/
SITE_PREVIEW_BASE_URL: ${{ needs.deploy-v2-cloudflare.outputs.deployment-url }}/preview/
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_BUILD_NAME: customers-v2-cloudflare
browserless-testing-v2-vercel:
@@ -235,7 +280,6 @@ jobs:
env:
BASE_URL: ${{needs.deploy-v2-vercel.outputs.deployment-url}}
SITE_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/url/
SITE_PREVIEW_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/preview/
# browserless-testing-v2-cloudflare:
# runs-on: ubuntu-latest
# name: Browserless Testing v2 (Cloudflare)
+9 -9
View File
@@ -7,7 +7,7 @@ jobs:
deploy-v2-vercel:
name: Deploy v2 to Vercel (production)
runs-on: ubuntu-latest
environment:
environment:
name: 2v-production
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
@@ -19,16 +19,16 @@ jobs:
id: deploy
uses: ./.github/composite/deploy-vercel
with:
environment: production
vercelOrg: ${{ secrets.VERCEL_ORG_ID }}
vercelProject: ${{ secrets.VERCEL_PROJECT_ID }}
vercelToken: ${{ secrets.VERCEL_TOKEN }}
opItem: op://gitbook-open/2v-production
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
environment: production
vercelOrg: ${{ secrets.VERCEL_ORG_ID }}
vercelProject: ${{ secrets.VERCEL_PROJECT_ID }}
vercelToken: ${{ secrets.VERCEL_TOKEN }}
opItem: op://gitbook-open/2v-production
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
deploy-v2-cloudflare:
name: Deploy v2 to Cloudflare Worker (production)
runs-on: ubuntu-latest
environment:
environment:
name: 2c-production
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
@@ -50,4 +50,4 @@ jobs:
commitMessage: ${{ github.sha }}
- name: Outputs
run: |
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
+9 -9
View File
@@ -7,7 +7,7 @@ jobs:
deploy-v2-vercel:
name: Deploy v2 to Vercel (staging)
runs-on: ubuntu-latest
environment:
environment:
name: 2v-staging
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
@@ -19,16 +19,16 @@ jobs:
id: deploy
uses: ./.github/composite/deploy-vercel
with:
environment: staging
vercelOrg: ${{ secrets.VERCEL_ORG_ID }}
vercelProject: ${{ secrets.VERCEL_PROJECT_ID }}
vercelToken: ${{ secrets.VERCEL_TOKEN }}
opItem: op://gitbook-open/2v-staging
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
environment: staging
vercelOrg: ${{ secrets.VERCEL_ORG_ID }}
vercelProject: ${{ secrets.VERCEL_PROJECT_ID }}
vercelToken: ${{ secrets.VERCEL_TOKEN }}
opItem: op://gitbook-open/2v-staging
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
deploy-v2-cloudflare:
name: Deploy v2 to Cloudflare Worker (staging)
runs-on: ubuntu-latest
environment:
environment:
name: 2c-staging
url: ${{ steps.deploy.outputs.deployment-url }}
outputs:
@@ -50,4 +50,4 @@ jobs:
commitMessage: ${{ github.sha }}
- name: Outputs
run: |
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
+8 -4
View File
@@ -4,7 +4,7 @@ on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
@@ -15,6 +15,10 @@ jobs:
id-token: write
pull-requests: write
contents: write
env:
# The repo is managed by Bun, but publishing uses npm for provenance.
# Keep Corepack from rejecting packageManager: bun@... when npm runs.
COREPACK_ENABLE_PROJECT_SPEC: 0
steps:
- name: Checkout Repo
uses: actions/checkout@v3
@@ -26,9 +30,10 @@ jobs:
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
# Ensure npm 11.5.1 or later is installed
- name: Update npm
run: npm install -g npm@latest
run: |
corepack enable npm
corepack install -g npm@latest
- name: Setup Bun
uses: ./.github/composite/setup-bun
- name: Install dependencies
@@ -45,4 +50,3 @@ jobs:
# Using a PAT instead of GITHUB_TOKEN because we need to run workflows when releases are created
# https://github.com/orgs/community/discussions/26875#discussioncomment-3253761
GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
+70
View File
@@ -0,0 +1,70 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 100,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"jsxSingleQuote": false,
"quoteProps": "as-needed",
"trailingComma": "es5",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf",
"sortImports": {
"customGroups": [
{
"groupName": "workspace",
"elementNamePattern": ["@gitbook/**"]
}
],
"groups": [
["value-builtin", "value-external", "type-builtin", "type-external"],
{ "newlinesBetween": true },
"workspace",
{ "newlinesBetween": true },
[
"value-internal",
"type-internal",
"value-parent",
"type-parent",
"value-sibling",
"type-sibling",
"value-index",
"type-index"
],
"type-import",
"unknown"
]
},
"sortPackageJson": false,
"sortTailwindcss": {
"config": "./packages/gitbook/tailwind.config.ts",
"attributes": ["class", "className", "style"],
"functions": ["clsx", "tw"]
},
"ignorePatterns": [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/public/**",
"**/.next/**",
"**/.open-next/**",
"**/.turbo/**",
"**/.vercel/**",
"**/.cache/**",
"**/.wrangler/**",
"**/*.log",
"**/*.MD",
"**/*.md",
"**/*.mdx",
"**/*.html",
"**/*.css",
"packages/embed/standalone/**",
"packages/openapi-parser/src/fixtures/**",
"packages/emoji-codepoints/index.ts",
"packages/icons/src/data/*.json",
"packages/gitbook/worker-configuration.d.ts"
]
}
+87
View File
@@ -0,0 +1,87 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"categories": {
"correctness": "warn",
"suspicious": "warn",
"perf": "warn"
},
"plugins": ["eslint", "typescript", "unicorn", "oxc", "react", "jsx-a11y", "vitest"],
"env": {
"builtin": true,
"browser": true,
"node": true,
"shared-node-browser": true,
"worker": true
},
"globals": {
"Bun": "readonly",
"GitBookIntegrationEvent": "readonly",
"React": "readonly"
},
"rules": {
"eslint/no-console": [
"warn",
{
"allow": ["assert", "error", "warn"]
}
],
"eslint/no-control-regex": "warn",
"eslint/no-prototype-builtins": "warn",
"eslint/no-cond-assign": "warn",
"eslint/no-undef": "error",
"eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"varsIgnorePattern": "^_"
}
],
"react/button-has-type": "warn",
"react/exhaustive-deps": "warn",
"react/jsx-key": "warn",
"react/jsx-no-useless-fragment": "warn",
"react/no-array-index-key": "warn",
"react/void-dom-elements-no-children": "warn",
"react/rules-of-hooks": "error",
"jsx-a11y/alt-text": "warn",
"jsx-a11y/anchor-is-valid": "warn",
"jsx-a11y/click-events-have-key-events": "warn",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/interactive-supports-focus": "warn",
"jsx-a11y/label-has-associated-control": "warn",
"jsx-a11y/no-noninteractive-tabindex": "warn",
"jsx-a11y/role-has-required-aria-props": "warn",
"jsx-a11y/tabindex-no-positive": "warn",
"typescript/array-type": "error",
"typescript/no-explicit-any": "warn",
"typescript/no-non-null-assertion": "warn",
"typescript/no-confusing-void-expression": "warn",
"typescript/only-throw-error": "error",
"vitest/no-focused-tests": "error",
"no-delete-var": "warn",
"no-debugger": "error",
"no-throw-literal": "error",
"use-isnan": "error",
"valid-typeof": "error"
},
"ignorePatterns": [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/public/**",
"**/.next/**",
"**/.open-next/**",
"**/.turbo/**",
"**/.vercel/**",
"**/.cache/**",
"**/.wrangler/**",
"packages/embed/standalone/**",
"packages/openapi-parser/src/fixtures/**",
"packages/emoji-codepoints/index.ts",
"packages/icons/src/data/*.json",
"packages/gitbook/worker-configuration.d.ts",
"**/*.css"
]
}
+1 -1
View File
@@ -1,3 +1,3 @@
{
"recommendations": ["biomejs.biome"]
"recommendations": ["oxc.oxc-vscode"]
}
+3 -5
View File
@@ -8,14 +8,12 @@
["style \\=([^;]*);", "\\`([^\\`]*)\\`"]
],
"tailwindCSS.classAttributes": ["class", "className", "style", ".*Style"],
"prettier.enable": false,
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"source.fixAll.biome": "explicit"
"source.fixAll.oxc": "always"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
"editor.defaultFormatter": "oxc.oxc-vscode"
}
}
+80 -1
View File
@@ -1,3 +1,82 @@
# AGENTS Instructions
- After making code changes, run `bun format`.
## Commands
```bash
bun install # Install dependencies
bun dev # Start dev server (all packages)
bun run build # Build all packages
bun run lint # Lint with Oxlint
bun run format # Format with Oxfmt (run after every change)
bun run typecheck # Type-check all packages
bun run unit # Run unit tests
```
## Development
The dev server proxies published GitBook sites locally. After `bun dev`, access any published site at:
```
http://localhost:3000/url/<published-gitbook-url>
```
Examples:
- `http://localhost:3000/url/gitbook.com/docs`
- `http://localhost:3000/url/open-source.gitbook.io/midjourney`
## Architecture
```
packages/
gitbook/ # Main Next.js app
src/
app/ # Next.js App Router (sites/)
components/ # React components
lib/ # Server utilities, data fetching
intl/ # Internationalization (translations/)
openapi-parser/ # OpenAPI 3.0/3.1/Swagger parser
react-openapi/ # OpenAPI rendering components
react-contentkit/ # ContentKit component rendering
embed/ # Embeddable GitBook components
shared/ # Shared utilities
icons/ # Icon assets
fonts/ # Font assets
colors/ # Color tokens
expr/ # GitBook expression evaluator
cache-do/ # Cloudflare DO cache
cache-tags/ # Cache tag utilities
```
## Testing
```bash
bun run unit # Unit tests via bun test (not vitest)
bun run e2e # Playwright e2e tests (requires built app)
```
Run a specific test file:
```bash
cd packages/gitbook && bun test src/lib/cache.test.ts
```
## Changesets
After committing code changes, create a changeset for the affected package:
```md
---
"gitbook": patch
---
Provide a short description of the change.
```
Save as `.changeset/<name>.md`, then commit it separately with message: `changeset`
## Formatting
Linting uses Oxlint and formatting uses Oxfmt. Always run `bun run format` before committing.
## Comments
Comment to explain *why*, not *what* — the code already shows what it does. Keep comments short, ideally a single line. Avoid multi-line block comments that narrate mechanics a reader can follow from the code; they add noise and go stale. Reserve longer comments for genuinely non-obvious rationale: a subtle invariant, or a workaround and the reason it exists.
+1
View File
@@ -0,0 +1 @@
@AGENTS.md
+4
View File
@@ -1,3 +1,7 @@
<p align="center">
<img src="./assets/gitbook_icon_dark.svg" alt="GitBook" width="48" />
</p>
<h1 align="center">GitBook</h1>
<p align="center">
+3
View File
@@ -0,0 +1,3 @@
<svg width="65" height="65" viewBox="0 0 65 65" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M27.3963 34.2195C30.5255 36.0255 32.09 36.9285 33.8082 36.93C35.5265 36.9315 37.0926 36.0313 40.2249 34.2308L60.1913 22.7534C61.0927 22.2353 61.6484 21.2749 61.6484 20.2352C61.6484 19.1955 61.0927 18.2351 60.1913 17.717L40.2177 6.23554C37.0888 4.43695 35.5243 3.53766 33.8078 3.53833C32.0912 3.539 30.5275 4.43951 27.4 6.24053L10.2292 16.1286C10.102 16.2019 10.0383 16.2385 9.97905 16.2732C4.11368 19.7068 0.489862 25.9754 0.441408 32.7717C0.440918 32.8404 0.440918 32.9138 0.440918 33.0607C0.440918 33.2074 0.440918 33.2807 0.441407 33.3494C0.489754 40.138 4.10549 46.4008 9.96041 49.837C10.0196 49.8718 10.0831 49.9085 10.2101 49.9818L20.9658 56.1918C27.2331 59.8104 30.3668 61.6197 33.808 61.6208C37.2493 61.622 40.3842 59.8148 46.6539 56.2005L58.008 49.6551C61.1474 47.8454 62.7171 46.9405 63.579 45.4487C64.4409 43.957 64.4409 42.1451 64.4409 38.5215V31.5212C64.4409 30.5159 63.8965 29.5895 63.0182 29.1004C62.1683 28.627 61.1325 28.6341 60.2891 29.1189L37.0074 42.5019C35.4453 43.3998 34.6643 43.8487 33.8072 43.849C32.9501 43.8493 32.1688 43.4008 30.6062 42.5038L14.8487 33.4586C14.0593 33.0055 13.6647 32.7789 13.3477 32.738C12.625 32.6448 11.9301 33.0497 11.6548 33.7244C11.534 34.0203 11.5365 34.4753 11.5414 35.3855C11.545 36.0555 11.5468 36.3905 11.6094 36.6987C11.7496 37.3887 12.1127 38.0136 12.6428 38.4771C12.8795 38.6842 13.1696 38.8516 13.7499 39.1866L30.5974 48.9103C32.164 49.8145 32.9473 50.2666 33.8075 50.2668C34.6677 50.267 35.4512 49.8154 37.0184 48.912L57.6684 37.0085C58.2037 36.7 58.4713 36.5457 58.672 36.6616C58.8727 36.7776 58.8727 37.0865 58.8727 37.7044V40.8796C58.8727 41.7855 58.8727 42.2385 58.6572 42.6114C58.4417 42.9844 58.0493 43.2106 57.2644 43.663L40.2322 53.4811C37.0966 55.2885 35.5288 56.1923 33.8078 56.1915C32.0869 56.1907 30.5199 55.2855 27.386 53.4752L11.4509 44.2701C11.4003 44.2409 11.375 44.2262 11.3514 44.2125C8.0102 42.26 5.94856 38.6882 5.92922 34.8185C5.92909 34.7911 5.92909 34.7619 5.92909 34.7035V31.7889C5.92909 29.6526 7.06686 27.678 8.9151 26.6067C10.5483 25.66 12.5628 25.6582 14.1977 26.6018L27.3963 34.2195Z" fill="#181C1F"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

-177
View File
@@ -1,177 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": [
"**/node_modules/**/*",
"**/dist/**/*",
"**/build/**/*",
"**/public/**/*",
"**/.next/**/*",
"**/.open-next/**/*",
"**/.turbo/**/*",
"**/.vercel/**/*",
"**/.cache/**/*",
"**/.wrangler/**/*",
"packages/embed/standalone/**/*",
"packages/openapi-parser/src/fixtures/**/*",
"packages/emoji-codepoints/index.ts",
"packages/icons/src/data/*.json",
"packages/gitbook/worker-configuration.d.ts",
"**/*.css"
]
},
"formatter": {
"enabled": true,
"useEditorconfig": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 4,
"lineEnding": "lf",
"lineWidth": 100,
"attributePosition": "auto",
"bracketSpacing": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"performance": {
"noDelete": "warn"
},
"security": {
"noDangerouslySetInnerHtml": "off"
},
"complexity": {
"noForEach": "off",
"noUselessFragments": "warn",
"noBannedTypes": "warn"
},
"correctness": {
"noUndeclaredVariables": "error",
"noUnusedVariables": "error",
"useArrayLiterals": "error",
"useHookAtTopLevel": "error",
"noUnusedImports": "error",
"noVoidElementsWithChildren": "warn",
"useJsxKeyInIterable": "warn",
"useExhaustiveDependencies": "warn",
"noUnknownFunction": "warn"
},
"style": {
"noNonNullAssertion": "warn",
"noParameterAssign": "off",
"useThrowOnlyError": "error"
},
"suspicious": {
"noConsole": {
"level": "warn",
"options": {
"allow": ["assert", "error", "warn"]
}
},
"noExplicitAny": "warn",
"noImplicitAnyLet": "warn",
"noConfusingVoidType": "warn",
"noControlCharactersInRegex": "warn",
"noPrototypeBuiltins": "warn",
"noAssignInExpressions": "warn",
"noArrayIndexKey": "warn"
},
"a11y": {
"useSemanticElements": "warn",
"useKeyWithClickEvents": "warn",
"noSvgWithoutTitle": "warn",
"useButtonType": "warn",
"useIframeTitle": "warn",
"useAltText": "warn",
"noPositiveTabindex": "warn",
"useFocusableInteractive": "warn",
"useAriaPropsForRole": "warn",
"useValidAnchor": "warn",
"noLabelWithoutControl": "warn",
"noNoninteractiveTabindex": "warn"
},
"nursery": {
"useSortedClasses": {
"level": "error",
"fix": "safe",
"options": {
"attributes": ["class", "className", "style"],
"functions": ["clsx", "tw"]
}
}
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto",
"bracketSpacing": true
}
},
"overrides": [
{
"include": [
"packages/gitbook/**/*",
"packages/react-openapi/**/*",
"packages/react-math/**/*",
"packages/react-contentkit/**/*",
"packages/icons/**/*"
],
"javascript": {
"globals": ["React"]
}
},
{
"include": ["packages/gitbook/**/*"],
"javascript": {
"globals": ["React", "GitBookIntegrationEvent"]
}
},
{
"include": ["*.css"],
"javascript": {
"globals": ["theme"]
}
},
{
"include": ["*.test.ts", "packages/gitbook/tests/**/*"],
"javascript": {
"globals": ["Bun"]
}
},
{
"include": [
"packages/cache-do/**/*",
"packages/gitbook/cf-env.d.ts",
"packages/gitbook/src/cloudflare-entrypoint.ts"
],
"javascript": {
"globals": [
"DurableObjectLocationHint",
"DurableObjectNamespace",
"DurableObjectStub",
"ContinentCode",
"Fetcher",
"ExportedHandler"
]
}
}
]
}
+658 -1690
View File
File diff suppressed because it is too large Load Diff
+20 -11
View File
@@ -5,10 +5,11 @@
"node": "^22.3.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@changesets/cli": "^2.30.0",
"turbo": "^2.8.13",
"vercel": "^50.26.1"
"@changesets/cli": "^2.31.0",
"oxfmt": "^0.62.0",
"oxlint": "^1.77.0",
"turbo": "^2.10.3",
"vercel": "50.37.3"
},
"packageManager": "bun@1.3.7",
"overrides": {
@@ -17,7 +18,9 @@
"@types/react-dom": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
"esbuild": "0.24.2"
"esbuild": "0.27.3",
"axios": "1.8.4",
"@radix-ui/react-slot": "1.2.4"
},
"private": true,
"scripts": {
@@ -25,8 +28,10 @@
"build": "turbo run build",
"clean-deps": "rm -rf node_modules && rm -rf packages/*/node_modules",
"typecheck": "turbo run typecheck",
"format": "biome check --write ./",
"format:check": "biome check --diagnostic-level=error ./",
"lint": "oxlint --quiet",
"lint:fix": "oxlint --fix --quiet",
"format": "oxfmt",
"format:check": "oxfmt --check",
"unit": "turbo run unit",
"e2e": "turbo run e2e",
"e2e-customers": "turbo run e2e-customers",
@@ -37,11 +42,13 @@
"clean": "turbo run clean"
},
"workspaces": {
"packages": ["packages/*"],
"packages": [
"packages/*"
],
"catalog": {
"@tsconfig/strictest": "^2.0.6",
"@tsconfig/node20": "^20.1.6",
"@gitbook/api": "0.167.0",
"@gitbook/api": "0.195.0",
"@scalar/api-client-react": "^1.3.46",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
@@ -53,11 +60,13 @@
"react-dom": "^19.0.1",
"tsdown": "^0.15.6",
"typescript": "^5.5.3",
"usehooks-ts": "^3.1.1"
"usehooks-ts": "^3.1.1",
"vercel": "^50.26.1"
}
},
"patchedDependencies": {
"decode-named-character-reference@1.0.2": "patches/decode-named-character-reference@1.0.2.patch",
"@vercel/next@4.4.2": "patches/@vercel%2Fnext@4.4.2.patch"
"@vercel/next@4.4.2": "patches/@vercel%2Fnext@4.4.2.patch",
"next@16.2.11": "patches/next@16.2.11.patch"
}
}
+5 -1
View File
@@ -25,7 +25,11 @@
"dev": "bun run build -- --watch ./src",
"publish-to-npm": "../../scripts/publish-if-new.sh"
},
"files": ["dist", "README.md", "CHANGELOG.md"],
"files": [
"dist",
"README.md",
"CHANGELOG.md"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
+18 -4
View File
@@ -5,14 +5,28 @@ export type GitBookIntegrationEvent = 'load' | 'unload';
export type GitBookIntegrationEventCallback = (...args: any[]) => void;
export type GitBookIntegrationToolConfirmation = {
icon?: IconName;
label: string;
/**
* Supporting context displayed to the user above the confirmation dialog,
* to help them understand what they are approving or rejecting.
* Limited to 512 characters.
*/
context?: string;
};
export type GitBookIntegrationTool = AIToolDefinition & {
/**
* Confirmation action to be displayed to the user before executing the tool.
* Provide a static object, or a function that receives the input provided by
* the AI assistant and returns the confirmation — useful to display dynamic
* context based on the arguments the tool is about to be executed with.
*/
confirmation?: {
icon?: IconName;
label: string;
};
confirmation?:
| GitBookIntegrationToolConfirmation
| ((input: object) => GitBookIntegrationToolConfirmation);
/**
* Callback when the tool is executed.
+5 -1
View File
@@ -24,7 +24,11 @@
"dev": "bun run build -- --watch ./src",
"publish-to-npm": "../../scripts/publish-if-new.sh"
},
"files": ["dist", "README.md", "CHANGELOG.md"],
"files": [
"dist",
"README.md",
"CHANGELOG.md"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
+5 -4
View File
@@ -1,14 +1,15 @@
import type { ComputedContentSource } from '@gitbook/api';
import assertNever from 'assert-never';
import type { ComputedContentSource } from '@gitbook/api';
/**
* Get a stringified cache tag for a given object.
*/
export function getCacheTag(
spec: /**
* All data related to a user
* @deprecated - in v2, no tag as this is an immutable data
*/
* All data related to a user
* @deprecated - in v2, no tag as this is an immutable data
*/
| {
tag: 'user';
user: string;
+6 -1
View File
@@ -17,10 +17,15 @@
"scripts": {
"build": "tsdown",
"typecheck": "tsc --noEmit",
"unit": "bun test",
"dev": "bun run build -- --watch ./src",
"publish-to-npm": "../../scripts/publish-if-new.sh"
},
"files": ["dist", "README.md", "CHANGELOG.md"],
"files": [
"dist",
"README.md",
"CHANGELOG.md"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
@@ -0,0 +1,69 @@
import { describe, expect, it } from 'bun:test';
import { colorScale } from './transformations';
describe('colorScale exact base', () => {
it('takes a very light tint as the exact background on step 1 (clean/bold)', () => {
const scale = colorScale('#F5F3EF', { baseStep: 1 });
expect(scale[0]).toBe('#F5F3EF');
});
it('anchors a very light tint to step 2 when the theme uses the subtle step (muted)', () => {
const scale = colorScale('#F5F3EF', { baseStep: 2 });
expect(scale[1]).toBe('#F5F3EF');
// Step 1 sits just above the exact base, toward white.
expect(scale[0]).not.toBe('#F5F3EF');
expect(scale[0]).not.toBe('#ffffff');
});
it('takes a darker-than-dark tint as the exact background, preserving hue and chroma', () => {
const scale = colorScale('#0B0F19', { darkMode: true, baseStep: 1 });
expect(scale[0]).toBe('#0B0F19');
});
it('does not trigger for a normal mid-lightness tint', () => {
const scale = colorScale('#787878', { baseStep: 2 });
// The default white background is kept; the tint only colors the scale.
expect(scale[0]).toBe('#ffffff');
expect(scale[1]).not.toBe('#787878');
});
it('does not trigger for a saturated light color, keeping the normal accent ramp', () => {
// Light enough (L≈0.93) to pass the lightness bound, but too chromatic to read as a
// background — emitting it verbatim would leave a vivid step 1 above a near-gray scale.
const scale = colorScale('#FFEB3B', { baseStep: 1 });
expect(scale[0]).toBe('#ffffff');
expect(scale[0]).not.toBe('#FFEB3B');
});
it('respects a custom light background instead of overriding it with the tint', () => {
// The color is darker than the requested background, so it is not the extreme end and the
// supplied base must be preserved rather than overwritten.
const scale = colorScale('#eeeeee', { baseStep: 1, background: '#f8f8f8' });
expect(scale[0]).not.toBe('#eeeeee');
});
it('anchors an exact base even when a neutral mix is supplied (tint === primary)', () => {
// getTintMixColor blends neutral into the tint when it equals the primary color; that must
// not darken a near-white tint out of the exact-base path.
const scale = colorScale('#F5F3EF', {
baseStep: 1,
mix: { color: '#787878', ratio: 0.4 },
});
expect(scale[0]).toBe('#F5F3EF');
});
it('does not trigger for a light accent color below the near-white threshold', () => {
// #D8DEEC (light blue-gray, L≈0.90) is a UI accent, not a background, so it must not anchor.
const scale = colorScale('#D8DEEC', { baseStep: 1 });
expect(scale[0]).toBe('#ffffff');
expect(scale[0]).not.toBe('#D8DEEC');
});
it('never anchors when no baseStep is given (accent scales and the bold theme)', () => {
// A scale that does not define the page background opts out of the exact base entirely.
const scale = colorScale('#F5F3EF', {});
expect(scale[0]).toBe('#ffffff');
expect(scale[0]).not.toBe('#F5F3EF');
});
});
+58 -10
View File
@@ -82,6 +82,22 @@ export const colorMixMapping = {
dark: [0, 0.03, 0.08, 0.1, 0.13, 0.15, 0.2, 0.25, 0.5, 0.55, 0.75, 1],
};
/**
* Light mode has no equivalent to the dark base bound (nothing is lighter than white), so a tint
* at or above this lightness is treated as an explicit, near-white background (e.g. a warm `#F5F3EF`
* at L≈0.96). Kept high so light UI accent colors (around L≈0.90) aren't mistaken for backgrounds.
*/
const EXACT_BASE_LIGHT_THRESHOLD = 0.95;
/**
* Only a near-neutral tint reads as a background. A saturated color would keep the exact hue at the
* anchored step while the rest of the low scale stays ~gray, so those keep the normal accent ramp.
*/
const EXACT_BASE_NEUTRAL_CHROMA = 0.05;
/** Lightness of the default white light background (≈0.99999, not exactly 1). */
const LIGHT_BASE_L = rgbToOklch(hexToRgbArray(LIGHT_BASE)).L;
/**
* Convert a hex color to an RGB color.
*/
@@ -159,6 +175,14 @@ export type ColorScaleOptions = {
/** Define a custom foreground color to use. If left undefined, the global `light`/`dark` values (in `colors.ts`) will be used. */
foreground?: string;
/**
* The 1-indexed scale step this scale renders as the page background (1 = `tint-base` for
* `clean`, 2 = `tint-subtle` for `muted`). When set, an extreme near-neutral tint is taken as
* the exact background, anchored to this step so it matches exactly. Omit for scales that don't
* define the page background (accents, or the two-tone `bold` theme) — they never anchor.
*/
baseStep?: number;
mix?: {
/** If set to a hex code, this color will be additionally mixed into the generated scale according to `mix.ratio`. */
color: string;
@@ -179,6 +203,7 @@ export function colorScale(
darkMode = false,
background = darkMode ? DARK_BASE : LIGHT_BASE,
foreground = darkMode ? LIGHT_BASE : DARK_BASE,
baseStep,
mix,
}: ColorScaleOptions = {}
) {
@@ -188,31 +213,51 @@ export function colorScale(
const backgroundColor = rgbToOklch(hexToRgbArray(background));
let mapping = darkMode ? colorMixMapping.dark : colorMixMapping.light;
if (mixColor && mix?.ratio && mix.ratio > 0) {
// If defined, we mix in a (tiny) bit of the mix color with the base color.
// A near-neutral tint at the extreme end of the scale is taken as the exact page background
// rather than tinting pure black/white with it — letting brands set an exact background such as
// a warm `#F5F3EF`. Only scales that define the page background opt in (via `baseStep`). In light
// mode the base is pure white by default, so a near-white tint also qualifies (nothing is lighter
// than white); a custom, lower background is respected instead. Decided on the raw color so a
// neutral mix (below) can't darken a tint out of the exact base.
const isExtremeBase = darkMode
? baseColor.L < backgroundColor.L
: backgroundColor.L >= LIGHT_BASE_L
? baseColor.L > EXACT_BASE_LIGHT_THRESHOLD
: baseColor.L > backgroundColor.L;
const isExactBase =
baseStep !== undefined && isExtremeBase && baseColor.C < EXACT_BASE_NEUTRAL_CHROMA;
const exactBaseIndex = (baseStep ?? 1) - 1;
if (mixColor && mix?.ratio && mix.ratio > 0 && !isExactBase) {
// Mix a little of the mix color into the base — but not when the tint is the exact base,
// where it must stay true to the supplied color (and match `--header-background`).
baseColor.L = mixColor.L * mix.ratio + baseColor.L * (1 - mix.ratio);
baseColor.C = mixColor.C * mix.ratio + baseColor.C * (1 - mix.ratio);
baseColor.H = mix.color === DEFAULT_TINT_COLOR ? baseColor.H : mixColor.H;
}
if (
(darkMode && baseColor.L < backgroundColor.L) ||
(!darkMode && baseColor.L > backgroundColor.L)
) {
// If the supplied color is outside of our lightness bounds, use the supplied color's lightness.
// This is mostly used to allow darker-than-dark backgrounds for brands that specifically want that look.
if (isExactBase) {
const difference = (backgroundColor.L - baseColor.L) / backgroundColor.L;
backgroundColor.L = baseColor.L;
// At the edges of the scale, the subtle lightness changes stop being perceptible. We need to amp up our mapping to still stand out.
const amplifier = 1;
mapping = mapping.map((step, index) =>
index < 9 ? step + step * amplifier * difference : step
);
// Anchor the supplied color to the step the theme renders as the background, solving the
// background lightness so neighbouring steps stay continuous with it.
const baseMix = mapping[exactBaseIndex]!;
backgroundColor.L = (baseColor.L - foregroundColor.L * baseMix) / (1 - baseMix);
}
const result = [];
for (let index = 0; index < mapping.length; index++) {
if (isExactBase && index === exactBaseIndex) {
result.push(hex);
continue;
}
const step = mapping[index]!;
const targetL = foregroundColor.L * step + backgroundColor.L * (1 - step);
@@ -238,7 +283,10 @@ export function colorScale(
case 11:
return 0.1;
default:
return index * 0.05;
// When the tint is the exact base, hold the steps from the base toward the
// accents at its chroma so the background stays tinted; steps lighter than the
// base (e.g. cards in `muted`) keep desaturating toward white.
return isExactBase && index >= exactBaseIndex ? 1 : index * 0.05;
}
})();
+24
View File
@@ -1,5 +1,29 @@
# @gitbook/embed
## 0.5.1
### Patch Changes
- 37a9453: Allow copying in embed
- Updated dependencies [47c8ccb]
- @gitbook/icons@0.5.0
## 0.5.0
### Minor Changes
- 88c38fa: Add Search tab to Docs Embed, refactor search
### Patch Changes
- 8d2a95b: Docs Embed: Better support light/dark mode overrides
## 0.4.0
### Minor Changes
- b3875a1: Support `assistantName` property to override Assistant name
## 0.3.0
### Minor Changes
+32 -11
View File
@@ -2,8 +2,9 @@
Embed your GitBook docs in your product or website.
The Docs Embed can contain two tabs:
The Docs Embed can contain three tabs:
- **Assistant**: The [GitBook Assistant](https://gitbook.com/docs/publishing-documentation/gitbook-ai-assistant) - an AI-powered chat interface to help users find answers
- **Search**: A search-focused surface for quickly finding pages and asking scoped questions
- **Docs**: A browser for navigating your documentation site
The embed is set up automatically based on your site's configuration. You can optionally customize and override the configuration with custom actions, tools, suggested questions, [Authenticated Access](https://gitbook.com/docs/publishing-documentation/authenticated-access), and more. See the [Configuration](#configuration) section for all available options.
@@ -40,7 +41,7 @@ GitBook('configure', {
label: 'Ask',
icon: 'assistant' // 'assistant' | 'sparkle' | 'help' | 'book'
},
tabs: ['assistant', 'docs'],
tabs: ['assistant', 'search', 'docs'],
actions: [
{
icon: 'circle-question',
@@ -72,6 +73,7 @@ const gitbook = createGitBook({
// Create an iframe and get its URL
const iframe = document.createElement('iframe');
iframe.src = gitbook.getFrameURL({
colorScheme: 'dark', // Optional: force the embed to render in dark mode
visitor: {
token: 'your-jwt-token', // Optional: for Adaptive Content or Authenticated Access
unsignedClaims: { // Optional: custom claims for dynamic expressions
@@ -92,7 +94,7 @@ frame.clearChat();
// Configure the embed (see Configuration section for all options)
frame.configure({
tabs: ['assistant', 'docs'],
tabs: ['assistant', 'search', 'docs'],
actions: [
{
icon: 'circle-question',
@@ -122,11 +124,12 @@ import { GitBookProvider, GitBookFrame } from '@gitbook/embed/react';
<GitBookProvider siteURL="https://docs.company.com">
<GitBookFrame
colorScheme="dark"
visitor={{
token: 'your-jwt-token', // Optional: for Adaptive Content or Authenticated Access
unsignedClaims: { userId: '123' } // Optional: custom claims for dynamic expressions
}}
tabs={['assistant', 'docs']}
tabs={['assistant', 'search', 'docs']}
greeting={{ title: 'Welcome!', subtitle: 'How can I help?' }}
assistantName="Support Assistant"
suggestions={['What is GitBook?', 'How do I get started?']}
@@ -150,7 +153,7 @@ import { useGitBook } from '@gitbook/embed/react';
function MyComponent() {
const gitbook = useGitBook();
const frameURL = gitbook.getFrameURL({ visitor: { token: '...' } });
const frameURL = gitbook.getFrameURL({ colorScheme: 'dark', visitor: { token: '...' } });
// ...
}
```
@@ -178,13 +181,13 @@ function MyComponent() {
### Standalone Script
- `GitBook('init', options: { siteURL: string }, frameOptions?: { visitor?: {...} })` - Initialize widget
- `GitBook('init', options: { siteURL: string }, frameOptions?: { colorScheme?: 'light' | 'dark', visitor?: {...} })` - Initialize widget
- `GitBook('show')` - Show widget button
- `GitBook('hide')` - Hide widget button
- `GitBook('open')` - Open widget window
- `GitBook('close')` - Close widget window
- `GitBook('toggle')` - Toggle widget window
- `GitBook('navigateToPage', path: string)` - Navigate to page
- `GitBook('navigateToPage', path: string)` - Navigate to page (accepts the page path within the site, an absolute path, or the full published URL; resolves pages in any space/section)
- `GitBook('navigateToAssistant')` - Navigate to assistant tab
- `GitBook('postUserMessage', message: string)` - Post message to chat
- `GitBook('clearChat')` - Clear chat history
@@ -195,11 +198,11 @@ function MyComponent() {
**Client Factory:**
- `createGitBook(options: { siteURL: string })` → `GitBookClient`
- `client.getFrameURL(options?: { visitor?: {...} })` → `string`
- `client.getFrameURL(options?: { colorScheme?: 'light' | 'dark', visitor?: {...} })` → `string`
- `client.createFrame(iframe: HTMLIFrameElement)` → `GitBookFrameClient`
**Frame Client:**
- `frame.navigateToPage(path: string)` → `void`
- `frame.navigateToPage(path: string)` → `void` (accepts the page path within the site, an absolute path, or the full published URL; resolves pages in any space/section)
- `frame.navigateToAssistant()` → `void`
- `frame.postUserMessage(message: string)` → `void`
- `frame.clearChat()` → `void`
@@ -228,10 +231,10 @@ Available in: Standalone script, NPM package, React components
Override which tabs are displayed. Defaults to your site's configuration.
- **Type**: `('assistant' | 'docs')[]`
- **Type**: `('assistant' | 'search' | 'docs')[]`
```javascript
tabs: ['assistant', 'docs']
tabs: ['assistant', 'search', 'docs']
```
### `closeButton`
@@ -457,6 +460,24 @@ visitor: {
}
```
### `colorScheme`
Available in: Standalone script (via `init`), NPM package (via `getFrameURL()`), React components (as prop)
Override the embed's color scheme. When omitted, the embed follows the iframe's CSS `color-scheme`, which lets it inherit the parent page or browser preference.
**Note**: This is not a configuration option but rather a parameter when initializing the frame or creating the frame URL.
**Standalone script**: Pass as the second argument to `GitBook('init', options, frameOptions)`
**NPM package**: Pass to `getFrameURL({ colorScheme: 'dark' })`
**React components**: Pass as the `colorScheme` prop on `<GitBookFrame>`
- **Type**: `'light' | 'dark'`
```javascript
colorScheme: 'dark'
```
### `button`
Available in: Standalone script only
+6 -2
View File
@@ -13,7 +13,7 @@
}
},
"sideEffects": false,
"version": "0.3.0",
"version": "0.5.1",
"dependencies": {
"@gitbook/api": "catalog:",
"@gitbook/icons": "workspace:",
@@ -39,7 +39,11 @@
"dev": "bun run build -- --watch ./src",
"publish-to-npm": "../../scripts/publish-if-new.sh"
},
"files": ["dist", "README.md", "CHANGELOG.md"],
"files": [
"dist",
"README.md",
"CHANGELOG.md"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
@@ -35,4 +35,17 @@ describe('createGitBook.getFrameURL', () => {
expect(url.searchParams.get('visitor.count')).toBe('3');
expect(url.searchParams.get('visitor.enabled')).toBe('false');
});
it('adds an explicit color scheme override when requested', () => {
const client = createGitBook({ siteURL: 'https://example.com/docs/' });
const url = new URL(
client.getFrameURL({
colorScheme: 'dark',
})
);
expect(url.pathname).toBe('/docs/~gitbook/embed');
expect(url.searchParams.get('theme')).toBe('dark');
});
});
@@ -8,6 +8,12 @@ export type CreateGitBookOptions = {
};
export type GetFrameURLOptions = {
/**
* Override the color scheme used by the embedded docs.
* When omitted, the embed follows the iframe's CSS `color-scheme`.
*/
colorScheme?: 'light' | 'dark';
/**
* Authentication to use for the frame.
*/
@@ -42,6 +48,10 @@ export function createGitBook(options: CreateGitBookOptions) {
const url = new URL(options.siteURL);
url.pathname = `${url.pathname.endsWith('/') ? url.pathname : `${url.pathname}/`}~gitbook/embed`;
if (frameOptions.colorScheme) {
url.searchParams.set('theme', frameOptions.colorScheme);
}
if (frameOptions.visitor?.token) {
url.searchParams.set('jwt_token', frameOptions.visitor.token);
}
@@ -1,4 +1,5 @@
import { createChannel } from 'bidc';
import type {
FrameToParentMessage,
GitBookEmbeddableConfiguration,
@@ -7,7 +8,12 @@ import type {
export type GitBookFrameClient = {
/**
* Navigate to a page by its path.
* Navigate to a page in the docs tab.
*
* Accepts the page's path within the site (e.g. `getting-started/quickstart`),
* an absolute path (e.g. `/help-center/integrations`), or its full published URL.
* The target page may live in any space/section of the site — including one other
* than the embed is currently showing — and is resolved to the right space.
*/
navigateToPage: (path: string) => void;
@@ -44,6 +50,16 @@ export function createGitBookFrame(iframe: HTMLIFrameElement): GitBookFrameClien
if (!iframe.contentWindow) {
throw new Error('Iframe must have a content window');
}
const allowTokens = iframe.allow
.split(';')
.map((token) => token.trim())
.filter(Boolean);
if (!allowTokens.includes('clipboard-write')) {
iframe.allow = [...allowTokens, 'clipboard-write'].join('; ');
}
const channel = createChannel(iframe.contentWindow);
channel.receive((message: FrameToParentMessage) => {
@@ -61,10 +77,10 @@ export function createGitBookFrame(iframe: HTMLIFrameElement): GitBookFrameClien
channel.send(message);
};
const events = new Map<string, Array<(...args: any[]) => void>>();
const events = new Map<string, ((...args: any[]) => void)[]>();
const configuration: GitBookEmbeddableConfiguration = {
tabs: ['assistant', 'docs'],
tabs: ['assistant', 'search', 'docs'],
actions: [],
greeting: { title: '', subtitle: '' },
suggestions: [],
+20 -5
View File
@@ -1,17 +1,32 @@
import type { AIToolCallResult, AIToolDefinition } from '@gitbook/api';
import type { IconName } from '@gitbook/icons';
/**
* Confirmation action to be displayed to the user before executing a tool.
*/
export type GitBookToolConfirmation = {
icon?: IconName;
label: string;
/**
* Supporting context displayed to the user above the confirmation dialog,
* to help them understand what they are approving or rejecting.
* Limited to 512 characters.
*/
context?: string;
};
/**
* Custom tool definition to be passed to the AI assistant.
*/
export type GitBookToolDefinition = AIToolDefinition & {
/**
* Confirmation action to be displayed to the user before executing the tool.
* Provide a static object, or a function that receives the input provided by
* the AI assistant and returns the confirmation — useful to display dynamic
* context based on the arguments the tool is about to be executed with.
*/
confirmation?: {
icon?: IconName;
label: string;
};
confirmation?: GitBookToolConfirmation | ((input: object) => GitBookToolConfirmation);
/**
* Callback when the tool is executed.
@@ -45,7 +60,7 @@ export type GitBookEmbeddableActionDefinition = {
*/
export type GitBookEmbeddableConfiguration = {
/** Tabs to display in the embed (if enabled on the site). */
tabs: ('assistant' | 'docs')[];
tabs: ('assistant' | 'docs' | 'search')[];
/** Additional buttons to be displayed in the header of the GitBook embed. */
actions: GitBookEmbeddableActionDefinition[];
+9 -2
View File
@@ -1,6 +1,7 @@
'use client';
import { useEffect, useMemo, useRef, useState } from 'react';
import type {
GetFrameURLOptions,
GitBookEmbeddableConfiguration,
@@ -19,12 +20,13 @@ export type GitBookFrameProps = {
export function GitBookFrame(props: GitBookFrameProps) {
const {
className,
colorScheme,
visitor,
actions = [],
greeting,
suggestions = [],
tools = [],
tabs = ['assistant', 'docs'],
tabs = ['assistant', 'search', 'docs'],
trademark = true,
closeButton = false,
assistantName,
@@ -34,7 +36,10 @@ export function GitBookFrame(props: GitBookFrameProps) {
const gitbook = useGitBook();
const [gitbookFrame, setGitbookFrame] = useState<GitBookFrameClient | null>(null);
const frameURL = useMemo(() => gitbook.getFrameURL({ visitor }), [gitbook, visitor]);
const frameURL = useMemo(
() => gitbook.getFrameURL({ visitor, colorScheme }),
[gitbook, visitor, colorScheme]
);
useEffect(() => {
if (frameRef.current) {
@@ -72,7 +77,9 @@ export function GitBookFrame(props: GitBookFrameProps) {
src={frameURL}
width="100%"
height="100%"
allow="clipboard-write"
className={className}
style={colorScheme ? { colorScheme } : undefined}
/>
);
}
@@ -1,6 +1,7 @@
'use client';
import * as React from 'react';
import { type CreateGitBookOptions, createGitBook } from '../client';
import { GitBookContext } from './context';

Some files were not shown because too many files have changed in this diff Show More