Appearance
Document links
Situation normal
Obsidian: Auto-updates wikilinks ([[file]]) when renaming/moving files within Obsidian VitePress: (via update docs) Detects and reports broken links
Problem
VitePress detects broken links but nothing fixes them, and the sidebar gets out of sync. We need these tools:
- Tool 1: Fix broken links (automated via
update docs) - Tool 2: Merge files (manual CLI command)
- Tool 3: Sync sidebar (automated via
update docs) - Tool 4: (reserved for future use)
- Tool 5: Generate docs database (automated via
update docs)
When I say "Fix broken links"
Invocation: Runs automatically during update docs builds
- [ ] read broken links from
vitepress.build.txt(format: "Dead link: path/to/file.md -> missing-file.md") - [ ] within notes and in VitePress config.mts:
- [ ] find each moved file by searching repo for filename matching its dead link (ignore path)
- [ ] update broken links to point to new locations (including path if relevant)
- [ ] update VitePress config sidebar entries
- [ ] if target file doesn't exist anywhere, delete the broken link
- [ ] report summary: fixed, deleted, unfixable
When I say "Sync sidebar"
Invocation: Runs automatically during update docs builds
- [ ] scan
/notes/designsdirectory recursively - [ ] build sidebar structure from actual filesystem
- [ ] preserve existing sidebar groups and collapsed states
- [ ] update
.vitepress/config.mtswith current file structure - [ ] report summary: added, removed, updated
When I say "Generate docs database"
Invocation: Runs automatically during update docs builds
- [ ] scan
/notes/designsdirectory recursively - [ ] generate TypeScript data file (
Docs.ts) with documentation structure - [ ] for each folder: create DocNode entry with optional link to index.md
- [ ] for each .md file: create DocNode entry with path (excluding index.md)
- [ ] auto-format names (kebab-case → Title Case)
- [ ] strip .md extensions from all paths (VitePress URLs)
- [ ] output to
/src/lib/ts/files/Docs.ts - [ ] used by DB_Docs to create graph visualization of documentation
When I say "Merge A into B"
Invocation: Manual CLI command with two file paths
- [ ] create backups: A.original and B.original
- [ ] analyze A and B, identify duplicate content in A
- [ ] copy unique content from A into B:
- [ ] for each unique section in A:
- [ ] find best-fit heading in B (or create new one)
- [ ] insert at start of that section
- [ ] for each unique section in A:
- [ ] update TOC in B
- [ ] preserve A, A.original and B.original (for manual review/undo)
- [ ] update all links pointing to A → redirect to B
- [ ] update VitePress config.mts: remove A, keep B
Constraints & Assumptions
File conventions:
- Process
.mdfiles only - Search within
/notesdirectory and subdirectories - Use relative paths from repo root
- Assume UTF-8 encoding
- No max file size limit (reasonable docs assumed)
Link conventions:
- Wikilinks:
[[file]]or[[file.md]] - Markdown links:
[text](path/file.md) - Image links are ignored (not modified)
- Links in code blocks are ignored (triple backticks)
Error Handling
Tool 1: (While parsing vitepress.build.txt for dead links)
- Missing build file → Done, log warning
- Malformed → Skip invalid lines, continue
- No target found for link → Delete it (as specified)
- Multiple files match same filename → Prompt user to choose, or skip (counts as "unfixable")
- VitePress config parse error → Log error, continue with markdown files (affected links count as "unfixable")
Tool 2: (Merge A into B)
- A or B doesn't exist → Exit with error, show usage
- A and B are same file → Exit with error
- Duplicate headings in B → Insert under first matching heading
- TOC parse fails → Log warning, skip TOC update
- Link update fails → Log warning, continue
Tool 3: (Sync sidebar)
- Cannot read .vitepress/config.mts → Exit with error
- Cannot parse config → Exit with error, show parse location
- Cannot write config → Exit with error, check permissions
- Malformed directory structure → Skip invalid entries, log warning
Tool 5: (Generate docs database)
- Cannot read /notes/designs → Exit with error
- Cannot write to Docs.ts → Exit with error, check permissions
- Malformed directory structure → Skip invalid entries, log warning
General:
- Circular links → Ignore, not our problem (VitePress will flag)
- File write permission errors → Exit with error message
- Git conflicts → User handles manually
Edge Cases
Tool 1:
- File links to itself → Ignore, valid self-reference
- Broken link appears in code block → Skip (don't modify)
- Link uses anchor
#heading→ Preserve anchor after fix- Example:
[text](old/path.md#section)becomes[text](new/path.md#section) - The
#sectionanchor must be preserved when updating the path
- Example:
- Multiple broken links to same missing file → Delete all
Tool 2:
- A is empty → Skip merge, just update links and config
- B is empty → Move A content wholesale, simpler merge
- Both files identical → Delete A, update links/config only
- Heading exists in both → Merge under existing heading
Tool 3:
- index.md files → Skip, don't add to sidebar
- .DS_Store and other system files → Ignore
- Files in srcExclude directories → Respect VitePress config, skip
- Nested directory depth → Support unlimited nesting
Tool 5:
- index.md files → Used as folder links, not separate nodes
- .DS_Store and other system files → Ignored
- Empty directories → Created as folders with no children
- Nested directory depth → Support unlimited nesting
Implementation Details
Language & tooling:
- Node.js with TypeScript
- Use existing project dependencies where possible
- New dependencies:
remark(markdown parsing),glob(file search)
Project structure:
notes/tools/
fix-links.ts # Tool 1
merge-files.ts # Tool 2
sync-sidebar.ts # Tool 3
create_docs_db_data.sh # Tool 5
lib/
markdown-parser.ts
link-finder.ts
config-updater.ts
generate-sidebar.ts # For Tool 3
src/lib/ts/
files/
Docs.ts # Generated by Tool 5
database/
DB_Docs.ts # Uses Docs.ts for Tool 5Command line usage:
Tool 1 (Fix broken links):
bash
node notes/tools/fix-links.ts # Run with default settings
node notes/tools/fix-links.ts -v # Verbose mode (show each change)
node notes/tools/fix-links.ts --help # Show usageTool 2 (Merge files):
bash
node notes/tools/merge-files.ts A.md B.md # Merge A into B
node notes/tools/merge-files.ts -v A.md B.md # Verbose mode
node notes/tools/merge-files.ts --help # Show usageTool 3 (Sync sidebar):
bash
node notes/tools/sync-sidebar.ts # Sync sidebar with filesystem
node notes/tools/sync-sidebar.ts -v # Verbose mode
node notes/tools/sync-sidebar.ts --help # Show usageTool 5 (Generate docs database):
bash
bash notes/tools/create_docs_db_data.sh # Generate Docs.tsVitePress config.mts structure:
typescript
export default {
themeConfig: {
sidebar: [
{
text: 'Guides',
items: [
{ text: 'Getting Started', link: '/notes/guides/getting-started' },
{ text: 'Debugging', link: '/notes/guides/debugging' },
// Tools update these link values when files move or sidebar syncs
]
}
]
}
}Tools identify entries by matching the link property against moved/deleted file paths.
Integration with update docs:
- Step 1: Build VitePress documentation
- Step 2: Compile TypeScript tools
- Step 3: Run fix-links tool (Tool 1)
- Step 4: Run sync-sidebar tool (Tool 3)
- Step 5: Run create_docs_db_data.sh (Tool 5)
- Check exit codes, proceed only if successful
- Tool 2 (merge-files) runs manually when needed
Testing Strategy
All testing is done in a test fixture, with a current copy of .vitepress/config.mts
Test fixtures location:
/notes/work/test-fixtures/- Contains sample markdown files with various link patterns
- Contains sample broken
vitepress.build.txt
Test approach:
- Copy the current version of
.vitepress/config.mts - Create fixtures, run tools, verify changes
- Use git to show diffs before/after
- Test each error condition with malformed inputs
- Run on fixtures before deploying to real docs
Rollback procedure: (NB, this only works if git status is up to date)
- All tools preserve
.originalbackup files - Use
git restorefor immediate rollback - Review
.originalfiles before deleting them
Backup cleanup strategy:
.originalfiles are never auto-deleted- Manual cleanup: User reviews and deletes when satisfied with changes
- Recommended workflow:
- Run tool, inspect results
- Test that links work
- If satisfied:
rm *.original - If not:
git restoreaffected files, review.originalfiles
Output & Logging
Console output:
- Summary: "Fixed 12 links, deleted 3, skipped 1"
- Detailed mode: Show each link changed (optional
-vflag) - Errors: Red text, clear error messages
- Warnings: Yellow text
File logging:
- Write detailed log to
notes/work/test-fixtures/fix-links.log - Append mode (don't overwrite)
- Include timestamp, file paths, actions taken
Exit codes:
- 0: Success
- 1: Error (file not found, parse error, etc.)
- 2: Warning (some operations skipped, but completed)
Implementation
Phase 1: Build Tool 1 (Fix broken links) ✅ COMPLETE & TESTED
- [x] Set up project structure in
notes/tools/ - [x] Install dependencies: Using existing TypeScript setup
- [x] Implement
lib/markdown-parser.ts- [x] Parse markdown files
- [x] Extract links (both wikilinks and markdown links)
- [x] Preserve code blocks (don't parse links inside them)
- [x] Implement
lib/link-finder.ts- [x] Search repo for files by filename
- [x] Handle multiple matches (currently skips, prompts user)
- [x] Return file paths
- [x] Implement
lib/config-updater.ts- [x] Parse VitePress config.mts
- [x] Update sidebar link entries
- [x] Remove entries for deleted files
- [x] Implement
fix-links.tsmain script- [x] Parse
vitepress.build.txt - [x] Find moved files
- [x] Update broken links in markdown files
- [x] Update VitePress config
- [x] Delete links to non-existent files (cleanly, no leftover bullets)
- [x] Generate summary report
- [x] Handle
-vand--helpflags
- [x] Parse
- [x] Create test fixtures
- [x] Test on fixtures - ALL TESTS PASSING
- [x] Update CLAUDE.MD
update docscommand
Phase 2: Build Tool 2 (Merge files) ✅ COMPLETE & TESTED
- [x] Implement
merge-files.tsmain script- [x] Parse command line args (A.md B.md)
- [x] Create
.originalbackups - [x] Analyze both files for duplicate content
- [x] Identify unique sections in A
- [x] Append unique content to B (simplified from original spec)
- [x] Update TOC in B
- [x] Find and update all links to A → B
- [x] Update VitePress config (remove A, keep B)
- [x] Handle
-vand--helpflags
- [x] Create test fixtures for merge scenarios
- [x] Test on fixtures - ALL TESTS PASSING
Phase 3: Build Tool 3 (Sync sidebar) ✅ COMPLETE & TESTED
- [x] Implement
lib/generate-sidebar.ts- [x] Recursively scan
/notes/designsdirectory - [x] Build sidebar structure from filesystem
- [x] Convert file/directory names to proper titles
- [x] Preserve existing group names and collapsed states
- [x] Generate proper link paths
- [x] Recursively scan
- [x] Implement
sync-sidebar.tsmain script- [x] Read current
.vitepress/config.mts - [x] Generate new sidebar from filesystem
- [x] Merge with existing config (preserve other settings)
- [x] Write updated config back
- [x] Generate summary report (added, removed, updated)
- [x] Handle
-vand--helpflags
- [x] Read current
- [x] Create test fixtures for sidebar sync
- [x] Test on fixtures - ALL TESTS PASSING
- [x] Integrate into update-docs workflow
Phase 4: Integration & Documentation ✅ COMPLETE
- [x] All three tools integrated into update-docs workflow
- [x] TypeScript source reorganized into lib/ directory
- [x] All tools tested and working in production
Phase 5: Build Tool 5 (Generate docs database) ✅ COMPLETE
- [x] Created
create_docs_db_data.shshell script- [x] Recursively scans /notes/designs
- [x] Generates Docs.ts with DocNode structure
- [x] Auto-formats names (kebab-case → Title Case)
- [x] Creates unique IDs for each node
- [x] Adds link property to folders with index.md
- [x] Skips index.md from appearing as separate nodes
- [x] Strips .md extensions from all paths
- [x] Created
DB_Docs.tsdatabase class- [x] Extends DB_Common
- [x] Imports and uses getDocsStructure() from Docs.ts
- [x] Creates Things for folders and files
- [x] Creates Relationships for hierarchy
- [x] Adds Link Traits to files and folders with index
- [x] Uses depth-based color coding
- [x] Created
/src/lib/ts/files/Docs.tsdata file- [x] DocNode interface definition
- [x] getDocsStructure() function
- [x] Auto-generated by create_docs_db_data.sh
- [x] Integrated into Databases.ts
- [x] Added T_Database.docs enum
- [x] Added DB_Name.docs enum
- [x] Added to database cycle
- [x] Added to db_forType() switch
- [x] Integrated into update-docs workflow (Step 5)
- [x] Tested and working in production