Folder convention
How to organize your project files and where to put each kind of code.
Every project that uses any of the @wanner.work/* rule packs is expected to
follow a single folder convention. The convention is intentionally small: one
src/ directory at the project root, with one well-named folder per kind of
file.
Not every project needs every folder. Pick the ones that match what your project actually contains — a project without enums or classes is perfectly fine to leave those folders out. The rules only fire on the folders that exist.
The tree
/
└── src/
├── styles/
├── methods/
├── components/
│ └── ui/ (optional for shadcn/ui)
├── hooks/
├── interfaces/
├── types/
├── constants/
├── enums/
├── classes/
├── lib/ (optional for external files — linting ignored)
├── app/ (optional only for Next.js app router)
└── routes/ (optional only for React Router / TanStack Router)Always use the src/ directory for .ts and .js files. Folders on the root
are not part of the lintable surface.
What goes where
| Folder | Purpose | Rule pack |
|---|---|---|
src/methods/ | Standalone, reusable method files. | Method rules |
src/components/ | React component files (.jsx / .tsx). | Component rules |
src/components/ui/ | Generated UI primitives (e.g. shadcn/ui). | — |
src/hooks/ | React hook files. | Hook rules |
src/interfaces/ | Standalone TypeScript interface files. | Interface rules |
src/types/ | Shared type aliases, generic types, and Options interfaces. | — |
src/constants/ | Readonly constant groups. | Constant rules |
src/enums/ | TypeScript enums. | — |
src/classes/ | Plain TypeScript classes. | — |
src/styles/ | Global stylesheets (CSS, SCSS, etc.). | — |
src/lib/ | Third-party or vendored code that you do not control. | Linting ignored |
src/app/ | Next.js App Router pages, layouts, and route handlers. | — |
src/routes/ | Routes for React Router or TanStack Router projects. | — |
The rules are folder-scoped, not whole-project. A .ts file in src/lib/ is
not linted by this pack because that folder is reserved for code outside your
control.
Subfolders
The tree above shows the minimum shape of a project. For anything beyond a
small project, drop files into subfolders organized by feature, domain, or
any other useful boundary. A flat dump of files in src/components/,
src/methods/, etc. does not scale — group related files together so the
folder itself tells you what the files are for.
Subfolders can nest as deep as useful. There is no fixed depth and no required grouping scheme (feature, domain, layer, etc. are all fine) — pick whatever makes the project easy to navigate.
src/
├── components/
│ ├── auth/
│ │ ├── LoginForm.tsx
│ │ └── SignupForm.tsx
│ ├── dashboard/
│ │ ├── charts/
│ │ │ └── RevenueChart.tsx
│ │ └── Overview.tsx
│ └── ui/ (shadcn/ui — stays flat)
├── methods/
│ ├── user/
│ │ ├── createUser.ts
│ │ └── deleteUser.ts
│ └── formatting/
│ └── formatCurrency.ts
└── hooks/
├── auth/
│ └── useSession.ts
└── user/
└── useProfile.tssrc/components/ui/ is the one folder that stays flat. It holds generated
shadcn/ui primitives that are managed by the CLI, not grouped by feature.
This is a guideline, not a lint rule. The oxlint rule pack only enforces per-file conventions (naming, exports, props interface, etc.) regardless of how deep a file sits inside its top-level folder.
Naming
All folder names must be lowercase. Use only lowercase letters, digits, and hyphens. No uppercase letters, no underscores, no spaces.
src/components/ ok
src/Components/ no uppercase
src/user_auth/ no underscore
src/UserProfile/ no uppercaseThis applies to every folder in the convention — including nested ones like
src/components/ui/.
Styles
All stylesheets (.css, .scss, .sass, .less, etc.) must live inside
src/styles/. Placing CSS files anywhere else in the project is not allowed.
src/styles/global.css ok
src/components/button.scss no stylesheet outside src/styles/
src/hooks/use-theme.css no stylesheet outside src/styles/Co-located styles (e.g. a Button.module.css next to Button.tsx) are not
permitted under this convention. Move all styles into src/styles/ and import
them from there.
Linking to the rules
Some lintable folder have a dedicated rule page that documents every enforced convention with a "Do / Don't" example: