diff --git a/biome.json b/biome.json index 35c6d596..2d5ea8e1 100644 --- a/biome.json +++ b/biome.json @@ -17,6 +17,7 @@ "!**/dist/**", "!**/coverage/**", "!**/.next/**", + "!**/.source/**", "!**/node_modules/**", "!**/*.gen.ts", "!**/*.generated.ts" diff --git a/docs-site/app/docs/[[...slug]]/page.tsx b/docs-site/app/docs/[[...slug]]/page.tsx index 1e0c18ad..d1ae21d4 100644 --- a/docs-site/app/docs/[[...slug]]/page.tsx +++ b/docs-site/app/docs/[[...slug]]/page.tsx @@ -9,6 +9,7 @@ import { notFound, redirect } from "next/navigation"; import defaultMdxComponents from "fumadocs-ui/mdx"; import { CodeBlock } from "@/components/code-block"; import { DocsPageActions } from "@/components/docs-page-actions"; +import { readDocsPageMarkdown } from "@/lib/docs-markdown"; const docsIndexPath = "/docs/getting-started/introduction"; const docsIndexSlug = ["getting-started", "introduction"] as const; @@ -33,6 +34,7 @@ export default async function Page(props: { if (!page) notFound(); const MDX = page.data.body; + const mdxSource = await readDocsPageMarkdown(page.slugs); const hero = isHeroPage(params.slug); @@ -44,7 +46,7 @@ export default async function Page(props: { {page.data.title} {page.data.description} diff --git a/docs-site/app/layout.tsx b/docs-site/app/layout.tsx index dff95ef4..35a4b1fa 100644 --- a/docs-site/app/layout.tsx +++ b/docs-site/app/layout.tsx @@ -1,5 +1,5 @@ import "./global.css"; -import { RootProvider } from "fumadocs-ui/provider"; +import { RootProvider } from "fumadocs-ui/provider/next"; import { Outfit, Inter, Geist_Mono } from "next/font/google"; import type { ReactNode } from "react"; import type { Metadata } from "next"; diff --git a/docs-site/components/code-block.tsx b/docs-site/components/code-block.tsx index 15ae5ce7..8362b304 100644 --- a/docs-site/components/code-block.tsx +++ b/docs-site/components/code-block.tsx @@ -1,18 +1,16 @@ "use client"; import { + type ComponentPropsWithoutRef, type ReactNode, type ReactElement, isValidElement, } from "react"; import { CopyButton } from "./copy-button"; -type Props = { - children?: ReactNode; - className?: string; +type Props = ComponentPropsWithoutRef<"pre"> & { title?: string; - // rehype-pretty-code adds data attributes such as data-language; capture them via index signature - [key: string]: unknown; + "data-language"?: string; }; const TERMINAL_LANGS = new Set(["bash", "sh", "shell", "zsh"]); diff --git a/docs-site/content/docs/concepts/the-context-layer.mdx b/docs-site/content/docs/concepts/the-context-layer.mdx index d9021a8e..a76cbe7d 100644 --- a/docs-site/content/docs/concepts/the-context-layer.mdx +++ b/docs-site/content/docs/concepts/the-context-layer.mdx @@ -134,13 +134,13 @@ my-project/ │ └── data-quality-notes.md ├── raw-sources/ │ └── warehouse/ -│ └── live-database/ # Scan artifacts and reports +│ └── database-ingest/ # Schema ingest artifacts and reports └── .ktx/ ├── db.sqlite # Local state (git-ignored) └── cache/ # Runtime cache (git-ignored) ``` -Semantic sources and wiki pages are committed to git. The SQLite database holds ephemeral state — scan results, embedding indexes, session logs — and is git-ignored. If you delete it, KTX rebuilds it on the next run. +Semantic sources and wiki pages are committed to git. The SQLite database holds ephemeral state — schema ingest results, embedding indexes, session logs — and is git-ignored. If you delete it, KTX rebuilds it on the next run. This means your analytics context travels with your code. You can fork it, branch it, review it in a PR, and merge it with the same tools you use for dbt models. There's no sync problem between a remote server and your local state. There's no migration to run. The files are the source of truth. diff --git a/docs-site/lib/docs-markdown.ts b/docs-site/lib/docs-markdown.ts new file mode 100644 index 00000000..60312627 --- /dev/null +++ b/docs-site/lib/docs-markdown.ts @@ -0,0 +1,33 @@ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; + +export async function readDocsPageMarkdown(slugs: string[]) { + if ( + slugs.length === 0 || + slugs.some((segment) => segment.includes("/") || segment.includes("..")) + ) { + throw new Error(`Invalid docs page slug: ${slugs.join("/")}`); + } + + const docsRoot = join(process.cwd(), "content/docs"); + const directPath = join(docsRoot, `${slugs.join("/")}.mdx`); + + try { + return await readFile(directPath, "utf8"); + } catch (error) { + if (!isNotFoundError(error)) { + throw error; + } + } + + return readFile(join(docsRoot, slugs.join("/"), "index.mdx"), "utf8"); +} + +function isNotFoundError(error: unknown) { + return ( + typeof error === "object" && + error !== null && + "code" in error && + error.code === "ENOENT" + ); +} diff --git a/docs-site/lib/llm-docs.ts b/docs-site/lib/llm-docs.ts index cbf9ba9e..561f73e0 100644 --- a/docs-site/lib/llm-docs.ts +++ b/docs-site/lib/llm-docs.ts @@ -1,4 +1,5 @@ import { source } from "@/lib/source"; +import { readDocsPageMarkdown } from "@/lib/docs-markdown"; const siteOrigin = "https://docs.kaelio.com/ktx"; @@ -102,7 +103,7 @@ function toLlmDocsPage(page: ReturnType[number]) { url: page.url, markdownUrl: `${page.url}.md`, slug: page.slugs, - getMarkdown: async () => normalizeMarkdown(page.data.content), + getMarkdown: async () => normalizeMarkdown(await readDocsPageMarkdown(page.slugs)), } satisfies LlmDocsPage; } diff --git a/docs-site/lib/source.ts b/docs-site/lib/source.ts index 2fbc90cc..edbe1cbf 100644 --- a/docs-site/lib/source.ts +++ b/docs-site/lib/source.ts @@ -1,4 +1,4 @@ -import { docs } from "@/.source"; +import { docs } from "@/.source/server"; import { loader } from "fumadocs-core/source"; export const source = loader({ diff --git a/docs-site/next-env.d.ts b/docs-site/next-env.d.ts index 830fb594..9edff1c7 100644 --- a/docs-site/next-env.d.ts +++ b/docs-site/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -/// +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/docs-site/tsconfig.json b/docs-site/tsconfig.json index e2a2cc10..bccc54a5 100644 --- a/docs-site/tsconfig.json +++ b/docs-site/tsconfig.json @@ -15,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -33,7 +33,8 @@ "**/*.tsx", ".source/**/*.ts", "next-env.d.ts", - ".next/types/**/*.ts" + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" ], "exclude": [ "node_modules"