Search & Knowledge Graph
Search index generation, header search dropdown, KnowledgeGraph visualization on /tags, and MiniGraph on article pages
Search & Knowledge Graph
Arcturus-Prime has two content discovery systems: a text search dropdown in the header and an interactive knowledge graph that visualizes relationships between posts, tags, and categories.
Search Index
Generation
The search index is built as a dynamic Astro endpoint at src/pages/search-index.json.js. At build time it pulls from all content collections (posts, journal, projects, configurations), filters out drafts in production, and outputs a JSON array at /search-index.json.
Each entry contains:
{
"slug": "post-title-slug",
"title": "Post Title",
"description": "Short excerpt",
"pubDate": "2026-02-23T00:00:00Z",
"category": "DevOps",
"tags": ["docker", "kubernetes"],
"readTime": "5 min read",
"type": "post",
"url": "/posts/post-title-slug/"
}
The endpoint sets Cache-Control: max-age=3600 (1 hour).
Header Search
The search dropdown lives in src/components/Header.astro. Clicking the magnifying glass icon toggles a 300px-wide panel with a text input.
How search works:
- User types at least 2 characters
- Input triggers
performSearch()with 300ms debounce - Fetches
/search-index.json(cached after first load) - Filters against
title,description,tags, andcategory(case-insensitive) - Displays up to 8 results
Each result shows a type badge (Blog/Project/Config/Journal), title, truncated description, and the first 3 tags. Clicking navigates to the full content page.
KnowledgeGraph
The full-page interactive graph visualization at src/components/KnowledgeGraph.astro (~3,360 lines). Used on /tags and individual tag pages to show how content connects through shared tags and categories.
Node Types
| Type | Color | Sizing |
|---|---|---|
| Posts | Blue (#3B82F6) | Scales by connection count |
| Tags | Green (#10B981) | Scales by connection count |
| Categories | Purple (#8B5CF6) | Scales by connection count |
Category-specific colors are defined for 14 categories (Kubernetes, Docker, Infrastructure, DevOps, Homelab, Security, etc.).
Interaction
- Click a node: Show details panel with metadata, connected posts, and related tags
- Hover: Spotlight effect — highlights the node + its neighbors, fades everything else
- Click background: Clear selection
Controls
| Control | Function |
|---|---|
| Zoom +/- | Zoom in/out |
| Reset | Reset viewport |
| Physics toggle | Enable/disable live physics simulation |
| Filter buttons | All / Posts / Tags |
| Layout selector | Force, Concentric, Spiral, Radial, Clustered, Grid, Organic, Tree, and two Obsidian-style presets |
Physics Engine
Five tunable parameters for the force-directed layout:
| Parameter | Default | Effect |
|---|---|---|
| Center Force | 0.05 | Pulls hub nodes toward center |
| Repel Force | 3500 | Pushes nodes apart |
| Link Force | 0.3 | Edge strength |
| Link Distance | 200 | Target edge length |
| Damping | 0.85 | Movement smoothness |
The Obsidian-style preset adds additional controls: Spine Length (tight connections for leaves), Bridge Length (loose connections for hubs), Node Scale, and Label Threshold.
Tag Hierarchy
The graph implements a taxonomy system where tags can be grouped hierarchically (e.g., gentoo, ubuntu, fedora → linux; docker, kubernetes → containers). About 40 hierarchical relationships are defined. Tags with only 1 connection are filtered out by default to reduce noise.
Built on @tendril/graph
The visualization uses the @tendril/graph package (packages/tendril-graph/), a framework-agnostic wrapper around Cytoscape.js. Key methods:
const graph = new TendrilGraph(selector, { nodes, edges, styles, physics, onNodeClick });
graph.setLayout('force'); // Change layout algorithm
graph.enablePhysics(true); // Toggle physics
graph.zoom(1.2); // Zoom in
graph.reset(); // Reset viewport
graph.filterByType('post'); // Filter by node type
MiniGraph
A lightweight version of the knowledge graph embedded on individual article pages at src/components/MiniGraph.astro (~1,578 lines). Shows the current post’s local neighborhood in the content graph.
Graph Building
The MiniGraph builds a 3-level neighborhood:
| Level | Content | Max Items |
|---|---|---|
| Level 0 | Current post | 1 |
| Level 1 | Posts sharing tags with current post + their tags | 6 posts |
| Level 2 | Posts sharing tags with Level 1 posts + their tags | Varies |
Related posts are scored by tag overlap count, then sorted by date. The getRelatedPosts() function in src/pages/posts/[slug].astro handles discovery, with fallback to recent posts if no tag matches exist.
Features
- Fullscreen mode: Toggle button expands the graph full-screen with a side-by-side layout — graph on left, info panel on right
- Content preview: Clicking a post node displays its metadata, tags, connected nodes, and a content excerpt
- Node navigation: Click through to the full article from the info panel
Edge Types
| Edge Type | Meaning |
|---|---|
post-tag | Post connected to its own tags |
post-related | Posts connected by shared tags |
tag-post | Tag connected to posts that use it |
Data Flow
Content Collections (posts, journal, projects, configs)
│
├──► /search-index.json ──► Header Search Dropdown
│
└──► Page Rendering
├──► /tags page ──► KnowledgeGraph (full interactive)
├──► /tag/[tag] ──► KnowledgeGraph (filtered to tag)
└──► /posts/[slug] ──► MiniGraph (local neighborhood)
Key Files
| File | Purpose |
|---|---|
src/pages/search-index.json.js | Search index generation |
src/components/Header.astro | Search dropdown UI |
src/components/KnowledgeGraph.astro | Full-page graph visualization |
src/components/MiniGraph.astro | Per-article graph widget |
packages/tendril-graph/ | Graph library (Cytoscape.js wrapper) |
src/pages/tag/[tag].astro | Tag page with filtered graph |