Research
Date: 2025-03-20 Status: Design input for Dataface board linking, quickstart packs, entity/detail navigation
Canonical copy of this landscape lives here (initiative research). A stub in ai_notes redirects for old links.
Consumers
- Quickstart dashboards assume workable cross-board links and optional entity/detail conventions; program setup is gated on dashboard-linking-v1.
Purpose
Capture how adjacent products handle cross-dashboard navigation, parameterized URLs, and how markdown-like formats express links—so we can compare to Dataface and avoid inventing patterns in a vacuum.
Related internal threads
- Quickstart initiative & research skill: Quickstart dashboards,
.codex/skills/quickstart-product-dashboard-research/SKILL.md - URL-driven variables (HTML / Cloud):
ai_notes/considerations/INTERACTIVE_VARIABLES_HTML.md - Chart clicks / drill (planned):
ai_notes/features/CLICK_INTERACTIONS.md, Drill-down example
Dataface today (short)
- Cloud: Query parameters (except a small internal allowlist) are passed through as dashboard variables—deep links like
?ticket_id=123work when YAML definesticket_id. - Markdown in boards:
face.contentis Jinja-resolved, then rendered as markdown (seedataface/core/render/faces.py/mdsvg). Standard[text](url)works; there is no built-in rewriter for “link to another face by repo-relative path” acrossdft servevs Cloud. - Chart-driven navigation: Documented as planned (
action: link,set_variable, etc.); not fully wired through Vega click handling yet.
Lightdash (dbt-native BI)
Pattern: Dashboard state in the URL, often as encoded JSON; dimensions can expose templated URLs (Liquid).
- Filtering via URL: the docs describe a
?filters=query key whose value is a URL-encoded JSON object; users copy a filtered dashboard URL and replace literals with Liquid expressions for click-through. - Dynamic values:
${ value.formatted | url_encode }(and related) when embedding URLs in dbt YAML (urlson dimensions). - “Clickable links” changelog/feature: dimension-level URLs, not a separate markdown board-link DSL.
Reference: How to filter a dashboard in the URL (Lightdash docs).
Takeaway: First-class parameter passing = opaque URL encoding of filter state, plus template engines in YAML (Liquid) for row/dimension context—not markdown autolink syntax.
Evidence (SQL + markdown in repo)
Pattern: Filesystem routes as pages; templated segments [param] in paths; ordinary markdown links to those routes; parameters exposed to queries/content as {params.name}.
- Example:
pages/customers/[customer].md→/customers/acme, link with[text](/customers/acme)or build path in SQL:'/customers/' || customer_name as customer_link. - Programmatic links:
<DataTable/>linkprop, or {#each} loops—not a special wikilink syntax.
Reference: Templated pages (Evidence docs).
Takeaway: “Headless” linking is [label](path/with/params) where the path is understood by the site generator; dynamic rows produce strings that look like URLs. Very close to conventional markdown + file-based routing.
Metabase (GUI BI; useful URL mental model)
Metabase is not YAML-in-git-first, but it’s the familiar comparison for many teams:
- Custom click behavior often maps to “Go to custom destination” → URL or dashboard, with column values substituted into the destination.
- Dashboards/questions live in app state; shareable links encode resource id and serialized parameters (similar idea to Lightdash’s filter blob: state in the URL, not pretty).
Internal compare note: ai_notes/archive/reviews/compare_metabase.md
Takeaway: Product BI tends toward opaque or structured query strings + UI-configured templates; code-first tools (Evidence) tend toward readable paths and builder-generated hrefs.
Markdown & adjacent formats (how “links” are usually done)
CommonMark / GitHub-flavored Markdown
- Standard:
[label](url)and<https://...>autolinks;urlis opaque to the spec (relative paths resolve against the current document or site base, which is host-specific). - No standard for “wiki-style” page references or entity shortcuts—that’s always an extension or postprocessor.
MDX (Markdown + JSX)
- Links are still markdown or
<a href>/ custom<Link />components; routers (e.g. Next.js) resolvehrefto dynamic routes. Parameterized routes are a framework concern, not markdown core. - Pattern: component or remark plugin rewrites
href—same role Dataface would need to rewriteboard:or relative face paths.
Wikilinks ([[Page]], Obsidian, many wikis)
- Double-bracket targets resolve by title or slug in a graph of notes; optional
[[page|alias]],[[page#heading]]. - Implementation is always a custom resolver (vault root, uniqueness rules, case folding).
Takeaway: If Dataface wants “link to board by slug without full URL”, wikilink-style or dft: scheme is consistent with the wider ecosystem—but out of scope for plain CommonMark; it must be a deliberate extension in Jinja/markdown preprocessing or mdsvg pipeline.
reStructuredText / Sphinx
:doc:and ref roles for cross-document links with builder-aware resolution—analogous to “symbolic board ref” in a static site. Heavier than most teams want in dashboards.
Synthesis for Dataface
| Approach | Fits Dataface well when… |
|---|---|
| Query-string variables (already in Cloud) | Detail boards use stable variable names; authors pass ?id= explicitly or via templates. |
Readable path per board (/d/slug) + markdown [](/d/slug?x=) |
Aligned with Evidence-style route + markdown; needs one resolver for dft serve vs Cloud base path. |
Symbolic / relative board id (board:slug, [[faces/ticket]], repo-relative path) |
Reduces duplication; requires compile- or render-time rewriting to absolute URLs. |
| Structured filter blob (Lightdash-style JSON in query) | Powerful for complex filters; good for parity with BI tools; worse for human-readable git diffs—probably secondary for YAML-first. |
Canonical / entity metadata (“detail board for ticket”) |
Optional registry for agents and default drill targets—not required if generic links are ergonomic. |
Practical ordering (from prior design chat):
- Make dashboard-root and board-relative paths (e.g.
/zendesk/tickets/list,../tickets) rewritten at render time for Cloud vsdft serve—normal markdown strings, resolver maps to storage slug. - Prefer path conventions (
…/list,…/detail) overcanonical_forYAML in v1; revisit in M5 only if needed (task).
Spec detail: spec.md — dashboard-root author paths (e.g. /zendesk/tickets/list); resolver maps to storage slug; no canonical_for in v1 (M5 task if ever).
Further reading (external)
- Lightdash URL filters: https://docs.lightdash.com/guides/developer/filtering-dashboard-in-url
- Evidence templated pages: https://docs.evidence.dev/core-concepts/templated-pages
- CommonMark spec (links): https://spec.commonmark.org/ (inline links)
Implementation alignment (summary)
The landscape above argues for readable, generator-resolved links (Evidence-style) over opaque BI filter blobs for v1. The concrete plan—dashboard-root paths (e.g. /zendesk/tickets/list), ../ from current board, render-time rewrite for Cloud vs serve, user docs in the same delivery, and no entity-registry metadata until M5 if needed—lives in spec and decisions (ADR-001/002). Implement: dashboard-linking-v1; optional registry: M5.
Runtime reminder
dft serve:GET /{path}→ project file{path}.yml, query → variables (dataface/core/serve/server.py).- Cloud:
/{org}/{project}/d/{slug}/+ query → variables (apps/cloud/apps/dashboards/views.py→render()).
Changelog
- 2025-03-20: Initial note (landscape + markdown + Dataface positioning).
- 2025-03-20: Moved canonical body from
ai_notes/research/to this initiative file;ai_notesretains a redirect stub. - 2026-03-20: Added implementation alignment pointer to spec/decisions/task.