Daniel Gray

Thoughts, Notes, Ideas, Projects

← Back to home

Blog Architecture - Advanced Features

This article explores the advanced features of the blog: semantic search, series organization, table of contents, and other sophisticated navigation and discovery mechanisms.

This is part 6 of the Blog Architecture Deep Dive series. Start with Blog Architecture - Overview if you haven't read it yet.

Semantic Search

The blog includes a semantic search system that uses vector embeddings to find relevant content, not just keyword matches.

How It Works

Search uses vector embeddings generated at build time:

  1. Embedding Generation - Each post is converted to a vector representation
  2. Query Processing - Search queries are converted to vectors
  3. Similarity Calculation - Cosine similarity finds the most relevant posts
  4. Results Ranking - Results are ranked by relevance score

Embedding Generation

Embeddings are generated at build time:

  • Searchable text: Combines title, excerpt, and categories
  • Feature vector: Creates a vector representation
  • Caching: Saves to lib/embeddings.json for fast search

Embedding Options

The system supports two approaches:

  1. Simple Feature Vectors (default)

    • Zero-cost, text-based vectors
    • Uses word frequency and features
    • Fast and works offline
  2. OpenAI Embeddings (optional)

    • Semantic embeddings using OpenAI API
    • Better understanding of meaning
    • Requires API key and has costs

Search API

The search API (/api/search) processes queries and returns results ranked by relevance.

Search Features

  • Real-time: Results update as you type (debounced)
  • Semantic: Finds posts by meaning, not just keywords
  • Contextual: Searches title, excerpt, and categories
  • Fast: Uses cached embeddings (no API calls)

Series Organization

The blog supports organizing posts into series, creating structured reading experiences.

Series Metadata

Series are defined in frontmatter:

---
title: Blog Architecture - Overview
series: Blog Architecture Deep Dive
seriesOrder: 1
---
  • series: - Name of the series
  • seriesOrder: - Order within the series (1, 2, 3, etc.)
  • parentSeries: - If this series is nested within another

Series Hierarchy

Series can be nested:

  • Simple series: Part 1 → Part 2 → Part 3
  • Nested series: A series can contain sub-series
  • Series within series: For example, "The 3D Background" contains "Atmospheric Effects" which has its own sub-posts

Series Navigation

When viewing a post in a series, you'll see:

  • Series header: Shows the series name and current part
  • Series list: All posts in the series with navigation
  • Previous/Next buttons: Move between parts

Series Carousel

On the home page, series are shown as a carousel:

  • Single card per series: Only the first post (seriesOrder: 1) appears in the main list
  • Navigation arrows: Click left/right to browse through series parts
  • Series badge: Visual indicator of series membership

This keeps the home page clean while still showing series content.

Table of Contents

Every blog post page includes a Table of Contents sidebar that shows the hierarchical structure of all content.

Content Tree

The TOC is built from the content tree (see Blog Architecture - Links and Navigation for details):

  • Root nodes: Posts without parents (or series parents)
  • Child nodes: Posts linked from parent posts
  • Series grouping: Series posts grouped under their parent

TOC Features

  • Persistent: Stays visible as you scroll (sticky positioning)
  • Collapsible: Click to show/hide
  • Responsive: Moves to the bottom on mobile devices
  • Auto-scrolls: Scrolls to highlight the current page
  • Highlights current: Shows which page you're viewing
  • Shows active parents: Highlights parent series/nodes

Series Display in TOC

For series, the TOC shows:

  • Series title only: Not individual articles (keeps it clean)
  • Highlighting: Highlights if you're viewing any post in the series
  • Navigation: Click to go to the series parent post

This creates a clean, organized view of the content structure.

Linked Posts

At the bottom of each post, you'll find Related Content based on links in the post.

Link Extraction

The system automatically extracts links from rendered HTML and converts them to related posts.

Lazy Loading

Linked posts use Intersection Observer for lazy loading:

  • Loads on scroll: Posts load as you scroll down
  • Performance: Doesn't load all posts at once
  • Smooth experience: Progressive loading feels fast

Category System

Every post can be tagged with multiple categories, creating flexible organization.

Category Extraction

Categories are extracted from:

  • categories: field (array or comma-separated)
  • category: field (single category)
  • tags: field (all tags except "published")

