Project Best Practices
When creating or scaffolding a new project, follow these guidelines.
Project Initialization
- •Always start with a package manager lockfile — run
npm init -y(orpnpm init) then install dependencies to generate a lockfile immediately. - •Use TypeScript by default — unless the user explicitly asks for JavaScript. Configure
strict: trueintsconfig.json. - •Add a
.gitignorefrom the start — includenode_modules/,dist/,.env, coverage reports, OS files. - •Initialize git —
git initwith an initial commit after scaffolding. - •Create a README.md — with project name, description, setup instructions, and available scripts.
Directory Structure
Follow a standard layout based on project type:
Node.js / Backend
code
src/ index.ts # Entry point routes/ # HTTP route handlers services/ # Business logic models/ # Data models / schemas utils/ # Shared utilities middleware/ # Express/Fastify middleware types/ # TypeScript type definitions tests/ # Test files mirroring src/ .env.example # Environment variable template (never commit .env)
Frontend (React/Vue/Svelte)
code
src/ components/ # Reusable UI components pages/ # Route-level views hooks/ # Custom hooks services/ # API client / business logic utils/ # Helpers types/ # TypeScript types assets/ # Static files (images, fonts) public/ # Public static assets
Library / Package
code
src/ index.ts # Public API exports lib/ # Internal implementation types/ # Type definitions tests/ examples/ # Usage examples
Code Quality
- •Linter — Add ESLint with a flat config (
eslint.config.js). Prefer@typescript-eslintrules. - •Formatter — Add Prettier with consistent config (single quotes, semicolons, 2-space indent).
- •Pre-commit hooks — Use
husky+lint-stagedto run lint/format on commit. - •EditorConfig — Add
.editorconfigfor consistent formatting across editors.
Testing
- •Test framework — Use Jest (with
ts-jest) or Vitest. Configure inpackage.jsonor dedicated config file. - •Test structure — Mirror
src/intests/. Name files*.test.tsor*.spec.ts. - •Coverage — Configure coverage reporting. Aim for 80%+ on critical paths.
- •Scripts — Add
npm test,npm run test:watch,npm run test:coverage.
Dependencies
- •Pin versions — Use exact versions or lockfiles for reproducibility.
- •Separate dev dependencies —
devDependenciesfor tools,dependenciesfor runtime. - •Minimize dependencies — Prefer built-in Node.js APIs (fs, path, crypto, http) over trivial packages.
- •Audit regularly — Run
npm auditto check for vulnerabilities.
Environment & Configuration
- •Use
.envfiles — withdotenvor framework-native support. Never commit secrets. - •Provide
.env.example— document all required environment variables with descriptions. - •Validate config at startup — fail fast if required variables are missing.
Scripts (package.json)
Always include these npm scripts:
json
{
"dev": "tsx src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"typecheck": "tsc --noEmit",
"validate": "npm run lint && npm run typecheck && npm test"
}
Security
- •Never hardcode secrets — use environment variables.
- •Validate all user input — at system boundaries (API endpoints, CLI args).
- •Use parameterized queries — never concatenate SQL strings.
- •Set security headers —
helmetfor Express, built-in for Fastify. - •CORS — configure explicitly, never use
*in production.
Commit Conventions
Use Conventional Commits:
- •
feat(scope): description— new feature - •
fix(scope): description— bug fix - •
docs: description— documentation - •
test: description— adding tests - •
refactor: description— code restructure - •
chore: description— tooling, deps, config