Skip to content

Commit

Permalink
chore: create public / private docs bundles (#392)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Jan 23, 2024
1 parent d5304d5 commit 8f17163
Show file tree
Hide file tree
Showing 91 changed files with 831 additions and 672 deletions.
303 changes: 189 additions & 114 deletions .pnp.cjs

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ FERN_NO_VERSION_REDIRECTION=true node <path to CLI> <args>

To build and run the NextJS docs UI, run either:

- `yarn workspace @fern-ui/fe-bundle dev:fern-dev`. This compiles and runs a NextJS app that communicates with our dev cloud environment.
- `yarn workspace @fern-ui/public-docs-bundle dev:fern-dev`. This compiles and runs a NextJS app that communicates with our dev cloud environment.

- `yarn workspace @fern-ui/fe-bundle dev:fern-prod`. This compiles and runs a NextJS app that communicates with our cloud production environment.
- `yarn workspace @fern-ui/public-docs-bundle dev:fern-prod`. This compiles and runs a NextJS app that communicates with our cloud production environment.

The frontend is served at `localhost:3000`. You can configure which docs are loaded by using `.env.local`:

```bash
# packages/ui/fe-bundle/.env.local
# packages/ui/public-docs-bundle/.env.local

# uncomment the next line when targeting the production cloud environment
# NEXT_PUBLIC_DOCS_DOMAIN=proficientai.docs.buildwithfern.com
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
"fern-script": "yarn workspace @fern-ui/scripts dist:cli && node $(yarn workspace @fern-ui/scripts bin fern-scripts)",
"check-docs-release-blockers": "yarn fern-script check-docs-release-blockers",
"root-package:check": "yarn fern-script check-root-package",
"root-package:fix": "yarn root-package:check --fix"
"root-package:fix": "yarn root-package:check --fix",
"dev:docs": "yarn workspace @fern-ui/public-docs-bundle run dev:fern-prod",
"dev:private-docs": "yarn workspace @fern-ui/private-docs-bundle run dev:fern-prod"
},
"devDependencies": {
"@babel/core": "^7.23.7",
Expand Down
9 changes: 8 additions & 1 deletion packages/ui/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@
"@fern-ui/loadable": "workspace:*",
"@fern-ui/react-commons": "workspace:*",
"@fontsource/ibm-plex-mono": "^4.5.13",
"@fortawesome/fontawesome-svg-core": "^6.4.2",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/pro-duotone-svg-icons": "^6.5.1",
"@fortawesome/pro-light-svg-icons": "^6.5.1",
"@fortawesome/pro-regular-svg-icons": "^6.5.1",
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "0.2.0",
"@headlessui/react": "^1.7.18",
"@react-hook/size": "^2.1.2",
"@vercel/speed-insights": "^1.0.7",
"algoliasearch": "^4.22.1",
"classnames": "^2.5.1",
"instantsearch.js": "^4.63.0",
Expand Down
13 changes: 10 additions & 3 deletions packages/ui/app/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
export { App } from "./App";
export { ThemeProvider } from "./docs/ThemeProvider";
export { useColorTheme } from "./hooks/useColorTheme";
export { proxyApiHandler } from "./next-apis/proxy";
export { revalidateAllApiHandler } from "./next-apis/revalidate-all";
export { revalidateV1ApiHandler } from "./next-apis/revalidate-v1";
export { revalidateV2ApiHandler } from "./next-apis/revalidate-v2";
export { serializeMdxApiHandler } from "./next-apis/serialize-mdx";
export { sitemapApiHandler } from "./next-apis/sitemap";
export { DocsPage, getDocsPageProps, getDocsPageStaticProps } from "./next-app/DocsPage";
export { NextApp } from "./next-app/NextApp";
export { NextDocument } from "./next-app/NextDocument";
export { getNotFoundPageStaticProps, NotFoundPage } from "./next-app/NotFoundPage";
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface ProxyResponseSuccess {

type ProxyResponse = ProxyResponseError | ProxyResponseSuccess;

const handler: NextApiHandler = async (req, res: NextApiResponse<ProxyResponse>) => {
export const proxyApiHandler: NextApiHandler = async (req, res: NextApiResponse<ProxyResponse>) => {
const startTime = performance.now();
try {
if (req.method !== "POST") {
Expand Down Expand Up @@ -71,5 +71,3 @@ const handler: NextApiHandler = async (req, res: NextApiResponse<ProxyResponse>)
});
}
};

export default handler;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FdrAPI, PathResolver } from "@fern-api/fdr-sdk";
import { NextApiHandler, NextApiResponse } from "next";
import { REGISTRY_SERVICE } from "../../service";
import { buildUrl } from "../../utils/buildUrl";
import { REGISTRY_SERVICE } from "../services/registry";
import { buildUrl } from "../util/buildUrl";
import { toValidPathname } from "./sitemap";

const handler: NextApiHandler = async (req, res: NextApiResponse<void>) => {
export const revalidateAllApiHandler: NextApiHandler = async (req, res: NextApiResponse<void>) => {
try {
if (req.method !== "POST") {
res.status(400).send();
Expand Down Expand Up @@ -55,5 +55,3 @@ const handler: NextApiHandler = async (req, res: NextApiResponse<void>) => {
res.status(500).send();
}
};

export default handler;
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FdrAPI, PathResolver } from "@fern-api/fdr-sdk";
import { NextApiHandler, NextApiResponse } from "next";
import { REGISTRY_SERVICE } from "../../service";
import { REGISTRY_SERVICE } from "../services/registry";

export interface Request {
url: string;
}

const handler: NextApiHandler = async (req, res) => {
export const revalidateV1ApiHandler: NextApiHandler = async (req, res) => {
try {
const url = req.body?.url;
const docsConfigId = req.body?.docsConfigId;
Expand Down Expand Up @@ -102,5 +102,3 @@ async function tryRevalidate(res: NextApiResponse, path: string): Promise<Revali
};
}
}

export default handler;
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function parseRequestBody(rawBody: unknown): ParseResult {
return { success: true, request: { path } };
}

const handler: NextApiHandler = async (req, res: NextApiResponse<ResponseBody>) => {
export const revalidateV2ApiHandler: NextApiHandler = async (req, res: NextApiResponse<ResponseBody>) => {
try {
if (req.method !== "POST") {
res.status(400).send({
Expand Down Expand Up @@ -92,5 +92,3 @@ const handler: NextApiHandler = async (req, res: NextApiResponse<ResponseBody>)
});
}
};

export default handler;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FdrAPI, PathResolver, type FullSlug } from "@fern-api/fdr-sdk";
import { SerializedMdxContent, serializeMdxContent } from "@fern-ui/app-utils";
import { isPlainObject } from "@fern-ui/core-utils";
import { NextApiHandler, NextApiResponse } from "next";
import { REGISTRY_SERVICE } from "../../service";
import { REGISTRY_SERVICE } from "../services/registry";

interface Request {
fullSlugs: string[];
Expand Down Expand Up @@ -44,7 +44,7 @@ function parseRequestBody(rawBody: unknown): Request | undefined {
}
}

const handler: NextApiHandler = async (req, res: NextApiResponse<Response>) => {
export const serializeMdxApiHandler: NextApiHandler = async (req, res: NextApiResponse<Response>) => {
try {
if (req.method !== "POST") {
res.status(400).send({
Expand Down Expand Up @@ -129,5 +129,3 @@ const handler: NextApiHandler = async (req, res: NextApiResponse<Response>) => {
});
}
};

export default handler;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FdrAPI, PathResolver } from "@fern-api/fdr-sdk";
import { NextApiHandler, NextApiResponse } from "next";
import { REGISTRY_SERVICE } from "../../service";
import { buildUrl } from "../../utils/buildUrl";
import { REGISTRY_SERVICE } from "../services/registry";
import { buildUrl } from "../util/buildUrl";

export function toValidPathname(pathname: string | string[] | undefined): string {
if (typeof pathname === "string") {
Expand All @@ -13,7 +13,7 @@ export function toValidPathname(pathname: string | string[] | undefined): string
return "";
}

const handler: NextApiHandler = async (req, res: NextApiResponse<string[]>) => {
export const sitemapApiHandler: NextApiHandler = async (req, res: NextApiResponse<string[]>) => {
try {
if (req.method !== "GET") {
res.status(400).json([]);
Expand Down Expand Up @@ -70,5 +70,3 @@ const handler: NextApiHandler = async (req, res: NextApiResponse<string[]>) => {
res.status(500).json([]);
}
};

export default handler;
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import type { ResolvedPath } from "@fern-ui/app-utils";
import "@fontsource/ibm-plex-mono";
import "normalize.css";
import { useEffect } from "react";
import { initializePosthog } from "./analytics/posthog";
import { CONTEXTS } from "./contexts";
import { DocsContextProvider } from "./docs-context/DocsContextProvider";
import { Docs } from "./docs/Docs";
import { NavigationContextProvider } from "./navigation-context/NavigationContextProvider";
import { initializePosthog } from "../analytics/posthog";
import { CONTEXTS } from "../contexts";
import { DocsContextProvider } from "../docs-context/DocsContextProvider";
import { Docs } from "../docs/Docs";
import { NavigationContextProvider } from "../navigation-context/NavigationContextProvider";

FocusStyleManager.onlyShowFocusOnTabs();

Expand All @@ -24,7 +24,7 @@ export declare namespace App {
}
}

export const App: React.FC<App.Props> = ({ docs, resolvedPath }) => {
export const DocsApp: React.FC<App.Props> = ({ docs, resolvedPath }) => {
useEffect(() => {
if (process.env.NEXT_PUBLIC_POSTHOG_API_KEY != null && process.env.NEXT_PUBLIC_POSTHOG_API_KEY.length > 0) {
initializePosthog(process.env.NEXT_PUBLIC_POSTHOG_API_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import {
loadDocTypography,
type ResolvedPath,
} from "@fern-ui/app-utils";
import { App, useColorTheme } from "@fern-ui/ui";
import { visitDiscriminatedUnion } from "@fern-ui/core-utils";
import { compact } from "lodash-es";
import { GetStaticPaths, GetStaticProps } from "next";
import { GetStaticProps, Redirect } from "next";
import Head from "next/head";
import { ReactElement } from "react";
import { REGISTRY_SERVICE } from "../../service";
import { buildUrl } from "../../utils/buildUrl";
import { useColorTheme } from "../hooks/useColorTheme";
import { REGISTRY_SERVICE } from "../services/registry";
import { buildUrl } from "../util/buildUrl";
import { DocsApp } from "./DocsApp";

export declare namespace Docs {
export declare namespace DocsPage {
export interface Props {
docs: DocsV2Read.LoadDocsForUrlResponse;
typographyStyleSheet?: string;
Expand All @@ -23,12 +25,12 @@ export declare namespace Docs {
}
}

export default function Docs({
export function DocsPage({
docs,
typographyStyleSheet = "",
backgroundImageStyleSheet = "",
resolvedPath,
}: Docs.Props): ReactElement {
}: DocsPage.Props): ReactElement {
const colorThemeStyleSheet = useColorTheme(docs.definition);
return (
<>
Expand All @@ -55,17 +57,22 @@ export default function Docs({
<link rel="icon" id="favicon" href={docs.definition.files[docs.definition.config.favicon]} />
)}
</Head>
<App docs={docs} resolvedPath={resolvedPath} />
<DocsApp docs={docs} resolvedPath={resolvedPath} />
</>
);
}

export const getStaticProps: GetStaticProps<Docs.Props> = async ({ params = {} }) => {
const xFernHost = process.env.NEXT_PUBLIC_DOCS_DOMAIN ?? params.host;
const slugArray = compact(params.slug);
export type DocsPageResult<Props> =
| { type: "props"; props: Props; revalidate?: number | boolean }
| { type: "redirect"; redirect: Redirect; revalidate?: number | boolean }
| { type: "notFound"; notFound: true; revalidate?: number | boolean };

export const getDocsPageProps = async (
xFernHost: string | undefined,
slugArray: string[]
): Promise<DocsPageResult<DocsPage.Props>> => {
if (xFernHost == null || Array.isArray(xFernHost)) {
return { notFound: true };
return { type: "notFound", notFound: true };
}

const pathname = slugArray != null ? slugArray.join("/") : "";
Expand All @@ -77,6 +84,7 @@ export const getStaticProps: GetStaticProps<Docs.Props> = async ({ params = {} }
// eslint-disable-next-line no-console
console.error(`Failed to fetch docs for path: /${pathname}`, docs.error);
return {
type: "notFound",
notFound: true,
revalidate: 60,
};
Expand All @@ -100,6 +108,7 @@ export const getStaticProps: GetStaticProps<Docs.Props> = async ({ params = {} }
// eslint-disable-next-line no-console
console.error(`Cannot resolve navigatable corresponding to "${pathname}"`);
return {
type: "notFound",
notFound: true,
revalidate: 60 * 60, // 1 hour
};
Expand All @@ -112,6 +121,7 @@ export const getStaticProps: GetStaticProps<Docs.Props> = async ({ params = {} }
});

return {
type: "props",
props: {
docs: docs.body,
typographyStyleSheet,
Expand All @@ -122,6 +132,16 @@ export const getStaticProps: GetStaticProps<Docs.Props> = async ({ params = {} }
};
};

export const getStaticPaths: GetStaticPaths = () => {
return { paths: [], fallback: "blocking" };
export const getDocsPageStaticProps: GetStaticProps<DocsPage.Props> = async ({ params = {} }) => {
const xFernHost = process.env.NEXT_PUBLIC_DOCS_DOMAIN ?? (params.host as string);
const slugArray = compact(params.slug);

const result = await getDocsPageProps(xFernHost, slugArray);

return visitDiscriminatedUnion(result, "type")._visit<ReturnType<GetStaticProps<DocsPage.Props>>>({
notFound: (notFound) => ({ notFound: true, revalidate: notFound.revalidate }),
redirect: (redirect) => ({ redirect: redirect.redirect, revalidate: redirect.revalidate }),
props: (props) => ({ props: props.props, revalidate: props.revalidate }),
_other: () => ({ notFound: true }),
});
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ThemeProvider } from "@fern-ui/ui";
import "@fortawesome/fontawesome-svg-core/styles.css";
import type { AppProps } from "next/app";
import { ReactElement } from "react";
import { setupFontAwesomeIcons } from "../setup-icons";
import "../styles/globals.css";
import { Docs } from "./[host]/[[...slug]]";
import { ThemeProvider } from "../docs/ThemeProvider";
import { setupFontAwesomeIcons } from "../util/setupFontAwesomeIcons";
import { DocsPage } from "./DocsPage";
import "./globals.css";

setupFontAwesomeIcons();

export default function App({ Component, pageProps }: AppProps<Partial<Docs.Props>>): ReactElement {
export function NextApp({ Component, pageProps }: AppProps<Partial<DocsPage.Props>>): ReactElement {
const theme = pageProps.docs?.definition.config.colorsV3.type;
return (
<ThemeProvider theme={theme}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SpeedInsights } from "@vercel/speed-insights/next";
import { Head, Html, Main, NextScript } from "next/document";
import { ReactElement } from "react";

export default function Document(): ReactElement {
export function NextDocument(): ReactElement {
return (
<Html lang="en" suppressHydrationWarning>
<Head />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import dynamic from "next/dynamic";
import { useRouter } from "next/router";
import { GetStaticProps } from "next/types";
import { REGISTRY_SERVICE } from "../service";
import { buildUrl } from "../utils/buildUrl";
import { REGISTRY_SERVICE } from "../services/registry";
import { buildUrl } from "../util/buildUrl";

export declare namespace NotFoundPage {
export interface Props {
Expand All @@ -16,11 +16,11 @@ const Core: React.FC<NotFoundPage.Props> = ({ basePath }) => {
return null;
};

const NotFoundPage = dynamic(() => Promise.resolve(Core), {
export const NotFoundPage = dynamic(() => Promise.resolve(Core), {
ssr: false,
});

export const getStaticProps: GetStaticProps<NotFoundPage.Props> = async ({ params = {} }) => {
export const getNotFoundPageStaticProps: GetStaticProps<NotFoundPage.Props> = async ({ params = {} }) => {
const host = params.host as string | undefined;
const slugArray = params.slug as string[] | undefined;
const pathname = slugArray != null ? slugArray.join("/") : "";
Expand All @@ -33,5 +33,3 @@ export const getStaticProps: GetStaticProps<NotFoundPage.Props> = async ({ param
revalidate: 60,
};
};

export default NotFoundPage;
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 0 additions & 5 deletions packages/ui/fe-bundle/src/service.ts

This file was deleted.

3 changes: 0 additions & 3 deletions packages/ui/fe-bundle/src/utils/dummy.ts

This file was deleted.

Loading

0 comments on commit 8f17163

Please sign in to comment.