From 1ab770d6af35e1376edb84c8589be0b82ae26cd7 Mon Sep 17 00:00:00 2001 From: Kaylee <65376239+KayleeWilliams@users.noreply.github.com> Date: Fri, 8 May 2026 21:32:36 -0700 Subject: [PATCH 01/13] Improve docs UX with /docs landing, agent .md, and live components - Redirect / to /docs via beforeLoad and remove the Home dashboard - Add a robot-icon "View as Markdown" toggle in the header that opens the agent-friendly .md variant of the current docs page - Wire pipeline:convert into dev/build so leadtype's convertAllMdx populates apps/example/public/docs/**/*.md before vite starts - Add a Vite middleware that negotiates Accept: text/markdown on /docs/* URLs so agents can hit canonical URLs with the right header - Render Mermaid client-side with @streamdown/mermaid; flatten the inner Streamdown chart wrapper so it shows as a single card - Restructure /docs/components into one section per component (description + usage + live example) so the page is a real reference and dogfoods the renderer + remark conversion at once - Wire the NotFound component into router + root route, and update it to point users back to /docs --- .gitignore | 1 + apps/example/package.json | 9 +- apps/example/playwright.config.ts | 6 + .../src/components/docs-mdx/mermaid.tsx | 16 +- apps/example/src/components/not-found.tsx | 28 ++ apps/example/src/components/site-footer.tsx | 2 +- apps/example/src/components/site-header.tsx | 57 +++- apps/example/src/lib/docs.ts | 5 - apps/example/src/router.tsx | 2 + apps/example/src/routes/__root.tsx | 2 + apps/example/src/routes/index.tsx | 143 +--------- apps/example/src/styles.css | 13 +- apps/example/vite.config.ts | 73 ++++- bun.lock | 3 + docs/components.mdx | 249 ++++++++++++------ 15 files changed, 370 insertions(+), 239 deletions(-) create mode 100644 apps/example/src/components/not-found.tsx diff --git a/.gitignore b/.gitignore index 96fab4f..2338209 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ yarn-error.log* # Misc .DS_Store *.pem +.gstack/ diff --git a/apps/example/package.json b/apps/example/package.json index d707cb5..17c0e26 100644 --- a/apps/example/package.json +++ b/apps/example/package.json @@ -4,9 +4,9 @@ "private": true, "type": "module", "scripts": { - "dev": "bun run --filter leadtype build && portless run vite dev", - "build": "bun run --filter leadtype build && vite build", - "preview": "portless run vite preview", + "dev": "bun run --filter leadtype build && bun run pipeline:convert && PORTLESS_PORT=1355 PORTLESS_HTTPS=0 portless run vite dev", + "build": "bun run --filter leadtype build && bun run pipeline:convert && vite build", + "preview": "PORTLESS_PORT=1355 PORTLESS_HTTPS=0 portless run vite preview", "check-types": "tsgo --noEmit", "test:e2e": "bun run --filter leadtype build && playwright test", "convert": "bun run pipeline:convert", @@ -28,15 +28,16 @@ "dependencies": { "@fontsource-variable/geist": "^5.2.8", "@fontsource-variable/geist-mono": "^5.2.7", - "leadtype": "workspace:*", "@mdx-js/react": "^3.1.1", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", + "@streamdown/mermaid": "^1.0.2", "@tanstack/react-router": "^1.167.4", "@tanstack/react-start": "^1.166.15", "ai": "^6.0.168", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "leadtype": "workspace:*", "nitro": "3.0.260415-beta", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/apps/example/playwright.config.ts b/apps/example/playwright.config.ts index ee595aa..1de72be 100644 --- a/apps/example/playwright.config.ts +++ b/apps/example/playwright.config.ts @@ -4,6 +4,7 @@ import { defineConfig, devices } from "@playwright/test"; const isCI = Boolean(process.env.CI); const HTTPS_PROTOCOL = "https://"; const HTTP_PROTOCOL = "http://"; +const PORTLESS_HTTP_PORT = "1355"; const DEFAULT_BASE_URL = "http://localhost:3000"; function getExampleBaseUrl(): string { @@ -16,6 +17,11 @@ function getExampleBaseUrl(): string { try { portlessUrl = execFileSync("portless", ["get", "example"], { encoding: "utf8", + env: { + ...process.env, + PORTLESS_HTTPS: "0", + PORTLESS_PORT: PORTLESS_HTTP_PORT, + }, maxBuffer: 10 * 1024 * 1024, timeout: 5000, }).trim(); diff --git a/apps/example/src/components/docs-mdx/mermaid.tsx b/apps/example/src/components/docs-mdx/mermaid.tsx index c8b64b4..a58e7d2 100644 --- a/apps/example/src/components/docs-mdx/mermaid.tsx +++ b/apps/example/src/components/docs-mdx/mermaid.tsx @@ -1,20 +1,20 @@ +"use client"; + +import { mermaid } from "@streamdown/mermaid"; import type { ReactNode } from "react"; +import { Streamdown } from "streamdown"; export interface MermaidProps { chart?: string; children?: ReactNode; } -/** - * Placeholder Mermaid renderer. Emits a `
` block so
- * consumer apps can hydrate it with their preferred mermaid client
- * (mermaid.js, react-mermaid2, etc.) or style it as-is.
- */
 export function Mermaid({ chart, children }: MermaidProps) {
   const source = chart ?? (typeof children === "string" ? children : "");
+  const markdown = `\`\`\`mermaid\n${source}\n\`\`\``;
   return (
-    
-      {source}
-    
+
+ {markdown} +
); } diff --git a/apps/example/src/components/not-found.tsx b/apps/example/src/components/not-found.tsx new file mode 100644 index 0000000..1317d25 --- /dev/null +++ b/apps/example/src/components/not-found.tsx @@ -0,0 +1,28 @@ +import { Link } from "@tanstack/react-router"; +import { SiteFooter } from "@/components/site-footer"; +import { SiteHeader } from "@/components/site-header"; + +export function NotFound() { + return ( +
+ +
+

404

+

+ Page not found +

+

+ We couldn't find that page. Check the URL, or head back to the + reference app. +

+ + Back to docs + +
+ +
+ ); +} diff --git a/apps/example/src/components/site-footer.tsx b/apps/example/src/components/site-footer.tsx index 9c1f731..ff1f890 100644 --- a/apps/example/src/components/site-footer.tsx +++ b/apps/example/src/components/site-footer.tsx @@ -1,6 +1,6 @@ const footerLinks = [ { - href: "https://github.com/inthhq/docs", + href: "https://github.com/inthhq/leadtype", label: "GitHub", }, { diff --git a/apps/example/src/components/site-header.tsx b/apps/example/src/components/site-header.tsx index e121769..b987782 100644 --- a/apps/example/src/components/site-header.tsx +++ b/apps/example/src/components/site-header.tsx @@ -5,23 +5,76 @@ import { navigationRoutes } from "@/lib/docs"; import { cn } from "@/lib/utils"; import { SearchBar } from "./search-bar"; +function RobotIcon() { + return ( + + ); +} + +const TRAILING_SLASH_PATTERN = /\/$/; + +function markdownHrefForPath(pathname: string): string | null { + if (!(pathname === "/docs" || pathname.startsWith("/docs/"))) { + return null; + } + if (pathname.endsWith(".md")) { + return null; + } + if (pathname === "/docs") { + return "/docs/index.md"; + } + return `${pathname.replace(TRAILING_SLASH_PATTERN, "")}.md`; +} + export function SiteHeader() { const pathname = useRouterState({ select: (state) => state.location.pathname, }); + const markdownHref = markdownHrefForPath(pathname); return (
leadtype
-