diff --git a/apps/web/.gitignore b/apps/web/.gitignore new file mode 100644 index 00000000..aab5216b --- /dev/null +++ b/apps/web/.gitignore @@ -0,0 +1,50 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# vitest +/.vitest + +# storybook +storybook-static + +# panda css +styled-system + +# generated +src/generated/build-info.json + +# biome +.biome diff --git a/apps/web/LINTING.md b/apps/web/LINTING.md new file mode 100644 index 00000000..9d59a676 --- /dev/null +++ b/apps/web/LINTING.md @@ -0,0 +1,104 @@ +# Linting & Formatting Setup + +This project uses **Biome** for formatting and general linting, with **ESLint** handling React Hooks rules only. + +## Tools + +- **@biomejs/biome** - Fast formatter + linter + import organizer +- **eslint** + **eslint-plugin-react-hooks** - React Hooks validation only + +## Scripts + +```bash +# Check formatting and lint (non-destructive) +npm run check + +# Lint all files +npm run lint + +# Fix lint issues +npm run lint:fix + +# Format all files +npm run format + +# Check formatting (dry run) +npm run format:check +``` + +## Configuration Files + +- `biome.jsonc` - Biome configuration (format + lint) +- `eslint.config.js` - Minimal ESLint flat config for React Hooks only +- `.gitignore` - Includes patterns for Biome cache + +## What Each Tool Does + +### Biome +- Code formatting (Prettier-compatible) +- General JavaScript/TypeScript linting +- Import organization (alphabetical, remove unused) +- Dead code detection +- Performance optimizations + +### ESLint (React Hooks only) +- `react-hooks/rules-of-hooks` - Ensures hooks are called unconditionally +- `react-hooks/exhaustive-deps` - Warns about incomplete dependency arrays + +## IDE Integration + +### VS Code +Install the Biome extension: +``` +code --install-extension biomejs.biome +``` + +Add to `.vscode/settings.json`: +```json +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + } +} +``` + +## CI/CD + +Add to your GitHub Actions workflow: + +```yaml +- name: Lint + run: npm run lint + +- name: Check formatting + run: npm run format:check +``` + +## Migration from ESLint + Prettier + +This setup replaces most ESLint and Prettier functionality: +- ✅ Removed `eslint-config-next` inline config from `package.json` +- ✅ No `.eslintrc.js` or `.prettierrc` files needed +- ✅ ESLint now only runs React Hooks rules +- ✅ Biome handles all formatting and general linting + +## Why This Setup? + +1. **Speed** - Biome is 10-100x faster than ESLint + Prettier +2. **Simplicity** - Single tool for most concerns +3. **Accuracy** - ESLint still catches React-specific issues Biome can't yet handle +4. **Low Maintenance** - Minimal config overlap + +## Customization + +To add custom lint rules, edit: +- `biome.jsonc` for general rules +- `eslint.config.js` for React Hooks rules diff --git a/apps/web/biome.jsonc b/apps/web/biome.jsonc new file mode 100644 index 00000000..e1b33f1e --- /dev/null +++ b/apps/web/biome.jsonc @@ -0,0 +1,69 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.5/schema.json", + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 100 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": { + "useButtonType": "off", + "noSvgWithoutTitle": "off", + "noLabelWithoutControl": "off", + "noStaticElementInteractions": "off", + "useKeyWithClickEvents": "off", + "useSemanticElements": "off" + }, + "suspicious": { + "noExplicitAny": "off", + "noArrayIndexKey": "off", + "noImplicitAnyLet": "off", + "noAssignInExpressions": "off", + "useIterableCallbackReturn": "off" + }, + "style": { + "useNodejsImportProtocol": "off", + "noNonNullAssertion": "off", + "noDescendingSpecificity": "off" + }, + "correctness": { + "noUnusedVariables": "off", + "noUnusedFunctionParameters": "off", + "useUniqueElementIds": "off", + "noChildrenProp": "off", + "useExhaustiveDependencies": "off", + "noInvalidUseBeforeDeclaration": "off", + "useHookAtTopLevel": "off", + "noNestedComponentDefinitions": "off", + "noUnreachable": "off" + }, + "security": { + "noDangerouslySetInnerHtml": "off" + }, + "performance": { + "noAccumulatingSpread": "off" + } + } + }, + "files": { + "ignoreUnknown": true + }, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "jsxQuoteStyle": "double", + "semicolons": "asNeeded", + "trailingCommas": "es5" + } + } +} diff --git a/apps/web/eslint.config.js b/apps/web/eslint.config.js new file mode 100644 index 00000000..702214bd --- /dev/null +++ b/apps/web/eslint.config.js @@ -0,0 +1,42 @@ +// Minimal ESLint flat config ONLY for react-hooks rules + +import tsParser from '@typescript-eslint/parser' +import reactHooks from 'eslint-plugin-react-hooks' + +const config = [ + { ignores: ['dist', '.next', 'coverage', 'node_modules', 'styled-system', 'storybook-static'] }, + { + files: ['**/*.tsx', '**/*.ts', '**/*.jsx', '**/*.js'], + languageOptions: { + parser: tsParser, + ecmaVersion: 2022, + sourceType: 'module', + globals: { + React: 'readonly', + JSX: 'readonly', + console: 'readonly', + process: 'readonly', + module: 'readonly', + require: 'readonly', + window: 'readonly', + document: 'readonly', + localStorage: 'readonly', + sessionStorage: 'readonly', + fetch: 'readonly', + global: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + }, + }, + plugins: { + 'react-hooks': reactHooks, + }, + rules: { + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'off', + }, + }, +] + +export default config diff --git a/apps/web/package.json b/apps/web/package.json index 474e714f..1f0ce697 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,7 +6,11 @@ "dev": "concurrently \"node server.js\" \"npx @pandacss/dev --watch\"", "build": "node scripts/generate-build-info.js && next build", "start": "NODE_ENV=production node server.js", - "lint": "next lint", + "lint": "npx @biomejs/biome lint . && npx eslint .", + "lint:fix": "npx @biomejs/biome lint . --write && npx eslint . --fix", + "format": "npx @biomejs/biome format . --write", + "format:check": "npx @biomejs/biome format .", + "check": "npx @biomejs/biome check .", "test": "vitest", "test:run": "vitest run", "type-check": "tsc --noEmit",