Skip to main content

Development Workflow & Best Practices

Git Workflow

⚠️ IMPORTANT: Non-Standard Branching in Use

The branching strategy shown below represents the ideal state we are transitioning towards. Currently:

  • main and develop branches are NOT actively used
  • We work directly from release branches (e.g., release/v1.38.0)
  • Hotfixes are created from the current release branch, NOT from main
  • Active discussions are underway to migrate to standard trunk-based development or GitFlow

Current Reality: Feature branches are created from release branches, and we deploy from release branches.

Branch Strategy (Target State)

main
├── develop
│ ├── release/v1.38.0
│ ├── release/v1.39.0
│ └── feature/DEV-XXXX-description
└── hotfix/v1.38.1

Branch Naming Convention

  • Feature: DEV-[JIRA-ID]-brief-description
  • Bugfix: DEV-[JIRA-ID]-fix-description
  • Release: release/v[MAJOR].[MINOR].[PATCH]
  • Hotfix: hotfix/v[MAJOR].[MINOR].[PATCH]

PR Process

  1. Create feature branch from release branch.
  2. Implement changes with atomic commits
  3. Run npm run gtg (lint + type-check), npm run test (test)
  4. Create PR with JIRA ticket in title
  5. Pass automated checks:
    • Linting
    • Type checking
    • E2E tests
    • Production build test
  6. Code review (1-2 approvals)
  7. Merge to develop

Development Commands

Essential Commands

# Development
npm run dev # Start dev server
npm run fast # Turbo dev mode (faster)

# Code Quality
npm run lint # Run ESLint
npm run lint:fix # Auto-fix linting issues
npm run format:write # Format code with Prettier
npm run type-check # TypeScript type checking
npm run gtg # "Good to go" - lint + type-check

# Testing
npm test # Run unit tests
npm test -- -t "test name" # Run specific test
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
npm run test:e2e # End-to-end tests

# Building
npm run build # Production build
npm run analyze # Bundle analysis

Project Structure

chatbot-ui/
├── app/ # Next.js App Router
│ ├── (dashboard)/ # Authenticated routes
│ ├── api/ # API endpoints
│ ├── auth/ # Authentication
│ └── components/ # Page components
├── components/ # Reusable components
├── lib/ # Utilities & helpers
├── hooks/ # Custom React hooks
├── types/ # TypeScript types
├── supabase/ # Database migrations
├── public/ # Static assets
└── tests/ # Test files

Coding Standards

TypeScript Guidelines

// Good - Strong typing
interface UserProps {
id: string;
name: string;
email: string;
isActive: boolean;
}

// Bad - Avoid any
const processUser = (user: any) => {
// ...
}

// Good - RORO pattern
interface CreateUserParams {
name: string;
email: string;
}

interface CreateUserResult {
user: User;
token: string;
}

async function createUser(params: CreateUserParams): Promise<CreateUserResult> {
// ...
}

React Component Patterns

// Good - Functional component with named export
export function UserCard({ user, onEdit }: UserCardProps) {
const [isLoading, setIsLoading] = useState(false);

return (
<Card>
<CardHeader>
<CardTitle>{user.name}</CardTitle>
</CardHeader>
{/* ... */}
</Card>
);
}

// Bad - Class components
class UserCard extends React.Component {
// Avoid OOP patterns
}

File Organization

// user-card.tsx (max 150 lines)
import { useState } from 'react';
import { Card } from '@/components/ui/card';
import { useUser } from '@/hooks/use-user';
import type { User } from '@/types';

interface UserCardProps {
user: User;
onEdit: (user: User) => void;
}

export function UserCard({ user, onEdit }: UserCardProps) {
// Component logic
}

// If file exceeds 150 lines, refactor:
// user-card/
// ├── index.tsx
// ├── user-card-header.tsx
// ├── user-card-body.tsx
// └── user-card.types.ts

Testing Strategy

Unit Testing

// user.test.ts
import { render, screen } from '@testing-library/react';
import { UserCard } from './user-card';

describe('UserCard', () => {
it('displays user name', () => {
const user = { id: '1', name: 'John Doe', email: 'john@example.com' };
render(<UserCard user={user} onEdit={jest.fn()} />);

expect(screen.getByText('John Doe')).toBeInTheDocument();
});
});

E2E Testing

// e2e/user-flow.spec.ts
import { test, expect } from '@playwright/test';

test('user can create and edit profile', async ({ page }) => {
await page.goto('/profile');
await page.fill('[name="name"]', 'John Doe');
await page.click('button[type="submit"]');

await expect(page.locator('.success-message')).toBeVisible();
});

Deployment Process

Environment Promotion

Local → Feature Branch → Develop → QA → Staging → Production

Release Process

  1. Create release branch for next release from current release
  2. Update version in package.json, slack
  3. Run full test suite
  4. Create release PR
  5. Deploy to QA environments
  6. QA validation
  7. Merge to main
  8. Tag release
  9. Deploy to production

Hotfix Process

  1. Create hotfix branch from main
  2. Implement fix
  3. Test thoroughly
  4. Deploy to QA
  5. Fast-track to production
  6. Backport to release branch

Debugging & Troubleshooting

Common Issues & Solutions

1. Type Errors

# Clear TypeScript cache
rm -rf node_modules/.cache
npm run type-check

2. Build Failures

# Clean build
rm -rf .next
npm run build

3. Dependency Issues

# Clean install
rm -rf node_modules package-lock.json
npm install

Debugging Tools

  • React DevTools: Component inspection
  • Redux DevTools: State debugging (for Zustand)
  • Network Tab: API debugging
  • Sentry: Error tracking in production

Documentation Standards

Code Comments

// Good - Explains why, not what
// Cache user data for 5 minutes to reduce API calls
// while maintaining reasonable data freshness
const CACHE_TTL = 5 * 60 * 1000;

// Bad - Obvious comment
// Set loading to true
setIsLoading(true);

Function Documentation

/**
* Creates a new user in the system
* @param params - User creation parameters
* @returns Created user and authentication token
* @throws {ValidationError} If email is invalid
* @throws {ConflictError} If email already exists
*/
async function createUser(params: CreateUserParams): Promise<CreateUserResult> {
// Implementation
}

Best Practices Checklist

Before Committing

  • Code passes npm run gtg
  • Tests are written and passing
  • No console.logs in production code
  • Sensitive data is not exposed
  • File sizes under 150 lines
  • TypeScript types are explicit (no any)
  • Component follows naming conventions

Before Creating PR

  • Branch is up to date with develop
  • Commits are atomic and well-described
  • PR description includes JIRA ticket
  • Screenshots included for UI changes
  • Breaking changes are documented
  • Performance impact considered

Code Review Checklist

  • Logic is correct and efficient
  • Edge cases are handled
  • Security implications considered
  • Code follows team standards
  • Tests provide good coverage
  • Documentation is updated