Single responsibility: Each source file should have a clear, focused scope/purpose
Split large files: Break files when they become large or handle too many concerns
Type separation: Always separate types and interfaces into types.ts or types/*.ts
Constants extraction: Move constants to a dedicated constants.ts file
Runtime Environment
Prefer isomorphic code: Write runtime-agnostic code that works in Node, browser, and workers whenever possible
Clear runtime indicators: When code is environment-specific, add a comment at the top of the file:
typescript
// @env node// @env browser
TypeScript
Explicit return types: Declare return types explicitly when possible
Avoid complex inline types: Extract complex types into dedicated type or interface declarations
Explicitness
Favor explicit, traceable code over implicit "magic". A reader (human or agent) should be able to follow where every name comes from without running tooling.
Explicit imports: Prefer explicit import statements. Avoid auto-imports — when a framework provides them (e.g. Nuxt/Nitro), turn them off for new projects (see app-development [blocked]).
No path aliases by default: Use relative imports (./foo, ../bar). Only use path aliases (@/, ~/, #imports, etc.) when they are already configured in the project; don't introduce new ones for greenfield code.
Comments
Avoid unnecessary comments: Code should be self-explanatory
Explain "why" not "how": Comments should describe the reasoning or intent, not what the code does
Testing (Vitest)
Test files: foo.ts → foo.test.ts (same directory)
Use describe/it API (not test)
Use toMatchSnapshot for complex outputs
Use toMatchFileSnapshot with explicit path for language-specific snapshots
Tooling Choices
@antfu/ni Commands
Command
Description
ni
Install dependencies
ni <pkg> / ni -D <pkg>
Add dependency / dev dependency
nr <script>
Run script
nu
Upgrade dependencies
nun <pkg>
Uninstall dependency
nci
Clean install (pnpm i --frozen-lockfile)
nlx <pkg>
Execute package (npx)
Checking npm Package Versions
Use fast-npm-meta to look up the latest version of a package — it queries a small metadata endpoint instead of downloading the full registry payload (which can be megabytes per package).
bash
nlx fast-npm-meta version vite # 7.3.1nlx fast-npm-meta version "nuxt@^3.5" # 3.5.22 — range-awarenlx fast-npm-meta version vite nuxt vue # multiple at oncenlx fast-npm-meta version vite --json # JSON for scriptingnlx fast-npm-meta full vite # full version list + dist-tags
Prefer this over npm view <pkg> version when you only need the latest version, and over reading package.json from the registry directly.