diff --git a/site/src/components/Dashboard/DashboardLayout.tsx b/site/src/components/Dashboard/DashboardLayout.tsx
index 72b9f910f6..7ffd518d5f 100644
--- a/site/src/components/Dashboard/DashboardLayout.tsx
+++ b/site/src/components/Dashboard/DashboardLayout.tsx
@@ -15,6 +15,7 @@ import Link from "@mui/material/Link"
import Box from "@mui/material/Box"
import InfoOutlined from "@mui/icons-material/InfoOutlined"
import Button from "@mui/material/Button"
+import { docs } from "utils/docs"
export const DashboardLayout: FC = () => {
const styles = useStyles()
@@ -79,9 +80,7 @@ export const DashboardLayout: FC = () => {
Coder {updateCheck?.version} is now available. View the{" "}
release notes and{" "}
-
- upgrade instructions
- {" "}
+ upgrade instructions{" "}
for more information.
diff --git a/site/src/components/PortForwardButton/PortForwardButton.tsx b/site/src/components/PortForwardButton/PortForwardButton.tsx
index efee48eebc..5c8b4943f8 100644
--- a/site/src/components/PortForwardButton/PortForwardButton.tsx
+++ b/site/src/components/PortForwardButton/PortForwardButton.tsx
@@ -17,6 +17,7 @@ import { Maybe } from "components/Conditionals/Maybe"
import { useMachine } from "@xstate/react"
import { portForwardMachine } from "xServices/portForward/portForwardXService"
import { SecondaryAgentButton } from "components/Resources/AgentButton"
+import { docs } from "utils/docs"
export interface PortForwardButtonProps {
host: string
@@ -129,7 +130,7 @@ const TooltipView: React.FC = (props) => {
-
+
Learn more about web port forwarding
diff --git a/site/src/components/SSHButton/SSHButton.tsx b/site/src/components/SSHButton/SSHButton.tsx
index 4e89b4b806..480ae617b7 100644
--- a/site/src/components/SSHButton/SSHButton.tsx
+++ b/site/src/components/SSHButton/SSHButton.tsx
@@ -9,6 +9,7 @@ import {
HelpTooltipLinksGroup,
HelpTooltipText,
} from "../Tooltips/HelpTooltip"
+import { docs } from "utils/docs"
export interface SSHButtonProps {
workspaceName: string
@@ -85,16 +86,16 @@ export const SSHButton: React.FC> = ({
-
+
Install Coder CLI
-
+
Connect via VS Code Remote SSH
-
+
Connect via JetBrains Gateway
-
+
SSH configuration
diff --git a/site/src/components/Tooltips/AuditHelpTooltip.tsx b/site/src/components/Tooltips/AuditHelpTooltip.tsx
index 05c5f816f4..a5c0e7905e 100644
--- a/site/src/components/Tooltips/AuditHelpTooltip.tsx
+++ b/site/src/components/Tooltips/AuditHelpTooltip.tsx
@@ -6,6 +6,7 @@ import {
HelpTooltipText,
HelpTooltipTitle,
} from "./HelpTooltip"
+import { docs } from "utils/docs"
export const Language = {
title: "What is an audit log?",
@@ -19,7 +20,7 @@ export const AuditHelpTooltip: FC = () => {
{Language.title}
{Language.body}
-
+
{Language.docs}
diff --git a/site/src/components/Tooltips/UserRoleHelpTooltip.tsx b/site/src/components/Tooltips/UserRoleHelpTooltip.tsx
index 232c56ab60..c446f5a32c 100644
--- a/site/src/components/Tooltips/UserRoleHelpTooltip.tsx
+++ b/site/src/components/Tooltips/UserRoleHelpTooltip.tsx
@@ -6,6 +6,7 @@ import {
HelpTooltipText,
HelpTooltipTitle,
} from "./HelpTooltip"
+import { docs } from "utils/docs"
export const Language = {
title: "What is a role?",
@@ -21,7 +22,7 @@ export const UserRoleHelpTooltip: FC = () => {
{Language.title}
{Language.text}
-
+
{Language.link}
diff --git a/site/src/components/Tooltips/WorkspaceHelpTooltip.tsx b/site/src/components/Tooltips/WorkspaceHelpTooltip.tsx
index 23524cd88f..58001bd9b8 100644
--- a/site/src/components/Tooltips/WorkspaceHelpTooltip.tsx
+++ b/site/src/components/Tooltips/WorkspaceHelpTooltip.tsx
@@ -6,6 +6,7 @@ import {
HelpTooltipText,
HelpTooltipTitle,
} from "./HelpTooltip"
+import { docs } from "utils/docs"
const Language = {
workspaceTooltipTitle: "What is a workspace?",
@@ -22,13 +23,13 @@ export const WorkspaceHelpTooltip: FC = () => {
{Language.workspaceTooltipTitle}
{Language.workspaceTooltipText}
-
+
{Language.workspaceTooltipLink1}
-
+
{Language.workspaceTooltipLink2}
-
+
{Language.workspaceTooltipLink3}
diff --git a/site/src/components/WorkspaceActions/BuildParametersPopover.tsx b/site/src/components/WorkspaceActions/BuildParametersPopover.tsx
index 02c884ac94..9aecbdf7ad 100644
--- a/site/src/components/WorkspaceActions/BuildParametersPopover.tsx
+++ b/site/src/components/WorkspaceActions/BuildParametersPopover.tsx
@@ -20,6 +20,7 @@ import {
} from "components/Tooltips/HelpTooltip/HelpTooltip"
import { useFormik } from "formik"
import { useRef, useState } from "react"
+import { docs } from "utils/docs"
import { getFormHelpers } from "utils/formUtils"
import { getInitialParameterValues } from "utils/richParameters"
@@ -118,7 +119,9 @@ export const BuildParametersPopover = ({
This template has no ephemeral build options.
-
+
Read the docs
diff --git a/site/src/pages/AuditPage/AuditFilter.tsx b/site/src/pages/AuditPage/AuditFilter.tsx
index d948d44729..882285fe8a 100644
--- a/site/src/pages/AuditPage/AuditFilter.tsx
+++ b/site/src/pages/AuditPage/AuditFilter.tsx
@@ -11,6 +11,7 @@ import {
import { UseFilterMenuOptions, useFilterMenu } from "components/Filter/menu"
import { BaseOption } from "components/Filter/options"
import capitalize from "lodash/capitalize"
+import { docs } from "utils/docs"
const PRESET_FILTERS = [
{
@@ -44,7 +45,7 @@ export const AuditFilter = ({
}) => {
return (
{
const { t } = useTranslation("auditLog")
@@ -15,17 +16,13 @@ export const AuditPaywall: FC = () => {
description={t("paywall.description")}
cta={
-
+
}>
{t("paywall.actions.upgrade")}
diff --git a/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx b/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx
index 2b0ac583a1..614682077f 100644
--- a/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx
+++ b/site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx
@@ -39,6 +39,7 @@ import {
import camelCase from "lodash/camelCase"
import capitalize from "lodash/capitalize"
import { VariableInput } from "./VariableInput"
+import { docs } from "utils/docs"
const MAX_DESCRIPTION_CHAR_LIMIT = 128
const MAX_TTL_DAYS = 30
@@ -322,7 +323,7 @@ export const CreateTemplateForm: FC = ({
) : (
<>
{commonT("licenseFieldTextHelper")}{" "}
-
+
{commonT("learnMore")}
.
@@ -459,7 +460,7 @@ export const CreateTemplateForm: FC = ({
This setting requires an enterprise license for the
-
+
'Template RBAC'
{" "}
feature to customize permissions.
diff --git a/site/src/pages/DeploySettingsPage/GeneralSettingsPage/GeneralSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/GeneralSettingsPage/GeneralSettingsPageView.tsx
index 4b664de25a..7bc000e96d 100644
--- a/site/src/pages/DeploySettingsPage/GeneralSettingsPage/GeneralSettingsPageView.tsx
+++ b/site/src/pages/DeploySettingsPage/GeneralSettingsPage/GeneralSettingsPageView.tsx
@@ -6,6 +6,7 @@ import { Header } from "components/DeploySettingsLayout/Header"
import OptionsTable from "components/DeploySettingsLayout/OptionsTable"
import { Stack } from "components/Stack/Stack"
import { useDeploymentOptions } from "utils/deployOptions"
+import { docs } from "utils/docs"
export type GeneralSettingsPageViewProps = {
deploymentOptions: DeploymentOption[]
@@ -22,7 +23,7 @@ export const GeneralSettingsPageView = ({
{Boolean(getDeploymentDAUsError) && (
diff --git a/site/src/pages/DeploySettingsPage/GitAuthSettingsPage/GitAuthSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/GitAuthSettingsPage/GitAuthSettingsPageView.tsx
index 219b5ec43f..19b46ce707 100644
--- a/site/src/pages/DeploySettingsPage/GitAuthSettingsPage/GitAuthSettingsPageView.tsx
+++ b/site/src/pages/DeploySettingsPage/GitAuthSettingsPage/GitAuthSettingsPageView.tsx
@@ -9,6 +9,7 @@ import { DeploymentValues, GitAuthConfig } from "api/typesGenerated"
import { Alert } from "components/Alert/Alert"
import { EnterpriseBadge } from "components/DeploySettingsLayout/Badges"
import { Header } from "components/DeploySettingsLayout/Header"
+import { docs } from "utils/docs"
export type GitAuthSettingsPageViewProps = {
config: DeploymentValues
@@ -24,7 +25,7 @@ export const GitAuthSettingsPageView = ({
@@ -38,7 +39,7 @@ export const NetworkSettingsPageView = ({
title="Port Forwarding"
secondary
description="Port forwarding lets developers securely access processes on their Coder workspace from a local machine."
- docsHref="https://coder.com/docs/coder-oss/latest/networking/port-forwarding"
+ docsHref={docs("/networking/port-forwarding")}
/>
diff --git a/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPageView.tsx b/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPageView.tsx
index 2aa5bf63c6..3e5da55fb9 100644
--- a/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPageView.tsx
+++ b/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPageView.tsx
@@ -12,6 +12,7 @@ import {
deploymentGroupHasParent,
useDeploymentOptions,
} from "utils/deployOptions"
+import { docs } from "utils/docs"
export type SecuritySettingsPageViewProps = {
options: DeploymentOption[]
@@ -46,7 +47,7 @@ export const SecuritySettingsPageView = ({
title="Audit Logging"
secondary
description="Allow auditors to monitor user operations in your deployment."
- docsHref="https://coder.com/docs/coder-oss/latest/admin/audit-logs"
+ docsHref={docs("/admin/audit-logs")}
/>
@@ -60,7 +61,7 @@ export const SecuritySettingsPageView = ({
title="Browser Only Connections"
secondary
description="Block all workspace access via SSH, port forward, and other non-browser connections."
- docsHref="https://coder.com/docs/coder-oss/latest/networking#browser-only-connections-enterprise"
+ docsHref={docs("/networking#browser-only-connections-enterprise")}
/>
diff --git a/site/src/pages/DeploySettingsPage/UserAuthSettingsPage/UserAuthSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/UserAuthSettingsPage/UserAuthSettingsPageView.tsx
index a88e0db8a2..a1c01adefc 100644
--- a/site/src/pages/DeploySettingsPage/UserAuthSettingsPage/UserAuthSettingsPageView.tsx
+++ b/site/src/pages/DeploySettingsPage/UserAuthSettingsPage/UserAuthSettingsPageView.tsx
@@ -11,6 +11,7 @@ import {
deploymentGroupHasParent,
useDeploymentOptions,
} from "utils/deployOptions"
+import { docs } from "utils/docs"
export type UserAuthSettingsPageViewProps = {
options: DeploymentOption[]
@@ -28,7 +29,7 @@ export const UserAuthSettingsPageView = ({
title="Login with OpenID Connect"
secondary
description="Set up authentication to login with OpenID Connect."
- docsHref="https://coder.com/docs/coder-oss/latest/admin/auth#openid-connect-with-google"
+ docsHref={docs("/admin/auth#openid-connect-with-google")}
/>
@@ -51,7 +52,7 @@ export const UserAuthSettingsPageView = ({
title="Login with GitHub"
secondary
description="Set up authentication to login with GitHub."
- docsHref="https://coder.com/docs/coder-oss/latest/admin/auth#github"
+ docsHref={docs("/admin/auth#github")}
/>
diff --git a/site/src/pages/GroupsPage/GroupsPageView.tsx b/site/src/pages/GroupsPage/GroupsPageView.tsx
index 43194c36c6..b14bc7fdf6 100644
--- a/site/src/pages/GroupsPage/GroupsPageView.tsx
+++ b/site/src/pages/GroupsPage/GroupsPageView.tsx
@@ -22,6 +22,7 @@ import { Link as RouterLink, useNavigate } from "react-router-dom"
import { Paywall } from "components/Paywall/Paywall"
import { Group } from "api/typesGenerated"
import { GroupAvatar } from "components/GroupAvatar/GroupAvatar"
+import { docs } from "utils/docs"
export type GroupsPageViewProps = {
groups: Group[] | undefined
@@ -49,7 +50,7 @@ export const GroupsPageView: FC = ({
cta={
}
@@ -59,7 +60,7 @@ export const GroupsPageView: FC = ({
diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx
index f260fa94e6..017a1ec167 100644
--- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx
+++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx
@@ -13,6 +13,7 @@ import { pageTitle } from "utils/page"
import { templateACLMachine } from "xServices/template/templateACLXService"
import { useTemplateSettingsContext } from "../TemplateSettingsLayout"
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"
+import { docs } from "utils/docs"
export const TemplatePermissionsPage: FC<
React.PropsWithChildren
@@ -38,7 +39,7 @@ export const TemplatePermissionsPage: FC<
cta={
@@ -50,7 +51,7 @@ export const TemplatePermissionsPage: FC<
diff --git a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateScheduleForm/TemplateScheduleForm.tsx b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateScheduleForm/TemplateScheduleForm.tsx
index 5a0a4f819e..3d3c5bd800 100644
--- a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateScheduleForm/TemplateScheduleForm.tsx
+++ b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateScheduleForm/TemplateScheduleForm.tsx
@@ -20,6 +20,7 @@ import { InactivityDialog } from "./InactivityDialog"
import { useWorkspacesToBeDeleted } from "./useWorkspacesToBeDeleted"
import { TemplateScheduleFormValues, getValidationSchema } from "./formHelpers"
import { TTLHelperText } from "./TTLHelperText"
+import { docs } from "utils/docs"
const MS_HOUR_CONVERSION = 3600000
const MS_DAY_CONVERSION = 86400000
@@ -222,9 +223,7 @@ export const TemplateScheduleForm: FC = ({
) : (
<>
{commonT("licenseFieldTextHelper")}{" "}
-
- {commonT("learnMore")}
-
+ {commonT("learnMore")}
.
>
),
diff --git a/site/src/pages/TemplatesPage/EmptyTemplates.tsx b/site/src/pages/TemplatesPage/EmptyTemplates.tsx
index 2e4deb6949..228cc3c83e 100644
--- a/site/src/pages/TemplatesPage/EmptyTemplates.tsx
+++ b/site/src/pages/TemplatesPage/EmptyTemplates.tsx
@@ -9,6 +9,7 @@ import { TemplateExampleCard } from "components/TemplateExampleCard/TemplateExam
import { FC } from "react"
import { useTranslation } from "react-i18next"
import { Link as RouterLink } from "react-router-dom"
+import { docs } from "utils/docs"
import { Permissions } from "xServices/auth/authXService"
// Those are from https://github.com/coder/coder/tree/main/examples/templates
@@ -54,7 +55,7 @@ export const EmptyTemplates: FC<{
for workspaces (e.g., docker_container, aws_instance,
kubernetes_pod). Select a starter template below or
diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx
index 90957ddbcb..77a8edad91 100644
--- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx
+++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx
@@ -41,6 +41,7 @@ import { colors } from "theme/colors"
import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined"
import { Avatar } from "components/Avatar/Avatar"
import { ErrorAlert } from "components/Alert/ErrorAlert"
+import { docs } from "utils/docs"
export const Language = {
developerCount: (activeCount: number): string => {
@@ -64,7 +65,7 @@ const TemplateHelpTooltip: React.FC = () => {
{Language.templateTooltipTitle}
{Language.templateTooltipText}
-
+
{Language.templateTooltipLink}
diff --git a/site/src/pages/TerminalPage/TerminalPageAlert.tsx b/site/src/pages/TerminalPage/TerminalPageAlert.tsx
index c81a5bb988..f40c70c3e5 100644
--- a/site/src/pages/TerminalPage/TerminalPageAlert.tsx
+++ b/site/src/pages/TerminalPage/TerminalPageAlert.tsx
@@ -3,6 +3,7 @@ import Button from "@mui/material/Button"
import Link from "@mui/material/Link"
import { Alert } from "components/Alert/Alert"
import { ReactNode } from "react"
+import { docs } from "utils/docs"
export type TerminalPageAlertType = "error" | "starting" | "success"
@@ -21,7 +22,7 @@ const mapAlertTypeToText: MapAlertTypeToComponent = {
The workspace{" "}
@@ -30,7 +31,7 @@ const mapAlertTypeToText: MapAlertTypeToComponent = {
, we recommend reloading this session and{" "}
@@ -39,7 +40,7 @@ const mapAlertTypeToText: MapAlertTypeToComponent = {
because{" "}
@@ -56,7 +57,7 @@ const mapAlertTypeToText: MapAlertTypeToComponent = {
but{" "}
@@ -74,7 +75,7 @@ const mapAlertTypeToText: MapAlertTypeToComponent = {
this{" "}
diff --git a/site/src/pages/UsersPage/UsersFilter.tsx b/site/src/pages/UsersPage/UsersFilter.tsx
index 4bbc5b99a2..5399ea2491 100644
--- a/site/src/pages/UsersPage/UsersFilter.tsx
+++ b/site/src/pages/UsersPage/UsersFilter.tsx
@@ -12,6 +12,7 @@ import {
import { BaseOption } from "components/Filter/options"
import { UseFilterMenuOptions, useFilterMenu } from "components/Filter/menu"
import { userFilterQuery } from "utils/filters"
+import { docs } from "utils/docs"
type StatusOption = BaseOption & {
color: string
@@ -56,7 +57,7 @@ export const UsersFilter = ({
return (
{menus.user && }
diff --git a/site/src/utils/docs.ts b/site/src/utils/docs.ts
new file mode 100644
index 0000000000..3fee2d5490
--- /dev/null
+++ b/site/src/utils/docs.ts
@@ -0,0 +1,28 @@
+const DEFAULT_DOCS_URL = "https://coder.com/docs/v2/latest"
+
+// Add cache to avoid DOM reading all the time
+let CACHED_DOCS_URL: string | undefined
+
+export const docs = (path: string) => {
+ return `${getBaseDocsURL()}${path}`
+}
+
+const getBaseDocsURL = () => {
+ if (!CACHED_DOCS_URL) {
+ const docsUrl = document
+ .querySelector('meta[property="docs-url"]')
+ ?.getAttribute("content")
+ const isValidDocsURL = docsUrl && isURL(docsUrl)
+ CACHED_DOCS_URL = isValidDocsURL ? docsUrl : DEFAULT_DOCS_URL
+ }
+ return CACHED_DOCS_URL
+}
+
+const isURL = (value: string) => {
+ try {
+ new URL(value)
+ return true
+ } catch {
+ return false
+ }
+}