Category Navigation

  • Click to filter: Click any category tag to see all posts in that category
  • Home page filtering: Use category links at the top
  • Multiple tags: Posts can belong to multiple categories

Category Display

Categories are shown as:

  • Tags on posts: Visual tags with hover effects
  • Scrollable: Horizontal scrolling for many categories
  • Clickable: Each tag links to filtered view

Image Handling

The blog handles images from Obsidian, including special syntax and URL encoding.

Obsidian Image Syntax

Obsidian uses ![image](/blog-content/image.png) syntax. The blog converts this to standard markdown:

![image](/blog-content/image.png) → ![alt](/blog-content/image.png)

Image Serving

Images are served from /blog-content/[...path] route:

  • URL encoding: Handles spaces and special characters
  • Path resolution: Matches images from vault structure
  • 404 handling: Graceful fallback for missing images

Performance Optimizations

Several optimizations ensure fast performance:

Static Generation

  • Pre-rendered pages: All pages generated at build time
  • Fast loading: No server-side rendering needed
  • SEO-friendly: Static HTML is great for search engines

Code Splitting

  • Route-based: Only loads code needed for each page
  • Component-based: Lazy loads heavy components
  • Optimized bundles: Tree-shaking removes unused code

Caching

  • Static pages: Next.js caches aggressively
  • Embeddings: Cached in JSON file
  • Images: Can be optimized with Next.js Image (future)

Lazy Loading

  • Linked posts: Load on scroll with Intersection Observer
  • Images: Native lazy loading with loading="lazy"
  • Components: React.lazy for code splitting

Future Enhancements

Planned improvements include:

  • Graph view: Visual representation of post relationships
  • Reading progress: Track reading progress across posts
  • Personalized recommendations: Based on reading history
  • Advanced filtering: Filter by multiple categories, date ranges, etc.
  • Export features: Export posts as PDF, EPUB, etc.
  • Backlinks: Show posts that link to current post
  • RSS feed: Automatic feed generation
  • Syntax highlighting: Enhanced code block highlighting

Conclusion

The advanced features of the blog create a rich, interconnected experience:

  • Semantic search finds relevant content by meaning
  • Series organization creates structured reading paths
  • Table of contents shows the full content hierarchy
  • Linked posts create natural exploration paths
  • Category system provides flexible organization

Together, these features create a blog that feels more like a knowledge base than a traditional blog: a place where ideas connect and readers can explore organically.

Series Conclusion

This concludes the Blog Architecture Deep Dive series. We've covered:

  1. Overview - High-level introduction to the architecture
  2. Why Obsidian? - Deep dive into Obsidian integration
  3. From Markdown to Web - Content processing pipeline
  4. Links and Navigation - Link resolution and navigation
  5. Build and Deployment - Build process and deployment
  6. Advanced Features - Search, series, TOC, and more

Each article builds on the previous ones, providing progressively more detail while maintaining context and references to the bigger picture.

Related Content


This article is part of the Blog Architecture Deep Dive series. Previous: Blog Architecture - Build and Deployment. This concludes the series.

Explore Categories

Related Content

Blog Architecture - Overview

Blog Architecture - Overview This is the first in a series of articles exploring the architecture of this blog. We'll start with a high-level overview that anyone can understand, then progressively di...

Blog Architecture - Links and Navigation

Blog Architecture - Links and Navigation This article explores how Obsidian `wiki links` become web navigation, how the content tree is built, and how users navigate the blog. This is part 4 of the Bl...

Blog Architecture - Why Obsidian?

Blog Architecture - Why Obsidian?

Blog Architecture - Why Obsidian? This article explores why Obsidian was chosen as the authoring tool for this blog and how its unique features integrate with the web publishing system. This is part 2...

Blog Architecture - From Markdown to Web

Blog Architecture - From Markdown to Web

Blog Architecture - From Markdown to Web This article explores the content processing pipeline: how Obsidian markdown files are transformed into web pages. We'll trace a file's journey from your Obsid...

Blog Architecture - Advanced Features

Blog Architecture - Advanced Features

Blog Architecture - Advanced Features This article explores the advanced features of the blog: semantic search, series organization, table of contents, and other sophisticated navigation and discovery...

Blog Architecture

As a side project getting started with this blog, I worked though An adventure with 3js 3d Backgrounds in 3js. I wanted something unique. Not quite what I intended when I set off to make it, but it se...