Master Documentation: Product Requirements (PRD), Technical Architecture (TRD), Customization Guide, & Developer Manual
A zero-maintenance, zero-runtime-dependency static web application and digital garden that compiles a raw Obsidian Markdown vault into a desktop-grade browser viewer with an interactive 2D Canvas force-directed knowledge graph, a client-side Obsidian Dataview query engine, KaTeX math typesetting, and multi-tab document navigation.
Live Deployment: yashagrawall.github.io/knowledge-base
- 1. Executive Summary & Vision
- 2. Product Requirements Document (PRD)
- 3. Technical Requirements Document (TRD)
- 4. Subsystem Technical Deep Dives
- 4.1 2D Canvas Force-Directed Knowledge Graph (
vault-graph.jsx) - 4.2 Client-Side Obsidian Dataview Query Evaluator (
vault-editor.jsx) - 4.3 Markdown, Math, & Syntax Pipeline (
vault-editor.jsx) - 4.4 Workspace Manager, Tab Handling, & Hash Router (
vault-app.jsx) - 4.5 File Explorer & Auto-Reveal Sidebar (
vault-sidebar.jsx) - 4.6 Context Inspector, Outlines, & Backlinks (
vault-rightpanel.jsx) - 4.7 Command Palette & Full-Text Search Engine (
vault-app.jsx) - 4.8 Theme Engine & Styling Architecture (
index.html)
- 4.1 2D Canvas Force-Directed Knowledge Graph (
- 5. Case Study: How This Vault Is Structured & Built
- 6. Customization & Personalization Guide (Recreating for YOUR Vault)
- 7. Repository Structure & File Map
- 8. Operations, Local Setup, & Maintenance
- 9. Security, Privacy, & Performance Benchmarks
- 10. License & Credits
Obsidian is an exceptional local-first Markdown note-taking environment. However, sharing a personal Zettelkasten or digital garden publicly often presents a trade-off between complex static site generators (Next.js, Astro, Hugo, Eleventy, Quartz) that require heavy build setups, NPM dependencies, and fragile deployment pipelines.
Yash's Knowledge Base eliminates this friction by operating on a zero-runtime-dependency static architecture:
- Compilation Phase: A single lightweight Node.js compilation script (
build-vault.js) parses the raw Markdown vault on disk into a unified, high-performance JavaScript data file (vault-data.js). - Runtime Phase: React 18, Babel Standalone, Marked.js, KaTeX, and an HTML5 Canvas 2D physics simulation run natively in the browser directly from vanilla static files hosted on GitHub Pages.
The platform provides a browser experience matching desktop Obsidian: interactive force-directed graph exploration, multi-tab workspace editing, live document outlines, two-way backlinks, and a client-side evaluator for Obsidian Dataview queries.
- Problem: Traditional digital garden SSG tools fail to render native Obsidian features—such as Dataview codeblock queries (
dataview), dynamic tag pages, WikiLinks with alias/heading anchors ([[Note#Heading|Alias]]), and customizable visual knowledge graphs—without heavy server-side processing, complex NPM build steps, or broken layouts. - Primary Objective: Provide a zero-maintenance, client-side web viewer that mirrors Obsidian's core interactive capabilities directly from plain Markdown files without requiring NPM packages or bundlers.
- Secondary Objective: Deliver instant page loads (<150ms), smooth 60fps graph physics, responsive mobile drawer navigation, and light/dark theme adaptation without requiring Webpack, Vite, or server-side rendering infrastructure.
- Vault Readers & Researchers: Visitors exploring published notes, literature summaries, and technical research via hierarchical folder trees, interactive tag indices, two-way backlinks, and visual graph nodes.
- Knowledge Author (Vault Owner): Writing notes in desktop Obsidian and running a single command (
auto-sync.batornode build-vault.js) to publish updates instantly to GitHub Pages.
| Epic | Feature | User Story / Functionality | Technical Requirement |
|---|---|---|---|
| Graph View | Interactive 2D Canvas Graph | As a user, I want to visualize connections between notes in a force-directed canvas. | HTML5 Canvas 2D, custom Verlet physics, zoom/pan touch controls. |
| Graph View | Floating Settings Control | As a user, I want to adjust node size, link distance, repulsion, and text threshold. | Non-cropping glassmorphic panel with sticky header and internal scrolling. |
| Dataview Engine | Client-Side Dataview Queries | As a user, I want LIST and TABLE queries in MOCs and Tag notes to execute dynamically. |
Custom client-side Dataview parser evaluating FROM, WHERE, SORT, and negations. |
| Tag Navigation | Automatic Tag Indexing | As a user, opening any Tag note should list all notes tagged with that topic. | Automatic fallback injection of LIST FROM [[TagName]] for 08 - Tags/ notes. |
| Reader View | Multi-Tab Interface | As a user, I want to open multiple notes in separate tabs and switch between them. | React tab state manager synchronized with URL hash routing (#slug). |
| Reader View | Markdown & Math Typesetting | As a user, I want GFM formatting, math equations, callout blocks, task lists, and highlights rendered cleanly. | Marked parser, KaTeX math shielding, GitHub callout styling, GFM checkboxes, inline ==highlight== extension. |
| Explorer | File Tree & Auto-Reveal | As a user, selecting a note should automatically expand its folder branch in the sidebar. | Recursive React tree component with automatic folder expansion state. |
| Search | Command Palette (Cmd+K) |
As a user, I want a quick search modal pre-filterable by #tags, folder paths, and titles. |
Global keyboard listener (Cmd+K/Ctrl+K), modal overlay, regex text matcher. |
| Context Panel | Outline, Backlinks, & Related | As a user, I want a table of contents, incoming links, outgoing links, and tag-based note suggestions. | Heading scroll-spy, two-way link index lookup, tag co-occurrence algorithm. |
The application utilizes a Static Data + In-Browser JSX Runtime architecture:
-
Compilation Phase (
build-vault.js):- Recursively traverses
notes/, skipping private directories defined inSKIP_DIRS. - Parses Markdown files for YAML frontmatter (
tags,date,aliases,status). - Extracts document headings (
h1–h6) for table of contents navigation. - Scans text for WikiLink syntax (
[[WikiLink]]) and tags (#tag). - Computes word count, reading time (
WPM = 200), and file modification timestamps. - Generates graph nodes (notes with connections) and directional graph edges.
- Maps attachment files in
07 - Annexure/Images/to absolute web paths. - Writes output to
vault-data.jsas global window objects (window.VAULT_NOTES,window.VAULT_FOLDERS,window.GRAPH_NODES,window.GRAPH_EDGES,window.VAULT_ASSETS).
- Recursively traverses
-
Runtime Phase (Browser):
index.htmlinitializes CSS variables, Google Fonts, KaTeX stylesheets, and script dependencies.vault-app.jsxmounts the root React component, initializing workspace state and URL hash router.vault-editor.jsxprocesses Markdown text, evaluates Dataview codeblocks, shields KaTeX math expressions, and renders WikiLinks.vault-graph.jsxstarts the Canvas 2D Verlet physics animation loop.
interface NoteObject {
id: string; // Normalized slug identifier (e.g. "moc-ai-and-machine-learning")
title: string; // Original note title (e.g. "MOC - AI and Machine Learning")
folder: string; // Folder name (e.g. "01 - MOCs")
path: string[]; // Folder trail hierarchy (e.g. ["01 - MOCs", "MOC - AI and Machine Learning.md"])
content: string; // Raw Markdown content
date: string; // ISO date stamp (e.g. "2026-08-07")
wordCount: number; // Total word count
readingTime: number; // Estimated reading time in minutes
tags: string[]; // Array of tags (e.g. ["AI", "Machine-Learning"])
links: string[]; // Outgoing note IDs linked from this note
backlinks: string[]; // Incoming note IDs linking to this note
outline: HeadingItem[]; // Document table of contents headings
}
interface HeadingItem {
id: string; // Slugified heading anchor ID
text: string; // Clean text title of the heading
level: number; // Heading level (1 to 6)
}interface GraphNode {
id: string; // Note ID slug
title: string; // Note display title
folder: string; // Note parent folder
val: number; // Node importance scale factor based on connection count
}
interface GraphEdge {
source: string; // Source Note ID
target: string; // Target Note ID
}The graph engine runs on an HTML5 Canvas 2D context using a customized Verlet force-directed physics engine:
- Repulsion Force: Electrostatic inverse-square law pushing non-connected nodes apart.
- Link Spring Tension: Hooke's law attraction pulling connected nodes toward their target distance.
- Center Gravity: Weak attraction pulling all nodes toward the canvas origin to prevent drifting.
-
Damping: Velocity decay constant (
$0.88$ ) ensuring physics stabilization. -
Render Optimizations: High-DPI device pixel ratio scaling (
window.devicePixelRatio), directional arrow heads, text threshold opacity fading, and viewport frustum clipping. -
Glassmorphic Settings Panel: Floating control panel providing sliders for center force, repel force, link distance, link thickness, node sizing, and label threshold. Styled with
maxHeight: 'calc(100% - 24px)'andoverflowY: 'auto'to ensure controls never crop.
Since static sites lack Obsidian's Dataview plugin environment, vault-editor.jsx implements a custom query parser renderDataviewBlock(code):
- Parser Execution: Intercepts
```dataviewcodeblocks in Markdown. - Query Grammar:
LIST/TABLE [field AS "Header"]FROM [[Topic]]/FROM #tagWHERE contains(file.folder, "03 - Notes")-([[ExcludeTopic]] or #tag)SORT file.mtime DESC / ASC
- Tag Page Auto-Injection: Opening any note in
08 - Tags/automatically appends a fallback Dataview blockLIST FROM [[TagName]] SORT file.mtime DESCif no explicit query is written in the note. - HTML Output: Renders standard bulleted lists (
<ul>) and tables (<table>) populated with interactive WikiLink buttons.
-
Native Marked Inline Extension: Uses
window.marked.use({ extensions: [highlightExtension] })to tokenize==highlight==into<mark>highlight</mark>tags while preserving raw code blocks (```) untouched. -
Task List Checkbox Cleaner: Strips
marked's prepended<input type="checkbox">elements inrenderer.listitemto prevent double checkbox rendering. -
Math Shielding: Shields inline
$…$and display$$…$$equations before Markdown parsing to prevent math underscores and asterisks from being mangled.
- Tab Manager: Maintains an array of open note IDs (
openTabs), active tab index (activeTabIndex), and tab switching history. - Hash Router: Synchronizes document navigation with the browser URL location hash (
#note-slug). Supports opening notes in new tabs, closing tabs, and browser back/forward history navigation.
- Hierarchical Tree: Renders nested vault folders with custom SVG icons for root categories.
- Smart Auto-Reveal: Listens for active note changes and recursively expands parent folder nodes in the tree state, scrolling the active file item smoothly into view.
-
Document Outline: Lists heading anchors (
h1–h6) with scroll-spy position tracking. Clicking a heading smooth-scrolls the reader window to the target element. -
Two-Way Link Graph: Computes incoming backlinks and outgoing links live from
VAULT_NOTES. -
Related Notes Algorithm: Calculates note similarity scores based on shared tag intersections:
$$\text{Score}(A, B) = | \text{Tags}_A \cap \text{Tags}_B |$$
- Hotkey Listener: Listens for
Cmd+K(macOS) andCtrl+K(Windows/Linux). - Search Scoring: Ranks search results by matching note titles, folder paths, and tag queries (
#tag). Supports keyboard selection (ArrowUp,ArrowDown,Enter).
- CSS Custom Properties: Theme variables defined on
:rootand[data-theme="light"]:--bg-main,--bg-sidebar,--bg-panel,--bg-content--text-primary,--text-secondary,--text-muted--border,--border-strong,--accent,--accent-soft
- Native Blockquote Rendering: Styled with
border-left: 2px solid var(--accent),background: transparent,font-style: normal, and tight nesting indentation to match Obsidian desktop typography.
This vault is organized according to a modified Para/Zettelkasten taxonomy:
notes/
├── 00 - Home/ # Core entry points (README, About Me, INDEX)
├── 01 - MOCs/ # Maps of Content (Topic hubs for AI, DSA, Math, Writing)
├── 02 - Raw Notes/ # Unprocessed course notes, book highlights, & raw paper summaries
├── 03 - Notes/ # Processed evergreen Zettelkasten notes (DSA, Math, DBMS, C, AI)
├── 04 - Research/ # Academic paper drafts & deep technical research
├── 05 - Creativity/ # Creative writing, startup ideas, & unstructured thoughts
├── 06 - Archive/ # Archived exam analysis & completed course materials
├── 07 - Annexure/ # Image attachments (Pasted image...), Excalidraw drawings, PDFs
├── 08 - Tags/ # Dedicated tag index notes with auto-injected Dataview queries
└── 09 - Templates/ # Obsidian templates for raw notes, research, and MOCs
- Atomic Notes: Every note in
03 - Notes/focuses on a single concept (e.g.Binary Search Tree.md,Duality.md,Law Of Demand.md). - WikiLinks & Anchors: Notes link to each other using
[[Note Name]]or[[Note Name#Section Title|Custom Label]]. - Maps of Content (MOCs): MOC notes in
01 - MOCs/serve as structured index hubs grouping related Zettelkasten notes. - Dynamic Tag Pages: Notes in
08 - Tags/(e.g.Finance.md,C.md) dynamically collect all notes across the vault tagged with#financeor#c.
Want to recreate this exact interactive digital garden for your own Obsidian vault? Follow these customization steps:
To prevent private folders, personal journals, or draft notes from being published to your public site, update SKIP_DIRS in build-vault.js:
const SKIP_DIRS = new Set([
'Private',
'Journal',
'Personal',
'.obsidian',
'.trash',
'.git',
]);Customize your website's colors, fonts, and borders by editing the CSS variable tokens in index.html:
:root {
--bg-main: #141517;
--bg-content: #1a1b1e;
--accent: #7c3aed; /* Accent color (purple/indigo/violet) */
--accent-soft: rgba(124, 58, 237, 0.15);
--text-primary: #e6e8ee;
--text-muted: #8a8f9e;
--font-body: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}- Header & Footer Titles: Update your site title and repository links in
index.htmlandvault-editor.jsx. - Social Media Icons: Update
SOCIAL_LINKSinvault-editor.jsx:const SOCIAL_LINKS = [ { id: 'github', href: 'https://github.com/yourusername', title: 'GitHub' }, { id: 'linkedin', href: 'https://linkedin.com/in/yourprofile', title: 'LinkedIn' }, { id: 'email', href: 'mailto:[email protected]', title: 'Email' }, ];
Place your image attachments inside your vault attachments folder (e.g. notes/07 - Annexure/Images/). build-vault.js automatically maps all image filenames to window.VAULT_ASSETS so Obsidian embeds like ![[Pasted image 20260807192239.png]] resolve seamlessly.
knowledge-base/
├── notes/ # Source of Truth: Obsidian Markdown Vault
│ ├── 00 - Home/ # Entry index & home pages
│ ├── 01 - MOCs/ # Maps of Content (Topic hubs)
│ ├── 02 - Raw Notes/ # Book summaries, course notes, research inputs
│ ├── 03 - Notes/ # Processed evergreen Zettelkasten notes
│ ├── 04 - Research/ # In-depth technical & academic research
│ ├── 05 - Creativity/ # Creative writing, project notes, & ideas
│ ├── 06 - Archive/ # Archived & inactive materials
│ ├── 07 - Annexure/ # Image attachments, Excalidraw drawings, PDFs
│ ├── 08 - Tags/ # Dedicated tag index notes
│ └── 09 - Templates/ # Obsidian note templates
│
├── .github/
│ └── workflows/
│ └── deploy.yml # GitHub Actions automated deployment workflow
│
├── build-vault.js # Node compilation script: notes/ -> vault-data.js
├── watch-vault.js # Live file-watcher for instant rebuilds while editing
├── auto-sync.bat # Windows 1-click script: build -> stage -> commit -> push
├── deploy.bat # Convenience alias for auto-sync.bat
├── sync.bat # Convenience alias for auto-sync.bat
├── vault-data.js # Compiled JSON graph & note database
│
├── index.html # Shell HTML, Google Fonts, & CSS theme variables
├── vault-app.jsx # Root React layout, workspace router, & hotkeys
├── vault-sidebar.jsx # File tree, auto-reveal, & mini graph preview
├── vault-editor.jsx # Markdown renderer, tabs, & Dataview evaluator
├── vault-rightpanel.jsx # Outline scroll-spy, backlinks, & related notes
├── vault-graph.jsx # 2D Canvas force graph & settings panel
└── vault-icons.jsx # Lucide SVG icon library & TagBadge component
- Node.js: Version 16.0 or higher.
- Git: Version 2.20 or higher.
-
Rebuild Vault Data:
node build-vault.js
-
Live Rebuilding While Writing in Obsidian:
node watch-vault.js
-
Serve Locally:
npx serve .Open
http://localhost:3000in your browser.
Double-clicking auto-sync.bat (or running deploy.bat / sync.bat) executes the following automated pipeline:
1. cd /d "%~dp0" # Sets working directory to repository root
2. node build-vault.js # Compiles notes/ to vault-data.js
3. Prompt for commit message # Asks user for message (or uses default timestamp)
4. git add . # Stages all note edits, assets, and code
5. git commit -m "!commit_msg!" # Commits staged changes
6. git pull origin obsidian --rebase # Safely syncs remote updates
7. git push origin obsidian # Deploys directly to GitHub PagesWhen changes are pushed to origin/obsidian, .github/workflows/deploy.yml automatically publishes the repository directly to GitHub Pages.
- Security Exclusions: Folders in
SKIP_DIRSinsidebuild-vault.jsare completely excluded during compilation and never published to the web. - Graph Physics Benchmarks: Smooth 60fps canvas rendering for up to 1,000 nodes and 3,000 edges.
- Memory Footprint:
vault-data.jsfor 700+ notes compiles to ~1.2 MB uncompressed, loading in under 150ms over standard broadband. - Lazy Execution: Math shielding, Dataview query parsing, and WikiLink processing run lazily inside React
useMemohooks, keeping document switching under 16ms.
- Author: Yash Agrawall (@yashagrawall)
- Core Stack: React 18, Babel Standalone, Canvas 2D, Marked.js, KaTeX, Highlight.js, Lucide Icons.
- License: MIT License.