@@ -157,9 +157,14 @@ export function Link(props: LinkProps) {
157157 ) ;
158158 }
159159
160- // Not sure why yet, but it seems necessary to force prefetch to true
161- // default behavior doesn't seem to properly use the client router cache.
162- const _prefetch = prefetch === null || prefetch === undefined ? true : prefetch ;
160+ // Not sure why yet, but forcing prefetch to true seems necessary for the
161+ // client router cache to be used properly.
162+ //
163+ // However, we need to disable prefetch for links with query params that
164+ // can trigger server-side side effects, such as persisting visitor claims in a
165+ // cookie or starting the assistant. Automatic RSC prefetch requests can otherwise
166+ // trigger those effects without user intent.
167+ const _prefetch = hasSideEffectQueryParams ( href ) ? false : ( prefetch ?? true ) ;
163168
164169 return (
165170 < NextLink
@@ -175,6 +180,31 @@ export function Link(props: LinkProps) {
175180 ) ;
176181}
177182
183+ /**
184+ * Whether the given href carries query params that have a server-side side effect when fetched:
185+ * - `visitor.*` params persist unsigned visitor claims into the `gitbook-visitor-public` cookie.
186+ * - `ask` triggers the assistant & `q` the search.
187+ *
188+ * NextLink automatically prefetches links (RSC requests) on hover/viewport, which would fire those
189+ * side effects without any user intent, so such links should not be prefetched.
190+ */
191+ function hasSideEffectQueryParams ( href : string ) : boolean {
192+ const baseURL = typeof window !== 'undefined' ? window . location . origin : 'http://localhost' ;
193+ const linkURL = URL . canParse ( href ) ? new URL ( href ) : new URL ( href , baseURL ) ;
194+
195+ if ( linkURL . searchParams . get ( 'ask' ) !== null || linkURL . searchParams . get ( 'q' ) !== null ) {
196+ return true ;
197+ }
198+
199+ for ( const key of linkURL . searchParams . keys ( ) ) {
200+ if ( key . startsWith ( 'visitor.' ) ) {
201+ return true ;
202+ }
203+ }
204+
205+ return false ;
206+ }
207+
178208/**
179209 * A box used to contain a link overlay.
180210 * It is used to create a clickable area that can contain other elements.
0 commit comments