Skip to main content

Stable URLs and Sidebar Strategy 2026

Problem: File moves break links, cause 404s, hurt SEO, disrupt sidebar order

Solution: Stable slugs + metadata-based ordering + LLM-assisted migration

Current State Analysis

What You Have Now

URL Structure:

  • ❌ Path-based: https://deepaksood619.github.io/ai/llm/fundamentals/intro
  • ❌ Moves create 404s: Rename folder → broken links
  • ❌ Poor SEO: URL changes lose search ranking

Links:

  • ❌ Relative paths: [Transformers](../architectures/transformers.md)
  • ❌ Break on moves: Move file → update all referencing files

Sidebar Ordering:

  • ❌ Alphabetical: sidebars.js uses {type: 'autogenerated', dirName: '.'}
  • ⚠️ Some numbered prefixes: 01-intro.md, 02-getting-started.md
  • ❌ Inconsistent: Only in some folders (databricks, concepts)

Slug Usage:

  • ❌ Only 1 file: readme.md has slug: /
  • ❌ No systematic slugs

Problems This Causes

  1. Link Rot

    • Refactor folder structure → all internal links break
    • External links (Google, social media) become 404s
    • Wastes SEO value accumulated over time
  2. Sidebar Chaos

    • Alphabetical order ≠ logical learning order
    • "Introduction" appears after "Advanced Topics"
    • Numbered prefixes ugly and manual
  3. Obsidian ≠ Docusaurus

    • Obsidian sorts alphabetically by filename
    • Docusaurus sorts alphabetically by sidebar config
    • No shared ordering mechanism
  4. Maintenance Burden

    • Move file → manually update all referencing links
    • Reorder topics → rename files with new numbers
    • Can't let LLM reorganize (too risky)

Solution Architecture

Three-Part System

┌─────────────────────────────────────────────────────┐
│ 1. STABLE SLUGS (Docusaurus URLs) │
│ Fixed forever, independent of file location │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│ 2. FRONTMATTER ORDERING (Both tools) │
│ sidebar_position, sidebar_label metadata │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│ 3. OBSIDIAN METADATA (Custom sort) │
│ Obsidian Dataview + custom CSS for visual order │
└─────────────────────────────────────────────────────┘

Part 1: Stable Slugs

Slug Design Principles

Good slugs are:

  • Permanent: Never change, even if file moves
  • Semantic: Describe content, not location
  • SEO-friendly: Keywords, hyphens, lowercase
  • Hierarchical: Show topic relationships
  • Human-readable: Make sense in URL bar

Examples:

File PathBad SlugGood Slug
ai/llm/fundamentals/intro.md/ai/llm/fundamentals/intro/llm-introduction
databases/clickhouse/architecture.md/databases/clickhouse/architecture/clickhouse-architecture
book-summaries/atomic-habits.md/book-summaries/atomic-habits/atomic-habits-summary

Why flatten hierarchy in slugs?

  • ✅ Shorter URLs (better for sharing)
  • ✅ Survives reorganization (move file, slug stays)
  • ✅ SEO boost (focus keywords in URL)

Slug Naming Convention

Format: /{domain}-{topic}-{specificity}

Templates by note type:

# Concepts
/{concept-name}
Examples: /transformers, /self-attention, /rag

# Tools/Technologies
/{tool-name}-{aspect}
Examples: /clickhouse-architecture, /kafka-streams, /airflow-operators

# Comparisons
/{x}-vs-{y}
Examples: /postgres-vs-mysql, /rest-vs-graphql

# Guides/Tutorials
/{action}-{object}
Examples: /deploy-kubernetes, /optimize-queries, /debug-llm

# Book Summaries
/{book-title}-summary
Examples: /atomic-habits-summary, /deep-work-summary

# Interview Prep
/{topic}-interview-questions
Examples: /llm-interview-questions, /system-design-interview

# People/Companies
/{name}
Examples: /sam-altman, /openai

# Frameworks/Methodologies
/{framework-name}
Examples: /zettelkasten, /gtd-getting-things-done

Frontmatter Slug Implementation

Every note gets:

