How to Add Interactive Links and Highlights to SVG Diagrams Using YAML Metadata Files in Astro-Big-Doc
Astro-Big-Doc automatically transforms static SVG diagrams into interactive visualizations by pairing them with YAML metadata files that define clickable links and hover highlights, requiring no code changes to the SVG itself.
The astro-big-doc repository provides a built-in mechanism for enhancing SVG diagrams with interactivity through external metadata. By placing a YAML file alongside your SVG asset, you can define clickable regions and hover-triggered highlights without modifying the original vector graphic. This approach keeps content separate from presentation while delivering rich, interactive documentation experiences.
How the YAML-to-SVG Pipeline Works
Astro-Big-Doc processes SVG interactivity through a five-stage pipeline that bridges server-side asset resolution with client-side DOM manipulation:
-
Asset Resolution – When an SVG is referenced in Markdown, the
MarkdownImage.astrocomponent invokesgetMetaData()fromsrc/libs/assets.js(lines 184-198). This function constructs a parallel file path by replacing the.svgextension with.yamland checks for existence usingexists(). -
Metadata Injection – The parsed YAML object is passed as the
metaprop to thePanzoomcomponent (src/components/panzoom/panzoom.astro, lines 13-36). The component serializes the metadata into adata-metaattribute on the container element usingJSON.stringify(meta)(line 35). -
Client-Side Processing – On page load,
panzoom_common.js(lines 21-30) reads thedata-metaattribute, parses the JSON, and conditionally invokessvg_add_links()andsvg_highlight()fromsrc/components/panzoom/lib_svg_utils.js(lines 29-146). -
Link Insertion – The
svg_add_links()function (lines 30-55) traverses all<text>nodes in the SVG DOM, compares theirtextContentagainst thelabelfields in the metadata'slinksarray, and wraps matches in SVG.jslinkToelements pointing to the specified URLs. -
Hover Highlights – The
svg_highlight()function (lines 57-96) attachesmouseoverandmouseoutevent listeners to trigger labels. When activated, it recolors (fill({color:'#292'})) and bolds every SVG text node whose content matches entries in the correspondinghighlightsarray.
YAML Schema for SVG Interactivity
The metadata file uses a strict schema with two top-level arrays: links for clickable navigation and highlights for visual emphasis on hover.
Links Configuration
The links array contains objects that map SVG text labels to URLs:
links:
- label: "Home"
link: "/" # Absolute URL opens in new tab
- label: "API Reference"
link: "/api/docs" # Relative URL navigates in-page
- label: "GitHub Repository"
link: "https://github.com/microwebstacks/astro-big-doc"
Key constraints:
- The
labelvalue must exactly match the text content of an SVG<text>node (case-sensitive) - Absolute URLs (starting with
httporhttps) automatically open in new tabs - Relative URLs and anchors (
#section) navigate within the current page context
Highlights Configuration
The highlights array defines hover-triggered visual connections between diagram elements:
highlights:
- label: "Critical Path"
highlights:
- "Step 1"
- "Step 3"
- "Database"
- label: "Optional Path"
highlights:
- "Step 2"
- "Step 4"
Behavior details:
- When the user hovers over the SVG text matching
label, all nodes listed in the nestedhighlightsarray receive a green fill (#292) and bold font weight - Moving the mouse out restores the original styling
- Multiple highlight groups can reference the same target nodes
Step-by-Step Implementation Guide
Follow these steps to add interactivity to any SVG diagram in your Astro-Big-Doc project:
-
Prepare your assets
- Export your diagram as
diagram.svgand place it in your content directory (e.g.,src/content/docs/architecture/)
- Export your diagram as
-
Create the metadata file
- In the same directory, create
diagram.yamlwith your links and highlights configuration:
links: - label: "Frontend" link: "/frontend-guide" - label: "Backend" link: "https://api.example.com" highlights: - label: "Frontend" highlights: - "React Component" - "CSS Module" - In the same directory, create
-
Reference in Markdown
- Use standard Markdown image syntax. The
MarkdownImage.astrocomponent (located atsrc/components/markdown/image/MarkdownImage.astro) automatically detects the companion YAML file:
 - Use standard Markdown image syntax. The
-
Verify the build
- Run
pnpm run devand navigate to your page - Inspect the SVG container to confirm the
data-metaattribute contains your YAML data - Test that clicking labeled elements navigates to the specified URLs
- Hover over trigger labels to verify target nodes highlight in green
- Run
Technical Deep Dive: Source Code Architecture
Understanding the underlying implementation helps troubleshoot edge cases and extend functionality.
Asset Resolution Layer
The getMetaData() function in src/libs/assets.js (lines 184-198) handles the filesystem lookup:
// Simplified logic from src/libs/assets.js
export async function getMetaData(url, dirpath) {
const basePath = resolvePath(url, dirpath);
const yamlPath = basePath.replace(/\.[^/.]+$/, '.yaml');
if (await exists(yamlPath)) {
return await load_yaml_abs(yamlPath);
}
return null;
}
This convention-based approach means any asset type can potentially support metadata by following the {filename}.{ext} → {filename}.yaml pattern.
Component Integration
The Panzoom.astro component (src/components/panzoom/panzoom.astro, lines 13-36) serves as the bridge between server-side data and client-side execution:
---
// Props interface includes meta object
const { src, alt, meta } = Astro.props;
---
<div class="panzoom-container" data-meta={JSON.stringify(meta)}>
<object data={src} type="image/svg+xml" aria-label={alt}></object>
</div>
The data-meta attribute stores the serialized YAML content, making it accessible to the client-side JavaScript without requiring additional fetch requests.
Client-Side Processing Engine
The panzoom_common.js file (src/components/panzoom/panzoom_common.js, lines 21-30) orchestrates the interactivity:
// Executed after DOMContentLoaded
const containers = document.querySelectorAll('.panzoom-container');
containers.forEach(container => {
const metaAttr = container.getAttribute('data-meta');
if (metaAttr) {
const meta = JSON.parse(metaAttr);
if (meta.links) svg_add_links(svgElement, meta.links);
if (meta.highlights) svg_highlight(svgElement, meta.highlights);
}
});
This initialization pattern ensures that SVG manipulation only occurs after the <object> element has fully loaded the SVG document.
SVG Manipulation Utilities
The lib_svg_utils.js file (src/components/panzoom/lib_svg_utils.js, lines 29-146) contains the core DOM manipulation logic using SVG.js:
Link Creation (lines 30-55):
export function svg_add_links(svgElement, links) {
const texts = svgElement.querySelectorAll('text');
texts.forEach(textNode => {
const content = textNode.textContent.trim();
const match = links.find(l => l.label === content);
if (match) {
// SVG.js wrapper for link creation
const svgText = SVG(textNode);
svgText.linkTo(match.link);
}
});
}
Highlight System (lines 57-96):
export function svg_highlight(svgElement, highlights) {
highlights.forEach(entry => {
const triggerNode = findTextNode(svgElement, entry.label);
if (!triggerNode) return;
triggerNode.addEventListener('mouseover', () => {
entry.highlights.forEach(targetLabel => {
const target = findTextNode(svgElement, targetLabel);
if (target) {
SVG(target).fill({ color: '#292' }).font({ weight: 'bold' });
}
});
});
triggerNode.addEventListener('mouseout', () => {
// Reset logic omitted for brevity
});
});
}
Code Examples
Minimal Configuration with Links Only
Create network-diagram.yaml alongside your SVG:
links:
- label: "Load Balancer"
link: "/infrastructure/load-balancer"
- label: "Database Cluster"
link: "https://db.internal.company.com"
Configuration with Hover Highlights Only
Create workflow.yaml:
highlights:
- label: "Initialization"
highlights:
- "Config Load"
- "Cache Warmup"
- label: "Processing"
highlights:
- "Worker Pool"
- "Queue Manager"
Complete Markdown Integration
File: src/content/docs/architecture.md
# System Architecture
The following diagram illustrates component relationships. Hover over any service to see its dependencies, or click labels to navigate to detailed documentation.

Required companion file: src/content/docs/architecture.yaml
links:
- label: "API Gateway"
link: "/api/gateway"
- label: "Auth Service"
link: "https://auth.example.com"
highlights:
- label: "API Gateway"
highlights:
- "Rate Limiter"
- "Router"
- label: "Auth Service"
highlights:
- "JWT Validator"
- "User Store"
Summary
- Convention-based pairing: Astro-Big-Doc automatically associates
diagram.svgwithdiagram.yamlwhen placed in the same directory, triggered by thegetMetaData()function insrc/libs/assets.js. - Zero-code configuration: The YAML schema supports two interaction modes—
linksfor navigation andhighlightsfor visual emphasis—without requiring modifications to the SVG source. - Client-side activation: The
panzoom_common.jsbootstrapper reads JSON-encoded metadata from thedata-metaattribute (injected byPanzoom.astro) and delegates DOM manipulation tosvg_add_links()andsvg_highlight()inlib_svg_utils.js. - SVG.js integration: Link creation uses the
linkTo()API, while highlights manipulate fill colors (#292) and font weights through SVG.js wrappers for robust cross-browser SVG manipulation.
Frequently Asked Questions
What happens if the YAML file is missing or malformed?
If diagram.yaml is absent, getMetaData() in src/libs/assets.js returns null, and the SVG renders as a static image without interactivity. If the YAML contains syntax errors, load_yaml_abs() will throw a parsing error during the build process, halting compilation until the file is fixed.
Can I use this feature with SVGs embedded directly in Markdown rather than referenced as files?
No. The current implementation in MarkdownImage.astro specifically processes external file references to enable the filesystem-based metadata lookup. Inline SVGs in Markdown bypass the asset resolution pipeline and will not trigger the getMetaData() call or the subsequent Panzoom wrapping.
How do I style the highlight colors or link appearances?
The highlight color is hardcoded to #292 (green) in svg_highlight() within src/components/panzoom/lib_svg_utils.js (line 78). To customize colors, modify the fill({color:'#292'}) call or extend the YAML schema to accept a color property and update the utility function to read it. Link styling inherits from the SVG.js linkTo() implementation, which creates standard SVG <a> elements.
Does this work with server-side rendering (SSR) or only static builds?
The feature works in both modes. During SSR or static generation, the Panzoom.astro component embeds the metadata as a JSON string in the data-meta attribute. The interactivity is then hydrated client-side by panzoom_common.js, ensuring the SVG DOM is fully loaded before svg_add_links() and svg_highlight() execute, regardless of the build output mode.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →