# How code-review-graph Generates Wiki Documentation From Community Structure

> Discover how code-review-graph generates wiki documentation from community structure. It transforms code-knowledge graphs into browsable markdown pages, detecting clusters and emitting an index file.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-08-15

---

**The `code-review-graph` project transforms its code-knowledge graph communities into browsable markdown pages by detecting clusters, generating per-community documentation, and emitting an index file.**

The `code-review-graph` open-source tool analyzes codebases as knowledge graphs and automatically produces wiki documentation. This article explains how it converts abstract **community structure** into practical markdown documentation based on the implementation in [`code_review_graph/wiki.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/wiki.py).

## Detecting Communities From the Graph

The wiki generation process begins by identifying cohesive code communities. The `generate_wiki` function calls `get_communities(store)` from **[`code_review_graph/communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/communities.py)** to obtain community data:

```python
def generate_wiki(store: GraphStore, output_dir: Path, force: bool = False) -> Dict[str, int]:
    communities = get_communities(store)  # Returns list of community dicts

    # ... each containing: name, size, members, cohesion, language, etc.

```

Each community dictionary contains metadata including **name**, **size**, **members**, **cohesion score**, and **dominant programming language**. These values drive the content of the resulting wiki pages.

## Creating Safe Filenames With _slugify

Community names must become filesystem-safe paths. The **`_slugify`** function in [`code_review_graph/wiki.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/wiki.py) handles this normalization:

- Normalizes Unicode to ASCII
- Drops non-ASCII characters entirely
- Replaces non-alphanumeric characters with hyphens
- Truncates to **80 characters maximum**
- Falls back to `"unnamed"` if the result is empty

```python
def _slugify(name: str) -> str:
    # Normalization and truncation logic (lines 24-30)

    # Returns filesystem-safe string for markdown filenames

```

## Building Per-Community Markdown Pages

The **`_generate_community_page`** function assembles comprehensive documentation for each community. This core generator creates structured markdown with multiple sections.

### Page Structure

| Section | Content Source |
|---------|---------------|
| Header | Community name as H1 |
| Overview | Size, cohesion, language, optional description |
| Members table | Up to 50 nodes via `store.get_node` |
| Execution Flows | Top 10 flows via `get_flows` and `store.get_flow_qualified_names` |
| Dependencies | Cross-community edges via `store.get_outgoing_targets` / `store.get_incoming_sources` |

The members table displays **node name**, **kind** (function, class, etc.), **file path**, and **line range**. Execution flows show how code travels through community members. Dependency counts reveal coupling between communities.

## Writing Pages and Handling Collisions

The main `generate_wiki` loop manages file output with several safeguards:

1. **Unique slugs** – Appends `"‑2"`, `"‑3"`, etc. when community names collide
2. **Change detection** – Skips writing if content matches existing file (unless `force=True`)
3. **Statistics tracking** – Returns counts of generated, updated, and unchanged pages

```python
stats = generate_wiki(store, Path("./wiki"), force=False)

# Returns: {'pages_generated': 12, 'pages_updated': 3, 'pages_unchanged': 5}

```

These mechanics ensure **incremental updates** rather than full regeneration, preserving modification timestamps and reducing I/O.

## Generating the Index Page

After all community pages are emitted, **`generate_wiki`** constructs an [`index.md`](https://github.com/tirth8205/code-review-graph/blob/main/index.md) listing every community with:

- Community name (linked to its page)
- Member count
- Quick navigation to subsections

The index follows the same change-detection logic—only rewritten when content differs from the previous version.

## Retrieving Pages Programmatically

The **`get_wiki_page`** function enables runtime access to generated documentation. It supports flexible lookup:

1. Slugified name match (primary)
2. Exact filename match with **path-traversal protection**
3. Partial substring search within the wiki directory

```python
from code_review_graph.wiki import get_wiki_page

# Find by natural name, exact file, or partial match

markdown = get_wiki_page("./wiki", "Data Processing")

```

This three-tier resolution makes the wiki navigable by both humans and automated tools.

## Practical Usage Example

```python
from pathlib import Path
from code_review_graph.graph import GraphStore
from code_review_graph.wiki import generate_wiki, get_wiki_page

# Load your analyzed codebase graph

store = GraphStore.load("/tmp/graph.db")

# Generate complete wiki documentation

stats = generate_wiki(store, Path("./wiki"))
print(f"Created {stats['pages_generated']} new pages, "
      f"updated {stats['pages_updated']}, "
      f"skipped {stats['pages_unchanged']} unchanged")

# Later: retrieve specific community documentation

content = get_wiki_page("./wiki", "Authentication Handlers")

```

Running this produces a directory structure like:

```

wiki/
├── index.md
├── authentication-handlers.md
├── data-processing.md
├── http-routing.md
└── ...

```

## Key Implementation Files

| File | Responsibility |
|------|---------------|
| [`code_review_graph/wiki.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/wiki.py) | Core generation: `_slugify`, `_generate_community_page`, `generate_wiki`, `get_wiki_page` |
| [`code_review_graph/communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/communities.py) | Cluster detection via `get_communities` |
| [`code_review_graph/flows.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/flows.py) | Execution flow analysis via `get_flows` |
| [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py) | Storage layer with `GraphStore`, `get_node`, `get_outgoing_targets`, `get_incoming_sources` |

## Summary

- **`generate_wiki`** orchestrates the full pipeline: community detection → page generation → index creation
- **`_slugify`** ensures safe, portable filenames from arbitrary community names
- **`_generate_community_page`** produces rich markdown with members, flows, and dependencies
- Incremental updates avoid unnecessary writes through content hashing
- **`get_wiki_page`** provides flexible runtime access with security protections

## Frequently Asked Questions

### How does code-review-graph prevent filename collisions between communities?

When slugified names conflict, `generate_wiki` appends incrementing suffixes (`"‑2"`, `"‑3"`, etc.) to create unique paths within the generation run. This ensures no community page overwrites another regardless of naming similarities.

### Can I force regeneration of unchanged wiki pages?

Yes. Pass `force=True` to `generate_wiki`. Without this flag, the function compares new content against existing files and skips writes when identical, tracking these as *unchanged* in the returned statistics.

### What limits exist on the members table in community pages?

The `_generate_community_page` function caps the members table at **50 entries** to prevent unwieldy documentation. All members remain queryable through the `GraphStore` directly; the wiki surfaces the most significant subset.

### How does get_wiki_page protect against directory traversal attacks?

Before returning any file, `get_wiki_page` validates that the resolved path remains within the specified wiki directory. This prevents malicious inputs like `"../../../etc/passwd"` from escaping the intended documentation root.