Saltar al contenido
Marketplace

wiki-dashboard

de ar9av

Create dynamic, queryable Obsidian dashboard views using Bases or Dataview. Use for auto-updating tables, indexes, or structured views of vault content; not for ordinary question answering.

Resumen

SKILL.mdLeída en 0cc5d90

Wiki Dashboard — Dynamic Vault Views

Two tools available: Obsidian Bases (native, GUI-driven, no plugin) and Dataview (community plugin, SQL-like, more powerful). Check which the user has and prefer Bases unless they ask for Dataview or need GROUP BY / computed columns.

Before You Start

Writing profile: Before drafting or rewriting natural-language Markdown, read and apply the Writing Profile Resolution section in llm-wiki/SKILL.md. Framework schema, provenance, safety, and operation-specific requirements take precedence. Apply WRITING.md preferences only to optional Markdown dashboard prose; .base syntax remains unchanged.

  1. Resolve config — follow the Config Resolution Protocol in llm-wiki/SKILL.md (inline @name override → walk up CWD for .env → global config → prompt setup). This gives OBSIDIAN_VAULT_PATH.
  2. Read $OBSIDIAN_VAULT_PATH/index.md to understand what categories and pages exist.
  3. Ask the user what they want to view if not specified — folder, tag, category, date range?
  4. Ask if they have Dataview installed if you're unsure which tool to use.

Option A — Obsidian Bases (.base files)

Bases are YAML files that define live views over vault notes. Native to Obsidian 1.8+, no plugin needed.

Official canonical schema

Top-level keys:

filters:      # Global filter applied to all views (expression strings under and/or/not)
formulas:     # Named computed properties — referenced as formula.<name>
properties:   # Display config per property — sets displayName for column headers
summaries:    # Aggregation formulas (e.g. mean, sum)
views:        # Array of view definitions (required)

Each item in views::

views:
  - type: table          # table | list | cards | map
    name: "View Name"    # display label
    limit: 50            # optional max rows
    order:               # column display order (list of property/formula names)
      - file.name
      - note.updated
    groupBy:             # grouping — goes INSIDE the view, NOT at top level
      property: note.tags
      direction: ASC     # ASC | DESC
    filters:             # view-specific filter (merges with global filters)
      and:
        - 'note.status != "done"'
    summaries:
      formula.myFormula: Average
Filter syntax — CRITICAL

Filters use expression strings, not typed objects. Always wrap in and:, or:, or not: — a bare list causes a "may only have one of and/or/not keys" parse error.

# CORRECT
filters:
  and:
    - file.inFolder("concepts")

# WRONG — typed objects (parse error)
filters:
  - type: folder
    folder: concepts

Filters support nesting:

filters:
  or:
    - file.hasTag("book")
    - and:
        - file.inFolder("concepts")
        - file.hasTag("research")
    - not:
        - file.hasTag("archived")
Property name conventions

Different contexts use different naming — confirmed from Obsidian's auto-reformat behaviour:

ContextFrontmatter field tagsFile nameFormula
properties: keysnote.tagsfile.nameformula.<name>
order: valuestags (bare)file.nameformula.<name>
groupBy.property:tags (bare)file.name—
filters: expressionsfile.hasTag(...) / note.tagsfile.nameformula.<name>
formulas: expressionsnote.tags, note.updatedfile.name—
Basic table — folder filter
filters:
  and:
    - file.inFolder("concepts")
properties:
  file.name:
    displayName: Page
  note.tags:
    displayName: Tags
  note.summary:
    displayName: Summary
  note.updated:
    displayName: Updated
views:
  - type: table
    name: Table
    order:
      - file.name
      - tags
      - summary
      - updated
Cards view — folder filter
filters:
  and:
    - file.inFolder("entities")
properties:
  file.name:
    displayName: Entity
  note.title:
    displayName: Full Name
  note.tags:
    displayName: Tags
  note.summary:
    displayName: Summary
views:
  - type: cards
    name: Cards
    order:
      - file.name
      - title
      - tags
      - summary
Group by property — groupBy goes INSIDE the view

When groupBy is set, omit that property from order: — it becomes the group header row and adding it as a column too causes duplication.

filters:
  and:
    - file.inFolder("concepts")
properties:
  file.name:
    displayName: Concept
  note.summary:
    displayName: Summary
  note.updated:
    displayName: Updated
views:
  - type: table
    name: By Domain
    groupBy:
      property: tags        # bare property name, no note. prefix
      direction: ASC
    order:
      - file.name           # do NOT include tags here — already the group header
      - summary
      - updated
