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"