Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .mintlify/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ Ship the redirect in the same change (principle 7):
2. Re-point any existing redirect whose destination you moved — redirects must never chain.
3. Rewrite inbound internal links to the final URL (`rg` the old slug); internal links never route through a redirect.

## Local preview

Start `mint dev --port 3333` **once** in the background and reuse it for the whole session — it hot-reloads `.mdx`, `snippets/`, `styles.css`, and `docs.json`, so never restart it to pick up an edit. If the port is taken, mint silently binds the next port up instead of failing, so relaunching stacks zombie servers. To stop it, kill the background task's PID (the process cmdline is `node .../mint/index.js dev`, so `pkill -f "mint dev"` matches nothing); check for strays with `procs mint`. Launching needs to run outside the sandbox (`mint` writes preview locks under `~/.mintlify`), as does spawning Chrome for screenshots.

## Before done

Frontmatter is complete, the page is reachable from nav, and `mint broken-links` passes.
Frontmatter is complete, the page is reachable from nav, and `mint broken-links` passes. Pages meant to be fetched by URL rather than browsed declare `hidden: true` in frontmatter instead of a nav entry — the validator exempts them from nav reachability, and `seo.indexing: "all"` in `docs.json` keeps them in `llms.txt` and the `.md` export. `start.mdx` (the agent endpoint behind the homepage copy-prompt button) is the one such page; don't add it to nav.

## Reference docs