Tag filter
filters:
  and:
    - file.hasTag("machine-learning")
properties:
  file.name:
    displayName: Page
  note.category:
    displayName: Category
  note.summary:
    displayName: Summary
views:
  - type: table
    name: Table
    order:
      - file.name
      - category
      - summary
Multi-filter (folder AND tag)
filters:
  and:
    - file.inFolder("projects")
    - file.hasTag("active")
properties:
  file.name:
    displayName: Project
  note.summary:
    displayName: Summary
  note.updated:
    displayName: Last Updated
views:
  - type: cards
    name: Cards
    order:
      - file.name
      - summary
      - updated
OR filter (two folders)
filters:
  or:
    - file.inFolder("concepts")
    - file.inFolder("entities")
properties:
  file.name:
    displayName: Page
  note.category:
    displayName: Category
  note.updated:
    displayName: Updated
views:
  - type: table
    name: Table
    order:
      - file.name
      - category
      - updated
Computed column via formulas
filters:
  and:
    - file.inFolder("concepts")
formulas:
  days_stale: "floor((now() - note.updated) / 86400000)"
properties:
  file.name:
    displayName: Page
  note.updated:
    displayName: Updated
  formula.days_stale:
    displayName: Days Stale
views:
  - type: table
    name: Stale
    order:
      - file.name
      - updated
      - formula.days_stale
