react-use
react use
hairy
Hairy's {Opinionated} preferences and best practices for web development
Full skill instructions
This skill covers Hairyf's preferred tooling, configurations, and best practices for web development. This skill is opinionated.
| Category | Preference |
|---|---|
| Package Manager | pnpm |
| Language | TypeScript (strict mode) |
| Module System | ESM ("type": "module") |
| Linting & Formatting | @antfu/eslint-config (no Prettier) |
| Testing | Vitest |
| Git Hooks | simple-git-hooks + lint-staged |
| Documentation | VitePress (in docs/) |
High-level cross-cutting preferences that should be respected whenever possible:
When a task is marked with "specify" (for example: "specify this repo according to hairy"):
@skills/arch-upkeep and the relevant arch-* skills.@skills/unjs).@skills/taze.lint + typecheck (and tests if present) before considering the "specify" task done.@skills/unjs and follow its recommendations.arch-* skillsarch-* stacks (tsdown library, CLI, monorepo, unplugin, webext, vscode, etc.).@skills/arch-upkeep to:
arch-* skill(s).tazetaze (see @skills/taze) to:
package.json unless there is a specific reason not to follow taze’s suggestions.nr lint → ESLint via @antfu/eslint-config.nr typecheck → TypeScript in strict mode (project-wide).lint on staged files.lint and typecheck on PRs and main pushes.Use pnpm as the package manager.
For monorepo setups, use pnpm workspaces:
# 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.
Use @antfu/ni for unified package manager commands. It auto-detects the package manager (pnpm/npm/yarn/bun) based on lockfile.
| Command | Description |
|---|---|
ni | Install dependencies |
ni <pkg> | Add dependency |
ni -D <pkg> | Add 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.
Always use TypeScript with strict mode enabled.
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}
Always work in ESM mode. Set "type": "module" in package.json.
Use @antfu/eslint-config for both formatting and linting. This eliminates the need for Prettier.
Create eslint.config.js with // @ts-check comment:
// @ts-check
import antfu from '@antfu/eslint-config'
export default antfu()
Add script to package.json:
{
"scripts": {
"lint": "eslint ."
}
}
When getting linting errors, try to fix them with nr lint --fix. Don't add lint:fix script.
Use simple-git-hooks with lint-staged for pre-commit linting:
{
"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"
}
}
Use Vitest for unit testing.
{
"scripts": {
"test": "vitest"
}
}
Conventions:
foo.ts → foo.test.ts (same directory)tests/ directory in each packagedescribe and it API (not test)expect API for assertionsassert only for TypeScript null assertionstoMatchSnapshot for complex output assertionstoMatchFileSnapshot with explicit file path and extension for language-specific output (exclude those files from linting)For library projects, publish through GitHub Releases triggered by bumpp:
{
"scripts": {
"release": "bumpp -r"
}
}
Use VitePress for documentation. Place docs under docs/ directory.
docs/
├── .vitepress/
│ └── config.ts
├── index.md
└── guide/
└── getting-started.md
Add script to package.json:
{
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs"
}
}
| Topic | Description | Reference |
|---|---|---|
| Prefer unjs ecosystem | Prefer unjs ecosystem frameworks and tooling; delegate to @skills/unjs | core-unjs-preferences |
| Architecture via arch-* | Map repo shape to canonical arch-* skills and upgrade via arch-upkeep | core-arch-upkeep-routing |
| Fresh dependencies with taze | Keep dependencies continuously fresh using taze and controlled upgrades | core-deps-taze |
| Lint + typecheck as gate | Always finish with lint + typecheck locally and in CI | core-lint-typecheck |
| Topic | Description | Reference |
|---|---|---|
| @antfu/eslint-config | ESLint flat config for formatting and linting | antfu-eslint-config |
| VS Code Extensions | Recommended extensions for development | vscode-extensions |
| Topic | Description | Reference |
|---|---|---|
| App Development | Preferences for Vue/Vite/Nuxt/UnoCSS web applications | app-development |
react use
valtio
valtio define
hairy react lib
overlastic
openapi specification v3.2
vitest
unjs
openapi specification v2
undocs
writing humanizer zh
tsdown
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience