diff --git a/site/src/components/ErrorBoundary/RuntimeErrorState.tsx b/site/src/components/ErrorBoundary/RuntimeErrorState.tsx index b9a3c7e3254db..7466259fa8f46 100644 --- a/site/src/components/ErrorBoundary/RuntimeErrorState.tsx +++ b/site/src/components/ErrorBoundary/RuntimeErrorState.tsx @@ -10,6 +10,7 @@ import { CoderIcon } from "components/Icons/CoderIcon"; import { Loader } from "components/Loader/Loader"; import { Margins } from "components/Margins/Margins"; import { Stack } from "components/Stack/Stack"; +import { getStaticBuildInfo } from "utils/buildInfo"; const fetchDynamicallyImportedModuleError = "Failed to fetch dynamically imported module"; @@ -116,21 +117,6 @@ export const RuntimeErrorState: FC = ({ error }) => { ); }; -// During the build process, we inject the build info into the HTML -const getStaticBuildInfo = () => { - const buildInfoJson = document - .querySelector("meta[property=build-info]") - ?.getAttribute("content"); - - if (buildInfoJson) { - try { - return JSON.parse(buildInfoJson) as BuildInfoResponse; - } catch { - return undefined; - } - } -}; - const styles = { root: { paddingTop: 32, diff --git a/site/src/utils/buildInfo.ts b/site/src/utils/buildInfo.ts new file mode 100644 index 0000000000000..d6da4be1685a5 --- /dev/null +++ b/site/src/utils/buildInfo.ts @@ -0,0 +1,24 @@ +import type { BuildInfoResponse } from "api/typesGenerated"; + +let CACHED_BUILD_INFO: BuildInfoResponse | undefined; + +// During the build process, we inject the build info into the HTML +export const getStaticBuildInfo = () => { + if (CACHED_BUILD_INFO) { + return CACHED_BUILD_INFO; + } + + const buildInfoJson = document + .querySelector("meta[property=build-info]") + ?.getAttribute("content"); + + if (buildInfoJson) { + try { + CACHED_BUILD_INFO = JSON.parse(buildInfoJson) as BuildInfoResponse; + } catch { + return undefined; + } + } + + return CACHED_BUILD_INFO; +}; diff --git a/site/src/utils/docs.ts b/site/src/utils/docs.ts index 1d921d0b2038c..ce357777634c9 100644 --- a/site/src/utils/docs.ts +++ b/site/src/utils/docs.ts @@ -1,4 +1,20 @@ -const DEFAULT_DOCS_URL = "https://coder.com/docs"; +import { getStaticBuildInfo } from "./buildInfo"; + +function defaultDocsUrl(): string { + const docsUrl = "https://coder.com/docs"; + // If we can get the specific version, we want to include that in default docs URL. + let version = getStaticBuildInfo()?.version; + if (!version) { + return docsUrl; + } + + // Strip the postfix version info that's not part of the link. + const i = version?.indexOf("-") ?? -1; + if (i >= 0) { + version = version.slice(0, i); + } + return `${docsUrl}/@${version}`; +} // Add cache to avoid DOM reading all the time let CACHED_DOCS_URL: string | undefined; @@ -12,8 +28,9 @@ const getBaseDocsURL = () => { const docsUrl = document .querySelector('meta[property="docs-url"]') ?.getAttribute("content"); + const isValidDocsURL = docsUrl && isURL(docsUrl); - CACHED_DOCS_URL = isValidDocsURL ? docsUrl : DEFAULT_DOCS_URL; + CACHED_DOCS_URL = isValidDocsURL ? docsUrl : defaultDocsUrl(); } return CACHED_DOCS_URL; };