Filter expression reference
ExpressionWhat it does
file.inFolder("path")Pages in that folder
file.hasTag("tag")Pages with that tag (no # prefix)
file.hasLink("Note Name")Pages linking to a note
file.name == "note-name"Exact filename match
file.ext == "md"Filter by extension
note.propertyNameAny frontmatter property
formula.formulaNameA named formula result
now()Current timestamp in ms

On Obsidian UI-generated format: When Obsidian's GUI writes or reformats a .base file it may output a simplified shorthand with top-level columns:, sort:, and view: keys instead of the canonical schema. That format also works — Obsidian accepts both. Manually authored files should use the canonical schema above.


Option B — Dataview (community plugin)

Dataview uses a SQL-like query language inside dataview code blocks in any note. More powerful than Bases for computed columns, GROUP BY, and cross-folder queries.

Basic table — folder
```dataview
TABLE
  tags AS "Tags",
  summary AS "Summary",
  file.mtime AS "Last Modified"
FROM "concepts"
SORT file.mtime DESC
```
Table with clickable links (TABLE WITHOUT ID)
```dataview
TABLE WITHOUT ID
  file.link AS "Entity",
  tags AS "Tags",
  summary AS "Summary"
FROM "entities"
SORT file.name ASC
```
GROUP BY — use rows. prefix after grouping

After GROUP BY, individual file properties must be prefixed with rows. — otherwise the column is empty or errors.

```dataview
TABLE WITHOUT ID
  rows.file.link AS "Concept",
  rows.summary AS "Summary"
FROM "concepts"
GROUP BY tags[0] AS "Domain"
```
Stale pages — use file.mtime for date math

Avoid choice(updated, date(updated), file.mtime) — mixed date formats in updated frontmatter cause arithmetic errors. file.mtime is always a valid DateTime.

```dataview
TABLE WITHOUT ID
  file.link AS "Page",
  category AS "Type",
  file.mtime AS "Last Modified",
  (date(today) - file.mtime).days + " days" AS "Age"
FROM "concepts" OR "entities" OR "projects"
WHERE file.name != file.folder
WHERE (date(today) - file.mtime).days > 30
SORT (date(today) - file.mtime).days DESC
```
Multi-folder query
```dataview
TABLE
  summary AS "Summary",
  file.mtime AS "Last Modified"
FROM "projects"
WHERE file.name != file.folder
SORT file.mtime DESC
```
Dataview reference
ClauseUsage
FROM "folder"All notes in folder
FROM #tagAll notes with tag
FROM "a" OR "b"Union of two folders
WHERE file.name != file.folderExclude folder index pages
GROUP BY field AS "Label"Group rows — use rows. for properties after this
SORT field DESCSort direction
file.linkClickable wikilink
file.mtimeLast modified time (always valid DateTime)
(date(today) - file.mtime).daysDays since last modification

Step 3: Write the File

Bases: Target path $OBSIDIAN_VAULT_PATH/_meta/<dashboard-name>.base

Dataview: Write queries directly into any .md note. A dedicated dashboard note at $OBSIDIAN_VAULT_PATH/_meta/dashboard.md works well for multi-section views.

Slug examples:

  • "All concepts" → _meta/concepts-index.base
  • "Recent ingests" → _meta/recent-ingests.base
  • "Project overview" → _meta/projects-overview.base
  • "Stale pages" → _meta/stale-pages.base
  • "Full dashboard" → _meta/dashboard.md

Create _meta/ if it doesn't exist yet.

Step 4: Embed Bases (optional)

To embed a .base inside a note:

## Entities
![[_meta/entities-tracker.base]]

Ask before modifying an existing note.

Step 5: Update Tracking

Append to $OBSIDIAN_VAULT_PATH/log.md:

- [TIMESTAMP] WIKI_DASHBOARD name="<slug>" tool=bases|dataview view=<type> filter="<description>"

No manifest or index update needed — dashboards are live queries, not static pages.

Common Dashboard Recipes

DashboardBest toolWhat it shows
Content indexBases or DataviewAll pages grouped by category, sorted by updated
Entity trackerBases (cards)Entity pages as a visual card gallery
Concepts by domainDataviewConcepts grouped by first tag using GROUP BY
Ingestion logEitherPages sorted by created date
Stale contentDataviewPages not touched in 30+ days with day count
Project overviewEitherProject pages with last-sync date
Research trackerDataviewSynthesis pages tagged research

Quality Checklist

  • [ ] Bases: filters use expression strings under and:/or:/not:, never typed objects
  • [ ] Bases: groupBy goes inside the view definition — not as a top-level key
  • [ ] Bases: column headers set via properties: <name>: displayName: "...", not columns: [{title}]
  • [ ] Bases: formulas: used for computed columns, referenced as formula.<name> in order/properties
  • [ ] Dataview: GROUP BY queries use rows.property not bare property
  • [ ] Dataview: date arithmetic uses file.mtime, not choice(updated, ...)
  • [ ] File written to _meta/ with a descriptive slug
  • [ ] log.md updated
  • [ ] User told how to embed Bases (![[_meta/<name>.base]]) or open the dashboard note

QMD Refresh After Vault Writes

QMD is a search index, not the source of truth. If $QMD_WIKI_COLLECTION is empty or unset, skip this step. Run it only after this skill has written or rewritten vault markdown. If QMD refresh fails, do not roll back the vault changes; report the QMD status separately.

Use $QMD_CLI if set; otherwise use qmd.

${QMD_CLI:-qmd} update

If the output says vectors are needed or embeddings may be stale, run:

${QMD_CLI:-qmd} embed

Verify the collection with either:

${QMD_CLI:-qmd} ls "$QMD_WIKI_COLLECTION"

or, when a specific page path is known:

${QMD_CLI:-qmd} get "qmd://$QMD_WIKI_COLLECTION/<page>.md" -l 5

Record one of:

  • QMD refreshed: update + embed + verified
  • QMD refreshed: update only + verified
  • QMD skipped: QMD_WIKI_COLLECTION unset
  • QMD skipped: qmd CLI unavailable
  • QMD failed: <short error summary>

Archivos 1 archivo

Instálala a mano

Deska ejecuta esto por ti, para cada agente que elijas. Para ejecutarlo tú en una terminal:

npx skills add ar9av/obsidian-wiki --skill wiki-dashboard

Más de ar9av

  • llm-wikiar9avExplain and apply the foundational LLM Wiki architecture and knowledge-management strategy. Use for setup, architecture, schema, or organization decisions; operational ingest/query/lint work uses dedicated skills.4,000 instalaciones en skills.sh0
  • wiki-ingestar9avIngest new documents, raw text, folders, or URLs into the Obsidian wiki as distilled, linked knowledge. Use for general wiki ingestion when no more specific ingest skill applies, including processing _raw/ staged content.3,600 instalaciones en skills.sh0
  • wiki-queryar9avSearch and synthesize answers from the compiled Obsidian wiki, including cited and multi-hop answers. Use for questions about existing wiki knowledge or fast index-only lookups. Supports named-vault routing such as wiki-query @work; not for ingesting new sources.3,500 instalaciones en skills.sh0
  • wiki-setupar9avInitialize or repair an Obsidian wiki vault's required structure and configuration. Use for new-vault setup, .env/config creation, reconfiguration, or broken setup recovery.3,500 instalaciones en skills.sh0
  • wiki-lintar9avAudit wiki health: broken links, orphans, contradictions, stale content, lifecycle and tag issues. Use for maintenance or health checks. Default is report-only; use wiki-dedup for page-identity merges.3,400 instalaciones en skills.sh0
Todas las skills de ar9av