lightsoutAlpha

feature-structure

a feature folder pre-creating layout the graduation rule has not earned

Agent checkadvisory by defaulttanstackcode

The argument

Feature Structure

A feature under src/features/ is a module — callers import each file it offers directly, and it carries no index.ts (folder-index-file rule) — and everything inside it grows by the graduation rule — a single file until companions or a shared subject earn a folder. There is no fixed feature tree to stamp out; these are the domain folders a TanStack feature commonly grows, each created when graduation triggers and never before:

  • screens/ — route-destination components; a screen graduates to its own folder exactly as any component does (component file structure)
  • queries/ — query-options factories (see the query-options rule)
  • serverFns/ — server functions (see the server-functions rule)
  • hooks/ — query-wrapping hooks
  • components/ — feature-wide components
  • common/ — feature-internal shared code

Where a piece of code lives — app-wide src/common/, feature common/, or beside its one consumer — is the base placement rule, unchanged here.

None of this is TanStack's requirement. What TanStack mandates — route filenames under routes/, the router.tsx/server.ts/client.tsx entry files — lives in the framework carve-out table; the layout above is this pack's convention for the code the framework says nothing about.

The proof

fail
import { getIssueRows } from './issuesUtils';

// The feature is a flat pile: no `screens/`, no `queries/`, no barrel, and a
// file named for the role of what it holds.
export const IssuesScreen = () => <ul>{getIssueRows().map((row) => <li key={row}>{row}</li>)}</ul>;
pass
export const getIssueRows = (): string[] => ['first', 'second'];

Turn it down

Both lines go in your lightsout.config.json.

"standards-checks": { "feature-structure": "advisory" }
"standards-checks": { "feature-structure": "off" }