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:
mainanddevelopbranches 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
- Create feature branch from release branch.
- Implement changes with atomic commits
- Run
npm run gtg(lint + type-check),npm run test(test) - Create PR with JIRA ticket in title
- Pass automated checks:
- Linting
- Type checking
- E2E tests
- Production build test
- Code review (1-2 approvals)
- 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
- Create release branch for next release from current release
- Update version in package.json, slack
- Run full test suite
- Create release PR
- Deploy to QA environments
- QA validation
- Merge to main
- Tag release
- Deploy to production
Hotfix Process
- Create hotfix branch from main
- Implement fix
- Test thoroughly
- Deploy to QA
- Fast-track to production
- 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