Compare commits

...

130 Commits

Author SHA1 Message Date
Nicolas Dorseuil 3bd9976524 Revert "super hacky solution to PPR cache body"
This reverts commit 4c36cf9abd.
2026-09-07 11:43:52 +02:00
Nicolas Dorseuil 4c36cf9abd super hacky solution to PPR cache body 2026-09-07 11:41:10 +02:00
Nicolas Dorseuil c1530706d0 Refactor PPR layout functions to use 'header' context and enhance type definitions for site context 2026-09-07 11:40:54 +02:00
Nicolas Dorseuil d4fa433d92 Split the PPR layout context between site and revision scopes
`SitePPRLayout` resolved a full site context, which fetches the published
site (site-scoped token) and the space with its revision. Only the site
part is needed to render the shell, and the shell is re-rendered on every
request.

Split `GitBookSiteContext` into a `GitBookSiteScopeContext` holding
everything derived from the published site, and the space context it is
merged with. The PPR layout now resolves only the site scope, under the
header scope so it shares its site fetch, and delegates the announcement,
header, table of contents, footer, admin toolbar and the page/tag icons to
cached components that resolve the revision under their own scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 11:40:54 +02:00
Nicolas Dorseuil a2170a352a Add PPR token exchange functionality: implement endpoint for exchanging revalidation tokens for scoped content API tokens, enhancing caching and claims management across components. 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil e05abafddb Fix PPR test module mocks leaking into the rest of the suite
`mock.module` replaces a module for the whole bun test process, so mocking
`@/lib/context` and `jwt-decode` wholesale in the PPR route params test broke
every later test file that imported them. Spread the real context module and
sign a real JWT instead.

