How CodeWiki Caches Diagrams for Performance: A Technical Deep Dive
CodeWiki caches generated Mermaid diagrams on the server filesystem and reuses them via lightweight HTTP endpoints, eliminating redundant LLM calls and reducing load times for repeat views.
CodeWiki is an open-source tool that automatically generates architectural diagrams from code repositories using Gemini-powered analysis. Because diagram generation involves expensive LLM operations, the project implements a robust server-side caching strategy. This article examines exactly how CodeWiki cache diagrams work, from filesystem storage to React hook consumption.
How CodeWiki Cache Diagrams Work: Architecture Overview
The caching system follows a cache-aside pattern with three distinct layers:
- Filesystem persistence – Diagrams stored as text files in
./.cache/diagram_cache - REST API layer – Fast endpoints for cache lookup and storage
- Client-side orchestration – React hooks that prioritize cached content
When a user requests a diagram, CodeWiki first checks the server cache. If found, it returns immediately. If not, it generates the diagram via LLM, streams the result to the client, then persists it to the cache for subsequent requests.
Server-Side Diagram Caching Implementation
Cache Directory Initialization
The cache location is defined in utils/constants.py, which creates the directory structure at application startup:
# utils/constants.py
DIAGRAM_CACHE_DIR = "./.cache/diagram_cache"
This path is used throughout the application to ensure consistent storage locations.
Cache File Naming Convention
To avoid collisions between repositories, CodeWiki generates unique filenames using the pattern:
{owner}_{repo}_{repo_type}_diagram_cache.txt
This convention is implemented in api/generate_diagram.py via the get_diagram_cache_path function:
# api/generate_diagram.py
def get_diagram_cache_path(owner: str, repo: str, repo_type: str) -> str:
filename = f"{owner}_{repo}_{repo_type}_diagram_cache.txt"
return os.path.join(DIAGRAM_CACHE_DIR, filename)
Cache Read and Write Operations
The server provides two async utilities for cache management:
Reading from cache:
# api/generate_diagram.py
async def read_diagram_cache_data(owner, repo, repo_type):
path = get_diagram_cache_path(owner, repo, repo_type)
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
return None
Writing to cache:
# api/generate_diagram.py
async def write_diagram_cache_data(owner, repo, repo_type, data):
path = get_diagram_cache_path(owner, repo, repo_type)
with open(path, "w", encoding="utf-8") as f:
f.write(data)
return True
REST API Endpoints for Cache Access
CodeWiki exposes two lightweight endpoints for cache interaction:
GET /api/diagram/cached – Retrieves cached diagrams:
# api/generate_diagram.py
@app.get("/api/diagram/cached")
async def get_cached_diagram(owner: str, repo: str, repo_type: str):
cached_data = await read_diagram_cache_data(owner, repo, repo_type)
if cached_data:
return {"diagram": cached_data}
return {"diagram": None}
POST /api/diagram/cached – Stores new diagrams:
# api/generate_diagram.py
@app.post("/api/diagram/cached")
async def post_cached_diagram(data: dict):
await write_diagram_cache_data(
data["owner"],
data["repo"],
data["repo_type"],
data["diagram"]
)
return {"status": "success"}
Client-Side Cache Consumption in CodeWiki
The useDiagram Hook Logic
The React frontend implements the caching strategy in frontend/hooks/useDiagram.ts. This hook orchestrates the cache-first loading pattern and manages the diagram generation state machine.
Cache-First Loading Strategy
The hook implements a specific sequence to minimize expensive operations:
- Mount phase – Immediately attempt to fetch from cache:
// frontend/hooks/useDiagram.ts (simplified)
const params = new URLSearchParams({ owner, repo });
const cached = await fetch(`/api/diagram/cached?${params}`);
if (cached.ok) {
const { diagram } = await cached.json();
setDiagram(diagram); // Use cached version, skip generation
return;
}
- Cache miss handling – If no cache exists, trigger generation:
// Trigger expensive generation pipeline
const generate = await fetch('/api/diagram/generate', {
method: 'POST',
body: JSON.stringify({ owner, repo })
});
- Cache population – After successful generation, persist to cache:
// Inside useEffect watching generation completion
if (state.status === 'complete' && generatedDiagram) {
await fetch(`/api/diagram/cached`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ owner, repo, diagram: generatedDiagram }),
});
}
This approach ensures that subsequent visits to the same repository return instantly with cached diagrams, while the first visit pays the generation cost once and stores the result for future users.
Code Examples: Implementing Diagram Caching
Server-Side Cache Utilities
Complete implementation from api/generate_diagram.py:
import os
from utils.constants import DIAGRAM_CACHE_DIR
def get_diagram_cache_path(owner: str, repo: str, repo_type: str) -> str:
"""Generate unique cache file path for repository."""
filename = f"{owner}_{repo}_{repo_type}_diagram_cache.txt"
return os.path.join(DIAGRAM_CACHE_DIR, filename)
async def read_diagram_cache_data(owner, repo, repo_type):
"""Retrieve cached diagram if available."""
path = get_diagram_cache_path(owner, repo, repo_type)
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as f:
return f.read()
return None
async def write_diagram_cache_data(owner, repo, repo_type, data):
"""Persist diagram to filesystem cache."""
path = get_diagram_cache_path(owner, repo, repo_type)
with open(path, "w", encoding="utf-8") as f:
f.write(data)
return True
Client-Side Cache Integration
React hook pattern from frontend/hooks/useDiagram.ts:
// Cache-first loading strategy
const loadDiagram = async (owner: string, repo: string) => {
// 1. Attempt cache hit
const params = new URLSearchParams({ owner, repo });
const cached = await fetch(`/api/diagram/cached?${params}`);
if (cached.ok) {
const { diagram } = await cached.json();
setDiagram(diagram);
return;
}
// 2. Cache miss - trigger generation
const response = await fetch('/api/diagram/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ owner, repo })
});
// Handle streaming response...
};
// Store to cache after generation
useEffect(() => {
if (state.status === 'complete' && generatedDiagram) {
fetch(`/api/diagram/cached`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
owner,
repo,
diagram: generatedDiagram
}),
});
}
}, [state.status, generatedDiagram]);
Summary
CodeWiki implements a server-side filesystem cache to eliminate redundant diagram generation costs. The key architectural decisions include:
- Persistent storage using text files in
./.cache/diagram_cachewith unique filenames per repository - Simple HTTP API exposing
GET /api/diagram/cachedfor retrieval andPOST /api/diagram/cachedfor storage - Cache-first client strategy in
useDiagram.tsthat checks the cache before triggering expensive LLM generation - Automatic cache warming that writes generated diagrams back to the cache immediately after creation
This approach reduces latency from seconds (LLM generation) to milliseconds (file I/O) for repeat views of the same repository.
Frequently Asked Questions
How does CodeWiki handle cache invalidation when repository code changes?
CodeWiki uses the repository owner, name, and type as the cache key components. When the underlying code changes but the repository identifier remains the same, the cached diagram becomes stale. Currently, the system does not implement automatic cache invalidation based on commit hashes or timestamps. To refresh a diagram, users must manually trigger a regeneration, which overwrites the existing cache file via write_diagram_cache_data.
What file format does CodeWiki use to store cached diagrams?
CodeWiki stores diagrams as plain text files with UTF-8 encoding. The files contain raw Mermaid diagram syntax rather than rendered images or binary data. This approach keeps the cache lightweight and allows the frontend to render diagrams dynamically using the Mermaid.js library. The specific filename pattern is {owner}_{repo}_{repo_type}_diagram_cache.txt, ensuring unique storage per repository combination.
Is the diagram cache persistent across application restarts?
Yes, the cache is fully persistent across restarts because it uses the filesystem rather than in-memory storage. The utils/constants.py module ensures the ./.cache/diagram_cache directory exists at application startup, and the read_diagram_cache_data and write_diagram_cache_data functions in api/generate_diagram.py interact with these files directly. This persistence model ensures that diagrams generated once remain available indefinitely without requiring regeneration.
How does the frontend know when to use a cached diagram versus generating a new one?
The React hook useDiagram.ts implements a cache-first strategy that checks for cached content immediately on component mount. It first calls GET /api/diagram/cached with the repository parameters. If the endpoint returns a 200 status with diagram data, the hook sets the state directly and skips the generation pipeline entirely. Only when the cache endpoint returns a miss (or non-ok status) does the hook proceed to call the expensive POST /api/diagram/generate endpoint. After successful generation, the hook automatically POSTs the result back to /api/diagram/cached to warm the cache for future requests.
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 →