# How to Customize Architectural Layer Detection in Understand-Anything: A Complete Guide

> Customize architectural layer detection in Understand-Anything by modifying its heuristic list. This guide helps you tailor file categorization to your project's unique structure for better code analysis.

- Repository: [Yuxiang Lin/Understand-Anything](https://github.com/Lum1104/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-05-22

---

**Understand-Anything automatically categorizes files into architectural layers by matching paths against a configurable heuristic list in [`packages/core/src/analyzer/layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/core/src/analyzer/layer-detector.ts), which you can modify and rebuild to fit your specific project structure.**

The open-source Understand-Anything toolkit analyzes codebases and visualizes them as interactive architectural graphs. By default, it groups files into logical layers like "API Layer" or "Data Layer" using pattern-based detection. If your repository uses non-standard directory names or requires additional architectural categories, you can customize this detection logic to ensure the dashboard accurately reflects your system's design.

## Where Layer Detection Lives in the Source Code

The architectural layer assignment logic resides in **[`packages/core/src/analyzer/layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/core/src/analyzer/layer-detector.ts)**. This module exports two primary mechanisms: a fast heuristic matcher that runs locally, and an optional LLM-based refinement system. The heuristic approach uses a static constant called `LAYER_PATTERNS` to categorize files based on their directory paths, while the LLM integration can propose additional layers through the `buildLayerDetectionPrompt` function.

When you run an analysis, the `detectLayers` function iterates over every file node in the knowledge graph, calls `matchFileToLayer` for each path, and constructs a `Layer` array containing IDs, names, descriptions, and the grouped node references.

## How the Heuristic Detection Works

The static detection system operates on a "first match wins" principle. The `LAYER_PATTERNS` constant defines an ordered array of objects, each specifying:
- `patterns` – directory names (singular or plural) to match
- `layerName` – the display label shown in the UI
- `description` – tooltip text explaining the layer's purpose

The `matchFileToLayer` function normalizes file paths by converting backslashes to forward slashes and lowercasing the string. It then splits the path into segments and checks each segment against the patterns array:

```typescript
function matchFileToLayer(filePath: string): string | null {
  const normalizedPath = filePath.replace(/\\/g, "/").toLowerCase();
  const segments = normalizedPath.split("/");

  for (const { patterns, layerName } of LAYER_PATTERNS) {
    for (const segment of segments) {
      for (const pattern of patterns) {
        if (segment === pattern || segment === pattern + "s") {
          return layerName;
        }
      }
    }
  }
  return null;
}

```

If no patterns match, the file falls into a default **Core** layer. Because the array order determines priority, placing specific patterns before generic ones prevents misclassification.

## Customizing Layer Patterns in Three Steps

### 1. Edit `LAYER_PATTERNS` in [`layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/layer-detector.ts)

Open [`packages/core/src/analyzer/layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/core/src/analyzer/layer-detector.ts) and locate the `LAYER_PATTERNS` constant. Add, remove, or reorder entries to match your project structure. For example, to recognize a custom "Job Scheduler" layer for files in `jobs/` or `scheduler/` directories, insert this entry before more generic patterns:

```typescript
{
  patterns: ["jobs", "scheduler"],
  layerName: "Job Scheduler Layer",
  description: "Cron jobs, scheduled tasks, and background workers",
},

```

### 2. Rebuild the Core Package

After modifying the source, compile the changes so the dashboard can consume them. From the repository root, run:

```bash
pnpm --filter @understand-anything/core build

```

Alternatively, run the full build pipeline with `pnpm install && pnpm build` to ensure all dependencies are synchronized.

### 3. Re-run the Analysis

Execute your standard Understand-Anything command to regenerate the knowledge graph with the new layer mappings:

```bash
understand --full

```

Or, if using the Claude Code integration: `/understand --full`.

## Extending Detection Without Forking Core Files

If you prefer to keep the original [`layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/layer-detector.ts) untouched, create an extension module that exports additional patterns and import it into the detector file. Create [`packages/core/src/analyzer/my-extensions.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/core/src/analyzer/my-extensions.ts):

```typescript
export const EXTRA_LAYER_PATTERNS = [
  {
    patterns: ["analytics", "metrics"],
    layerName: "Analytics Layer",
    description: "Data collection, reporting, and metrics aggregation",
  },
];

```

Then modify [`layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/layer-detector.ts) to merge the arrays:

```typescript
import { EXTRA_LAYER_PATTERNS } from "./my-extensions.js";

export const LAYER_PATTERNS = [
  // ... original entries ...
  ...EXTRA_LAYER_PATTERNS,
];

```

This approach preserves the original order while appending your custom definitions, allowing you to maintain a clean diff when updating the repository.

## Leveraging LLM-Assisted Layer Detection

Beyond static patterns, Understand-Anything can invoke a language model to suggest architectural layers. The system builds a prompt via `buildLayerDetectionPrompt`, which requests a JSON array of layer objects. The LLM response is parsed by `parseLayerDetectionResponse` and merged with heuristic results through `applyLLMLayers` (used downstream in the analysis pipeline).

To customize the LLM behavior, modify the prompt string in `buildLayerDetectionPrompt`. For instance, to request up to 10 layers instead of the default 3-7, or to ask for file extension-based categorization:

```typescript
export function buildLayerDetectionPrompt(graph: KnowledgeGraph): string {
  const filePaths = /* gather from graph */;
  const fileListStr = /* format as string */;

  return `You are a software architecture analyst. 
From the file list below, propose **up to 10** logical layers.
For each layer provide:
  - "name"
  - "description" 
  - "filePatterns" (example path prefixes)
Ensure every file appears in exactly one layer.
Respond ONLY with a JSON array.

Files:
${fileListStr}`;
}

```

After changing the prompt, rebuild the core package and re-run the analysis. The LLM-generated layers supplement, rather than replace, your heuristic patterns, filling gaps for files that don't match static directory rules.

## Summary

- **[`packages/core/src/analyzer/layer-detector.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/core/src/analyzer/layer-detector.ts)** contains the `LAYER_PATTERNS` constant and `matchFileToLayer` function that drive architectural layer assignment.
- The heuristic matcher evaluates patterns in array order, assigning the first matching layer or defaulting to "Core".
- To customize: edit `LAYER_PATTERNS`, run `pnpm --filter @understand-anything/core build`, and re-run the analysis command.
- You can extend patterns from external modules to avoid modifying core source files directly.
- The `buildLayerDetectionPrompt` function controls LLM-based layer suggestions, which are merged with heuristic results via `parseLayerDetectionResponse` and `applyLLMLayers`.

## Frequently Asked Questions

### What happens if a file doesn't match any pattern in `LAYER_PATTERNS`?

When `matchFileToLayer` returns `null` for a given path, the file is automatically assigned to the **Core** layer. This fallback ensures that every file appears in the architectural visualization even if it resides outside recognized directory conventions.

### Can I customize layer detection based on file extensions or naming conventions instead of directories?

Yes. While the default `matchFileToLayer` implementation checks directory segments, you can modify the function to analyze file extensions, prefixes, or even content signatures. Replace the segment-matching logic with checks like `filePath.endsWith('.test.ts')` or regex patterns, then rebuild the core package to apply your custom detection logic.

### How do I prevent the LLM from overriding my heuristic layer assignments?

The LLM-generated layers merge with heuristic results rather than replacing them. The `applyLLMLayers` function (used downstream) combines both sources, with heuristic matches typically taking precedence for files already categorized. To exclude LLM suggestions entirely, simply don't trigger the LLM analysis phase or remove the call to `buildLayerDetectionPrompt` from your analysis workflow.

### Where is the layer information stored after detection?

The `detectLayers` function constructs `Layer` objects containing `id`, `name`, `description`, and `nodeIds` arrays. This data flows into **[`packages/dashboard/src/store.ts`](https://github.com/Lum1104/Understand-Anything/blob/main/packages/dashboard/src/store.ts)**, which persists the layer mappings for UI rendering. The layer IDs follow a kebab-case format like `layer:api-layer` (generated by `toLayerId`), allowing the dashboard to apply consistent coloring and filtering across the visualization.