---
id: stable-unique-id-2024-03-15
title: "Transformer Architecture in LLMs"
slug: /transformer-architecture # ← THE STABLE URL
sidebar_position: 3
sidebar_label: "Transformers"
description: "Deep dive into transformer architecture and self-attention mechanisms"
keywords: [transformers, self-attention, neural networks, llm]
---

Slug rules:

  1. Unique across entire vault (LLM checks for collisions)
  2. Never changes (set once, frozen forever)
  3. Short (2-4 words max)
  4. No nested paths (unless absolutely needed for disambiguation)

Exception - Hierarchical slugs when needed:

# Use nested slugs for:
# - Large subsystems (Kafka has 50+ pages)
# - Disambiguation (multiple "architecture" pages)

slug: /kafka/streams/architecture
slug: /clickhouse/architecture
slug: /kubernetes/architecture

Migration Strategy for Slugs

Phase 1: Generate slugs for all notes

def generate_slug(note_path, note_content):
"""LLM generates SEO-friendly slug from note content"""

# Extract context
domain = extract_domain_from_path(note_path) # ai/llm
title = extract_title(note_content)
keywords = extract_keywords(note_content)
note_type = classify_note_type(note_content)

# LLM prompt
prompt = f"""
Generate a permanent, SEO-friendly URL slug for this note.

Note context:
- Domain: {domain}
- Title: {title}
- Type: {note_type}
- Keywords: {keywords}

Rules:
1. 2-4 words max, separated by hyphens
2. Lowercase only
3. Focus on main concept, not file location
4. SEO-friendly (include searchable keywords)
5. No year/date (timeless)
6. Check uniqueness against existing slugs

Examples:
- "Introduction to LLMs" → /llm-introduction
- "ClickHouse Architecture Deep Dive" → /clickhouse-architecture
- "GPT vs BERT Comparison" → /gpt-vs-bert

Output format:
slug: /your-slug-here
reasoning: Why this slug is optimal
"""

response = call_llm(prompt)
slug = extract_slug(response)

# Check for collisions
if slug_exists(slug):
# Try variations
slug = f"{slug}-{domain}"

return slug

Phase 2: Update all notes with slugs

# LLM script
python scripts/add_slugs_to_frontmatter.py

# Output:
# ✓ Generated 3,074 slugs
# ✓ 0 collisions (auto-resolved)
# ✓ Updated frontmatter
# ✓ Created slug registry (slugs.json)

Phase 3: Update internal links

Options:

Option A: Keep relative paths, add slug metadata

---
slug: /transformer-architecture
---

# Transformers

See [Self-Attention](self-attention.md) for details.
<!-- LLM adds: target_slug: /self-attention -->

Option B: Convert to slug-based links (RECOMMENDED)

See [Self-Attention](/self-attention) for details.

Benefits:

  • ✅ Works in both Obsidian and Docusaurus
  • ✅ Survives file moves
  • ✅ Cleaner (no relative path hell)

Phase 4: Set up redirects

// docusaurus.config.js
module.exports = {
plugins: [
[
'@docusaurus/plugin-client-redirects',
{
redirects: [
// Old path → New slug
{
from: '/ai/llm/fundamentals/intro',
to: '/llm-introduction',
},
{
from: '/databases/clickhouse/architecture',
to: '/clickhouse-architecture',
},
],
createRedirects(existingPath) {
// Auto-generate redirects from file path to slug
// LLM generates this mapping
return generateRedirectsFromSlugRegistry(existingPath);
},
},
],
],
};

Slug Registry

Create: docs/.slugs/registry.json

{
"slugs": [
{
"slug": "/transformer-architecture",
"file": "ai/llm/architectures/transformers.md",
"title": "Transformer Architecture",
"created": "2024-03-15",
"last_verified": "2026-06-19",
"old_paths": [
"/ai/llm/fundamentals/transformers",
"/ai/transformers"
]
},
{
"slug": "/clickhouse-architecture",
"file": "databases/clickhouse/architecture.md",
"title": "ClickHouse Architecture",
"created": "2023-05-10",
"old_paths": [
"/databases/clickhouse/architecture"
]
}
],
"collisions": [],
"reserved": ["/", "/about-deepak-sood", "/ai", "/databases"]
}

LLM uses registry to:

  • Detect slug collisions before creating
  • Generate redirects automatically
  • Validate links (ensure target slug exists)
  • Track slug history for analytics

