Development Guide

This comprehensive guide covers development best practices, coding standards, and workflows for the HostingCo system.

Development Environment Setup

Prerequisites

Node.js 18+ and npm 8+
PostgreSQL 15+
Redis 7+
Git
VS Code (recommended)

Local Development Setup

1. Clone Repository

git clone https://github.com/your-org/hostingco-system.git
cd hostingco-system

2. Install Dependencies

# Use the automated setup script (recommended)
./scripts/setup.sh development

# Or install manually
npm run install:all

# Or install individually
npm install
cd backend && npm install
cd ../frontend && npm install
cd ../shared && npm install

3. Environment Configuration

# Copy environment template
cp .env.example .env

# Edit environment variables
nano .env

4. Database Setup

# Create database
createdb hostingco_dev

# Run migrations
npm run migrate:latest

# Seed database
npm run seed:dev

Development Workflow

Daily Development

# Start development servers
npm run dev

# Or start individually
npm run dev:backend  # Backend on port 3003
npm run dev:frontend # Frontend on port 3000

Testing Workflow

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

# Run specific test suites
npm run test:unit
npm run test:integration
npm run test:e2e

Building for Production

# Build all packages
npm run build

# Build specific packages
npm run build:frontend
npm run build:backend

# Build for production
npm run build:prod

📝 Coding Standards

TypeScript Configuration

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  }
}

ESLint Configuration

// .eslintrc.json
{
  "extends": [
    "@typescript-eslint/recommended",
    "prettier"
  ],
  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/explicit-function-return-type": "warn",
    "prefer-const": "error",
    "no-var": "error"
  }
}

Code Style Guidelines

Functions: Use arrow functions for callbacks
Variables: Use const by default, let when needed
Classes: Use classes for complex objects
Imports: Use ES6 import/export syntax
Comments: Document complex logic and APIs

📁 Project Structure

Monorepo Organization

hostingco-system/
├── backend/                 # Node.js backend
│   ├── src/
│   │   ├── controllers/      # Route handlers
│   │   ├── middleware/       # Express middleware
│   │   ├── models/          # Database models
│   │   ├── routes/          # API routes
│   │   ├── services/        # Business logic
│   │   └── utils/           # Utility functions
│   ├── tests/               # Backend tests
│   └── package.json
├── frontend/                # React frontend
│   ├── src/
│   │   ├── components/      # React components
│   │   ├── hooks/           # Custom hooks
│   │   ├── pages/           # Page components
│   │   ├── services/        # API services
│   │   ├── utils/           # Utility functions
│   │   └── styles/          # CSS/SCSS files
│   ├── public/              # Static assets
│   └── package.json
├── shared/                  # Shared code
│   ├── src/
│   │   ├── types/           # TypeScript types
│   │   └── utils/           # Shared utilities
│   └── package.json
├── scripts/                 # Automation scripts
├── docs/                    # Documentation
└── package.json            # Root package.json

Package Management

// Root package.json
{
  "private": true,
  "workspaces": [
    "backend",
    "frontend",
    "shared"
  ],
  "scripts": {
    "install:all": "npm install --workspaces",
    "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"",
    "test": "npm run test --workspaces",
    "build": "npm run build --workspaces",
    "clean": "npm run clean --workspaces"
  }
}

Database Development

Migration Workflow

# Create new migration
npm run migrate:create add_user_table

# Run migrations
npm run migrate:latest

# Rollback migration
npm run migrate:rollback

# Check migration status
npm run migrate:status

Database Schema

// Example model
import { knex } from '../database';

export class User {
  static async findById(id: string) {
    return knex('users').where('id', id).first();
  }

  static async create(userData: CreateUserDto) {
    const [user] = await knex('users').insert(userData).returning('*');
    return user;
  }

  static async update(id: string, updates: Partial<User>) {
    return knex('users').where('id', id).update(updates);
  }
}

Seeding Data

# Seed development data
npm run seed:dev

# Seed specific data
npm run seed:users
npm run seed:servers

# Reset and reseed
npm run seed:reset

🔌 API Development

Route Structure

// Example controller
import { Request, Response } from 'express';
import { UserService } from '../services/UserService';

