Overview
TailStack uses a PNPM workspace-based monorepo structure that enables efficient development across multiple packages. This guide covers the essential workflows for daily development.
Running Development Servers
The Core package (full-stack monorepo) includes a unified dev command that runs both frontend and backend simultaneously.
Start All Services
From the packages/core directory:
This command uses Concurrently to run multiple dev servers in parallel:
{
"scripts" : {
"dev" : "concurrently \" pnpm --filter ./source/frontend dev \" \" pnpm --filter ./source/Server dev \" "
}
}
What happens:
Frontend (Vite) starts on http://localhost:5173
Backend (Express) starts on http://localhost:3000
Both output logs to the same terminal with color-coded prefixes
Hot Reload: Both frontend and backend support hot module replacement (HMR). Changes are reflected immediately without restarting servers.
Start Individual Services
Frontend Only
Backend Only
pnpm --filter ./source/frontend dev
Starts only the React frontend with Vite. pnpm --filter ./source/Server dev
Starts only the Express backend with Nodemon.
Development URLs
Service URL Description Frontend http://localhost:5173React app with Vite HMR Backend http://localhost:3000Express API server Backend Health http://localhost:3000/healthAPI health check endpoint
PNPM Workspace Commands
TailStack’s monorepo structure uses PNPM workspaces for package management. Understanding workspace commands is essential for efficient development.
Filtering Packages
Run command in specific package:
pnpm --filter < package-nam e > < comman d >
Examples:
# Install dependencies for frontend only
pnpm --filter ./source/frontend install
# Build backend only
pnpm --filter ./source/Server build
# Add dependency to specific package
pnpm --filter ./source/frontend add axios
Running Commands Across Workspace
Run command in all packages:
Examples:
# Run build in all packages
pnpm -r build
# Run tests in all packages
pnpm -r test
# Clean all packages
pnpm -r clean
Installing Dependencies
This installs dependencies for all packages in the workspace.
Add dependency to a specific package:
# Add to frontend
pnpm --filter ./source/frontend add react-query
# Add dev dependency to backend
pnpm --filter ./source/Server add -D jest
# Add dependency to root (affects all packages)
pnpm add -w husky
# Update all packages
pnpm update -r
# Update specific package
pnpm --filter ./source/frontend update
Useful PNPM Commands
# List all workspace packages
pnpm list -r --depth 0
# Check for outdated packages
pnpm outdated -r
# Why is a package installed?
pnpm why < package-nam e >
# Remove package from workspace
pnpm --filter < package-nam e > remove < dependenc y >
# Rebuild all node_modules
pnpm install --force
Workspace Flag: Use -w flag when installing root-level dependencies (like Husky, ESLint configs). Without it, PNPM will show an error.
Git Workflow
TailStack enforces strict commit standards using Commitlint and Husky .
All commits must follow Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>
Type must be one of:
feat - New feature
fix - Bug fix
docs - Documentation changes
style - Code style changes (formatting, semicolons, etc.)
refactor - Code refactoring
perf - Performance improvements
test - Adding or updating tests
build - Build system changes
ci - CI configuration changes
chore - Other changes (dependencies, configs)
revert - Revert previous commit
Commit Examples
Good Commits
Bad Commits (Will Fail)
# Feature with scope
git commit -m "feat(auth): add JWT authentication middleware"
# Bug fix with detailed body
git commit -m "fix(api): resolve memory leak in WebSocket connections
The WebSocket connections were not properly closed on client disconnect,
causing memory accumulation over time.
Fixes #123"
# Breaking change
git commit -m "feat(api): migrate to REST API v2
BREAKING CHANGE: API endpoints now require /v2/ prefix"
Commit Limits
Configured in commitlint.config.cjs:
modules . exports = {
extends: [ '@commitlint/config-conventional' ],
rules: {
'header-max-length' : [ 2 , 'always' , 150 ],
'body-max-line-length' : [ 2 , 'always' , 250 ],
},
};
Header: Maximum 150 characters
Body lines: Maximum 250 characters each
Pre-commit Checks
Every commit triggers automated checks:
git commit -m "feat(api): add user endpoint"
The .husky/pre-commit hook automatically executes:
🔍 Running pre-commit security checks...
pnpm lint-staged
Gitleaks scans staged files for secrets
If secrets detected, commit is blocked
Sensitive data is automatically redacted in output
Commit Message Validation
The .husky/commit-msg hook validates your commit message:
✔ Commit message meets Conventional Commits standards
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
Quick Tip: If you need to bypass hooks temporarily (NOT recommended), use:git commit --no-verify -m "emergency fix"
Only use this in genuine emergencies!
Branch Workflow
Recommended branching strategy:
# Create feature branch
git checkout -b feat/user-authentication
# Make changes and commit
git add .
git commit -m "feat(auth): implement JWT tokens"
# Push to remote
git push origin feat/user-authentication
# Create pull request
gh pr create --title "Add user authentication" --body "Implements JWT-based auth"
Building for Production
Build All Packages
# From root
pnpm -r build
Build Specific Package
# Build frontend
pnpm --filter ./source/frontend build
# Build backend
pnpm --filter ./source/Server build
Build Output
Frontend: Built to source/frontend/dist/
Backend: Built to source/Server/dist/ (if using TypeScript compilation)
Testing
Run Tests
# Run all tests
pnpm -r test
# Run tests for specific package
pnpm --filter ./source/frontend test
# Run tests in watch mode
pnpm --filter ./source/frontend test:watch
Test Coverage
# Generate coverage report
pnpm -r test:coverage
Environment Variables
Frontend Environment
Create .env in source/frontend/:
VITE_API_URL = http://localhost:3000
VITE_APP_TITLE = TailStack App
Access in code:
const apiUrl = import . meta . env . VITE_API_URL ;
Backend Environment
Create .env in source/Server/:
PORT = 3000
NODE_ENV = development
DATABASE_URL = postgresql://localhost:5432/mydb
JWT_SECRET = your-secret-key
Access in code:
const port = process . env . PORT || 3000 ;
Security: Never commit .env files to Git. They’re included in .gitignore by default. Use .env.example as a template.
Debugging
Frontend Debugging
VS Code Launch Configuration:
{
"type" : "chrome" ,
"request" : "launch" ,
"name" : "Debug Frontend" ,
"url" : "http://localhost:5173" ,
"webRoot" : "${workspaceFolder}/source/frontend"
}
Backend Debugging
VS Code Launch Configuration:
{
"type" : "node" ,
"request" : "launch" ,
"name" : "Debug Backend" ,
"runtimeExecutable" : "pnpm" ,
"runtimeArgs" : [ "--filter" , "./source/Server" , "dev" ],
"skipFiles" : [ "<node_internals>/**" ],
"console" : "integratedTerminal"
}
Common Workflows
Adding a New Feature
git checkout -b feat/new-feature
Edit code in frontend and/or backend.
pnpm dev # Verify changes work
git add .
git commit -m "feat(feature): add new feature implementation"
git push origin feat/new-feature
gh pr create
Updating Dependencies
Update Specific Dependency
pnpm --filter < packag e > update < dependenc y >
git commit -m "chore(deps): update dependencies to latest versions"
Fixing Build Errors
Faster Installations
# Use TailStack's parallel install script
./scripts/install.sh # 2x faster than standard install
# Skip optional dependencies
pnpm install --no-optional
# Use frozen lockfile (CI/CD)
pnpm install --frozen-lockfile
Faster Builds
# Build in parallel (default with -r flag)
pnpm -r build
# Build only changed packages (requires Turborepo)
pnpm build --filter=...^HEAD
Reduce Context Switching
# Run everything from root
pnpm dev # from packages/core
pnpm -r test # from root
pnpm -r build # from root
Troubleshooting
Port Already in Use
# Find process using port 3000
lsof -i :3000
# Kill process
kill -9 < PI D >
# Or change port in .env
PORT = 3001 pnpm dev
PNPM Link Issues
# Rebuild node_modules
pnpm install --force
# Or use clean script
./scripts/clean.sh
./scripts/install.sh
Git Hooks Not Working
# Reinstall Husky
pnpm husky
# Make hooks executable (Unix)
chmod +x .husky/ *
Next Steps