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.
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.
.codex/skills/quickstart-product-dashboard-research/SKILL.mdai_notes/considerations/INTERACTIVE_VARIABLES_HTML.mdai_notes/features/CLICK_INTERACTIONS.md, Drill-down example?ticket_id=123 work when YAML defines ticket_id.face.content is Jinja-resolved, then rendered as markdown (see dataface/core/render/faces.py / mdsvg). Standard [text](url) works; there is no built-in rewriter for “link to another face by repo-relative path” across dft serve vs Cloud.action: link, set_variable, etc.); not fully wired through Vega click handling yet.Pattern: Dashboard state in the URL, often as encoded JSON; dimensions can expose templated URLs (Liquid).
?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.${ value.formatted | url_encode } (and related) when embedding URLs in dbt YAML (urls on dimensions).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.
Pattern: Filesystem routes as pages; templated segments [param] in paths; ordinary markdown links to those routes; parameters exposed to queries/content as {params.name}.
pages/customers/[customer].md → /customers/acme, link with [text](/customers/acme) or build path in SQL: '/customers/' || customer_name as customer_link.<DataTable/> link prop, or {% raw %}{#each}{% endraw %} 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 is not YAML-in-git-first, but it’s the familiar comparison for many teams:
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.
[label](url) and <https://...> autolinks; url is opaque to the spec (relative paths resolve against the current document or site base, which is host-specific).<a href> / custom <Link /> components; routers (e.g. Next.js) resolve href to dynamic routes. Parameterized routes are a framework concern, not markdown core.href—same role Dataface would need to rewrite board: or relative face paths.[[Page]], Obsidian, many wikis)[[page|alias]], [[page#heading]].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.
: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.| 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):
/zendesk/tickets/list, ../tickets) rewritten at render time for Cloud vs dft serve—normal markdown strings, resolver maps to storage slug.…/list, …/detail) over canonical_for YAML 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).
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)./{org}/{project}/d/{slug}/ + query → variables (apps/cloud/apps/dashboards/views.py → render()).ai_notes/research/ to this initiative file; ai_notes retains a redirect stub.