Inspiration

As codebases grow, one of the hardest questions for developers isn't “What does this function do?” but “What will break if I change it?”

A small change to a utility function can propagate through dozens of callers, files, and features. Traditional code search can show where something is referenced, but understanding the transitive impact of a change is much harder.

That led us to build BlastRadius — a developer tool that turns a TypeScript/JavaScript codebase into a graph and lets developers visually explore the impact of changing any function.

The idea was especially well suited to Neo4j because dependencies and function calls are naturally represented as relationships in a graph.

What We Built

BlastRadius takes a TypeScript/JavaScript repository and analyzes its structure to build a project-scoped call graph in Neo4j AuraDB.

We model the codebase using nodes and relationships such as:

  • (:File)
  • (:Function)
  • (:File)-[:IMPORTS]->(:File)
  • (:Function)-[:DEFINED_IN]->(:File)
  • (:Function)-[:CALLS]->(:Function)

Once the graph is created, developers can search for any function and click it to see its blast radius — the functions that transitively depend on it.

The core graph query is:

MATCH (t:Function {id: $id})<-[:CALLS*1..6]-(affected:Function)
RETURN DISTINCT affected

This lets us answer a question that is inherently graph-shaped: “Which functions are upstream of this function within six levels of calls?”

We then visualize the result as an interactive force-directed graph and use AI to provide a plain-English explanation of what developers should double-check before modifying the selected function.

How We Built It

The application is built with Next.js 14 and TypeScript, with Neo4j AuraDB serving as the graph database.

For code analysis, we used ts-morph rather than manually walking the TypeScript AST. This allowed us to resolve functions, methods, imports, aliases, and call relationships using TypeScript's type system.

The ingestion pipeline works roughly like this:

  1. Accept a GitHub repository or local TypeScript/JavaScript project.
  2. Parse the source using ts-morph.
  3. Identify files, functions, imports, and function calls.
  4. Resolve call relationships through the TypeScript type checker.
  5. Batch-write the resulting graph into Neo4j AuraDB.
  6. Generate a unique projectId so multiple analyses can coexist.
  7. Query Neo4j when a developer selects a function.
  8. Traverse the graph to identify its blast radius.
  9. Visualize the affected subgraph and generate an AI explanation.

The frontend uses react-force-graph-2d to make the dependency graph interactive, allowing developers to move from a high-level overview to the exact functions affected by a change.

What We Learned

The biggest lesson was that code dependencies are naturally graph problems.

We initially approached the problem from the perspective of parsing code and finding references. But once we represented functions and calls as nodes and edges, questions about dependency chains became much simpler.

We also learned how important symbol resolution is when analyzing real TypeScript projects. Imports can be aliased, functions can be re-exported, and projects can use tsconfig path mappings such as @/. Using the TypeScript type checker through ts-morph helped us resolve these relationships much more reliably than simple text-based matching.

Working with Neo4j also changed how we thought about querying dependencies. Instead of repeatedly joining tables to follow relationships, a variable-length graph traversal can directly express the concept of “follow callers upstream.”

Challenges

One of the biggest challenges was building a useful call graph from real-world TypeScript rather than a simplified demo codebase.

We had to handle:

  • Imported functions and aliases
  • Functions and methods
  • Arrow-function variables
  • Cross-file call relationships
  • tsconfig.json path aliases
  • Avoiding generated files, node_modules, and declaration files
  • Efficiently writing large numbers of graph relationships
  • Keeping separate analyses isolated from one another

Another challenge was balancing the richness of the graph with performance. Instead of loading everything into the UI at once, BlastRadius allows developers to focus on the affected subgraph and switch back to the full graph when needed.

We also had to account for serverless execution limits during repository ingestion, which led us to support both a hosted workflow for smaller repositories and a local CLI for larger codebases.

Why Neo4j?

Neo4j wasn't just used as a storage layer — it shaped the core of the product.

The key operation in BlastRadius is finding transitive relationships between functions. A graph database allows us to express that relationship directly using variable-length traversals.

This is the fundamental idea behind BlastRadius:

Code dependencies form a graph, so understanding change impact should be a graph query.

What's Next

BlastRadius currently focuses on TypeScript and JavaScript. The next step would be making the analysis language-agnostic by building on the Language Server Protocol (LSP).

That could eventually allow the same approach to work across languages such as Python, Java, Go, and Rust — giving developers a unified way to understand the potential impact of changes across their codebases.

Share this project:

Updates

Submission history