diff --git a/docs-site/components/product-mechanics.tsx b/docs-site/components/product-mechanics.tsx
new file mode 100644
index 00000000..1bf04e8e
--- /dev/null
+++ b/docs-site/components/product-mechanics.tsx
@@ -0,0 +1,402 @@
+import type { ReactNode } from "react";
+
+const sourceInputs = [
+ {
+ name: "Warehouse schema",
+ detail: "tables, columns, types, constraints, row counts",
+ signal: "grounds definitions in live database structure",
+ accent: "border-fd-primary",
+ },
+ {
+ name: "Metabase and query history",
+ detail: "historic SQL, questions, dashboards, usage patterns",
+ signal: "extracts joins, filters, grain, and trusted examples",
+ accent: "border-orange-500",
+ },
+ {
+ name: "dbt, MetricFlow, LookML",
+ detail: "models, metrics, dimensions, explores, joins",
+ signal: "maps existing modeling logic into semantic entities",
+ accent: "border-amber-500",
+ },
+ {
+ name: "Notion and docs",
+ detail: "definitions, policies, caveats, analyst notes",
+ signal: "links business language back to semantic references",
+ accent: "border-slate-500 dark:border-cyan-200",
+ },
+];
+
+const ingestSteps = [
+ {
+ title: "extract evidence",
+ body: "Pull structured facts from schemas, SQL, BI metadata, and docs.",
+ },
+ {
+ title: "reconcile entities",
+ body: "Merge names, measures, joins, and caveats into one project model.",
+ },
+ {
+ title: "validate references",
+ body: "Check semantic fields and joins against database context before agents use them.",
+ },
+];
+
+const artifacts = [
+ {
+ path: "semantic-layer/*.yaml",
+ title: "Typed query model",
+ body: "sources, grain, joins, dimensions, measures, filters, segments",
+ },
+ {
+ path: "wiki/*.md",
+ title: "Business context",
+ body: "rules and caveats with sl_refs back to semantic-layer entities",
+ },
+ {
+ path: "raw-sources/",
+ title: "Evidence trail",
+ body: "scan artifacts, extracted metadata, relationship evidence",
+ },
+ {
+ path: ".ktx/",
+ title: "Local indexes",
+ body: "embeddings and search indexes, not the source of truth",
+ },
+];
+
+const runtimeSteps = [
+ {
+ title: "Search wiki",
+ body: "Find business rules, caveats, synonyms, and sl_refs.",
+ },
+ {
+ title: "Resolve semantic refs",
+ body: "Map measure and dimension names to approved entities.",
+ },
+ {
+ title: "Validate fields",
+ body: "Check source, columns, joins, grain, filters, and segments.",
+ },
+ {
+ title: "Build query plan",
+ body: "Create a semantic query plan before SQL is generated.",
+ },
+ {
+ title: "Compile dialect SQL",
+ body: "Generate warehouse-shaped SQL instead of copying examples.",
+ },
+ {
+ title: "Execute with bounds",
+ body: "Optionally run with bounded rows and return provenance.",
+ },
+];
+
+export function ProductMechanics() {
+ return (
+
+
+
+ Product mechanics
+
+
+ A semantic compiler for analytics agents
+
+
+ KTX builds typed semantic files, links wiki context back to those
+ entities, validates the model against database evidence, then compiles
+ agent requests into executable SQL.
+
+
+
+
+
+
+
+
+ );
+}
+
+function IngestionDiagram() {
+ return (
+
+
+
+
+
+ Inputs KTX reads
+
+ {sourceInputs.map((source) => (
+
+
+ {source.name}
+
+
+ {source.detail}
+
+
+ {source.signal}
+
+
+ ))}
+
+
+
+
+ KTX builds the model
+
+
+
+ Ingest pipeline
+
+
+ {ingestSteps.map((step, index) => (
+
+ ))}
+
+
+
+
+ {artifacts.map((artifact) => (
+
+ ))}
+
+
+
+
+
+ );
+}
+
+function RuntimeDiagram() {
+ return (
+
+
+
+
+
+ Agent sends
+
+ connection: warehouse
+ measure: orders.total_revenue
+ dimension: customers.segment
+ filter: orders.created_date >= '2024-01-01'
+
+
+ This is the API surface agents should use: compact semantic intent,
+ not hand-written warehouse SQL.
+
+
+
+
+ KTX planning and execution
+
+ {runtimeSteps.map((step, index) => (
+
+ ))}
+
+
+
+
+
+
+ Semantic query plan
+
+
+ source:{" "}
+ orders joined to customers as many_to_one
+
+
+ measure:{" "}
+ total_revenue = sum(amount) with refund filter
+
+
+ grain: segment
+ group-by with date predicate
+
+
+ result: dialect
+ SQL, bounded rows, and provenance
+
+
+
+
+
+ KTX returns
+
+ select
+ customers.segment,
+ sum(orders.amount) as total_revenue
+ from analytics.orders
+ join analytics.customers
+ on orders.customer_id = customers.id
+ where orders.status != 'refunded'
+ and orders.created_date >= '2024-01-01'
+ group by 1
+
+
+ The output can be SQL-only or executed results with provenance, so
+ the agent can show where the answer came from.
+
+
+
+
+ );
+}
+
+function DiagramHeader({
+ body,
+ eyebrow,
+ id,
+ title,
+}: {
+ body: string;
+ eyebrow: string;
+ id: string;
+ title: string;
+}) {
+ return (
+
+
+ {eyebrow}
+
+
+ {title}
+
+
+ {body}
+
+
+ );
+}
+
+function Artifact({
+ body,
+ path,
+ title,
+}: {
+ body: string;
+ path: string;
+ title: string;
+}) {
+ return (
+
+
+ {path}
+
+
{title}
+
+ {body}
+
+
+ );
+}
+
+function PipelineStep({
+ body,
+ dark = false,
+ index,
+ title,
+}: {
+ body: string;
+ dark?: boolean;
+ index: number;
+ title: string;
+}) {
+ return (
+
+
+ {index}
+
+
+
+ {title}
+
+
+ {body}
+
+
+
+ );
+}
+
+function ColumnLabel({ children }: { children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+function CodeBox({ children }: { children: ReactNode }) {
+ return (
+
+ );
+}
diff --git a/docs-site/content/docs/getting-started/introduction.mdx b/docs-site/content/docs/getting-started/introduction.mdx
index d87d8af3..7a6c9b3e 100644
--- a/docs-site/content/docs/getting-started/introduction.mdx
+++ b/docs-site/content/docs/getting-started/introduction.mdx
@@ -3,10 +3,12 @@ title: Introduction
description: How KTX gives analytics agents trusted context for warehouse work.
---
-
-
+import { ProductMechanics } from "@/components/product-mechanics";
+
+
+
- Make analytics context{'\n'}usable by agents
+ Make analytics context usable by agents
-
- KTX turns warehouse metadata, semantic definitions, and business knowledge
- into reviewable project files that agents can use while planning, querying,
- and updating analytics work.
+
+ {'KTX turns warehouse metadata, semantic definitions, and business knowledge into reviewable project files that agents can use while planning, querying, and updating analytics work.'}
-
-## Who KTX is for
+
+
+## What agents can do with KTX
KTX is built for analytics engineers and data teams who want data agents to
-work on real analytics systems - not just generate one-off SQL.
+work on real analytics systems, not just generate one-off SQL.
-Use KTX when you want agents to:
+Use it when agents need to:
-- **Generate SQL** from approved measures and joins
-- **Repair semantic definitions** through reviewable diffs
-- **Explain metric provenance** with warehouse evidence
-- **Work alongside** dbt, LookML, MetricFlow, Looker, Metabase, and modern BI platforms
+- **Generate SQL** from approved measures, dimensions, joins, and filters
+- **Explain provenance** with wiki context and warehouse evidence
+- **Repair context** through reviewable YAML and Markdown diffs
+- **Work alongside** dbt, LookML, MetricFlow, Looker, Metabase, and warehouses
-Works with SQLite, PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, and SQL
-Server.
+KTX works with SQLite, PostgreSQL, Snowflake, BigQuery, ClickHouse, MySQL, and
+SQL Server.
-## Explore the docs
+## Read next
Set up KTX and build your first context in under 10 minutes.
-
- Understand what a context layer is and why agents need one.
-
Hands-on workflows for scanning, ingesting, writing, and serving.
+
+ Edit semantic-layer YAML and wiki Markdown safely.
+
Complete flag and subcommand reference for every KTX command.
diff --git a/docs-site/tests/product-mechanics-content.test.mjs b/docs-site/tests/product-mechanics-content.test.mjs
new file mode 100644
index 00000000..0efe06ba
--- /dev/null
+++ b/docs-site/tests/product-mechanics-content.test.mjs
@@ -0,0 +1,85 @@
+import assert from "node:assert/strict";
+import { readFile } from "node:fs/promises";
+import { dirname, join } from "node:path";
+import { test } from "node:test";
+import { fileURLToPath } from "node:url";
+
+const docsSiteDir = join(dirname(fileURLToPath(import.meta.url)), "..");
+
+async function readDocsFile(path) {
+ return readFile(join(docsSiteDir, path), "utf8");
+}
+
+test("docs introduction shows the ingestion and runtime mechanics early", async () => {
+ const introduction = await readDocsFile(
+ "content/docs/getting-started/introduction.mdx",
+ );
+
+ assert.match(
+ introduction,
+ /import\s+\{\s*ProductMechanics\s*\}\s+from\s+"@\/components\/product-mechanics";/,
+ );
+ assert.match(introduction, //);
+
+ const heroIndex = introduction.indexOf("Make analytics context");
+ const mechanicsIndex = introduction.indexOf("");
+ const useCaseIndex = introduction.indexOf("## What agents can do with KTX");
+ const heroSource = introduction.slice(0, mechanicsIndex);
+
+ assert.ok(heroIndex >= 0, "introduction should include the custom hero");
+ assert.ok(
+ mechanicsIndex > heroIndex,
+ "mechanics component should appear after the hero",
+ );
+ assert.ok(
+ mechanicsIndex < useCaseIndex,
+ "mechanics component should appear before use-case sections",
+ );
+ assert.doesNotMatch(heroSource, /Get Started/);
+ assert.doesNotMatch(heroSource, /The Context Layer/);
+ assert.doesNotMatch(heroSource, /Building Context/);
+ assert.doesNotMatch(heroSource, /flex flex-wrap gap-3/);
+});
+
+test("product mechanics component covers source-specific context and SQL expansion", async () => {
+ const component = await readDocsFile("components/product-mechanics.tsx");
+
+ for (const expectedText of [
+ "A semantic compiler for analytics agents",
+ "Ingestion",
+ "Runtime",
+ "wiki/",
+ "semantic-layer/",
+ "raw-sources/",
+ ".ktx/",
+ "sl_refs",
+ "Notion",
+ "Metabase",
+ "query history",
+ "extract evidence",
+ "reconcile entities",
+ "validate references",
+ "semantic query plan",
+ "dialect SQL",
+ "bounded rows",
+ "provenance",
+ "measure: orders.total_revenue",
+ "dimension: customers.segment",
+ "select",
+ ]) {
+ assert.ok(
+ component.includes(expectedText),
+ `component should include: ${expectedText}`,
+ );
+ }
+
+ assert.doesNotMatch(component, /KTX does more than retrieve Markdown/);
+ assert.doesNotMatch(component, /Plain Markdown \+ RAG/);
+ assert.doesNotMatch(component, /comparisonRows/);
+ assert.doesNotMatch(component, /ComparisonTable/);
+ assert.doesNotMatch(component, /Not just retrieval/);
+ assert.doesNotMatch(component, /KTX works in two moments/);
+ assert.doesNotMatch(component, /w-\[calc\(100vw/);
+ assert.doesNotMatch(component, /xl:grid-cols-2/);
+ assert.doesNotMatch(component, /lg:grid-cols-\[[^\]]*_2rem_/);
+});