Skip to content

Development Workflow

Learn the recommended development workflow for the TypeScript Project Template.

Overview

The template provides multiple development approaches optimized for different scenarios:

  1. Fast Development with tsx (recommended)
  2. Watch Mode for continuous development
  3. Traditional build-and-run approach

Quick Development Cycle

1. Start Development

bash
# Fastest option - direct TypeScript execution
npm run dev:tsx

Benefits:

  • No compilation step required
  • Instant startup
  • Direct TypeScript execution
  • Perfect for rapid iteration

2. Make Changes

Edit files in src/ directory:

  • src/index.ts - Main application logic
  • src/utils.ts - Utility functions
  • src/validation.ts - Zod validation schemas
  • src/logger.ts - Winston logging configuration
  • src/config.ts - Configuration management
  • Add new files as needed

Best Practices:

  • Use validation for all external data
  • Use structured logging instead of console.log
  • Load configuration through ConfigManager
  • Write tests for validation logic

3. Run Quality Checks

bash
# Comprehensive quality gates
npm run check

This runs:

  • ESLint (linting)
  • Prettier (formatting check)
  • Jest (testing)
  • TypeScript (compilation check)

4. Auto-Fix Issues

bash
# Fix formatting and auto-fixable linting issues
npm run fix

Development Modes

bash
# Direct TypeScript execution with tsx
npm run dev:tsx

When to use:

  • Rapid prototyping
  • Quick testing of changes
  • Development iteration
  • Learning the template

Advantages:

  • Fastest startup time
  • No build step
  • Immediate feedback
  • Simple workflow

Watch Mode Development

bash
# Auto-restart on file changes
npm run dev:watch

When to use:

  • Long development sessions
  • Continuous testing
  • File watching needed
  • Automated restart preferred

Features:

  • Automatic restart on changes
  • Continuous monitoring
  • Background execution
  • Development server simulation

Traditional Development

bash
# Build then run
npm run dev

# Or step by step
npm run build
npm start

When to use:

  • Production-like testing
  • Build verification
  • Distribution preparation
  • CI/CD simulation

Process:

  1. TypeScript compilation
  2. Output to dist/ directory
  3. Execute compiled JavaScript
  4. Full build verification

Quality Assurance Workflow

Continuous Quality Checks

Run quality checks frequently during development:

bash
# Quick check during development
npm run lint

# Format check
npm run format:check

# Run tests
npm test

# Full quality gate
npm run check

Pre-Commit Workflow

Before committing changes:

bash
# 1. Auto-fix issues
npm run fix

# 2. Run comprehensive checks
npm run check

# 3. Build verification
npm run build

# 4. Commit if all pass
git add .
git commit -m "feat: add new feature"

Testing Workflow

Running Tests

bash
# Run all tests
npm test

# Watch mode for development
npm run test:watch

# Coverage report
npm run test:coverage

# CI mode (no watch)
npm run test:ci

Writing Tests

  1. Create test file in __tests__/ directory
  2. Mirror source structure (src/utils.ts__tests__/utils.test.ts)
  3. Follow naming convention (*.test.ts)
  4. Include test categories:
    • Expected use cases
    • Edge cases
    • Error conditions

Test Example

typescript
import { jest } from '@jest/globals';
import { myFunction } from '../src/utils.js';
import { validateUserInput } from '../src/validation.js';

// Mock logger for testing
jest.mock('../src/logger.js', () => ({
  logger: {
    error: jest.fn(),
    warn: jest.fn(),
    info: jest.fn(),
    debug: jest.fn()
  }
}));

describe('myFunction', () => {
  it('should handle normal input', () => {
    const result = myFunction('test');
    expect(result).toBe('expected');
  });

  it('should handle edge case', () => {
    const result = myFunction('');
    expect(result).toBe('default');
  });

  it('should throw on invalid input', () => {
    expect(() => myFunction(null)).toThrow();
  });
});

describe('validation', () => {
  it('should validate correct user input', () => {
    const result = validateUserInput({
      name: 'John Doe',
      email: 'john@example.com',
      age: 30
    });

    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.name).toBe('John Doe');
    }
  });

  it('should reject invalid email', () => {
    const result = validateUserInput({
      name: 'John Doe',
      email: 'invalid-email',
      age: 30
    });

    expect(result.success).toBe(false);
  });
});

Validation and Logging Workflow

Adding Input Validation

When adding new features that handle external data:

bash
# 1. Define validation schema in src/validation.ts
# 2. Create validation function
# 3. Add tests for validation
# 4. Use validation in your code

Example workflow:

typescript
// 1. Add schema to src/validation.ts
const NewFeatureSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1),
  value: z.number().positive()
});

