antfu · diff

v2026.1.28 to v2026.1.28

37 added, 147 removed. Audit B to B.

---
name: antfu
- description: Anthony Fu's {Opinionated} preferences and best practices for web development
+ description: Anthony Fu's opinionated tooling and conventions for JavaScript/TypeScript projects. Use when setting up new projects, configuring ESLint/Prettier alternatives, monorepos, library publishing, or when the user mentions Anthony Fu's preferences.
metadata:
author: Anthony Fu
version: "2026.1.28"
---
# Anthony Fu's Preferences
- This skill covers Anthony Fu's preferred tooling, configurations, and best practices for web development. This skill is opinionated.
-
- ## Quick Summary
-
| Category | Preference |
|----------|------------|
- | Package Manager | pnpm |
- | Language | TypeScript (strict mode) |
- | Module System | ESM (`"type": "module"`) |
- | Linting & Formatting | @antfu/eslint-config (no Prettier) |
+ | Package Manager | pnpm (with `@antfu/ni` for unified commands) |
+ | Language | TypeScript (strict mode, ESM only) |
+ | Linting & Formatting | `@antfu/eslint-config` (no Prettier) |
| Testing | Vitest |
| Git Hooks | simple-git-hooks + lint-staged |
- | Documentation | VitePress (in `docs/`) |
+ | Bundler (Libraries) | tsdown |
+ | Documentation | VitePress |
---
- ## Core Stack
-
- ### Package Manager (pnpm)
-
- Use pnpm as the package manager.
-
- For monorepo setups, use pnpm workspaces:
-
- ```yaml
- # pnpm-workspace.yaml
- packages:
- - 'packages/*'
- ```
-
-
- Use pnpm named catalogs in `pnpm-workspace.yaml` to manage dependency versions:
-
- | Catalog | Purpose |
- |---------|---------|
- | `prod` | Production dependencies |
- | `inlined` | Dependencies inlined by bundler |
- | `dev` | Development tools (linter, bundler, testing, dev-server) |
- | `frontend` | Frontend libraries bundled into frontend |
-
- Catalog names are not limited to the above and can be adjusted based on needs. Avoid using default catalog.
-
- #### @antfu/ni
+ ## Core Conventions
- Use `@antfu/ni` for unified package manager commands. It auto-detects the package manager (pnpm/npm/yarn/bun) based on lockfile.
+ ### @antfu/ni Commands
| Command | Description |
|---------|-------------|
| `ni` | Install dependencies |
- | `ni <pkg>` | Add dependency |
- | `ni -D <pkg>` | Add dev dependency |
+ | `ni <pkg>` / `ni -D <pkg>` | Add dependency / dev dependency |
| `nr <script>` | Run script |
| `nu` | Upgrade dependencies |
| `nun <pkg>` | Uninstall dependency |
- | `nci` | Clean install (like `pnpm i --frozen-lockfile`) |
- | `nlx <pkg>` | Execute package (like `npx`) |
-
- Install globally with `pnpm i -g @antfu/ni` if the commands are not found.
-
- ### TypeScript (Strict Mode)
+ | `nci` | Clean install (`pnpm i --frozen-lockfile`) |
+ | `nlx <pkg>` | Execute package (`npx`) |
- Always use TypeScript with strict mode enabled.
+ ### TypeScript Config
```json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}
```
- ### ESM (ECMAScript Modules)
-
- Always work in ESM mode. Set `"type": "module"` in `package.json`.
-
- ---
-
- ## Code Quality
-
- ### ESLint (@antfu/eslint-config)
-
- Use `@antfu/eslint-config` for both formatting and linting. This eliminates the need for Prettier.
-
- Create `eslint.config.js` with `// @ts-check` comment:
+ ### ESLint Setup
```js
- // @ts-check
+ // eslint.config.mjs
import antfu from '@antfu/eslint-config'
export default antfu()
```
- Add script to `package.json`:
-
- ```json
- {
- "scripts": {
- "lint": "eslint ."
- }
- }
- ```
-
- When getting linting errors, try to fix them with `nr lint --fix`. Don't add `lint:fix` script.
+ Fix linting errors with `nr lint --fix`. Do NOT add a separate `lint:fix` script.
- ### Git Hooks (simple-git-hooks + lint-staged)
+ For detailed configuration options: [antfu-eslint-config](references/antfu-eslint-config.md)
- Use `simple-git-hooks` with `lint-staged` for pre-commit linting:
+ ### Git Hooks
```json
{
"simple-git-hooks": {
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
},
- "lint-staged": {
- "*": "eslint --fix"
- },
- "scripts": {
- "prepare": "npx simple-git-hooks"
- }
- }
- ```
-
- ### Unit Testing (Vitest)
-
- Use Vitest for unit testing.
-
- ```json
- {
- "scripts": {
- "test": "vitest"
- }
+ "lint-staged": { "*": "eslint --fix" },
+ "scripts": { "prepare": "npx simple-git-hooks" }
}
```
- **Conventions:**
+ ### Vitest Conventions
- - Place test files next to source files: `foo.ts` → `foo.test.ts` (same directory)
- - High-level tests go in `tests/` directory in each package
- - Use `describe` and `it` API (not `test`)
- - Use `expect` API for assertions
- - Use `assert` only for TypeScript null assertions
- - Use `toMatchSnapshot` for complex output assertions
- - Use `toMatchFileSnapshot` with explicit file path and extension for language-specific output (exclude those files from linting)
+ - 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
---
- ## Project Setup
-
- ### Publishing (Library Projects)
-
- For library projects, publish through GitHub Releases triggered by `bumpp`:
-
- ```json
- {
- "scripts": {
- "release": "bumpp -r"
- }
- }
- ```
-
- ### Documentation (VitePress)
-
- Use VitePress for documentation. Place docs under `docs/` directory.
+ ## pnpm Catalogs
- ```
- docs/
- ├── .vitepress/
- │ └── config.ts
- ├── index.md
- └── guide/
- └── getting-started.md
- ```
+ Use named catalogs in `pnpm-workspace.yaml` for version management:
- Add script to `package.json`:
+ | Catalog | Purpose |
+ |---------|---------|
+ | `prod` | Production dependencies |
+ | `inlined` | Bundler-inlined dependencies |
+ | `dev` | Dev tools (linter, bundler, testing) |
+ | `frontend` | Frontend libraries |
- ```json
- {
- "scripts": {
- "docs:dev": "vitepress dev docs",
- "docs:build": "vitepress build docs"
- }
- }
- ```
+ Avoid the default catalog. Catalog names can be adjusted per project needs.
---
## References
- ### Project Setup
-
| Topic | Description | Reference |
|-------|-------------|-----------|
- | @antfu/eslint-config | ESLint flat config for formatting and linting | [antfu-eslint-config](references/antfu-eslint-config.md) |
- | GitHub Actions | Preferred workflows using sxzz/workflows | [github-actions](references/github-actions.md) |
- | .gitignore | Preferred .gitignore for JS/TS projects | [gitignore](references/gitignore.md) |
- | VS Code Extensions | Recommended extensions for development | [vscode-extensions](references/vscode-extensions.md) |
-
- ### Development
-
- | Topic | Description | Reference |
- |-------|-------------|-----------|
- | App Development | Preferences for Vue/Vite/Nuxt/UnoCSS web applications | [app-development](references/app-development.md) |
- | Library Development | Preferences for bundling and publishing TypeScript libraries | [library-development](references/library-development.md) |
+ | ESLint Config | Framework support, formatters, rule overrides, VS Code settings | [antfu-eslint-config](references/antfu-eslint-config.md) |
+ | Project Setup | .gitignore, GitHub Actions, VS Code extensions | [setting-up](references/setting-up.md) |
+ | App Development | Vue/Nuxt/UnoCSS conventions and patterns | [app-development](references/app-development.md) |
+ | Library Development | tsdown bundling, pure ESM publishing | [library-development](references/library-development.md) |
| Monorepo | pnpm workspaces, centralized alias, Turborepo | [monorepo](references/monorepo.md) |