Feature: opt-out prefix (e.g. `_`) to exclude files/folders from `src/routes` resolution
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 22.1k
- Forks
- 1.4k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 52
Description
Feature: opt-out prefix (e.g. _) to exclude files/folders from src/routes resolution
Labels: qwik-city · enhancement · dx
Summary
Qwik City's file-system router treats any folder under src/routes as a potential route segment, and any file matching a special name (index.*, layout*.tsx, index@*.tsx, 404.tsx, 500.tsx, plugin*.ts, service-worker.ts) as routable. This makes colocating route-specific components inside the route folder unsafe: a single accidental index.tsx (copy/paste, scaffolding tool, refactor) silently creates a publicly reachable route.
There is currently no documented way to mark a folder or file as "router-ignored". The only escape is the (group) convention, which still participates in routing — it just hides the segment from the URL.
Other file-system routers solve this with a prefix convention:
| Framework | Ignore convention |
|---|---|
| Next.js (app router) | _folder and _file.tsx are private, never routed |
| SvelteKit | _lib, anything prefixed with _ is ignored |
| Remix | + / _ conventions depending on version |
| TanStack Router | -folder ignored |
Proposal
Add a documented prefix (suggest _, matching Next/SvelteKit) such that:
- Any folder in
src/routeswhose name starts with_is excluded from route resolution, including anyindex.*/layout.tsxinside it. - Any file in
src/routeswhose name starts with_is excluded, even if it would otherwise match a special filename (e.g._index.tsx,_layout.tsx). (group)semantics are unchanged.- Dynamic segments (
[param],[...rest]) and named layouts (index@narrow.tsx) are unchanged.
Why it matters
- Enables safe colocation of route-specific components, hooks, styles, tests, and fixtures next to the route they belong to — the dominant pattern in modern React/Vue/Svelte apps.
- Removes the only structural reason teams move logic out of
src/routesinto a parallelsrc/pagesorsrc/featuresmirror tree. - Makes accidental route creation impossible at the framework level instead of requiring custom lint/CI scripts.
- Brings Qwik City in line with peer frameworks, reducing migration friction.
Example
src/routes/
└── product/
└── [id]/
├── index.tsx # /product/:id
├── layout.tsx
└── _components/ # ignored — safe to colocate
├── gallery.tsx
├── price.tsx
└── reviews/
└── index.tsx # NOT a route (parent folder starts with _)
Alternatives considered
(group)folders — still routed, just URL-invisible. Doesn't solve the problem.- Naming discipline (never call a colocated file
index.tsx) — works but is unenforced. - External lockfile / lint script — works but every team has to reinvent it; framework support is the right home.
- Separate
src/componentstree — forces double-maintenance and breaks colocation.
Open questions
- Prefix choice:
_(Next/SvelteKit precedent) vs.-(TanStack) vs.+vs. something Qwik-specific._seems most familiar. - Should the ignore apply to files at any depth, or only direct children of
src/routes? (Suggest: any depth, so a single_components/ignores everything inside.) - Interaction with
plugin@*.tsandservice-worker.tsif someone names them_plugin@auth.ts— proposal: prefix wins, file is ignored.
Willing to contribute
(Yes/no — your call.) Happy to open a PR if the team agrees on the prefix and semantics.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue does not name implementation files or tests. Start by locating Qwik City's src/routes resolution entry point and its route-discovery tests; confirm how special filenames, dynamic segments, groups, plugins, and service workers are recognized. Resolve the prefix and nesting semantics, then update documentation and add coverage showing prefixed files and folders are excluded while existing routes remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- developer-experience, frontend, web-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100