export class UserController {
  static async create(req: Request, res: Response) {
    try {
      const user = await UserService.create(req.body);
      res.status(201).json(user);
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }

  static async getAll(req: Request, res: Response) {
    try {
      const users = await UserService.getAll();
      res.json(users);
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  }
}

Middleware

// Authentication middleware
export const authenticate = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const token = req.headers.authorization?.replace('Bearer ', '');
    const user = await UserService.verifyToken(token);
    req.user = user;
    next();
  } catch (error) {
    res.status(401).json({ error: 'Unauthorized' });
  }
};

Error Handling

// Global error handler
export const errorHandler = (error: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(error);
  
  if (error instanceof ValidationError) {
    return res.status(400).json({ error: error.message });
  }
  
  if (error instanceof AuthenticationError) {
    return res.status(401).json({ error: error.message });
  }
  
  res.status(500).json({ error: 'Internal server error' });
};

⚛️ Frontend Development

Component Structure

// Example component
import React, { useState, useEffect } from 'react';
import { User } from '../types';

interface UserListProps {
  users: User[];
  onUserSelect: (user: User) => void;
}

export const UserList: React.FC<UserListProps> = ({ users, onUserSelect }) => {
  const [selectedUser, setSelectedUser] = useState<User | null>(null);

  return (
    <div className="user-list">
      {users.map(user => (
        <div
          key={user.id}
          className={`user-item ${selectedUser?.id === user.id ? 'selected' : ''}`}
          onClick={() => {
            setSelectedUser(user);
            onUserSelect(user);
          }}
        >
          {user.name}
        </div>
      ))}
    </div>
  );
};

State Management

// Custom hook example
import { useState, useEffect } from 'react';
import { User } from '../types';

export const useUsers = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await fetch('/api/users');
        const data = await response.json();
        setUsers(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  return { users, loading, error };
};

Styling

/* Component-specific styles */
.user-list {
  display: grid;
  gap: 1rem;
  padding: 1rem;
}

.user-item {
  padding: 1rem;
  border: 1px solid var(--border-primary);
  border-radius: var(--border-radius-md);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.user-item:hover {
  background-color: var(--bg-tertiary);
  transform: translateY(-1px);
}

.user-item.selected {
  background-color: var(--primary-color);
  color: var(--text-inverse);
}

Testing Strategy

Test Organization

tests/
├── unit/                   # Unit tests
│   ├── controllers/
│   ├── services/
│   └── utils/
├── integration/            # Integration tests
│   ├── api/
│   └── database/
├── e2e/                    # End-to-end tests
│   ├── user-flows/
│   └── admin-flows/
└── fixtures/               # Test data

Test Examples

// Unit test example
import { UserService } from '../services/UserService';

describe('UserService', () => {
  describe('create', () => {
    it('should create a new user', async () => {
      const userData = {
        email: 'test@example.com',
        name: 'Test User'
      };

      const user = await UserService.create(userData);

      expect(user).toBeDefined();
      expect(user.email).toBe(userData.email);
      expect(user.name).toBe(userData.name);
    });

    it('should throw error for duplicate email', async () => {
      const userData = {
        email: 'existing@example.com',
        name: 'Test User'
      };

      await expect(UserService.create(userData))
        .rejects.toThrow('Email already exists');
    });
  });
});

Test Configuration

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  roots: ['<rootDir>/tests'],
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
  collectCoverageFrom: [
    'src/**/*.ts',
    '!src/**/*.d.ts',
    '!src/index.ts'
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  }
};

🐛 Debugging

Backend Debugging

# Start backend with debugging
npm run dev:debug

# Or with VS Code launch configuration
node --inspect-brk dist/index.js

Frontend Debugging

# Start frontend with debugging
npm run dev:debug

# Or with Chrome DevTools
# Open Chrome DevTools and use the React DevTools extension

VS Code Configuration

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Backend",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/backend/dist/index.js",
      "outFiles": ["${workspaceFolder}/backend/dist/**/*.js"],
      "env": {
        "NODE_ENV": "development"
      }
    },
    {
      "name": "Debug Frontend",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}/frontend/src"
    }
  ]
}