After #2 (kind field) and #3 (Next.js page extraction), other framework extractors still emit kind: "api" for everything — even routes that are clearly pages or websockets in their respective frameworks. Tracking the remaining gaps as a checklist; each row can land as a separate PR.
Pages
WebSockets
Already done: Next.js (#3), FastAPI (@router.websocket() already emits kind: "websocket").
Per-PR requirements
Each row above lands as its own PR (single extractor file + fixture). For every PR:
Per-framework PRs are small (single extractor file + fixture test). Easiest wins are class-annotation-driven detection (Spring, NestJS); body-inspection (Flask, Express, Laravel view()) is middle-difficulty; class-hierarchy detection (Django CBV, Rails) is most involved.
Builds on #2. Test infrastructure landing in #4 makes the verification step mechanical.
After #2 (kind field) and #3 (Next.js page extraction), other framework extractors still emit
kind: "api"for everything — even routes that are clearly pages or websockets in their respective frameworks. Tracking the remaining gaps as a checklist; each row can land as a separate PR.Pages
@Controller(page) vs@RestController(api). Class-level annotation, easy.@Render('view')decorator on controller methods.routes/web.phpis page-shaped; handler returningview().render_template(...).HTMLResponseorJinja2Templates.TemplateResponse.res.render(...)orres.sendFile(...).TemplateView/ListView/DetailViewwithtemplate_name; FBV returningrender(...).ActionController::Base(page) vsActionController::API(api).WebSockets
@WebSocketGateway()+@SubscribeMessage()decorators.websocket_urlpatternsinrouting.py,AsyncWebsocketConsumersubclasses.@MessageMapping,@SubscribeMapping,WebSocketHandlerimplementations.socket.io,ws,express-ws(io.on('connection', ...)patterns).gorilla/websocket, ginc.Upgrade().Already done: Next.js (#3), FastAPI (
@router.websocket()already emitskind: "websocket").Per-PR requirements
Each row above lands as its own PR (single extractor file + fixture). For every PR:
kindis correct for the new category. Add fixture test cases undersrc/extractors/__fixtures__/<framework>/that assertkind: "page"(or"websocket") on the new detection paths AND that existing API-route detection in the same extractor still emitskind: "api"(no regressions). The test must fail if the wrong kind is returned for either category.Per-framework PRs are small (single extractor file + fixture test). Easiest wins are class-annotation-driven detection (Spring, NestJS); body-inspection (Flask, Express, Laravel
view()) is middle-difficulty; class-hierarchy detection (Django CBV, Rails) is most involved.Builds on #2. Test infrastructure landing in #4 makes the verification step mechanical.