Development Setup
This guide helps you set up your development environment for contributing to ABP React or extending the template for your own projects.
Prerequisites
Before starting development, ensure you have the following tools installed:
Required Tools
-
Node.js (18.0 or higher)
- Download from nodejs.org
- Verify:
node --version
-
pnpm (8.0 or higher)
- Install:
npm install -g pnpm
- Verify:
pnpm --version
- Install:
-
.NET 8 SDK
- Download from dotnet.microsoft.com
- Verify:
dotnet --version
-
Git
- Download from git-scm.com
- Verify:
git --version
Recommended Tools
-
Visual Studio Code with extensions:
- ESLint
- Prettier
- TypeScript and JavaScript Language Features
- Tailwind CSS IntelliSense
- GitLens
- Thunder Client (for API testing)
-
Docker Desktop (for containerized development)
- Download from docker.com
Project Setup
1. Clone the Repository
# Clone the main repository
git clone https://github.com/antosubash/abp-react.git
cd abp-react
# Or clone your fork
git clone https://github.com/YOUR_USERNAME/abp-react.git
cd abp-react
2. Install Dependencies
# Install all dependencies
pnpm install
# Verify installation
pnpm --version
3. Environment Configuration
Create your development environment file:
# Copy the sample environment file
cp .env.sample .env.local
# Edit the environment file
nano .env.local
Configure your environment variables:
# Application
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-super-secret-key-for-development
# API Configuration
NEXT_PUBLIC_API_URL=http://localhost:44300
# Database (if running locally)
DATABASE_URL=postgresql://username:password@localhost:5432/abp_react_dev
# Authentication Providers
NEXT_PUBLIC_AUTH_PROVIDERS=credentials,google,github
# Google OAuth (optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# GitHub OAuth (optional)
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# Feature Flags
NEXT_PUBLIC_ENABLE_ANALYTICS=true
NEXT_PUBLIC_ENABLE_MULTI_TENANCY=true
NEXT_PUBLIC_ENABLE_DEBUG=true
4. Generate API Client
If you have an ABP backend running:
# Generate/update the API client
pnpm generate-client
# Or if you need to specify a different API URL
pnpm generate-client --input https://your-api-url.com/swagger/v1/swagger.json
5. Start Development Server
# Start the development server
pnpm dev
# Or start with debug mode
pnpm dev:debug
Your application should now be running at http://localhost:3000.
Development Workflow
Git Workflow
We follow the Git Flow branching model:
# Create a new feature branch
git checkout -b feature/your-feature-name
# Make your changes
# ... code changes ...
# Stage and commit your changes
git add .
git commit -m "feat: add new feature description"
# Push to your fork
git push origin feature/your-feature-name
# Create a pull request on GitHub
Commit Message Convention
We follow the Conventional Commits specification:
# Feature
git commit -m "feat: add user management component"
# Bug fix
git commit -m "fix: resolve authentication redirect issue"
# Documentation
git commit -m "docs: update API integration guide"
# Style changes
git commit -m "style: improve button component design"
# Refactoring
git commit -m "refactor: simplify user service implementation"
# Performance improvement
git commit -m "perf: optimize image loading"
# Tests
git commit -m "test: add unit tests for user hooks"
# Build/CI
git commit -m "build: update dependencies"
# Breaking change
git commit -m "feat!: redesign authentication flow"
Code Standards
TypeScript Configuration
The project uses strict TypeScript configuration:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true
}
}
ESLint Rules
Key ESLint rules to follow:
// .eslintrc.json
{
"extends": [
"next/core-web-vitals",
"@typescript-eslint/recommended",
"prettier"
],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn",
"prefer-const": "error",
"no-var": "error"
}
}
Prettier Configuration
Code formatting rules:
// prettier.config.js
module.exports = {
semi: true,
trailingComma: 'es5',
singleQuote: true,
printWidth: 100,
tabWidth: 2,
useTabs: false,
};
Component Development
Component Structure
Follow this structure for new components:
// src/components/user/UserProfile.tsx
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { useUser } from '@/hooks/useUser';
import type { User } from '@/client/types.gen';
interface UserProfileProps {
userId: string;
onEdit?: () => void;
}
export const UserProfile: React.FC<UserProfileProps> = ({ userId, onEdit }) => {
const { data: user, isLoading, error } = useUser(userId);
if (isLoading) {
return <div>Loading user profile...</div>;
}
if (error) {
return <div>Error loading user profile</div>;
}
if (!user) {
return <div>User not found</div>;
}
return (
<Card>
<CardHeader>
<CardTitle>{user.name}</CardTitle>
</CardHeader>
<CardContent>
<p>{user.email}</p>
{onEdit && (
<Button onClick={onEdit} variant="outline">
Edit Profile
</Button>
)}
</CardContent>
</Card>
);
};
Custom Hooks
Create reusable custom hooks:
// src/hooks/useUser.ts
import { useQuery } from '@tanstack/react-query';
import { UserService } from '@/client';
export const useUser = (id: string) => {
return useQuery({
queryKey: ['user', id],
queryFn: () => UserService.getUser({ id }),
enabled: !!id,
staleTime: 5 * 60 * 1000, // 5 minutes
});
};
Testing
Testing Setup
The project uses Jest and React Testing Library:
# Install testing dependencies
pnpm add -D jest @testing-library/react @testing-library/jest-dom @testing-library/user-event
# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coverage
Writing Tests
Component Tests
// src/components/user/__tests__/UserProfile.test.tsx
import { render, screen } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { UserProfile } from '../UserProfile';
const mockUser = {
id: '1',
name: 'John Doe',
email: 'john@example.com',
};
const createWrapper = () => {
const queryClient = new QueryClient({
defaultOptions: {
queries: { retry: false },
},
});
return ({ children }: { children: React.ReactNode }) => (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
};
describe('UserProfile', () => {
it('renders user information', async () => {
render(<UserProfile userId="1" />, { wrapper: createWrapper() });
expect(await screen.findByText('John Doe')).toBeInTheDocument();
expect(screen.getByText('john@example.com')).toBeInTheDocument();
});
it('shows edit button when onEdit is provided', () => {
const mockOnEdit = jest.fn();
render(<UserProfile userId="1" onEdit={mockOnEdit} />, { wrapper: createWrapper() });
expect(screen.getByText('Edit Profile')).toBeInTheDocument();
});
});
Hook Tests
// src/hooks/__tests__/useUser.test.ts
import { renderHook, waitFor } from '@testing-library/react';
import { useUser } from '../useUser';
describe('useUser', () => {
it('fetches user data successfully', async () => {
const { result } = renderHook(() => useUser('1'), {
wrapper: createWrapper(),
});
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
expect(result.current.data).toEqual(mockUser);
});
});
Debugging
Development Tools
Browser DevTools
- React DevTools: Install the browser extension for React debugging
- Redux DevTools: For state management debugging (if using Redux)
VS Code Debugging
Create a launch configuration:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/next",
"args": ["dev"],
"cwd": "${workspaceFolder}",
"env": {
"NODE_OPTIONS": "--inspect"
}
},
{
"name": "Next.js: debug client-side",
"type": "pwa-chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}
Common Issues and Solutions
1. Module Resolution Issues
# Clear Next.js cache
rm -rf .next
# Clear node_modules and reinstall
rm -rf node_modules
pnpm install
2. TypeScript Errors
# Regenerate TypeScript types
pnpm generate-client
# Check TypeScript configuration
npx tsc --noEmit
3. API Client Issues
# Verify API URL is accessible
curl https://your-api-url.com/swagger/v1/swagger.json
# Regenerate client with verbose output
pnpm generate-client --verbose
Performance Optimization
Bundle Analysis
Analyze your bundle size:
# Install bundle analyzer
pnpm add -D @next/bundle-analyzer
# Run bundle analysis
pnpm analyze
Code Splitting
Implement code splitting for large components:
// Lazy load components
const UserManagement = lazy(() => import('@/components/user/UserManagement'));
// Use with Suspense
<Suspense fallback={<div>Loading...</div>}>
<UserManagement />
</Suspense>
Image Optimization
Use Next.js Image component:
import Image from 'next/image';
<Image
src="/profile-picture.jpg"
alt="Profile"
width={200}
height={200}
priority
/>
Continuous Integration
GitHub Actions
The project includes GitHub Actions for CI/CD:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: pnpm install
- run: pnpm lint
- run: pnpm test
- run: pnpm build
Pre-commit Hooks
Set up pre-commit hooks with Husky:
# Install Husky
pnpm add -D husky
# Add pre-commit hook
npx husky add .husky/pre-commit "pnpm lint-staged"
Deployment
Production Build
# Build for production
pnpm build
# Start production server
pnpm start
Docker Deployment
# Build Docker image
docker build -t abp-react .
# Run Docker container
docker run -p 3000:3000 abp-react
Environment Variables
Set production environment variables:
NEXTAUTH_URL=https://your-production-domain.com
NEXTAUTH_SECRET=your-production-secret
NEXT_PUBLIC_API_URL=https://your-production-api.com
Contributing Guidelines
Before Contributing
- Check existing issues and pull requests
- Follow the code style and conventions
- Add tests for new features
- Update documentation as needed
- Ensure all tests pass
Pull Request Process
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests and documentation
- Submit a pull request
- Address review feedback
Code Review Checklist
- Code follows project conventions
- Tests are included and passing
- Documentation is updated
- No breaking changes (or properly documented)
- Performance impact is considered
- Security implications are addressed
Getting Help
Resources
- Documentation: ABP React Docs
- GitHub Issues: Report bugs and request features
- Discussions: Community discussions
Community
- Discord: Join our Discord server
- Twitter: @antosubash
- Email: antosubash@outlook.com
Follow these development guidelines to ensure a consistent and high-quality codebase. Happy coding! 🚀