Expand Down
3 changes: 3 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"library": "tabler"
},
"favicon": "/favicon.png",
"seo": {
"indexing": "all"
},
"navigation": {
"tabs": [
{
Expand Down
4 changes: 4 additions & 0 deletions introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ description: "Enterprise-ready agentic analytics that turns questions into insig
mode: "wide"
---

import { CopyPromptButton } from "/snippets/copy-prompt-button.jsx";

At its core, Lightdash builds a shared understanding of your data and your business — a single source of truth for what everything means. The more your team uses Lightdash, the richer and smarter that foundation becomes.

Lightdash then allows your team to use conversational analytics, build dashboards, and custom data apps all with an AI-powered experience that means they don't need to write any SQL. Everything is built from a single source of truth, so you have lineage for every data asset and can trace any query to its official definition.

Everything you create in Lightdash can be shared instantly with your team with control over roles, permissions, and row-level security to make sure people see all the data they need and nothing more.

<CopyPromptButton />

<Callout icon="message-chatbot" color="#9990C4">
**Talk to the docs with your agent** over MCP, no authentication required. Get [step-by-step instructions here](/agents/lightdash-mcp#lightdash-docs-mcp).
</Callout>
Expand Down
163 changes: 163 additions & 0 deletions snippets/copy-prompt-button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
{/* Mintlify evaluates each snippet export in isolation inside the page's MDX
scope, so everything the component references must live inside this one
export — module-level constants would be undefined at runtime. */}

export const CopyPromptButton = () => {
const START_PROMPT =
"Read https://docs.lightdash.com/start.md then help me setup a Lightdash project...";
const PROMPT_DISPLAY = "“" + START_PROMPT + "”";
const COPIED_DISPLAY =
"✓ Copied — now paste that into your coding agent for a guided walkthrough!";
const CYCLE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_./:;[]<>";
const AGENT_ICONS = [
{
name: "Claude Code",
path: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z",
},
{
name: "Codex",
path: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z",
},
{
name: "opencode",
path: "M16 6H8v12h8V6zm4 16H4V2h16v20z",
},
{
name: "Cursor",
path: "M22.106 5.68L12.5.135a.998.998 0 00-.998 0L1.893 5.68a.84.84 0 00-.419.726v11.186c0 .3.16.577.42.727l9.607 5.547a.999.999 0 00.998 0l9.608-5.547a.84.84 0 00.42-.727V6.407a.84.84 0 00-.42-.726zm-.603 1.176L12.228 22.92c-.063.108-.228.064-.228-.061V12.34a.59.59 0 00-.295-.51l-9.11-5.26c-.107-.062-.063-.228.062-.228h18.55c.264 0 .428.286.296.514z",
},
];

const [target, setTarget] = useState(PROMPT_DISPLAY);
const [cycle, setCycle] = useState(0);
const [copied, setCopied] = useState(false);
const [text, setText] = useState(PROMPT_DISPLAY);
const rafRef = useRef(0);
const resetRef = useRef(0);
const wrapRef = useRef(null);

useEffect(() => {
setText(target);
}, [target]);

/* Scramble-and-settle on the preview line: each character cycles through
random glyphs then settles to the target, staggered left-to-right.
Re-runs on every `cycle` bump; the full sweep lands in about a second.
Skipped entirely under prefers-reduced-motion. */
useEffect(() => {
if (!cycle) return;
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
setText(target);
return;
}

const totalFrames = 6;
const staggerPerChar = 0.2;
const interval = 900 / 30;
const chars = target.split("");
const total = chars.length * staggerPerChar + totalFrames;
let frame = 0;
let last = 0;

cancelAnimationFrame(rafRef.current);
const tick = (t) => {
if (t - last < interval) {
rafRef.current = requestAnimationFrame(tick);
return;
}
last = t;

setText(
chars
.map((c, i) => {
const settleStart = i * staggerPerChar;
if (frame >= settleStart + totalFrames) return c;
if (c === " ") return c;
if (frame < settleStart && Math.random() >= 0.35) return c;
return CYCLE_CHARS[Math.floor(Math.random() * CYCLE_CHARS.length)];
})
.join(""),
);

if (frame > total) {
setText(target);
rafRef.current = 0;
return;
}
frame++;
rafRef.current = requestAnimationFrame(tick);
};

rafRef.current = requestAnimationFrame(tick);
return () => cancelAnimationFrame(rafRef.current);
}, [cycle, target]);

useEffect(
() => () => {
cancelAnimationFrame(rafRef.current);
clearTimeout(resetRef.current);
},
[],
);

const handleClick = () => {
if (navigator.clipboard) {
navigator.clipboard.writeText(START_PROMPT).catch(() => { });
}
setCopied(true);
setTarget(COPIED_DISPLAY);
setCycle((c) => c + 1);
clearTimeout(resetRef.current);
resetRef.current = setTimeout(() => {
/* If the reader is still on the button (or reached it by keyboard) the
preview stays visible, so scramble back to the prompt; otherwise the
is-copied class drop fades it out and the text can swap silently. */
const wrap = wrapRef.current;
const stillWatching =
wrap &&
(wrap.matches(":hover") ||
wrap.querySelector(".copy-prompt-btn:focus-visible"));
setCopied(false);
setTarget(PROMPT_DISPLAY);
if (stillWatching) setCycle((c) => c + 1);
}, 2200);
};

return (
<div className="copy-prompt not-prose" ref={wrapRef}>
<button
type="button"
className="copy-prompt-btn"
aria-label="Copy the agent start prompt to your clipboard"
onClick={handleClick}
>
<span className="copy-prompt-icons" aria-hidden="true">
{AGENT_ICONS.map((icon) => (
<svg
key={icon.name}
viewBox="0 0 24 24"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
xmlns="http://www.w3.org/2000/svg"
>
<path d={icon.path} />
</svg>
))}
</span>
<span className="copy-prompt-label">Copy Prompt</span>
</button>
<span role="status" className="copy-prompt-sr-status">
{copied ? "Prompt copied to clipboard" : ""}
</span>
<p
className={
copied ? "copy-prompt-preview is-copied" : "copy-prompt-preview"
}
aria-hidden="true"
>
{text}
</p>
</div>
);
};
112 changes: 112 additions & 0 deletions start.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
title: "Start"
description: "A guided walkthrough for coding agents helping a user set up Lightdash from scratch"
hidden: true
---

You are a coding agent helping a user set up [Lightdash](https://www.lightdash.com), a code-based BI and agentic analytics platform built on a semantic layer. Your job: get their tools installed, help them choose a path, and get them to their first explorable data in Lightdash Cloud. Work conversationally — ask the questions below one at a time, run commands only with the user's permission, and share the linked docs pages so they can read along.

Any page on `docs.lightdash.com` can be fetched as plain markdown by appending `.md` to its URL. Do that whenever you need more detail than this walkthrough carries.

## Step 1: Install the CLI and agent skills

Install the Lightdash CLI. On macOS, prefer Homebrew (no Node.js required):

```bash
brew tap lightdash/lightdash
brew install lightdash
```

Anywhere with Node.js available, npm works too:

```bash
npm install -g @lightdash/cli
```

Verify with `lightdash --version`. For Windows (WSL or PowerShell) and direct binary downloads, follow https://docs.lightdash.com/workflow/cli/install.

Then install the Lightdash agent skills so you can work with semantic layer YAML fluently. Run the variant matching your own harness, from the project directory the user will work in:

```bash
lightdash install-skills # Claude Code (also read by GitHub Copilot)
lightdash install-skills --agent cursor # Cursor
lightdash install-skills --agent codex # Codex
```

Add `--global` if the user wants the skills available across all their projects. Details: https://docs.lightdash.com/workflow/install-agent-skills.

## Step 2: Real project or sandbox?

Ask the user which they want:

- **A real project** — they have data in a warehouse (or a dbt project) and want Lightdash on top of it. Continue to Step 3.
- **A sandbox** — they want to try Lightdash on sample data first. Skip to Step 4.

If they want a real project but have no data warehouse yet, treat that as the sandbox path — it gets them a working warehouse too.

Lightdash connects to BigQuery, Postgres, Supabase, Redshift, Snowflake, Databricks, Trino, ClickHouse, DuckDB (MotherDuck or DuckLake), and Athena. Full connection reference: https://docs.lightdash.com/get-started/quickstart/connect-project.

## Step 3: Real project

Ask whether the user works with dbt.

### With dbt

Lightdash generates its semantic layer from dbt models (dbt v1.4 or later, available on the path as `dbt`).

1. Navigate to their dbt project. If they want a brand-new one, scaffold it with `dbt init` and dbt's own guide (https://docs.getdbt.com/tutorial/setting-up) before continuing. dbt Cloud users need the repo cloned locally.
2. Create the Lightdash account — see Step 5 — then authenticate the CLI: `lightdash login <instance URL>` opens a browser OAuth flow.
3. Generate Lightdash Tables from their dbt models and deploy:

```bash
lightdash dbt run
lightdash deploy --create
```

Follow https://docs.lightdash.com/get-started/quickstart/prepare-your-dbt-project as the canonical script for this path, and https://docs.lightdash.com/get-started/quickstart/connect-project for the warehouse connection settings the deploy will ask for.

### Without dbt

Define the semantic layer directly in Lightdash YAML — no dbt project needed:

1. Create `lightdash.config.yml` at the project root declaring the warehouse type, and model files under `lightdash/models/*.yml` (`type: model`, `name`, `sql_from`, plus `metrics` and `dimensions`). With the skills from Step 1 installed, use the `developing-in-lightdash` skill to profile the user's warehouse and generate sensible starter models.
2. Validate with `lightdash lint`.
3. Create the Lightdash account — see Step 5 — then `lightdash login <instance URL>` and deploy without credentials:

```bash
lightdash deploy --create --no-warehouse-credentials
```

4. Have the user add warehouse credentials in the app (Settings → Current project → Connection settings).

Canonical reference for this whole path: https://docs.lightdash.com/semantic-layer/yaml.

## Step 4: Sandbox project

The fastest sandbox today is Supabase — free tier, no dbt required:

1. Clone https://github.com/lightdash/lightdash-supabase-quickstart. It includes setup scripts (macOS/Linux and Windows), a preconfigured Supabase MCP so you can generate Lightdash models from the schema, and a `set-warehouse` script that wires up credentials via the API.
2. Have the user create a free project at https://supabase.com if they don't have one.
3. Follow the repo's README — it goes from zero to charts in about 15 minutes, including the account creation from Step 5.

Alternatively, MotherDuck (managed DuckDB, free trial at https://motherduck.com) works well with the Lightdash YAML path from Step 3: connect to one of MotherDuck's built-in sample databases, generate models with the `developing-in-lightdash` skill, and deploy. The MotherDuck connection settings are documented at https://docs.lightdash.com/get-started/quickstart/connect-project.

{/* Placeholder: a dedicated sandbox template repo (warehouse trial + preloaded models) is planned; link it here when it ships. */}

## Step 5: Create the Lightdash account

Every path lands here. Send the user to sign up — this is their step, in the browser:

https://www.lightdash.com/start

Once they have an instance (Lightdash Cloud is `app.lightdash.cloud`, or `eu1.lightdash.cloud` in the EU), return to wherever you left off: `lightdash login <instance URL>`, deploy, and confirm the project appears in the app.

## After setup

Point the user at their next steps:

- Explore their first Tables: https://docs.lightdash.com/get-started/explore-your-data
- Grow the semantic layer with metrics and dimensions: https://docs.lightdash.com/get-started/build-your-semantic-layer
- Connect you (the agent) to their Lightdash instance over MCP: https://docs.lightdash.com/agents/lightdash-mcp
- Preview changes safely before deploying: https://docs.lightdash.com/workflow/preview-projects
- Invite their team: https://docs.lightdash.com/get-started/quickstart/invite-new-users
Loading
Loading