Part 2: Sidebar Ordering

Current Problem

Docusaurus autogenerated sidebar:

// sidebars.js
const sidebars = {
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
};

Result: Alphabetical order (not learning order)

❌ Current sidebar (alphabetical):
- Advanced Topics
- Applications
- Fundamentals
- Introduction

Desired sidebar (logical order):

✅ Desired:
1. Introduction
2. Fundamentals
3. Applications
4. Advanced Topics

Solution: Frontmatter-Based Ordering

Every note gets sidebar_position:

---
slug: /llm-introduction
sidebar_position: 1
sidebar_label: "Introduction"
---

Docusaurus automatically sorts by sidebar_position (built-in feature).

Numbering Convention

Use gap numbering for flexibility:

# Allow insertions without renumbering everything
sidebar_position: 10 # Introduction
sidebar_position: 20 # Fundamentals
sidebar_position: 30 # Intermediate
sidebar_position: 40 # Advanced
sidebar_position: 50 # References

# Insert new page between Fundamentals and Intermediate:
sidebar_position: 25 # New section (no renumbering needed)

Per-folder numbering:

docs/ai/llm/
├── intro.md (sidebar_position: 10)
├── fundamentals/
│ ├── models.md (sidebar_position: 10)
│ ├── training.md (sidebar_position: 20)
│ └── inference.md (sidebar_position: 30)
├── applications/
│ ├── chatbots.md (sidebar_position: 10)
│ └── summarization.md (sidebar_position: 20)

Category ordering with _category_.json:

// docs/ai/llm/_category_.json
{
"label": "Large Language Models",
"position": 20,
"link": {
"type": "doc",
"id": "ai/llm/readme"
},
"collapsible": true,
"collapsed": false
}

Remove Number Prefixes from Filenames

Migrate from:

01-intro.md
02-getting-started.md
03-advanced.md

To:

# intro.md
---
sidebar_position: 10
---

# getting-started.md
---
sidebar_position: 20
---

# advanced.md
---
sidebar_position: 30
---

Benefits:

  • ✅ Clean filenames
  • ✅ Easier to reference
  • ✅ Works in both Obsidian and Docusaurus
  • ✅ Reordering doesn't require file renames

LLM Migration Script:

def remove_number_prefixes():
numbered_files = find_files_with_pattern(r'^\d{2,3}-.*\.md$')

for file in numbered_files:
# Extract number
number = extract_leading_number(file.name) # "01-intro.md" → 1

# Remove prefix from filename
new_name = remove_prefix(file.name) # "01-intro.md" → "intro.md"

# Add sidebar_position to frontmatter
add_frontmatter(file, sidebar_position=number * 10)

# Rename file
rename_file(file, new_name)

# Update all links to this file
update_links_in_vault(old_name=file.name, new_name=new_name)

Part 3: Obsidian Ordering

Challenge: Obsidian Doesn't Read Frontmatter for Sorting

Obsidian file browser sorts by:

  • ❌ Filename (alphabetically or by number prefix)
  • ❌ Created date
  • ❌ Modified date

Not by:

  • ❌ Frontmatter sidebar_position

Solution: Obsidian Plugins + Visual Indicators

Option A: Custom File Explorer Order (Plugin)

Use Obsidian Custom File Explorer plugin:

  1. Install plugin: obsidian42-custom-file-explorer
  2. Configure sort by frontmatter:
// .obsidian/plugins/custom-file-explorer/data.json
{
"sortBy": "frontmatter",
"frontmatterKey": "sidebar_position",
"fallbackSort": "alphabetical"
}

Option B: Numbered Emoji Prefixes (Visual Only)

Add visual indicators without changing filenames:

---
title: "📍 1. Introduction to LLMs"
sidebar_position: 10
sidebar_label: "Introduction"
slug: /llm-introduction
---

Obsidian displays: 📍 1. Introduction to LLMs Docusaurus displays: Introduction (uses sidebar_label)

Option C: Dataview Dynamic Index (RECOMMENDED)

Create _index.md in each folder:

<!-- docs/ai/llm/_index.md -->

# LLM Knowledge Base

> Ordered index of all LLM notes (auto-generated)

