Inside the code scanner
Point Elva at a repo and it reads your source the way a senior engineer would: it finds the frameworks, follows the routers, and pulls out every real endpoint across five language ecosystems. No annotations to add, no config to write, no code to run.
One scan, three layers of discovery, every endpoint scored by confidence.
The scanner is the muscle behind the living catalog. This page opens it up so you can judge the depth before you connect a single repo.
Static parse only. Elva reads your code with an AST parser and pattern matchers. It never executes your code, never installs your dependencies, and never runs your tests. The clone is shallow, lands in a temp directory, and is deleted the moment the scan finishes.
Three layers of discovery
Elva does not rely on a single trick. It runs three passes over the clone and keeps the strongest signal for every route, so a repo with a hand-written spec, framework routes, and undocumented handlers all end up in one catalog.
1. OpenAPI and Swagger specs. If your repo already ships a contract (openapi.yaml, swagger.json, api-docs, and friends), Elva parses it directly. These endpoints carry a discovery confidence of 1.0, because the spec is the source of truth. The raw spec files are archived too, so insights and MCP generation can use the original contract.
2. Static analysis of framework routes. Elva walks your actual source with a real parser (ts-morph for JS/TS) and resolves routes the way the framework does at runtime, including mounted-router prefixes. Confidence lands between 0.55 and 0.95 depending on how unambiguous the route is.
3. AI fallback extraction. When AI scanning is enabled, Elva sends routing-looking files that the first two passes missed to an LLM, which extracts endpoints at confidence 0.5. This catches custom routers and exotic patterns the static analyzers do not know.
Endpoints are deduplicated by service | method | path, and the highest-confidence discovery wins. A route found in both your spec and your code is counted once, at confidence 1.0.
Language and framework coverage
Static analysis is tuned per framework. Each detector knows the idioms of its ecosystem, from Express route chaining to Spring’s class-level @RequestMapping base paths.
Ecosystem | Frameworks detected | Discovery confidence |
JavaScript / TypeScript | Express, Fastify, NestJS, Koa, Hono | NestJS |
Python | FastAPI, Flask, Django | FastAPI decorators |
Go | gin, echo, chi, net/http | Router calls |
Java / Kotlin | Spring MVC | Method annotations ( |
Any (spec) | OpenAPI 3.x, Swagger 2.0 |
|
Any (AI) | LLM fallback on routing files |
|
The JS/TS analyzer resolves mounted prefixes across files, so app.use('/api/v1', userRouter) plus userRouter.get('/profile') correctly produces /api/v1/profile. Local mounts override file-level mounts, and template-literal routes keep their shape by swapping ${...} for {param}.
What each service becomes
Before scanning routes, Elva splits your repo into services by detecting manifest files. A monorepo with a Node gateway, a Go worker, and a Python service is scanned as three distinct services, each with its own language and framework.
Manifest | Detected as |
| Node service (express / fastify / nestjs / koa / hono) |
| Go service (gin / echo / chi) |
| Java or Kotlin service (Spring) |
| Python service (fastapi / flask / django) |
| Container service |
| Spec-only service |
Nested workspace roots are collapsed so an aggregator package.json at the repo root does not shadow real sub-services.
The scan pipeline
A scan job moves through named stages, and the progress bar you see in the app maps directly to them. Every stage writes to the ScanJob record so you can watch it live.
On this page
- Inside the code scanner