A configuration-driven, multi-vault query and dashboard system for Obsidian that transforms static Dataview queries into interactive, real-time dashboards.
- Configuration-Driven: Define your catalog structure once, use it everywhere
- Portable Across Vaults: Ship with sensible defaults, customize per vault
- Real-Time Updates: Dashboards refresh automatically as your vault changes
- Multiple Presets: Bundled configurations for Pulp Fiction, General Library, and Manuscripts
- Customizable Schemas: Add/remove fields and configure component visibility
- Mobile-Ready: Responsive design works on iOS, Android, and desktop
Copy the entire plugin folder to your Obsidian vault:
<vault>/.obsidian/plugins/cartographer/
Then enable it in Settings → Community plugins.
Open Settings → Datacore and select a preset:
- Pulp Fiction (default): Horror pulp fiction catalog with 13 fields and editorial workflow
- General Library: Book collection tracker with reading status
- Manuscripts: Writing project tracker with submission workflow
- Custom: Start from scratch with your own schema
Use the ribbon icon or commands:
Datacore: Open Status Dashboard- See items grouped by statusDatacore: Open Works Table- Browse all items in sortable table
This plugin is built with a clean, layered architecture:
- Data Access Layer (
hooks/useDataLoading.ts): Load and parse markdown files from vault with real-time subscriptions - Query Layer (
queries/queryFunctions.ts): Pure functions for filtering, sorting, grouping, and aggregating - State Management: Filter state, sort state, pagination
- View Layer (
components/): Obsidian ItemView components for rendering - Settings Layer (
config/settingsManager.ts): Persistent configuration management
src/
├── main.ts # Plugin entry point
├── index.ts # Public API exports
├── types/
│ ├── settings.ts # DatacoreSettings, CatalogSchema
│ ├── dynamicWork.ts # CatalogItem, state types
│ └── types.ts # Utility functions
├── config/
│ ├── presets.ts # PULP_FICTION, GENERAL_LIBRARY, MANUSCRIPTS presets
│ └── settingsManager.ts # SettingsManager + settings UI tab
├── hooks/
│ └── useDataLoading.ts # File loading, vault subscriptions, filtering
├── queries/
│ └── queryFunctions.ts # 20+ query utility functions
├── components/
│ ├── DatacoreComponentView.ts # Base ItemView class
│ ├── StatusDashboardView.ts # Status summary component
│ └── WorksTableView.ts # Works table component
└── styles/
└── components.css # Component-specific styles (imported into main)
##Development
npm installnpm run buildnpm run devnpm run lintThis project uses GitHub Actions for automated testing and deployment:
- Linting - ESLint checks code style (
npm run lint) - Type Checking - TypeScript strict mode (via
npm run buildwhich includestsc -noEmit) - Plugin Build - Compiles TypeScript to JavaScript (
npm run build) - Storybook Build - Generates component documentation (
npm run build:storybook)
Deployment: Storybook automatically deploys to GitHub Pages on push to main.
See CI-PIPELINE.md for detailed pipeline specification.
Before pushing:
npm run lint && npm run build && npm run build:storybookIf all pass locally, CI will pass on push.
- Entry Point:
main.ts- Plugin class and command registration - Build Output:
main.js- Bundled JavaScript (created by esbuild) - Manifest:
manifest.json- Plugin metadata - Styles:
styles.css- All plugin styling
Access Settings → Datacore to:
- Select a preset configuration
- Set the catalog directory path (relative to vault root)
- Enable/disable individual dashboard components
- Configure UI options (items per page, compact mode, etc.)
- Path:
works/ - 13 Fields: title, authors, year, catalog-status, word-count, publications, bp-candidate, bp-approved, date-reviewed, date-approved, date-cataloged, keywords, content-warnings
- Status Workflow: raw → reviewed → approved → published
- Dashboards: Status Summary, Works Table, Publication Dashboard, Author Card, Backstage Pass Pipeline
- Path:
library/ - 6 Fields: title, author, genre, status, year, rating
- Status Workflow: unread → reading → completed
- Dashboards: Status Summary, Works Table, Author Card
- Path:
manuscripts/ - 9 Fields: title, author, genre, status, word-count, draft-date, query-date, agent, publisher
- Status Workflow: draft → revising → querying → published
- Dashboards: Status Summary, Works Table, Manuscript Pipeline
- Path:
catalog/ - Fields: Minimal (title only)
- Start from scratch and add your own fields
Shows item counts grouped by a status field.
┌─────────────────────────────┐
│ Status Summary │
├──────────────┬──────────────┤
│ Status │ Count │
├──────────────┼──────────────┤
│ raw │ 5 │
│ reviewed │ 8 │
│ approved │ 2 │
└──────────────┴──────────────┘
Interactive table with sorting and pagination.
- Sortable columns
- Pagination controls
- Respects field visibility settings
- Mobile-responsive
Shows all works in a specific publication (wikilink array field).
Shows all works by a specific author with statistics.
Custom workflow showing items at different stages (e.g., candidate → approved → in-pipeline).
Export for use in other scripts or custom components:
import {
filterByField,
filterByText,
filterByRange,
sortByField,
groupByField,
countByField,
getUniqueValues,
getNumericStats,
paginate,
} from 'cartographer';See src/queries/queryFunctions.ts for full API documentation.
Full TypeScript support with exported types:
import type {
DatacoreSettings,
CatalogSchema,
SchemaField,
CatalogItem,
FilterState,
SortState,
CatalogStatistics,
} from 'cartographer';The plugin includes responsive CSS for:
- iOS (Safari in Obsidian app)
- Android (Obsidian app)
- Desktop (Chrome, Edge, Safari)
All components gracefully degrade on small screens:
- Tables switch to card view on mobile
- Filter bar stacks vertically
- Pagination handled automatically
- Client-side filtering: Instant responses, no server calls
- Memoized operations: Expensive computations cached
- Lazy loading: Components load on-demand
- Real-time subscriptions: Minimal overhead for vault changes
- Pagination: Handle large catalogs efficiently
Catalog items use standard Obsidian markdown with YAML frontmatter:
---
title: "The Shadow in the Attic"
authors: ["Lovecraft, Howard Phillips"]
year: 1922
catalog-status: "approved"
word-count: 3500
bp-candidate: true
publications: ["[[Weird Tales Vol 5 No 1]]"]
---
# The Shadow in the Attic
Story content and description...Extend DatacoreComponentView:
import {
DatacoreComponentView,
loadCatalogItems
} from 'cartographer';
export class MyCustomView extends DatacoreComponentView {
async loadData() {
this.items = await loadCatalogItems(this.app, this.settings);
}
async renderComponent() {
// Render your custom UI
}
}Interactive component library for testing and documenting all dashboard components in isolation.
- View Live:
npm run storybook→ http://localhost:6006/ - Build Static:
npm run build:storybook→ generatesstorybook-static/ - Full Guide: STORYBOOK-GUIDE.md
- StatusDashboard (5 variants): Aggregate view grouped by status
- WorksTable (8 variants): Sortable, paginated table
- FilterBar (7 variants): Multi-type filter interface
Each story includes interactive prop controls, mobile viewport testing, and realistic sample data.
Add custom fields in settings:
- Define field in schema
- Parse with
parseFieldValue()utility - Display with
formatFieldValue()utility
Logic/unit tests use node:test. UI/component tests use @testing-library/preact with a simulated DOM (jsdom). Migration to Vitest is planned for unified testing (see Migration Guide).
npm testFor UI tests, ensure jsdom is available. See troubleshooting below if DOM errors occur.
Performance tests are in tests/performance.test.ts. These check rendering speed, filtering, and sorting for typical catalog sizes. Update sample data for larger benchmarks as needed.
Test coverage is tracked via CI. See CI-PIPELINE.md for details.
Sample settings and data for tests and Storybook are in .storybook/fixtures/ and src/sampleLibrary.ts. Use these for consistent test results and UI demos. Update fixtures as schema evolves.
- DOM Environment Errors: If UI tests fail with DOM errors, ensure jsdom is installed and configured. For Vitest, use the
environment: 'jsdom'setting. - Type Errors: Use TypeScript strict mode. Check types in
src/types/and update tests if schema changes. - Test Runner Issues: If tests do not run, check runner configuration in
package.jsonand CI pipeline. See Migration Guide for Vitest setup. - Sample Data Mismatch: Update fixtures and sample settings to match current schema.
See AGENTS.md for code standards and contribution guidelines. All code must pass lint, type check, and tests before PR submission. Document new components in Storybook and update sample data as needed.
For questions or suggestions, open an issue or discussion on GitHub.
0-BSD License - See LICENSE file for details
Status: Phase 6 Implementation
Version: 0.2.0
Last Updated: 2026-20-01