diff --git a/docs/images/blast-radius.png b/docs/images/blast-radius.png
new file mode 100644
index 000000000..31535e212
Binary files /dev/null and b/docs/images/blast-radius.png differ
diff --git a/docs/mint.json b/docs/mint.json
index 3546fbd79..1f9fd103b 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -73,6 +73,7 @@
"pages": [
"tutorials/at-a-glance",
"tutorials/migrating-apis",
+ "tutorials/codebase-visualization",
"tutorials/organize-your-codebase",
"tutorials/modularity",
"tutorials/deleting-dead-code",
diff --git a/docs/tutorials/codebase-visualization.mdx b/docs/tutorials/codebase-visualization.mdx
new file mode 100644
index 000000000..93c0e5003
--- /dev/null
+++ b/docs/tutorials/codebase-visualization.mdx
@@ -0,0 +1,383 @@
+---
+title: "Codebase Visualization"
+sidebarTitle: "Codebase Visualization"
+description: "This guide will show you how to create codebase visualizations using [codegen](/introduction/overview)."
+icon: "flashlight"
+iconType: "solid"
+---
+
+
+
+
+
+## Overview
+
+To demonstrate the visualization capabilities of the codegen we will generate three different visualizations of PostHog's open source [repository](https://github.com/PostHog/posthog).
+ - [Call Trace Visualization](#call-trace-visualization)
+ - [Function Dependency Graph](#function-dependency-graph)
+ - [Blast Radius Visualization](#blast-radius-visualization)
+
+
+## Call Trace Visualization
+
+Visualizing the call trace of a function is a great way to understand the flow of a function and for debugging. In this tutorial we will create a call trace visualization of the `patch` method of the `SharingConfigurationViewSet` class. View the source code [here](https://github.com/PostHog/posthog/blob/c2986d9ac7502aa107a4afbe31b3633848be6582/posthog/api/sharing.py#L163).
+
+
+### Basic Setup
+First, we'll set up our codebase, graph and configure some basic parameters:
+
+```python
+import networkx as nx
+from codegen import Codebase
+
+# Initialize codebase
+codebase = Codebase("path/to/posthog/")
+
+# Create a directed graph for representing call relationships
+G = nx.DiGraph()
+
+# Configuration flags
+IGNORE_EXTERNAL_MODULE_CALLS = True # Skip calls to external modules
+IGNORE_CLASS_CALLS = False # Include class definition calls
+MAX_DEPTH = 10
+
+COLOR_PALETTE = {
+ "StartFunction": "#9cdcfe", # Light blue - Start Function
+ "PyFunction": "#a277ff", # Soft purple/periwinkle - PyFunction
+ "PyClass": "#ffca85", # Warm peach/orange - PyClass
+ "ExternalModule": "#f694ff" # Bright magenta/pink - ExternalModule
+}
+```
+
+### Building the Visualization
+We'll create a function that will recursively traverse the call trace of a function and add nodes and edges to the graph:
+
+```python
+def create_downstream_call_trace(src_func: Function, depth: int = 0):
+ """Creates call graph by recursively traversing function calls
+
+ Args:
+ src_func (Function): Starting function for call graph
+ depth (int): Current recursion depth
+ """
+ # Prevent infinite recursion
+ if MAX_DEPTH <= depth:
+ return
+
+ # External modules are not functions
+ if isinstance(src_func, ExternalModule):
+ return
+
+ # Process each function call
+ for call in src_func.function_calls:
+ # Skip self-recursive calls
+ if call.name == src_func.name:
+ continue
+
+ # Get called function definition
+ func = call.function_definition
+ if not func:
+ continue
+
+ # Apply configured filters
+ if isinstance(func, ExternalModule) and IGNORE_EXTERNAL_MODULE_CALLS:
+ continue
+ if isinstance(func, Class) and IGNORE_CLASS_CALLS:
+ continue
+
+ # Generate display name (include class for methods)
+ if isinstance(func, Class) or isinstance(func, ExternalModule):
+ func_name = func.name
+ elif isinstance(func, Function):
+ func_name = f"{func.parent_class.name}.{func.name}" if func.is_method else func.name
+
+ # Add node and edge with metadata
+ G.add_node(func, name=func_name,
+ color=COLOR_PALETTE.get(func.__class__.__name__))
+ G.add_edge(src_func, func, **generate_edge_meta(call))
+
+ # Recurse for regular functions
+ if isinstance(func, Function):
+ create_downstream_call_trace(func, depth + 1)
+```
+
+### Adding Edge Metadata
+We can enrich our edges with metadata about the function calls:
+
+```python
+def generate_edge_meta(call: FunctionCall) -> dict:
+ """Generate metadata for call graph edges
+
+ Args:
+ call (FunctionCall): Function call information
+
+ Returns:
+ dict: Edge metadata including name and location
+ """
+ return {
+ "name": call.name,
+ "file_path": call.filepath,
+ "start_point": call.start_point,
+ "end_point": call.end_point,
+ "symbol_name": "FunctionCall"
+ }
+```
+### Visualizing the Graph
+Finally, we can visualize our call graph starting from a specific function:
+```python
+# Get target function to analyze
+target_class = codebase.get_class('SharingConfigurationViewSet')
+target_method = target_class.get_method('patch')
+
+# Add root node
+G.add_node(target_method,
+ name=f"{target_class.name}.{target_method.name}",
+ color=COLOR_PALETTE["StartFunction"])
+
+# Build the call graph
+create_downstream_call_trace(target_method)
+
+# Render the visualization
+codebase.visualize(G)
+```
+
+### Common Use Cases
+The call graph visualization is particularly useful for:
+ - Understanding complex codebases
+ - Planning refactoring efforts
+ - Identifying tightly coupled components
+ - Analyzing critical paths
+ - Documenting system architecture
+
+### Take a look
+
+
+## Function Dependency Graph
+
+Understanding symbol dependencies is crucial for maintaining and refactoring code. This tutorial will show you how to create visual dependency graphs using Codegen and NetworkX. We will be creating a dependency graph of the `get_query_runner` function. View the source code [here](https://github.com/PostHog/posthog/blob/c2986d9ac7502aa107a4afbe31b3633848be6582/posthog/hogql_queries/query_runner.py#L152).
+
+### Basic Setup
+
+We'll use the same basic setup as the [Call Trace Visualization](/tutorials/codebase-visualization#call-trace-visualization) tutorial.
+
+
+### Building the Dependency Graph
+The core function for building our dependency graph:
+```python
+def create_dependencies_visualization(symbol: Symbol, depth: int = 0):
+ """Creates visualization of symbol dependencies
+
+ Args:
+ symbol (Symbol): Starting symbol to analyze
+ depth (int): Current recursion depth
+ """
+ # Prevent excessive recursion
+ if depth >= MAX_DEPTH:
+ return
+
+ # Process each dependency
+ for dep in symbol.dependencies:
+ dep_symbol = None
+
+ # Handle different dependency types
+ if isinstance(dep, Symbol):
+ # Direct symbol reference
+ dep_symbol = dep
+ elif isinstance(dep, Import):
+ # Import statement - get resolved symbol
+ dep_symbol = dep.resolved_symbol if dep.resolved_symbol else None
+
+ if dep_symbol:
+ # Add node with appropriate styling
+ G.add_node(dep_symbol,
+ color=COLOR_PALETTE.get(dep_symbol.__class__.__name__,
+ "#f694ff"))
+
+ # Add dependency relationship
+ G.add_edge(symbol, dep_symbol)
+
+ # Recurse unless it's a class (avoid complexity)
+ if not isinstance(dep_symbol, PyClass):
+ create_dependencies_visualization(dep_symbol, depth + 1)
+```
+
+### Visualizing the Graph
+Finally, we can visualize our dependency graph starting from a specific symbol:
+```python
+# Get target symbol
+target_func = codebase.get_function("get_query_runner")
+
+# Add root node
+G.add_node(target_func, color=COLOR_PALETTE["StartFunction"])
+
+# Generate dependency graph
+create_dependencies_visualization(target_func)
+
+# Render visualization
+codebase.visualize(G)
+```
+
+### Take a look
+
+
+## Blast Radius visualization
+
+Understanding the impact of code changes is crucial for safe refactoring. A blast radius visualization shows how changes to one function might affect other parts of the codebase by tracing usage relationships. In this tutorial we will create a blast radius visualization of the `export_asset` function. View the source code [here](https://github.com/PostHog/posthog/blob/c2986d9ac7502aa107a4afbe31b3633848be6582/posthog/tasks/exporter.py#L57).
+
+### Basic Setup
+
+We'll use the same basic setup as the [Call Trace Visualization](/tutorials/codebase-visualization#call-trace-visualization) tutorial.
+
+
+### Helper Functions
+We'll create some utility functions to help build our visualization:
+```python
+# List of HTTP methods to highlight
+HTTP_METHODS = ["get", "put", "patch", "post", "head", "delete"]
+
+def generate_edge_meta(usage: Usage) -> dict:
+ """Generate metadata for graph edges
+
+ Args:
+ usage (Usage): Usage relationship information
+
+ Returns:
+ dict: Edge metadata including name and location
+ """
+ return {
+ "name": usage.match.source,
+ "file_path": usage.match.filepath,
+ "start_point": usage.match.start_point,
+ "end_point": usage.match.end_point,
+ "symbol_name": usage.match.__class__.__name__
+ }
+
+def is_http_method(symbol: PySymbol) -> bool:
+ """Check if a symbol is an HTTP endpoint method
+
+ Args:
+ symbol (PySymbol): Symbol to check
+
+ Returns:
+ bool: True if symbol is an HTTP method
+ """
+ if isinstance(symbol, PyFunction) and symbol.is_method:
+ return symbol.name in HTTP_METHODS
+ return False
+```
+
+### Building the Blast Radius Visualization
+The main function for creating our blast radius visualization:
+```python
+def create_blast_radius_visualization(symbol: PySymbol, depth: int = 0):
+ """Create visualization of symbol usage relationships
+
+ Args:
+ symbol (PySymbol): Starting symbol to analyze
+ depth (int): Current recursion depth
+ """
+ # Prevent excessive recursion
+ if depth >= MAX_DEPTH:
+ return
+
+ # Process each usage of the symbol
+ for usage in symbol.usages:
+ usage_symbol = usage.usage_symbol
+
+ # Determine node color based on type
+ if is_http_method(usage_symbol):
+ color = COLOR_PALETTE.get("HTTP_METHOD")
+ else:
+ color = COLOR_PALETTE.get(usage_symbol.__class__.__name__, "#f694ff")
+
+ # Add node and edge to graph
+ G.add_node(usage_symbol, color=color)
+ G.add_edge(symbol, usage_symbol, **generate_edge_meta(usage))
+
+ # Recursively process usage symbol
+ create_blast_radius_visualization(usage_symbol, depth + 1)
+```
+
+### Visualizing the Graph
+Finally, we can create our blast radius visualization:
+```python
+# Get target function to analyze
+target_func = codebase.get_function('export_asset')
+
+# Add root node
+G.add_node(target_func, color=COLOR_PALETTE.get("StartFunction"))
+
+# Build the visualization
+create_blast_radius_visualization(target_func)
+
+# Render reversed graph to show impact flow
+codebase.visualize(G.reverse())
+```
+
+### Take a look
+
+
+## What's Next?
+
+
+
+ Learn how to use Codegen to create modular codebases.
+
+
+ Learn how to use Codegen to delete dead code.
+
+
+ Learn how to use Codegen to increase type coverage.
+
+
+ Explore the complete API documentation for all Codegen classes and methods.
+
+
\ No newline at end of file