Skip to content

Commit 51329cf

Browse files
authored
feat: next -> main (#378)
1 parent 5f3667b commit 51329cf

File tree

6 files changed

+160
-14
lines changed

6 files changed

+160
-14
lines changed

website/src/components/Link.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ export function Link(props: LinkProps) {
1414
);
1515
}
1616

17-
return <InternalLink {...props} href={"/getting-started"} />;
17+
return <InternalLink {...props} href={href} />;
1818
}

website/src/components/Scripts.tsx

+13-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export function Scripts() {
77
const scripts = usePageContext().bundle.config.scripts;
88

99
// We don't want to load the scripts in preview mode or in preview environments.
10-
if (ctx.preview || getEnvironment() !== "production") {
10+
if (ctx.preview) {
1111
return null;
1212
}
1313

@@ -20,15 +20,21 @@ export function Scripts() {
2020
/>
2121
)}
2222
{!!scripts?.googleAnalytics && (
23-
<Script
24-
async
25-
dangerouslySetInnerHTML={{
26-
__html: `
23+
<>
24+
<Script
25+
async
26+
src={`https://www.googletagmanager.com/gtag/js?id=${scripts.googleAnalytics}`}
27+
/>
28+
<Script
29+
async
30+
dangerouslySetInnerHTML={{
31+
__html: `
2732
window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments)}
2833
gtag('js', new Date()); gtag('config', '${scripts.googleAnalytics}');
2934
`,
30-
}}
31-
/>
35+
}}
36+
/>
37+
</>
3238
)}
3339
{"domain" in ctx && !!ctx.domain && !!scripts?.plausible && (
3440
<Script

website/src/components/Sidebar.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function GroupHeading(props: { title: string; icon?: string }) {
5959

6060
// A recursive sidebar navigation component, renders a list of links and groups.
6161
function SidebarLinks(
62-
props: { pages: Pages } & { open: boolean; depth: number },
62+
props: { pages: Pages } & { open: boolean; depth: number }
6363
) {
6464
return (
6565
<ul aria-expanded={props.open}>

website/src/context.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,13 @@ export async function getRequestContext(
5555
) {
5656
const { owner, repository, ref, path } = opts;
5757

58-
const vanity = request.headers["x-docs-page-vanity-domain"] !== undefined;
58+
// Checks if the incoming request is from the vanity domain proxy.
59+
const isVanityDomainRequest =
60+
request.headers["x-docs-page-vanity-domain"] !== undefined;
61+
62+
// Checks if the incoming request is from a custom domain.
63+
const isCustomDomainRequest =
64+
request.headers["x-docs-page-custom-domain"] !== undefined;
5965

6066
const bundle = await getBundle({
6167
owner,
@@ -68,6 +74,8 @@ export async function getRequestContext(
6874
const environment = getEnvironment();
6975

7076
// Check whether the repository has a domain assigned.
77+
// We still do this here since we need to know if internal links
78+
// should be prefixed with the domain if one is set.
7179
const domain = domains
7280
.find(([, repo]) => repo === `${owner}/${repository}`)
7381
?.at(0);
@@ -85,7 +93,7 @@ export async function getRequestContext(
8593
}
8694

8795
let url = "";
88-
if (vanity) {
96+
if (isVanityDomainRequest) {
8997
url = `https://${owner}.docs.page/${repository}`;
9098
if (ref) url += `~${ref}`;
9199
url += redirectTo;
@@ -115,8 +123,13 @@ export async function getRequestContext(
115123
owner,
116124
repository,
117125
ref: ref || null,
118-
domain: domain && environment === "production" ? domain : null,
119-
vanity,
126+
domain:
127+
isCustomDomainRequest && environment === "development"
128+
? "localhost:8787"
129+
: domain && environment === "production"
130+
? domain
131+
: null,
132+
vanity: isVanityDomainRequest,
120133
bundle,
121134
preview: false,
122135
} satisfies Context;

website/src/pages/[[...path]].tsx

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import type { GetServerSideProps, InferGetServerSidePropsType } from "next";
2+
import type { BundleErrorResponse } from "~/api";
3+
import { type Context, getRequestContext } from "~/context";
4+
import type { SharedEnvironmentVariables } from "~/env";
5+
6+
import { Documentation } from "~/layouts/Documentation";
7+
import { Error } from "~/layouts/Error";
8+
import { Homepage } from "~/layouts/homepage";
9+
import { Site } from "~/layouts/Site";
10+
import { Redirect, bundleCodeToStatusCode } from "~/utils";
11+
12+
export const getServerSideProps = (async ({ params, req, res }) => {
13+
const env = {
14+
VERCEL: process.env.VERCEL || null,
15+
VERCEL_ENV: process.env.VERCEL_ENV || null,
16+
VERCEL_GIT_COMMIT_SHA: process.env.VERCEL_GIT_COMMIT_SHA || null,
17+
} satisfies SharedEnvironmentVariables;
18+
19+
const param = params?.path ? params.path : [];
20+
const chunks = Array.isArray(param) ? param : [param];
21+
22+
// If there are no chunks, render the homepage.
23+
if (chunks.length === 0) {
24+
return { props: { env, ctx: null } };
25+
}
26+
27+
// Any paths with only one chunk are invalid, and should be handled
28+
// by other page routes.
29+
if (chunks.length === 1) {
30+
return { notFound: true };
31+
}
32+
33+
// Any paths with two chunks or more are a repository page.
34+
let [owner, repository, ...path] = chunks;
35+
let ref: string | undefined;
36+
37+
// Check if the repo includes a ref (invertase/foo~bar)
38+
if (repository.includes("~")) {
39+
[repository, ref] = repository.split("~");
40+
}
41+
42+
let ctx: Context | null = null;
43+
44+
try {
45+
ctx = await getRequestContext(req, {
46+
owner,
47+
repository,
48+
ref,
49+
path: path.join("/"),
50+
});
51+
} catch (error) {
52+
// If error is a Redirect instance
53+
if (error instanceof Redirect) {
54+
return {
55+
redirect: {
56+
destination: error.url,
57+
permanent: false,
58+
},
59+
};
60+
}
61+
62+
// If error is a Response instance
63+
if (error instanceof Response) {
64+
// Parse the response body as JSON.
65+
const body = (await error.json()) as BundleErrorResponse;
66+
67+
// Set the status code to the bundle error code.
68+
res.statusCode = bundleCodeToStatusCode(body);
69+
70+
return {
71+
props: {
72+
error: body,
73+
},
74+
};
75+
}
76+
77+
throw error;
78+
}
79+
80+
// Cache the response for 1 second, and revalidate in the background.
81+
res.setHeader(
82+
"Cache-Control",
83+
"public, s-maxage=1, stale-while-revalidate=59"
84+
);
85+
86+
return { props: { env, ctx } };
87+
}) satisfies GetServerSideProps<
88+
| {
89+
env: SharedEnvironmentVariables;
90+
ctx: Context | null;
91+
}
92+
| {
93+
error: BundleErrorResponse;
94+
}
95+
>;
96+
97+
export default function Route({
98+
env,
99+
ctx,
100+
error,
101+
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
102+
// If there is an error, render the error page.
103+
if (error) {
104+
return (
105+
<Site>
106+
<Error error={error} />
107+
</Site>
108+
);
109+
}
110+
111+
if (!ctx) {
112+
return <Homepage />;
113+
}
114+
115+
return (
116+
<>
117+
<script
118+
dangerouslySetInnerHTML={{
119+
__html: `window.ENV = ${env ? JSON.stringify(env) : "{}"}`,
120+
}}
121+
/>
122+
<Documentation ctx={ctx} />
123+
</>
124+
);
125+
}

website/src/utils.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import cx from "classnames";
22
import { twMerge } from "tailwind-merge";
33
import type { BundleResponse } from "./api";
44
import type { Context } from "./context";
5+
import { getEnvironment } from "./env";
56

67
export class Redirect extends Error {
78
url: string;
@@ -114,7 +115,8 @@ export function getHref(ctx: Context, path: string) {
114115
}
115116
// Ensure all links start with the custom domain if it's set.
116117
else if (ctx.domain) {
117-
href += `https://${ctx.domain}`;
118+
const protocol = getEnvironment() === 'development' ? 'http' : 'https';
119+
href += `${protocol}://${ctx.domain}`;
118120
}
119121
// Prefix the path with the owner and repository, e.g. `/invertase/docs.page`.
120122
else {

0 commit comments

Comments
 (0)