​```dataview
TABLE
sidebar_position as "#",
file.link as "Note",
description as "Description"
FROM "ai/llm"
WHERE file.name != "_index" AND file.name != "readme"
SORT sidebar_position ASC
​```

Result in Obsidian:

#NoteDescription
10[[intro]]Introduction to LLMs
20[[fundamentals/models]]LLM architectures and models
30[[applications/chatbots]]Building chatbots with LLMs

Option D: Folder Notes Plugin

Use Folder Note plugin to make readme.md the folder note:

  1. Install: alx-folder-note
  2. Configure: Treat readme.md as folder overview
  3. Add ordered navigation section to each readme.md:
<!-- ai/llm/readme.md -->

# LLM

## Learning Path (In Order)

1. [Introduction](fundamentals/intro.md) - Start here
2. [Models](fundamentals/models.md) - Core architectures
3. [Training](fundamentals/training.md) - How LLMs learn
4. [Applications](applications/readme.md) - Real-world use
5. [Advanced Topics](advanced/readme.md) - Deep dives

<!-- Auto-generated from sidebar_position -->

Recommended: Combine B + C + D

  • Visual emoji prefixes for quick scanning
  • Dataview tables for structured navigation
  • Folder notes for curated learning paths

Comprehensive Frontmatter Schema

Complete Template

---
# Identity (stable, never changes)
id: transformer-architecture-2024-03-15
slug: /transformer-architecture

# Display
title: "Transformer Architecture in LLMs"
sidebar_label: "Transformers" # Short label for sidebar
description: "Deep dive into transformer architecture, self-attention mechanisms, and positional encoding"

# Ordering
sidebar_position: 25

# SEO
keywords:
- transformers
- self-attention
- neural networks
- llm architecture
- attention mechanism

# Content metadata (from previous recommendations)
type: concept
domain: ai/llm/architectures
status: evergreen
confidence: high
created: 2024-03-15
updated: 2026-06-19
last_verified: 2026-06-19
review_by: 2027-06-19
decay_rate: medium

# Relationships
related:
- id: self-attention
type: prerequisite
slug: /self-attention
- id: bert-architecture
type: implements
slug: /bert-architecture
- id: gpt-architecture
type: sibling
slug: /gpt-architecture

# Flashcards
has_flashcards: true
flashcard_file: ai/llm/architectures/flashcards.md
flashcard_count: 12

# Learning
tags:
- domain/ai/ml/deep-learning/architectures/transformers
- application/nlp/text-generation
- technique/attention-mechanisms

# Obsidian-specific (visual ordering)
aliases:
- "📍 2.5 Transformers"
- "attention-is-all-you-need"
---

Minimal Required Fields

For new notes, minimum:

---
slug: /your-permanent-slug
sidebar_position: 10
title: "Note Title"
---

LLM auto-generates rest.

Migration Playbook

Phase 1: Slug Generation (Week 1-2)

Goal: Every note gets a permanent slug

Steps:

  1. LLM Script: Generate slugs

    python scripts/generate_slugs.py

    For each note:

    • Analyze title, content, domain
    • Generate SEO-friendly slug
    • Check uniqueness
    • Add to frontmatter
    • Update slug registry
  2. Human Review: Sample check

    • Review 100 random slugs
    • Check for collisions
    • Verify SEO quality
    • Approve or regenerate
  3. Commit: Slug additions

    git commit -m "feat: add permanent slugs to all notes"

Estimated:

  • LLM time: 3-4 hours (3,074 notes × 4 sec each)
  • Human review: 2 hours
  • Cost: $15-25 (Claude API)

Phase 2: Sidebar Positions (Week 3-4)

Goal: Every note gets logical ordering

Steps:

  1. LLM Script: Assign positions

    def assign_sidebar_positions():
    for folder in get_all_folders():
    notes = get_notes_in_folder(folder)

    # LLM determines logical order
    prompt = f"""
    Order these notes from beginner to advanced:
    {[note.title for note in notes]}

    Consider:
    - Prerequisites first
    - Concepts before applications
    - Simple before complex

    Output: Ordered list with gap numbering (10, 20, 30...)
    """

    ordered = call_llm(prompt)

    for note, position in zip(notes, ordered):
    add_frontmatter(note, sidebar_position=position)
  2. Category files: Create _category_.json

    • LLM generates for each folder
    • Sets position relative to sibling folders
    • Adds labels and descriptions
  3. Validate: Build Docusaurus

    npm run build
    # Check sidebar order in output

