Loaded by review-remix-v2 (umbrella) to flag routing anti-patterns in app/routes/ modules. See remix-v2-routing for canonical patterns.
Issue TypeReferenceFilename smells ( index.tsx, __auth, wrong escape, non-route files)references/route-files.mdMissing <Outlet />, orphan dotted segments, duplicated layout logicreferences/layouts-outlets.mdDefault export on a resource, <Link> without reloadDocument, splat paramsreferences/resource-routes.mdreact-router-dom imports, __double folders, v1-adapter fallbackreferences/v1-holdovers.mdMissing <Meta />/ <Links />/ <Scripts />/ <ScrollRestoration />, Vite-vs-Classic <LiveReload />, root ErrorBoundary without document shellreferences/root-shell.md
This skill flags issues in:
app/routes/ (filenames, exports, imports, JSX shape)app/root.tsx (document shell, root <Outlet />)remix.config.js (entries that change route discovery: routes(), ignoredRouteFiles, @remix-run/v1-route-convention)<Link> usage)Out of scope: loader/action data contracts (covered by remix-v2-data-flow-review), form behavior ( remix-v2-forms-review), meta/headers ( remix-v2-meta-sessions-review).
_index.tsx, not index.tsx_auth.tsx), not double ( __auth/)users.profile.tsx) have a parent module or use trailing underscore ( users_.profile.tsx)<Outlet />params["*"], never params.splat / params.restsitemap[.]xml.tsx)default export<Link> to a resource route uses reloadDocument (or is a plain <a>)@remix-run/react, not react-router-domroute.tsx, or are listed in ignoredRouteFiles($lang) narrow params.lang in the loader (see references/route-files.md)_-prefixed pathless layout file without <Outlet /> when the module is intentionally a wrapper that renders fixed UI only. Confirm by checking children — if no *.{segment}.tsx siblings exist, the wrapper-only shape is intentional._ that don't appear in any URL — pathless layouts and _index are supposed to be hidden from the URL.@remix-run/v1-route-convention wired up in remix.config.js — legitimate migration adapter, not a smell on its own. Only flag if v1-style files appear without the adapter installed.useLoaderData<typeof loader>() — type annotation, not assertion.params["*"] with bracket syntax — that is the only correct access pattern.app/routes/dashboard/ with route.tsx plus sibling .server.ts, .css, component files — co-location is the documented pattern.concerts_.mine.tsx) when a sibling concerts.tsx layout exists and this URL intentionally skips it.Only flag these issues when the specific context applies:
IssueFlag ONLY IFindex.tsx under app/routes/Project is v2 and @remix-run/v1-route-convention is NOT wired in remix.config.jsParent module without <Outlet />Sibling dotted children ( parent.*.tsx) exist in app/routes/``__double underscore folderNo v1-convention adapter is installedTrailing-underscore segmentNo corresponding parent layout exists (nothing to opt out of)Default export on a module returning non-HTMLThe loader/action actually returns a raw Response (PDF, JSON, RSS)<Link> to resource routeTarget route has no default export AND <Link> lacks reloadDocument
Run these in order. Do not draft user-facing findings until every gate passes for the batch you are about to report.
Location evidence — Pass: Each issue lists a repo path (file under app/routes/ or remix.config.js) and either a line range or a short verbatim quote from the file you read. Filename-only smells must quote the literal filename.
Exemption check — Pass: For each issue, state in one line why it is not covered by Valid Patterns (Do NOT Flag). Resource-route flags require explicit evidence of a default export or a <Link> without reloadDocument.
Version check — Pass: Confirm the project is Remix v2 (check package.json for @remix-run/react ^2, or presence of v2 flat-routes filenames elsewhere in app/routes/). If @remix-run/v1-route-convention is wired in remix.config.js, v1 filenames ( __auth/, index.tsx) are intentional — do not flag them as smells.
Protocol — Pass: Complete the Pre-Report Verification Checklist in review-verification-protocol for this review.
app/routes/ → references/route-files.md<Link> to such a module → references/resource-routes.mdapp/root.tsx (document shell, <Meta />/ <Links />/ <Scripts />/ <ScrollRestoration />, <LiveReload /> on Vite vs Classic Compiler, root ErrorBoundary) → references/root-shell.md<Outlet />, or is it a deliberate wrapper-only?_ for pathless, _index for index, [...] for escapes)?default exports, and do all <Link> s to them use reloadDocument?@remix-run/react (and server helpers from @remix-run/node)?@remix-run/v1-route-convention wired up — or are they accidental?index.tsx, __double folders, wrong escape syntax, dot/underscore confusion, non-route files under app/routes/.<Outlet />, orphan dotted children, duplicated layout logic.<Link> without reloadDocument, splat params["*"] access.react-router-dom imports, __auth folders, @remix-run/v1-route-convention as a deliberate-vs-accidental tell.