Also restore the `x-gitbook-route-site` debug header, commented out by mistake.
2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 7e0e76e58a Implement GitBook-secret signature for PPR headers: enforce signature requirement and update related handling in middleware, tests, and proxy scripts. 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 42ab12a387 Enhance PPR route parameters: add basePath handling for variant consistency in getPPRHeaderRouteParams 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 2251b36673 Refactor getPPRDefaults function: streamline error handling and validation for decoded PPR defaults 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 8ef76487c2 Refactor PPR route parameter handling: simplify getPPRTableOfContentsRouteParams by removing unnecessary cache path variation 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil e401c4d4c7 Apply oxfmt import ordering after rebase
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 11:39:51 +02:00
Nicolas Dorseuil fb971aefcc Refactor PPR cache handling: implement scoped cache tags for components to ensure independent revalidation and improve data fetching efficiency 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil b6770d959a Prefix cache tags with ppr: for PPR route rendering to ensure cache entries are partitioned from static ones 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 8d881d88f6 Remove redundant cache tagging in PPRTableOfContents, PPRPageBody, and cachedGenerateSitePageMetadata functions 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 351c4ffa28 Fix proxy host header handling in forward function to prevent 404 errors 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil bd608e6beb Add PPR development proxy and update documentation for local testing 2026-09-07 11:39:51 +02:00
Nicolas Dorseuil 825e245703 Refactor navigation components: implement client-side selection handling and improve context management 2026-09-07 11:39:50 +02:00
Nicolas Dorseuil 828ce66cd9 Refactor getPPRHeaderRouteParams and getPPRTableOfContentsRouteParams: enhance caching logic and add API token handling 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 8e1fdedf83 Remove NotFound component: delete unused page not found file 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 4a88202274 Refactor getPPRHeaderRouteParams: destructure revision from site URL data 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil d077e1a6b6 remove revalidationId from site data 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 7605d03d8c Refactor PPR components: remove unused files, add default site parameters, and enhance route handling 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 80026d2724 Refactor PPR components: remove deprecated files, enhance site context handling, and streamline API token management 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil b86ee531d4 Refactor PPR components: remove old files, add new layout and page components, and update utility functions for visitor tokens 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil d939d4c1fd Implement PPR route enhancements with revision and revalidation IDs, refactor headers handling, and add new layout and page components 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 0cc9a03add fix attempt 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 3805bac462 Fix invocation of cachedGenerateSitePageMetadata in generateMetadata function 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 23b438404c Refactor caching functions for site page metadata and viewport in PPR components 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 40d14b02d8 linting 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil ef0b6f020a Implement caching for site page metadata and viewport generation 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil d6c0d2dbcd comment 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 125872769f Refactor PPR tokens and enhance route parameter handling in utils 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil a04513f887 Implement PPR routing with token-based headers and restructure related components 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 7adbb5068f Enhance caching strategy in PPR components with remote cache and tagging 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil 2b146dbc6a Add dynamic export for force-static rendering in page component 2026-09-07 11:38:07 +02:00
Nicolas Dorseuil ea9420817f wip 2026-09-07 11:38:07 +02:00
Tomek 1f250d1fa8 Add site structure e2e tests for external links (#4584) 2026-09-07 09:31:50 +02:00
Brett Jephson 46b3a18b25 Fix nested select css (#4583)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-04 16:20:52 +01:00
Nolann B. 2ff77e15b5 Attribute a markdown request from the page actions menu (#4581) 2026-09-04 12:17:00 +02:00
Tomek d7c867aa63 Fix MCP/Markdown copy confirmation closing dropdown instantly (#4579)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 16:08:53 +02:00
Tomek bcd1c41aa1 Scroll to top when selecting current page in search (#4578)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-03 11:35:07 +02:00
Viktor Renkema 77058e3f17 Support merged cells (#4500)
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-09-03 10:26:43 +02:00
Tomek 8ad7465801 Simplify carousel overflow with edge masks & fix carousel scroll (#4577)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-02 14:32:53 +00:00
arnau 1b7ac0e41b Open inline Ask AI questions in the configured assistant (#4574) 2026-09-02 12:05:37 +02:00
Tomek 5f88f4e680 Improve cross-space page breadcrumbs (#4571)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-02 11:43:35 +02:00
Peter White 7009bb9311 Drop the body-anchored cover gate from paragraph contrast text (#4573) 2026-09-02 11:24:54 +02:00
Johan Preynat e460ec381e Preserve linked page destinations in published search (#4566) 2026-09-01 15:06:26 +02:00
Johan Preynat 0a82628298 Trap keyboard focus within published search (#4567) 2026-09-01 13:12:01 +02:00
conico974 18ff11b68b Bump @opennextjs/aws and @opennextjs/cloudflare versions (#4570) 2026-09-01 12:14:55 +02:00
Peter White 3bf55cef10 Allow adding query params to the @webframe.navigate action (#4569) 2026-09-01 10:14:07 +02:00
Peter White e041e49f11 Wait for integrations to register before showing the cookie banner (#4568) 2026-09-01 09:09:15 +02:00
Johan Preynat c1b5be05eb Allow search to target any section (#4564) 2026-08-31 18:32:02 +02:00
Johan Preynat 7543eb83ad Prewarm Turbopuffer when published search opens (#4563) 2026-08-31 13:32:47 +00:00
Tomek 523b7cd4b6 Support external links (#4561)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-31 13:11:13 +02:00
spastorelli af698a49f5 Extend MCP tests (#4562) 2026-08-31 11:59:46 +02:00
conico974 db67585ee2 Remove MCP authentication path from internal paths registry (#4560) 2026-08-28 14:57:21 +02:00
Peter White a566153d98 Chunk oversized visitor authentication cookies (#4554) 2026-08-28 12:28:53 +02:00
conico974 530f98a9c4 Skip internal paths in URL lookup (#4557) 2026-08-28 12:24:29 +02:00
Tomek 39391259c8 Disable zoom for inline images (#4555) 2026-08-28 11:32:19 +02:00
Nolann B. 35be3835f3 Skip rendering work for off-screen OpenAPI blocks (#4502) 2026-08-27 18:41:33 +02:00
Tomek 4452fd793c Fix link title showing site section name (4542) (#4553)
Co-authored-by: Kai Kewley <kaikewley@gmail.com>
2026-08-27 09:57:32 +02:00
conico974 90566879d2 Improve image signature handling and resizing functionality (#4511) 2026-08-26 15:55:57 +02:00
Zeno Kapitein 40a879ad5f Keep section group dropdown columns readable when space is tight (#4549)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 15:05:28 +02:00
Johan Preynat cc441c99c6 Fix published search scope fusion (#4552) 2026-08-26 14:22:33 +02:00
conico974 64e143a15b Bump Next.js to version 16.3.3 (#4547) 2026-08-26 12:32:56 +02:00
Peter White 8c10d92f77 Keep the section group menu open over the collapsed sidebar rail (#4548) 2026-08-26 12:16:13 +02:00
Zeno Kapitein 0a22eb5340 Stop expecting a cookies dialog in the faq.wanttopay.net e2e test (#4550)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 11:54:31 +02:00
Zeno Kapitein d9fc4608e3 Stop suggesting previously asked questions in the GitBook Assistant (#4546)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 18:00:30 +02:00
Zeno Kapitein ded2f560e3 Show loose sections in a section group dropdown as secondary links unless the group starts with one (#4545)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 17:14:58 +02:00
Zeno Kapitein a9c5d1b546 Fix the gap between columns in large section group dropdowns (#4544)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 16:45:41 +02:00
Zeno Kapitein 0ff21b7ae2 Hide the section tabs scroll button when all tabs already fit (#4540)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 16:35:38 +02:00
Zeno Kapitein 94a496c561 Match the Docs Embed widget to the page it is embedded in (#4533)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 16:34:54 +02:00
Johan Preynat 148a43ac01 Preserve backend ranking across site sections (#4541) 2026-08-25 14:55:17 +02:00
Johan Preynat 5da854f09c Preserve backend ranking in published search (#4537) 2026-08-25 12:54:24 +02:00
spastorelli b772f74c2b Evaluate <if> blocks when serving markdown pages (#4538) 2026-08-25 12:18:53 +02:00
Zeno Kapitein e0bd04f641 Render headings with the site's heading font (#4531)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 12:08:03 +02:00
conico974 8d7c3edda8 Disable metadata fetching in revision-related API calls (#4459) 2026-08-24 13:55:50 +02:00
conico974 80951e9889 Remove CODEOWNERS file for API data cache functions (#4536) 2026-08-24 13:43:37 +02:00
Nolann B. 185dd8337e Defer tracking scripts until after load and idle (#4529) 2026-08-24 12:18:30 +02:00
Peter White da7fb13d83 Fail closed in /~gitbook/revalidate when GITBOOK_SECRET is unset (#4535) 2026-08-24 12:11:40 +02:00
conico974 49c993f181 Add API token expiration check (#4532) 2026-08-21 11:29:38 +02:00
Zeno Kapitein 90b54682e5 Redesign the site OAuth consent screen for published sites MCP (RND-12071) (#4530)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:45:46 +02:00
Zeno Kapitein 1dccf8f06c Fix table-of-contents page group's first item cut off after navigation (RND-11314) (#4391)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zenoachtig <8304582+zenoachtig@users.noreply.github.com>
2026-08-20 15:28:02 +02:00
Nolann B. 810244e8a9 Stop preloading zoom-modal images at render time (#4528) 2026-08-20 15:02:00 +02:00
Tomek 0dd2f4fbcd Show containing section name when hovering direct space links (RND-12437) (#4525) 2026-08-20 14:06:10 +02:00
Nolann B. 8a700222e6 Only track embed view events once the frame is shown (RND-12362) (#4517) 2026-08-20 14:04:14 +02:00
Nolann B. b13fd91afc Compute the AI chat time greeting after mount to avoid a hydration mismatch (#4527) 2026-08-20 13:52:52 +02:00
Nolann B. 8a6baaba6a Load the admin toolbar and its CSS lazily (RND-12524) (#4526) 2026-08-20 13:47:49 +02:00
Zeno Kapitein 48fba7cb49 Fix: highlight a TOC link entry when on the page or section it points to (RND-11155) (#4476)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:48:45 +02:00
Zeno Kapitein 6928a9b00a Hide card fields that render no content (#4523)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:48:37 +02:00
Nolann B. 7bab574c63 Self-host default fonts and inline only the ones a site uses (RND-12524) (#4522) 2026-08-20 12:36:55 +02:00
conico974 75bdff3ff3 Add support for AI agent detection and robots directives in markdown (#4524) 2026-08-20 12:18:17 +02:00
Peter White 56c25587db Make keyboard shortcuts work on non-QWERTY layouts (#4516) 2026-08-19 15:03:34 +00:00
Zeno Kapitein cf4efc7213 Fix search input losing focus before hydration (RND-11849) (#4438)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-19 12:30:11 +02:00
Zeno Kapitein 1ef71609e7 Show the light/dark toggle on laptop-width screens (#4515)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 12:29:58 +02:00
Zeno Kapitein 195c9e6b84 Apply and remember the ?theme= light/dark override in the docs embed (#4380)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 11:07:23 +02:00
Zeno Kapitein 09f39f8300 Vertically center breadcrumb icons (#4513) 2026-08-19 08:52:10 +00:00
Peter White 9002f6598a Fix embed search suggested questions not opening the assistant (#4514) 2026-08-18 17:19:25 +02:00
Zeno Kapitein 01c9b059c6 Require Ctrl/Cmd to zoom Mermaid diagrams with the wheel (RND-12338) (#4465)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-18 16:37:49 +02:00
Zeno Kapitein 6d02b8ab72 Fix TS code block comment punctuation color in dark mode (RND-12204) (#4460)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-18 16:36:07 +02:00
Peter White 177ef8582a Fix Docs Embed host actions not reaching the assistant (#4512) 2026-08-18 16:33:03 +02:00
Zeno Kapitein 78c589ffba Align Previous/Next page navigation to opposite edges (RND-11235) (#4494)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-18 13:36:08 +02:00
Nolann B. e4b214e6bd Fix large OpenAPI payload section not being scrollable (RND-12291) (#4510) 2026-08-18 13:17:33 +02:00
Tomek 64ce9e180d Render site-space custom home page at root (#4475)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-18 12:20:52 +02:00
conico974 c64d3a50e8 Refactor CSS compatibility checks (#4504) 2026-08-18 10:30:43 +02:00
spastorelli fd070ce9ca Redirect to the upstream auth logout URL on ~gitbook/auth/logout (#4489) 2026-08-18 10:27:48 +02:00
Tomek 048c4e4c70 Fix tooltip data-popup-open state conflict and AI messages collapsible (#4509)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-18 10:22:47 +02:00
conico974 fb01dc9ecb Remove unused Cloudflare image resizing function (#4507) 2026-08-17 17:26:32 +02:00
Nolann B. d33e570bc7 Fix the spacebar being swallowed in the search bar (RND-12484) (#4508) 2026-08-17 13:21:21 +00:00
Tomek 87fd234d55 Fix dropdown icon rotation by reading dropdown open state (#4503)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-17 14:55:09 +02:00
Claire Chabas 0f32eb17d1 Fix toggle chevron alignment in ToC (#4505) 2026-08-17 14:41:44 +02:00
Tomek 3e29680792 Stabilize visual CI tests (#4506)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-17 13:14:47 +02:00
Nolann B. b3db1c58c8 Migrate headless UI primitives from Radix and react-aria to Base UI (#4499) 2026-08-15 21:05:32 +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
811 changed files with 21134 additions and 7263 deletions
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix "View activity" disclosure in AI Chat not opening after the Base UI migration.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Stop showing previously asked questions as suggestions in the GitBook Assistant
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Simplify carousel overflow with symmetric edge masks and visible-item paging. Replaces complex negative-margin bleed logic with transparent edge fades and page-by-visible-item scrolling.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep the breadcrumbs from covering the page actions' hit area.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Bump Next.js to 16.3.3.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Chunk oversized visitor auth cookies to fix an infinite redirect loop when the visitor token exceeds the browser cookie size limit.
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Fix inline Ask AI buttons opening a configured custom assistant.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Stop the built-in cookie banner from flashing on sites using a consent integration such as Osano or OneTrust.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix breadcrumbs for cross-space page links in grouped sites.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Show the theme toggle in the footer whenever the outline column that hosts the other toggle isn't pinned open, so it stays reachable on laptop-sized screens in wide layouts and while the AI chat is open.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Disable click-to-zoom for inline line sized images.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix host action buttons in the Docs Embed not reaching the assistant.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the Docs Embed widget rendering with a dark surface when the visitor's OS is in dark mode, even on a light page or a site published with a light theme. The embed script now accepts `?theme=light|dark` to force a scheme.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix suggested question clicks in the embed search not opening the assistant.
@@ -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/embed": patch
---
Make the Docs Embed widget match the page it is embedded in rather than the visitor's OS: a widget on a light page stays light even when the visitor's system is in dark mode, and the widget's own chrome and the docs inside it always render in the same scheme. Sites published with a single theme impose it on the widget too, since they render in it regardless. The standalone script takes `?theme=light` on its URL, and calling `init` twice now updates the options instead of throwing.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": minor
---
Support external links in published site navigation.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Skip internal paths (`~gitbook/*`, `.well-known/oauth-protected-resource`, `llms.txt`, `robots.txt`, `sitemap.xml`, `rss.xml`) when building URL lookup alternatives, to avoid resolving URLs that can never match content.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep published search results within the selected site-space scope during local and remote result fusion.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix page link titles showing the site section name instead of the target space title.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Self-host default Google fonts and inline only the @font-face rules of the fonts a site uses, instead of shipping render-blocking stylesheets covering all 23 families on every page.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Hide card fields that render no content, along with their title
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Upgrade react-hotkeys-hook to v5 and use its native `useKey` option so keyboard shortcuts match the produced key on non-QWERTY layouts.
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Keep embed demos and frames on the deployment that served them.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix a hydration mismatch on every page load caused by the AI chat time-based greeting being computed in the server timezone.
+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.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Stop preloading the zoom-modal variant of every zoomable image at render time; it downloaded each image twice during the initial page load. The modal image still loads on hover or click.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Serve an indexable `X-Robots-Tag` on markdown pages requested by AI agents
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Bump `@gitbook/api` to 0.199.0, and record a markdown request made from the page actions menu as a page action rather than an agent request.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the page-actions dropdown closing before the "Copied" confirmation could be shown when copying the MCP server URL, an MCP install command, or the page as Markdown.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Mermaid diagrams no longer hijack page scrolling: zooming with the wheel now requires holding Ctrl/Cmd inline, while the fullscreen view keeps free wheel zoom.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Migrate the headless UI primitives from Radix and react-aria to Base UI.
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Redesign the site OAuth consent screen for published sites MCP and translate its strings
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Drop a column instead of shrinking them all when a section group dropdown runs out of room
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Let a section group dropdown scroll when it is taller than the screen
+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
---
Skip the rendering work for off-screen OpenAPI blocks, so pages with many operations stay smooth to scroll.
@@ -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.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix OpenAPI webhook payload and schema example panels being clipped instead of scrollable.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Move paragraph block styles behind a single `paragraph` class and drop the `page-cover-background:` gate from the cover-contrast text. The gate combined with the per-paragraph `:not(:has(...))` made every DOM insertion re-style all paragraphs, which froze very long pages.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Prefix all cache tags with `ppr:` when rendering under the PPR route, so PPR cache entries are partitioned from the static ones.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Require a GitBook-secret signature on the `x-gbo-*` PPR headers, so a client can't opt itself into the PPR route.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Exchange the PPR revalidation token for a content API token scoped to each PPR component, so the API receives claims it understands and the header and table of contents can be cached across pages.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Preserve external page destinations returned by published search.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Use one canonical backend-ranked result set for published searches across site sections.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Preserve canonical backend ranking and present page or section context that matches each published search destination.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Align the Previous page navigation button to the left edge and the Next button to the right edge, including when only one of them is present.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Prewarm published search caches when readers open the search interface.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Inject site tracking scripts (analytics integrations) after `load` + idle instead of preloading them and executing them during the critical loading window.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Render horizontal and vertical merged table cells on published pages.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix text disappearing in Firefox and iOS Safari on pages with a background cover
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Render a site-space custom home page at its placement root while preserving the full space and normal page URLs.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fail closed in `/~gitbook/revalidate` when `GITBOOK_SECRET` is not configured, returning `403 Revalidation is disabled` instead of skipping the signature check, consistent with `force-revalidate`.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the docs embed not applying `?theme=light`/`?theme=dark`. The theme was dropped when the embed redirected to its default tab, and the embed tabs couldn't read it because they render statically (their request headers are empty). The middleware now threads a forced embed theme through the embed route context (scoped to the embed, not the main site), so the embed tabs honor it while staying statically rendered, and the redirect forwards it to the default tab. The forced theme is also persisted to the embed's own theme storage so it is remembered across tab navigation instead of only applying while the query string is present.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the search field losing focus if it was focused just before the page finished hydrating.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix code block syntax highlighting so comment delimiters (e.g. `//`, `/*`) use the same color as the rest of the comment. Previously the delimiter fell through to the generic punctuation scope, making it a different color from the comment body (most visible in dark mode).
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Scroll to the top when selecting a search result for the page already being viewed.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Add end-to-end coverage for root and nested external links in site section navigation.
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Allow published search to be scoped to any visible site section.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the spacebar being ignored in the search bar, which made multi-word queries impossible.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Keep keyboard focus within search while the results are open.
+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.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Show the containing section name when hovering a direct link to a space.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the section group menu dismissing while the mouse is still inside it, when the collapsed sidebar rail overlaps the menu on no-sidebar pages.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Show loose sections in a section group dropdown as secondary links unless the group starts with one
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Stop the section tabs in the header from showing a scroll button and faded edge when all tabs already fit.
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Render headings with the site's heading font when one is configured, falling back to the main font otherwise.
@@ -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
---
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
---
Fix tabs nested inside another tab group rendering an empty body once a tab in the outer group was selected.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Load the admin toolbar and its CSS lazily so published pages no longer ship a render-blocking stylesheet for admin-only UI.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Remove the gap between the columns of a section group dropdown holding a large group
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Support localized custom AI Assistant greeting subtitles.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix the first item of a table-of-contents page group appearing cut off (faded under the group header) after client-side navigation.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Highlight a table-of-contents link entry as active when it points to the page — or the section of a page — you are currently viewing.
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Fix chevrons and open-state styling incorrectly reacting to a tooltip opening on the same trigger, by switching from the shared Base UI `data-popup-open` attribute to `aria-expanded`.
+6
View File
@@ -0,0 +1,6 @@
---
"gitbook": patch
"@gitbook/react-contentkit": patch
---
Support query params in the `@webframe.navigate` action.
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Only track embed view events once the frame is actually shown to the reader
+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
-3
View File
@@ -1,3 +0,0 @@
# Changes to the API data cache functions can invalidate all existing data cache
# causing a massive amount of revalidation, impacting our API.
packages/gitbook/src/lib/data/api.ts @SamyPesse
+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 }}"
+53 -53
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,33 +42,34 @@ 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_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
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_EXCHANGE_TOKEN_URL: ${{ inputs.opItem }}/GITBOOK_EXCHANGE_TOKEN_URL
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_BLOCK_SEARCH_INDEXATION: ${{ inputs.environment == 'preview' && 'true' || '' }}
GITBOOK_ALLOW_CUSTOMIZATION_OVERRIDE: ${{ inputs.environment == 'preview' && 'true' || '' }}
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
@@ -135,11 +136,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 }}"
+60 -60
View File
@@ -1,31 +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
headSha:
description: 'Git ref to deploy, used for the deploymentId'
required: false
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:
@@ -40,51 +40,52 @@ 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_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
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_EXCHANGE_TOKEN_URL: ${{ inputs.opItem }}/GITBOOK_EXCHANGE_TOKEN_URL
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
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
GITBOOK_HEAD_SHA: ${{ inputs.headSha }}
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
@@ -92,10 +93,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,34 @@
name: CSS browser compatibility
on:
pull_request_target:
types: [opened, reopened, synchronize]
permissions:
contents: read
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 }}
+57 -9
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:
@@ -47,8 +47,8 @@ jobs:
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:
@@ -72,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 }}"
@@ -187,6 +187,54 @@ jobs:
SITE_BASE_URL: ${{ needs.deploy-v2-vercel.outputs.deployment-url }}/url/
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)
+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 }}"
+1 -1
View File
@@ -4,7 +4,7 @@ on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
+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"
}
}
+32 -2
View File
@@ -6,7 +6,8 @@
bun install # Install dependencies
bun dev # Start dev server (all packages)
bun run build # Build all packages
bun run format # Format with Biome (run after every change)
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
```
@@ -23,6 +24,35 @@ Examples:
- `http://localhost:3000/url/gitbook.com/docs`
- `http://localhost:3000/url/open-source.gitbook.io/midjourney`
### PPR routes
PPR requests are normally resolved upstream and arrive with a large set of `x-gbo-*` headers, so they
can't be reproduced by hitting the dev server directly. `bun run dev:ppr` (from `packages/gitbook`)
starts a dev-only proxy on port 3001 that resolves the URL, injects those headers and signs them.
The app rejects an unsigned set, so `GITBOOK_SECRET` must be set in `.env.local` (any value works
locally, as long as both processes read the same one).
The app also exchanges the PPR token for one scoped to each component, against
`GITBOOK_EXCHANGE_TOKEN_URL`. That endpoint only accepts a revalidation token, which the
published-URLs lookup never returns, so the proxy mints one with `PPR_DEV_API_TOKEN_SECRET` — a
local-only stand-in for the API token secret the cache worker holds in production. It must match the
secret the target `/token` endpoint verifies with, so local PPR needs a local gitbook-x sites stack.
The secret is read only by the proxy script: never add it to `src/lib/env`, `next.config.mjs` or a
deploy workflow.
```
GITBOOK_SECRET=<any value>
GITBOOK_EXCHANGE_TOKEN_URL=http://localhost:8788/token
PPR_DEV_API_TOKEN_SECRET=<local gitbook-x functionsConfig.api.tokenSecret>
```
```
http://localhost:3001/url/<published-gitbook-url>
```
Responses carry `x-gitbook-route-type: ppr` when the PPR route was used. Hot reload doesn't work
through the proxy (its websocket can't be forwarded), so keep using port 3000 while iterating.
## Architecture
```
@@ -74,7 +104,7 @@ Save as `.changeset/<name>.md`, then commit it separately with message: `changes
## Formatting
Uses Biome (not ESLint/Prettier). Always run `bun run format` before committing.
Linting uses Oxlint and formatting uses Oxfmt. Always run `bun run format` before committing.
## Comments
-178
View File
@@ -1,178 +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",
"gitbook/tsconfig.json",
"**/*.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"
]
}
}
]
}
+312 -716
View File
File diff suppressed because it is too large Load Diff
+13 -8
View File
@@ -5,8 +5,9 @@
"node": "^22.3.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@changesets/cli": "^2.31.0",
"oxfmt": "^0.62.0",
"oxlint": "^1.77.0",
"turbo": "^2.10.3",
"vercel": "50.37.3"
},
@@ -18,8 +19,7 @@
"react": "catalog:",
"react-dom": "catalog:",
"esbuild": "0.27.3",
"axios": "1.8.4",
"@radix-ui/react-slot": "1.2.4"
"axios": "1.8.4"
},
"private": true,
"scripts": {
@@ -27,8 +27,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",
@@ -39,11 +41,14 @@
"clean": "turbo run clean"
},
"workspaces": {
"packages": ["packages/*"],
"packages": [
"packages/*"
],
"catalog": {
"@tsconfig/strictest": "^2.0.6",
"@tsconfig/node20": "^20.1.6",
"@gitbook/api": "0.192.0",
"@base-ui/react": "^1.7.0",
"@gitbook/api": "0.199.0",
"@scalar/api-client-react": "^1.3.46",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
@@ -62,6 +67,6 @@
"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",
"next@16.2.11": "patches/next@16.2.11.patch"
"next@16.3.3": "patches/next@16.3.3.patch"
}
}

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