Estimated:

  • LLM time: 2-3 hours
  • Human review: 3 hours (verify learning paths)
  • Cost: $10-20

Phase 3: Remove Number Prefixes (Week 5)

Goal: Clean filenames, migrate to frontmatter

Steps:

  1. Find numbered files:

    find . -name "[0-9][0-9]-*.md"
  2. LLM Script: Migrate

    • Extract number → sidebar_position
    • Remove prefix from filename
    • Update all internal links
    • Update git history (preserve)
  3. Test: Verify no broken links

    npm run build # Docusaurus will catch broken links

Estimated:

  • LLM time: 1 hour (only ~50 numbered files based on find results)
  • Cost: $5

Goal: All internal links use slugs, not relative paths

Options:

Option A: Gradual migration

  • Keep relative paths
  • LLM adds slug metadata in comments
  • Convert to slugs when notes move

Option B: Full migration (RECOMMENDED)

  • LLM converts all links to slugs
  • One-time pain, permanent benefit

Script:

def convert_links_to_slugs():
slug_registry = load_slug_registry()

for note in get_all_notes():
content = read(note)

# Find all markdown links
links = find_markdown_links(content)

for link in links:
target_file = resolve_relative_path(link.path, note.path)

if target_file in slug_registry:
target_slug = slug_registry[target_file].slug

# Replace: [Text](../path/to/file.md) → [Text](/slug)
content = content.replace(
f"[{link.text}]({link.path})",
f"[{link.text}]({target_slug})"
)

write(note, content)

Risk mitigation:

  • Backup entire vault first
  • Test on 10 notes
  • Build Docusaurus after each batch
  • Commit in small batches (100 notes at a time)

Estimated:

  • LLM time: 4-6 hours (link parsing + conversion)
  • Human review: 5 hours (verify critical links)
  • Cost: $20-30

Phase 5: Obsidian Visual Ordering (Week 9)

Goal: Make ordering visible in Obsidian

Steps:

  1. Install plugins:

    • Custom File Explorer
    • Dataview
    • Folder Note
  2. Create _index.md in each folder:

    • LLM generates Dataview queries
    • Links to ordered notes
    • Auto-updates on change
  3. Add emoji prefixes (optional):

    aliases: ["📍 1.5 Transformers"]
  4. Configure Obsidian:

    • Set File Explorer to sort by frontmatter
    • Enable Folder Note for readme.md

Estimated:

  • Setup: 2 hours
  • LLM generation of index files: 1 hour
  • Cost: $5

Phase 6: Redirects & SEO (Week 10)

Goal: Preserve existing SEO, prevent 404s

Steps:

  1. Install redirect plugin:

    npm install @docusaurus/plugin-client-redirects
  2. LLM generates redirect rules:

    • Read slug registry
    • Map old paths → new slugs
    • Generate redirect config
  3. Submit to Google Search Console:

    • Upload new sitemap
    • Request recrawl
    • Monitor 404s

Estimated:

  • Setup: 3 hours
  • Monitoring: Ongoing

Obsidian-Specific Solutions

Dataview Queries for Navigation

Master index with ordering:

<!-- docs/_master-index.md -->

# Complete Knowledge Base (Ordered)

​```dataview
TABLE
domain as "Domain",
sidebar_position as "#",
file.link as "Note",
status as "Status",
updated as "Last Updated"
FROM ""
WHERE type = "concept" AND status = "evergreen"
SORT domain ASC, sidebar_position ASC
​```

Domain-specific ordered views:

<!-- docs/ai/llm/_navigation.md -->

# LLM Learning Path

​```dataview
LIST
FROM "ai/llm"
WHERE sidebar_position != null
SORT sidebar_position ASC
​```

## By Topic

​```dataview
TABLE
sidebar_position as "#",
description as "What You'll Learn"
FROM "ai/llm"
GROUP BY type
SORT sidebar_position ASC
​```

Custom CSS for Visual Ordering

Add to .obsidian/snippets/ordered-files.css:

