diff --git a/src/app/[spaceId]/.gitbook/pdf/page.tsx b/src/app/[spaceId]/.gitbook/pdf/page.tsx
index 9ebddb820..f9a5fbdcf 100644
--- a/src/app/[spaceId]/.gitbook/pdf/page.tsx
+++ b/src/app/[spaceId]/.gitbook/pdf/page.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
-import { api } from '@/lib/api';
+import { getPageDocument, getSpace, getCurrentRevision } from '@/lib/api';
import { resolvePageId } from '@/lib/pages';
import { pagePDFContainerId, PageHrefContext } from '@/lib/links';
import { DocumentView } from '@/components/DocumentView';
@@ -27,9 +27,9 @@ export default async function PDFHTMLOutput(props: {
const { params, searchParams } = props;
const { spaceId } = params;
- const [{ data: space }, { data: revision }] = await Promise.all([
- api().spaces.getSpaceById(spaceId),
- api().spaces.getCurrentRevision(spaceId),
+ const [space, revision] = await Promise.all([
+ getSpace(spaceId),
+ getCurrentRevision(spaceId),
]);
const pages = selectPages(revision, searchParams).slice(0, 4); // TODO: remove slice
@@ -75,9 +75,7 @@ async function PDFPageDocument(props: {
}) {
const { space, revision, page, linksContext } = props;
- const {
- data: { document },
- } = await api().spaces.getPageInRevisionById(space.id, revision.id, page.id);
+ const document = await getPageDocument(space.id, revision.id, page.id);
return (
diff --git a/src/app/[spaceId]/[[...pathname]]/page.tsx b/src/app/[spaceId]/[[...pathname]]/page.tsx
index fda08e280..94cfef92d 100644
--- a/src/app/[spaceId]/[[...pathname]]/page.tsx
+++ b/src/app/[spaceId]/[[...pathname]]/page.tsx
@@ -3,7 +3,7 @@ import { PageHrefContext, absoluteHref, pageHref } from '@/lib/links';
import { Metadata } from 'next';
import { notFound, redirect } from 'next/navigation';
import { PagePathParams, fetchPageData, getPagePath } from '../fetch';
-import { api } from '@/lib/api';
+import { getPageDocument } from '@/lib/api';
/**
* Fetch and render a page.
@@ -20,9 +20,7 @@ export default async function Page(props: { params: PagePathParams }) {
redirect(pageHref(page, linksContext));
}
- const {
- data: { document },
- } = await api().spaces.getPageInRevisionById(space.id, revision.id, page.id);
+ const document = await getPageDocument(space.id, revision.id, page.id);
return (
) : null}
@@ -34,7 +34,7 @@ export function PageFooterNavigation(props: {
icon={IconArrowRight}
label={t({ space }, 'next_page')}
title={next.title}
- href={pageHref(next.path)}
+ href={pageHref(next)}
/>
) : null}
diff --git a/src/components/TableOfContents/PageDocumentItem.tsx b/src/components/TableOfContents/PageDocumentItem.tsx
index 2ac71243d..cc5c500a9 100644
--- a/src/components/TableOfContents/PageDocumentItem.tsx
+++ b/src/components/TableOfContents/PageDocumentItem.tsx
@@ -1,6 +1,6 @@
import { RevisionPageDocument, RevisionPageGroup } from '@gitbook/api';
import { tcls } from '@/lib/tailwind';
-import Link, { LinkProps } from 'next/link';
+import Link from 'next/link';
import { PagesList } from './PagesList';
import { pageHref } from '@/lib/links';
import { ToggeableLinkItem } from './ToggeableLinkItem';
diff --git a/src/components/TableOfContents/PageLinkItem.tsx b/src/components/TableOfContents/PageLinkItem.tsx
new file mode 100644
index 000000000..f5076aa7b
--- /dev/null
+++ b/src/components/TableOfContents/PageLinkItem.tsx
@@ -0,0 +1,30 @@
+import { RevisionPageLink } from '@gitbook/api';
+import { tcls } from '@/lib/tailwind';
+import Link from 'next/link';
+
+export function PageLinkItem(props: {
+ page: RevisionPageLink;
+}) {
+ const { page } = props;
+
+ return (
+
+ {page.title}
+
+ );
+}
diff --git a/src/components/TableOfContents/PagesList.tsx b/src/components/TableOfContents/PagesList.tsx
index dd62ae5c3..4bdd7a1c1 100644
--- a/src/components/TableOfContents/PagesList.tsx
+++ b/src/components/TableOfContents/PagesList.tsx
@@ -2,6 +2,7 @@ import { RevisionPage, RevisionPageDocument, RevisionPageGroup } from '@gitbook/
import { ClassValue, tcls } from '@/lib/tailwind';
import { PageDocumentItem } from './PageDocumentItem';
import { PageGroupItem } from './PageGroupItem';
+import { PageLinkItem } from './PageLinkItem';
export function PagesList(props: {
pages: RevisionPage[];
@@ -23,6 +24,13 @@ export function PagesList(props: {
ancestors={ancestors}
/>
);
+ } else if (page.type === 'link') {
+ return (
+
+ );
}
return (
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 56c198887..0685eb7f5 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,7 +1,8 @@
import 'server-only';
import { headers } from 'next/headers';
-import { GitBookAPI } from '@gitbook/api';
+import { unstable_cache } from 'next/cache';
+import { GitBookAPI, JSONDocument } from '@gitbook/api';
/**
* Create an API client for the current request.
@@ -17,3 +18,36 @@ export function api(): GitBookAPI {
return gitbook;
}
+
+/**
+ * Get a space by its ID.
+ */
+export const getSpace = unstable_cache(async (spaceId: string) => {
+ const { data } = await api().spaces.getSpaceById(spaceId);
+ return data;
+}, ['api', 'spaces'], {
+ tags: ['api', 'spaces']
+});
+
+/**
+ * Get the current revision of a space
+ */
+export const getCurrentRevision = unstable_cache(async (spaceId: string) => {
+ const { data } = await api().spaces.getCurrentRevision(spaceId);
+ return data;
+}, ['api', 'revisions'], {
+ tags: ['api', 'revisions']
+});
+
+/**
+ * Get the document for a page.
+ */
+export const getPageDocument = unstable_cache(async (spaceId: string, revisionId: string, pageId: string) => {
+ const { data } = await api().spaces.getPageInRevisionById(spaceId, revisionId, pageId);
+ // @ts-ignore
+ return data.document as JSONDocument;
+}, ['api', 'documents'], {
+ tags: ['api', 'documents']
+});
+
+