dft serve and Cloud after resolution.dashboard_render query parsing)..md / .yaml / .yml suffixes on paths may be stripped as author sugar (tool behavior, not CommonMark).canonical_for / entity-registry YAML — deferred to M5 and only if needed; see ADR-002 and task. Prefer path conventions (e.g. …/list, …/detail) instead.slug / url_path frontmatter overrides — not v1; file location is source of truth (move the file to change URL).ai_notes/features/CLICK_INTERACTIONS.md; v1 makes href targets unambiguous so clicks can reuse the same resolver later.[[board]] in v1 unless trivial on top of the same resolver.Dashboard URL root (author view): paths are root-relative from the logical dashboard namespace—authors do not type a storage prefix like faces/.
Examples:
{% raw %}
[Open tickets](/zendesk/tickets/list?status=open)
[Ticket detail](/zendesk/tickets/detail?id={{ ticket_id }})
{% endraw %}
Implementation mapping: the resolver maps author path → canonical project slug used by Cloud and dft serve today (typically under faces/ on disk, e.g. faces/zendesk/tickets/list). Exact normalization rules must match dashboard discovery / existing slug behavior—see open questions.
Relative paths: ../ and ./ resolve against the current board’s slug directory (after the same author-root ↔ storage-slug mapping), then rewrite for Cloud vs serve—see ADR-001.
Convention for “views” (no metadata): teams can standardize recognizable paths such as:
…/list — filtered / overview table…/detail — single-entity board (variables in query, e.g. ?id=)This is documentation + habit, not enforced schema in v1.
| Concern | Compile time | Render time |
|---|---|---|
| Knows Cloud org/project | No | Yes (dashboard_render) |
| Same YAML in CLI and Cloud | Yes | Yes |
Browsers resolve relative href against the HTML page URL (Suite: /{org}/{project}/d/{slug}/), not the repo slug tree—so we rewrite board links when rendering. Same pattern as static site generators that “fix” .md links: tool behavior, not CommonMark.
| Runtime | Shape (conceptual) |
|---|---|
dft serve |
/{storage_slug_path}?{query} per dataface/core/serve/server.py |
| Cloud | /{org}/{project}/d/{dashboard_slug}/?{query} + merge branch (allowlist TBD) from current request when absent on link |
Pass link_context through render(..., **options) into the content pipeline (dataface/core/render/faces.py, etc.); centralize in e.g. dataface/core/render/board_links.py with tests.
| Phase | Scope |
|---|---|
| 1a | Root-relative /… + board-relative ../ / ./ in face.content; suffix strip; serve + Cloud |
| 1b | Context merge (branch, allowlist) |
| 2 | Optional escape hatch only if ambiguity appears (e.g. explicit scheme)—not default |
M5 (separate task): optional canonical_for / entity index only if product proves need beyond conventions—task.
../, suffix strip, query merge, Cloud vs serve).docs/docs/ page stating author rules (this section), branch behavior, and examples; link from variables docs. Update drill-down example when action: link shares resolver._templates/link-matrix.template.md with /connector/... style examples.branch only vs more).faces/ and dashboards/ trees exist (precedence, explicit disambiguation).