You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Next.js App Router: app/**/route.ts handlers produce 0 Route nodes, so cross-repo-intelligence finds no edges #759
Fleet of TypeScript repos indexed into one store with mode: full
Problem
Next.js App Router projects define HTTP endpoints via the file convention: app/api/**/route.ts exporting GET / POST / PUT / DELETE handler functions. These handlers are indexed as plain Function nodes, but zero Route nodes are extracted:
search_graph(project=..., label="Route")
→ {"total":0, "results":[], "hint":"No nodes with this label. Available labels: Function, Method, Class, Interface, Route, ..."}
Verified on two independent Next.js App Router codebases (one with ~20 route handlers under src/app/api/, including nested dynamic segments). Both index cleanly (~4k nodes) with correct call graphs — only route extraction is affected.
Because no Route nodes exist, index_repository(mode="cross-repo-intelligence", target_projects=["*"]) reports projects_scanned: N but 0 edges of every CROSS_* type, even though sibling repos in the store call these endpoints.
Expected
Route nodes derived from the file convention:
path from the directory structure relative to app/ (e.g. src/app/api/chatgpt/actions/route.ts → /api/chatgpt/actions), with [param] / [...slug] segments normalized
method from the export name (GET, POST, etc.)
App Router has been the Next.js default since v13, so this likely affects a large share of modern TS repos — the pages-style pages/api/*.ts convention may deserve the same treatment.
Related
Possibly also worth covering: Convex httpRouter registrations (http.route({ path, method, handler }) in convex/http.ts) are similarly not extracted as Route nodes — happy to split that into a separate issue if you prefer.
Adjacent existing reports for other frameworks: #678 (FastAPI), #686 (Fiber), #734 (Spring prefix), #292 (protocol-aware matching design).
Thanks for the Next.js App Router report. Triage: route extraction / cross-repo intelligence under #592 and #398.
app/**/route.ts handlers should emit Route nodes with method/path information, otherwise cross-repo matching has nothing to join against. The regression should cover at least GET/POST route handlers and dynamic path segments before matching is layered on top.
I'd like to contribute a focused fix for this, following the regression coverage you requested.
For example, src/app/api/users/[id]/route.ts exporting GET and POST should produce GET /api/users/:id and POST /api/users/:id Route nodes, linked to their handlers.
I propose deriving the path from the App Router directory structure and the method from each handler's export name during extraction. These would populate the existing handler route metadata, allowing the existing route-node pass to create the Route nodes and HANDLES edges.
Regression coverage would include GET/POST, nested dynamic segments, catch-all paths, and handler changes/deletions during re-indexing. Cross-repo matching, Pages Router and other frameworks would remain separate.
Would you be open to a PR implementing this approach?
@petterip, thank you for offering to take this on, and sorry for the silence since the 16th. Yes, please go ahead with the approach you described: derive the path from the App Router directory and the method from each exported handler name, fill the existing handler route metadata, and let the route-node pass create the Route nodes and HANDLES edges.
There's a close precedent you can copy: SvelteKit's file-convention routes in src/pipeline/pass_route_nodes.c (sveltekit_file_kind / sveltekit_route_path). They already map [param] → :param and [...slug] → *slug, strip (group) segments, and give the Route nodes the handler's file_path. Please do the same, so that search_graph --file-pattern works on them (see #1366).
The regression list you gave is exactly right: GET/POST, nested dynamic segments, catch-all, and handler change/delete across a re-index. Keeping Pages Router, Convex and cross-repo matching out of scope is the right call too. export const GET = async () => … handlers are already indexed as Function nodes on current main, so there's something to link to. Thanks again for the careful proposal, and thanks @webface for the original report!
Thank you again for the App Router proposal. The September reply already approved the focused route-extraction approach and its regression scope. I have no new implementation result to add; if there is an existing draft, please link it here so the work stays connected to the original report.
Written with AI assistance (Claude Code); I reviewed it and stand behind it.
Thanks @DeusData. Linking the work as you asked: #2738 is the groundwork PR. On every index the route pass rebuilds each handler's Route from its stored route_path, which it read with a quote scan, so an App Router directory with a quote in its name would get a second Route cut at the quote and HANDLES properties that are not valid JSON. #2738 makes the route pass read and write those properties as valid JSON, with five regression tests that fail on main without it.
The App Router change itself is #2747, stacked on #2738 and using the approach you approved. The path comes from the directory and the method from the exported handler name, both filled into the existing handler route metadata. The route-node pass then creates the Route nodes (with the handler's file_path) and the HANDLES edges. Its regressions cover GET/POST, nested dynamic segments, catch-all, and handler change/delete across a re-index. Pages Router, Convex and cross-repo matching stay out of scope.
Activity
DeusData commentedon Jul 3, 2026
Thanks for the Next.js App Router report. Triage: route extraction / cross-repo intelligence under #592 and #398.
app/**/route.tshandlers should emit Route nodes with method/path information, otherwise cross-repo matching has nothing to join against. The regression should cover at least GET/POST route handlers and dynamic path segments before matching is layered on top.petterip commentedon Sep 16, 2026
I'd like to contribute a focused fix for this, following the regression coverage you requested.
For example,
src/app/api/users/[id]/route.tsexportingGETandPOSTshould produceGET /api/users/:idandPOST /api/users/:idRoute nodes, linked to their handlers.I propose deriving the path from the App Router directory structure and the method from each handler's export name during extraction. These would populate the existing handler route metadata, allowing the existing route-node pass to create the Route nodes and HANDLES edges.
Regression coverage would include GET/POST, nested dynamic segments, catch-all paths, and handler changes/deletions during re-indexing. Cross-repo matching, Pages Router and other frameworks would remain separate.
Would you be open to a PR implementing this approach?
DeusData commentedon Sep 25, 2026
@petterip, thank you for offering to take this on, and sorry for the silence since the 16th. Yes, please go ahead with the approach you described: derive the path from the App Router directory and the method from each exported handler name, fill the existing handler route metadata, and let the route-node pass create the Route nodes and HANDLES edges.
There's a close precedent you can copy: SvelteKit's file-convention routes in
src/pipeline/pass_route_nodes.c(sveltekit_file_kind/sveltekit_route_path). They already map[param]→:paramand[...slug]→*slug, strip(group)segments, and give the Route nodes the handler'sfile_path. Please do the same, so thatsearch_graph --file-patternworks on them (see #1366).The regression list you gave is exactly right: GET/POST, nested dynamic segments, catch-all, and handler change/delete across a re-index. Keeping Pages Router, Convex and cross-repo matching out of scope is the right call too.
export const GET = async () => …handlers are already indexed as Function nodes on current main, so there's something to link to. Thanks again for the careful proposal, and thanks @webface for the original report!DeusData commentedon Oct 19, 2026
Thank you again for the App Router proposal. The September reply already approved the focused route-extraction approach and its regression scope. I have no new implementation result to add; if there is an existing draft, please link it here so the work stays connected to the original report.
petterip commentedon Oct 20, 2026
Written with AI assistance (Claude Code); I reviewed it and stand behind it.
Thanks @DeusData. Linking the work as you asked: #2738 is the groundwork PR. On every index the route pass rebuilds each handler's Route from its stored
route_path, which it read with a quote scan, so an App Router directory with a quote in its name would get a second Route cut at the quote and HANDLES properties that are not valid JSON. #2738 makes the route pass read and write those properties as valid JSON, with five regression tests that fail onmainwithout it.The App Router change itself is #2747, stacked on #2738 and using the approach you approved. The path comes from the directory and the method from the exported handler name, both filled into the existing handler route metadata. The route-node pass then creates the Route nodes (with the handler's
file_path) and the HANDLES edges. Its regressions cover GET/POST, nested dynamic segments, catch-all, and handler change/delete across a re-index. Pages Router, Convex and cross-repo matching stay out of scope.