// 2. Create validation function
export function validateNewFeature(data: unknown) {
  try {
    const validated = NewFeatureSchema.parse(data);
    return { success: true, data: validated };
  } catch (error) {
    if (error instanceof z.ZodError) {
      const validationError = new ValidationError('Validation failed', error.issues);
      return { success: false, error: validationError.getFormattedMessage() };
    }
    return { success: false, error: 'Unknown validation error' };
  }
}

// 3. Use in your application
const result = validateNewFeature(inputData);
if (result.success) {
  // Use validated data with full TypeScript typing
  processFeature(result.data);
} else {
  logger.error('Validation failed', { error: result.error });
  throw new Error(`Invalid input: ${result.error}`);
}

Logging Best Practices

Replace console.log with structured logging:

typescript
// ❌ Don't use console.log
console.log('User logged in:', userId);
console.error('Error occurred:', error.message);

// ✅ Use structured logging
logger.info('User logged in', { userId, timestamp: new Date() });
logger.error('Operation failed', {
  error: { message: error.message, stack: error.stack },
  operation: 'userLogin',
  userId
});

// ✅ Use utility functions for common patterns
loggerUtils.logValidationSuccess(logger, 'Input validated', validatedData);
loggerUtils.logSectionHeader(logger, 'Processing Phase');
loggerUtils.logCompletion(logger, 'Operation completed successfully');

Configuration Management

Use ConfigManager for all configuration:

typescript
// ❌ Don't hardcode configuration
const port = 3000;
const logLevel = 'info';

// ✅ Use ConfigManager
const configManager = new ConfigManager();
const result = configManager.loadConfig();

if (result.success) {
  const serverConfig = configManager.getServerConfig();
  const logger = createLoggerFromConfig(configManager.getLoggingConfig());

  // Use feature flags
  if (configManager.isFeatureEnabled('enableMetrics')) {
    setupMetrics();
  }
}

Documentation Workflow

Local Documentation Development

bash
# Start documentation server
npm run docs:dev

Features:

  • Hot reload on changes
  • Live preview
  • Search functionality
  • Mobile responsive

Adding Documentation

  1. Create markdown files in appropriate docs/ subdirectory
  2. Update sidebar in docs/.vitepress/config.ts
  3. Add cross-references from related pages
  4. Test locally before committing

Documentation Structure

docs/
├── getting-started/    # User onboarding
├── development/        # Development guides
├── configuration/      # Setup and config
├── api/               # API reference
└── deployment/        # Deployment guides

Build and Deployment

Local Build

bash
# Build TypeScript
npm run build

# Build documentation
npm run docs:build

# Preview documentation
npm run docs:preview

Production Verification

bash
# Full production simulation
npm run clean
npm run build
npm start

# Documentation build test
npm run docs:build
npm run docs:preview

Troubleshooting

Common Issues

TypeScript Compilation Errors

bash
# Clear TypeScript cache
rm -rf dist/
npm run build

Jest Test Failures

bash
# Clear Jest cache
npm test -- --clearCache
npm test

ESLint Configuration Issues

bash
# Check ESLint configuration
npx eslint --print-config src/index.ts

# Fix auto-fixable issues
npm run lint:fix

Prettier Formatting Issues

bash
# Check what files need formatting
npm run format:check

# Auto-format all files
npm run format

Performance Optimization

Faster Development

  1. Use tsx for development (npm run dev:tsx)
  2. Skip type checking during rapid iteration
  3. Use watch mode for continuous development
  4. Run tests selectively during development

Faster Builds

  1. Incremental compilation with TypeScript
  2. Parallel testing with Jest
  3. Cache optimization in CI/CD
  4. Selective quality checks during development

IDE Integration

VS Code Setup

Recommended extensions:

  • TypeScript and JavaScript Language Features
  • ESLint
  • Prettier - Code formatter
  • Jest
  • GitLens

Settings

json
{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "eslint.validate": ["typescript"],
  "typescript.preferences.importModuleSpecifier": "relative"
}

Git Workflow

Branch Strategy

bash
# Feature development
git checkout -b feature/new-feature
# ... make changes ...
npm run check
git commit -m "feat: add new feature"

# Bug fixes
git checkout -b fix/bug-description
# ... make changes ...
npm run check
git commit -m "fix: resolve issue with X"

Commit Message Format

Follow conventional commits:

  • feat: - New features
  • fix: - Bug fixes
  • docs: - Documentation updates
  • refactor: - Code refactoring
  • test: - Test additions/updates
  • chore: - Maintenance tasks

Next Steps

Released under the MIT License.