# How CodeWiki Caches Diagrams for Performance: A Technical Deep Dive

> Discover how CodeWiki caches diagrams on the server filesystem, reusing them via HTTP endpoints to boost performance and reduce load times. Learn the technical details.

- Repository: [Luong Quang Dung/codewiki](https://github.com/quangdungluong/codewiki)
- Tags: deep-dive
- Published: 2026-02-16

---

**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:

1. **Filesystem persistence** – Diagrams stored as text files in `./.cache/diagram_cache`
2. **REST API layer** – Fast endpoints for cache lookup and storage
3. **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`](https://github.com/quangdungluong/codewiki/blob/main/utils/constants.py), which creates the directory structure at application startup:

```python

# 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`](https://github.com/quangdungluong/codewiki/blob/main/api/generate_diagram.py) via the `get_diagram_cache_path` function:

```python

# 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:**

```python

# 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:**

```python

# 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:

```python

# 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:

```python

# 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`](https://github.com/quangdungluong/codewiki/blob/main/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:

1. **Mount phase** – Immediately attempt to fetch from cache:

```typescript
// 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;
}

```

2. **Cache miss handling** – If no cache exists, trigger generation:

```typescript
// Trigger expensive generation pipeline
const generate = await fetch('/api/diagram/generate', {
  method: 'POST',
  body: JSON.stringify({ owner, repo })
});

```

3. **Cache population** – After successful generation, persist to cache:

```typescript
// 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`](https://github.com/quangdungluong/codewiki/blob/main/api/generate_diagram.py):

```python
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`](https://github.com/quangdungluong/codewiki/blob/main/frontend/hooks/useDiagram.ts):

```typescript
// 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_cache` with unique filenames per repository
- **Simple HTTP API** exposing `GET /api/diagram/cached` for retrieval and `POST /api/diagram/cached` for storage
- **Cache-first client strategy** in [`useDiagram.ts`](https://github.com/quangdungluong/codewiki/blob/main/useDiagram.ts) that 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`](https://github.com/quangdungluong/codewiki/blob/main/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`](https://github.com/quangdungluong/codewiki/blob/main/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`](https://github.com/quangdungluong/codewiki/blob/main/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.