wanner.work|rules

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

FolderPurposeRule 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.ts

src/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   uppercase

This 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:

On this page