/* Show sidebar_position in file explorer */
.nav-file-title::before {
content: attr(data-position) ". ";
color: var(--text-muted);
font-size: 0.9em;
}

/* Highlight notes with no position */
.nav-file[data-position=""] .nav-file-title {
opacity: 0.6;
font-style: italic;
}

Enable via plugin or Templater:

// Add data-position attribute to file elements
const files = document.querySelectorAll('.nav-file');
files.forEach(file => {
const position = getFileMetadata(file, 'sidebar_position');
file.setAttribute('data-position', position || '');
});

Integration with Previous Recommendations

Enhanced Frontmatter (Combined Schema)

---
# IDENTITY (Stable URLs - this doc)
id: transformer-architecture-2024-03-15
slug: /transformer-architecture

# DISPLAY (Stable URLs - this doc)
title: "Transformer Architecture in LLMs"
sidebar_label: "Transformers"
sidebar_position: 25
description: "Deep dive into transformer architecture and self-attention"
keywords: [transformers, self-attention, llm architecture]

# CONTENT (PKM Scaling recommendations)
type: concept
domain: ai/llm/architectures
status: evergreen
confidence: high
created: 2024-03-15
updated: 2026-06-19
last_verified: 2026-06-19
review_by: 2027-06-19
decay_rate: medium

# RELATIONSHIPS (PKM Scaling)
related:
- id: self-attention
type: prerequisite
slug: /self-attention
- id: bert
type: implements
slug: /bert-architecture

# FLASHCARDS (Flashcard Integration)
has_flashcards: true
flashcard_file: ai/llm/architectures/flashcards.md
flashcard_count: 12

# LEARNING (PKM Scaling + Flashcards)
tags:
- domain/ai/ml/deep-learning/architectures/transformers
- application/nlp/text-generation

# OBSIDIAN (Stable URLs - this doc)
aliases: ["📍 2.5 Transformers", "attention-is-all-you-need"]

# PERSONAL (PKM Scaling)
personal_experience:
- Implemented transformers at OpsTree for NLP pipeline
- Debugged attention memory issues at scale
learning_date: 2023-08-15
mastery_level: expert
---

LLM Workflows Updated

Daily workflow adds:

  • Generate slug for new notes
  • Assign sidebar_position based on folder context
  • Update slug registry
  • Validate no slug collisions

Weekly workflow adds:

  • Detect moved files (path changed, slug preserved)
  • Update slug registry
  • Generate redirects for old paths
  • Validate all slug-based links

Monthly workflow adds:

  • Audit sidebar_position gaps/overlaps
  • Rebalance positions if needed
  • Update category ordering
  • Check for 404s in published site

Best Practices

1. Slug Immutability

Once set, slugs NEVER change.

# ✅ Good: Set once, frozen forever
slug: /transformer-architecture

# ❌ Bad: Changing slug
# Old: slug: /transformers
# New: slug: /transformer-architecture-guide # NEVER DO THIS

If you must change a slug:

  1. Create new note with new slug
  2. Add redirect from old → new
  3. Mark old note as deprecated
  4. Update all internal links
  5. Monitor analytics for old slug usage

2. Sidebar Position Gaps

Always use gap numbering:

# ✅ Good: Room for insertions
sidebar_position: 10
sidebar_position: 20
sidebar_position: 30

# ❌ Bad: No room to insert
sidebar_position: 1
sidebar_position: 2
sidebar_position: 3

# Need to insert between 2 and 3?
# Must renumber everything after

Rebalancing trigger:

  • If gaps < 5, LLM script rebalances folder
  • Auto-renumber to 10, 20, 30 spacing
  • Happens monthly

3. Slug vs Relative Path

When to use each:

# ✅ Internal wiki links: Use slugs
See [Transformers](/transformer-architecture) for details.

# ✅ Same-folder references: Relative paths OK
In this section, we cover [basics](basics.md) and [advanced](advanced.md).

# ⚠️ Cross-domain links: Prefer slugs
From databases note: See [LLM concepts](/llm-introduction)

# ❌ Never use full paths
Bad: [Link](../../ai/llm/fundamentals/intro.md)
Good: [Link](/llm-introduction)

4. Obsidian Compatibility

Test both tools:

# After link changes:
1. Build Docusaurus → check for errors
npm run build

2. Open Obsidian → check links resolve
(Click through 20 random links)

3. Check slug registry → no duplicates
python scripts/validate_slugs.py

5. SEO Optimization

Good slug SEO:

# ✅ Good: Keywords, readable
slug: /clickhouse-materialized-views
slug: /react-hooks-useeffect
slug: /system-design-interview-prep

# ❌ Bad: Generic, not searchable
slug: /page-1
slug: /note
slug: /document-123

Use keywords from:

  • Note title
  • Primary tag
  • Most common search queries (Google Search Console)

Potential Issues & Solutions

Issue 1: Slug Collisions

Problem: Two notes want same slug

Solution:

# LLM auto-resolves
if slug_exists("/transformers"):
# Try variations
suggestions = [
"/transformer-architecture",
"/llm-transformers",
"/transformers-neural-network"
]

# Or add domain prefix
slug = f"/{domain}-{base_slug}" # /ai-transformers

Problem: Obsidian autocomplete suggests filename, not slug

Solution:

# Add filename as alias
aliases:
- "transformers.md" # For autocomplete
- "📍 2.5 Transformers" # For visual ordering

Obsidian: Type [[transform]] → suggests transformers.md → resolves to note Docusaurus: Renders as /transformer-architecture

Issue 3: Git History After File Moves

Problem: Moving file loses git history

Solution:

# Use git mv instead of rename
git mv old-path/file.md new-path/file.md

# Git preserves history with proper similarity detection
git log --follow new-path/file.md

Problem: Blog posts, social media links to old URLs

Solution:

// Comprehensive redirects
{
// Old path → slug
from: '/ai/llm/fundamentals/intro',
to: '/llm-introduction',
},
{
// With and without trailing slash
from: '/ai/llm/fundamentals/intro/',
to: '/llm-introduction',
},
{
// Old numbered versions
from: '/ai/llm/01-intro',
to: '/llm-introduction',
}

Issue 5: Performance with 50K Notes

Problem: Slug registry becomes huge

Solution:

// Shard slug registry
slugs/
├── a-c.json // Slugs starting with a, b, c
├── d-f.json
├── g-i.json
...

// Fast lookup
function get_slug(note_id) {
first_letter = note_id[0].lower();
shard = load_shard(first_letter);
return shard[note_id];
}

Summary

Three-pillar solution:

  1. Stable Slugs

    • Permanent URLs independent of file location
    • SEO-friendly, hierarchical where needed
    • LLM-generated, collision-free
    • Slug registry tracks all mappings
  2. Frontmatter Ordering

    • sidebar_position for both tools
    • Gap numbering (10, 20, 30) for flexibility
    • Category files for folder ordering
    • Remove ugly number prefixes from filenames
  3. Obsidian Visual Ordering

    • Dataview queries show ordered navigation
    • Custom File Explorer plugin reads frontmatter
    • Emoji aliases for quick visual scanning
    • Folder notes for curated learning paths

Migration timeline:

  • Week 1-2: Generate slugs
  • Week 3-4: Assign sidebar positions
  • Week 5: Remove number prefixes
  • Week 6-8: Convert links to slugs
  • Week 9: Obsidian visual setup
  • Week 10: Redirects & SEO

Investment:

  • Time: 40-50 hours (mostly LLM automated)
  • Cost: $50-80 (Claude API)
  • Risk: Low (incremental, reversible)

Payoff:

  • ✅ Zero 404s from file moves
  • ✅ Preserved SEO value
  • ✅ Clean, logical sidebar ordering
  • ✅ Obsidian + Docusaurus harmony
  • ✅ LLM can safely reorganize structure

Next Steps:

  1. ✅ Read this document
  2. ⬜ Backup vault (git commit)
  3. ⬜ Run Phase 1: Generate slugs (week 1)
  4. ⬜ Test build, verify no errors
  5. ⬜ Run Phase 2: Sidebar positions (week 3)
  6. ⬜ Gradual rollout over 10 weeks
  7. ⬜ Monitor analytics for 404s
  8. ⬜ Celebrate stable URLs! 🎉

Remember: URLs are forever. File paths are temporary. Invest in permanent slugs now, reorganize freely forever.