diff --git a/site/src/routes/docs/+layout.svelte b/site/src/routes/docs/+layout.svelte
index 2ff77a3d2..3950a2fd4 100644
--- a/site/src/routes/docs/+layout.svelte
+++ b/site/src/routes/docs/+layout.svelte
@@ -1,13 +1,32 @@
-
+{#snippet navLinkSnippet(navLink: NormalizedNavLink)}
+ {#if "items" in navLink}
+
{@render children()}
diff --git a/site/src/routes/docs/+layout.ts b/site/src/routes/docs/+layout.ts
index 826199949..85a4f8bef 100644
--- a/site/src/routes/docs/+layout.ts
+++ b/site/src/routes/docs/+layout.ts
@@ -1,8 +1,8 @@
-const articles = import.meta.glob("./**/*.md");
+import { navLinks } from "./settings";
+import { normalizeNavLinks } from "./utils";
export function load() {
- const paths = Object.keys(articles).map(
- (key) => key.slice("./".length, -".md".length) + "/",
- );
- return { paths };
+ return {
+ navLinks: normalizeNavLinks(navLinks),
+ };
}
diff --git a/site/src/routes/docs/[...path]/+page.ts b/site/src/routes/docs/[...path]/+page.ts
index 15149c71e..eb3d2ab34 100644
--- a/site/src/routes/docs/[...path]/+page.ts
+++ b/site/src/routes/docs/[...path]/+page.ts
@@ -1,13 +1,20 @@
import { error } from "@sveltejs/kit";
-const articles = import.meta.glob<{
- content: string;
- frontmatter: {};
- toc: {};
-}>("../**/*.md");
+const articles = Object.fromEntries(
+ Object.entries(
+ import.meta.glob<{
+ content: string;
+ frontmatter: Record;
+ toc: string;
+ }>("../**/*.md"),
+ ).map(([key, fn]) => [key.slice("../".length, -".md".length), fn]),
+);
export async function load({ params }) {
- const article = articles[`../${params.path.slice(0, -"/".length)}.md`];
+ const path = params.path.endsWith("/")
+ ? params.path.slice(0, -1)
+ : params.path;
+ const article = articles[path];
if (!article) {
error(404, "");
}
diff --git a/site/src/routes/docs/settings.ts b/site/src/routes/docs/settings.ts
new file mode 100644
index 000000000..429324e44
--- /dev/null
+++ b/site/src/routes/docs/settings.ts
@@ -0,0 +1,8 @@
+import type { NavLink } from "./utils";
+
+export const navLinks: NavLink[] = [
+ {
+ label: "Getting Started",
+ items: ["getting-started/add-machines"],
+ },
+];
diff --git a/site/src/routes/docs/utils.ts b/site/src/routes/docs/utils.ts
new file mode 100644
index 000000000..a747caa3b
--- /dev/null
+++ b/site/src/routes/docs/utils.ts
@@ -0,0 +1,91 @@
+export const articles = Object.fromEntries(
+ Object.entries(
+ import.meta.glob<{
+ content: string;
+ frontmatter: Record;
+ toc: string;
+ }>("./**/*.md", { eager: true }),
+ ).map(([key, fn]) => [key.slice("./".length, -".md".length), fn]),
+);
+
+export type NavLink =
+ | string
+ | {
+ label: string;
+ items: NavLink[];
+ badge?: Badge;
+ }
+ | {
+ label?: string;
+ slug: string;
+ badge?: Badge;
+ };
+
+export type NormalizedNavLink =
+ | {
+ label: string;
+ items: NormalizedNavLink[];
+ badge?: NormalizedBadge;
+ }
+ | {
+ label: string;
+ slug: string;
+ badge?: NormalizedBadge;
+ };
+
+export type Badge = string | NormalizedBadge;
+
+export type NormalizedBadge = {
+ text: string;
+ variant: "caution" | "normal";
+};
+
+export function normalizeNavLinks(navLinks: NavLink[]): NormalizedNavLink[] {
+ return navLinks.map(normalizeNavLink);
+}
+
+export function normalizeNavLink(navLink: NavLink): NormalizedNavLink {
+ if (typeof navLink === "string") {
+ const article = articles[navLink];
+ if (!article) {
+ throw new Error(`Doc not found: ${navLink}`);
+ }
+ return {
+ label: article.frontmatter.title,
+ slug: `/docs/${navLink}`,
+ };
+ }
+
+ if (!("items" in navLink)) {
+ const article = articles[navLink.slug];
+ if (!article) {
+ throw new Error(`Doc not found: ${navLink}`);
+ }
+ return {
+ ...navLink,
+ label: navLink.label ?? article.frontmatter.title,
+ badge: normalizeBadge(navLink.badge),
+ };
+ }
+
+ return {
+ ...navLink,
+ badge: normalizeBadge(navLink.badge),
+ items: navLink.items.map(normalizeNavLink),
+ };
+}
+
+export function normalizeBadge(
+ badge: Badge | undefined,
+): NormalizedBadge | undefined {
+ if (!badge) {
+ return undefined;
+ }
+ if (typeof badge === "string") {
+ return {
+ text: badge,
+ variant: "normal",
+ };
+ }
+ return badge;
+}