Code Standards & Best Practices
Standards and conventions for Pet Service Management System across backend (NestJS) and frontend (Next.js/React).
TypeScript Strict Mode: All files use strict mode with no implicit any types and null/undefined checking enforced.
TypeScript Conventions
Naming Conventions
Files & Directories
Types & Interfaces
Variables & Constants
Functions & Methods
Use kebab-case for file names: auth.guard.ts, booking.service.ts
Feature directories in lowercase: auth/, bookings/, services/
Components in PascalCase: DashboardHeader.tsx, LanguageSwitcher.tsx
Use PascalCase: User, Booking, Pet, CreateBookingDto
Suffix DTOs with Dto: CreateUserDto, UpdatePetDto
Suffix types with Type if needed: AuthTokenType, PetSpeciesType
Use camelCase for variables: userId, isActive, totalAmount
Use UPPER_SNAKE_CASE for constants: MAX_RETRY_COUNT, API_TIMEOUT
Use UPPER_SNAKE_CASE for enums: BookingStatus, ServiceCategory
Use camelCase: getUserById(), createBooking(), validateEmail()
Use verb prefixes: get, create, update, delete, fetch, process
Async functions should be clear: fetchUserFromDB(), submitBooking()
Type Annotations
DO: Explicit Type Annotations
DON'T: Avoid Implicit Types
const userId : string = user . id ;
const booking : Booking = await bookingService . getById ( id );
function processBooking ( id : string ) : Promise < Booking > { }
/**
* Retrieves a booking by ID with all related data
* @param id - The booking identifier
* @returns The booking or undefined if not found
* @throws NotFoundException if booking doesn't exist
*/
async getBookingById ( id : string ): Promise < Booking > {
// Fetch booking with relations
return this.prisma.booking.findUnique({
where : { id },
include : {
pets : true ,
services : true ,
assignedStaff : true ,
},
});
}
Common Type Patterns
DTOs for API Endpoints
Response Types
Database Model Types
Enum Types
export class CreateBookingDto {
customerId : string ;
petIds : string [];
serviceIds : string [];
startDate : Date ;
notes ?: string ;
}
Backend (NestJS) Standards
Module Organization
src/bookings/
├── dto/
│ ├── create-booking.dto.ts
│ ├── update-booking.dto.ts
│ └── booking-filters.dto.ts
├── bookings.controller.spec.ts
├── bookings.controller.ts
├── bookings.module.ts
├── bookings.service.spec.ts
└── bookings.service.ts
Controllers
import { Controller , Get , Post , Body , Param , UseGuards } from '@nestjs/common' ;
import { AuthGuard } from '../auth/guards/auth.guard' ;
import { BookingsService } from './bookings.service' ;
import { CreateBookingDto } from './dto/create-booking.dto' ;
@ Controller ( 'bookings' )
@ UseGuards ( AuthGuard ) // Protect entire controller
export class BookingsController {
constructor ( private readonly bookingsService : BookingsService ) {}
@ Get ()
async getBookings () {
return this . bookingsService . findAll ();
}
@ Get ( ':id' )
async getBookingById (@ Param ( 'id' ) id : string ) {
return this . bookingsService . findById ( id );
}
@ Post ()
async createBooking (@ Body () createDto : CreateBookingDto ) {
return this . bookingsService . create ( createDto );
}
}
Controller Patterns:
One controller per module
Use decorators: @Controller, @Get, @Post, @Put, @Delete, @Patch
Parameters: @Param, @Body, @Query
Guards for authentication/authorization
Error handling with appropriate HTTP status codes
Services
import { Injectable , NotFoundException } from '@nestjs/common' ;
import { PrismaService } from '../prisma/prisma.service' ;
import { CreateBookingDto } from './dto/create-booking.dto' ;
import { Booking } from '@prisma/client' ;
@ Injectable ()
export class BookingsService {
constructor ( private readonly prisma : PrismaService ) {}
async findAll () : Promise < Booking []> {
return this . prisma . booking . findMany ({
include: {
pets: true ,
services: true ,
assignedStaff: true ,
},
});
}
async findById ( id : string ) : Promise < Booking > {
const booking = await this . prisma . booking . findUnique ({
where: { id },
include: {
pets: true ,
services: true ,
},
});
if ( ! booking ) {
throw new NotFoundException ( `Booking ${ id } not found` );
}
return booking ;
}
async create ( createDto : CreateBookingDto ) : Promise < Booking > {
// Validation
if ( createDto . petIds . length === 0 ) {
throw new BadRequestException ( 'At least one pet is required' );
}
// Business logic
return this . prisma . booking . create ({
data: {
customerId: createDto . customerId ,
startDate: createDto . startDate ,
status: 'PENDING' ,
pets: {
connect: createDto . petIds . map ( id => ({ id })),
},
services: {
connect: createDto . serviceIds . map ( id => ({ id })),
},
},
include: {
pets: true ,
services: true ,
},
});
}
}
Service Patterns:
Inject PrismaService for database access
One responsibility per method
Throw appropriate exceptions
Return typed responses
Use async/await
Include relations in queries
Add business logic validation
Error Handling
import {
BadRequestException ,
NotFoundException ,
UnauthorizedException ,
ConflictException ,
} from '@nestjs/common' ;
// Use appropriate exceptions
if ( ! booking ) {
throw new NotFoundException ( 'Booking not found' );
}
if ( booking . status === 'COMPLETED' ) {
throw new BadRequestException ( 'Cannot update completed booking' );
}
if ( ! hasPermission ( user , 'UPDATE_BOOKING' )) {
throw new UnauthorizedException ( 'Permission denied' );
}
if ( emailExists ) {
throw new ConflictException ( 'Email already registered' );
}
Frontend (React/Next.js) Standards
Component Structure
// components/DashboardHeader.tsx
import React , { FC , ReactNode } from 'react' ;
interface DashboardHeaderProps {
title : string ;
subtitle ?: string ;
actions ?: ReactNode ;
}
/**
* Dashboard header component with title and optional actions
*/
export const DashboardHeader : FC < DashboardHeaderProps > = ({
title ,
subtitle ,
actions ,
}) => {
return (
< div className = "flex justify-between items-center p-6 bg-white border-b" >
< div >
< h1 className = "text-2xl font-bold" > { title } </ h1 >
{ subtitle && < p className = "text-gray-600" > { subtitle } </ p > }
</ div >
{ actions && < div >{ actions }</ div >}
</ div >
);
};
DashboardHeader . displayName = 'DashboardHeader' ;
Page Components
// app/[locale]/dashboard/booking/page.tsx
import { ReactNode } from 'react' ;
import { useTranslations } from 'next-intl' ;
import { DashboardHeader } from '@/components/DashboardHeader' ;
interface BookingPageProps {
params : Promise <{
locale : string ;
}>;
}
export const metadata = {
title: 'Bookings Management' ,
};
export default async function BookingPage ({ params } : BookingPageProps ) {
const { locale } = await params ;
const t = useTranslations ( 'dashboard.booking' );
return (
< div >
< DashboardHeader
title = { t ( 'title' )}
subtitle = { t ( 'subtitle' )}
/>
{ /* Content */ }
</ div >
);
}
API Clients
// lib/api/bookings.ts
import { API_URL } from '@/lib/config' ;
import { Booking , CreateBookingDto } from '@/types/booking' ;
const BASE_URL = ` ${ API_URL } /bookings` ;
export async function getBookings () : Promise < Booking []> {
const response = await fetch ( BASE_URL , {
headers: {
'Authorization' : `Bearer ${ getToken () } ` ,
},
});
if ( ! response . ok ) {
throw new Error ( `Failed to fetch bookings: ${ response . statusText } ` );
}
return response . json ();
}
export async function getBookingById ( id : string ) : Promise < Booking > {
const response = await fetch ( ` ${ BASE_URL } / ${ id } ` , {
headers: {
'Authorization' : `Bearer ${ getToken () } ` ,
},
});
if ( ! response . ok ) {
throw new Error ( 'Booking not found' );
}
return response . json ();
}
export async function createBooking ( data : CreateBookingDto ) : Promise < Booking > {
const response = await fetch ( BASE_URL , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ getToken () } ` ,
},
body: JSON . stringify ( data ),
},);
if ( ! response . ok ) {
throw new Error ( 'Failed to create booking' );
}
return response . json ();
}
Styling Guidelines
Design System Overview
Framework: Tailwind CSS 4 with custom design tokens
Color Palette
Brand Colors (Coral Red)
Background
Border & Dividers
Text Colors
'#FF6B6B' // Primary brand color - buttons, links, accents
'#FF5A5A' // Hover state
'#E24D4D' // Active/pressed state
Component Patterns
Git & Version Control
Commit Conventions
Format: <type>: <subject>
Types:
feat: New feature
fix: Bug fix
refactor: Code refactoring
style: Formatting changes
test: Testing additions
docs: Documentation updates
chore: Build or dependency updates
perf: Performance improvements
Examples:
feat: Add booking status update endpoint
fix: Resolve duplicate booking creation issue
refactor: Extract booking validation logic into separate module
docs: Update README with setup instructions
test: Add unit tests for BookingService
chore: Upgrade NestJS to v11.0.1
Branch Naming
Format: <type>/<short-description>
Examples:
feat/booking-status-workflow
fix/duplicate-pet-creation
refactor/auth-guards
docs/api-documentation
Testing Standards
Unit Tests
Coverage Target: 80% minimum
describe ( 'BookingsService' , () => {
describe ( 'create' , () => {
it ( 'should create a booking with valid data' , async () => {
// Arrange
const createDto : CreateBookingDto = { /* ... */ };
// Act
const result = await service . create ( createDto );
// Assert
expect ( result ). toBeDefined ();
expect ( result . id ). toBeDefined ();
expect ( result . status ). toBe ( 'PENDING' );
});
it ( 'should throw error if no pets provided' , async () => {
// Arrange
const createDto = { ... validDto , petIds: [] };
// Act & Assert
await expect ( service . create ( createDto )). rejects . toThrow (
BadRequestException
);
});
});
});
Backend
API response time: < 300ms (p95)
Database queries with proper indexing
Implement pagination for list endpoints
Use select to avoid unnecessary fields
Connection pooling configured
Frontend
Lazy load components and routes
Image optimization with Next.js Image component
CSS-in-JS: Minimal runtime overhead
Code splitting by route
Minimize bundle size
Security Standards
Backend
HTTPS/TLS enforced in production
CORS configured for specific origins
Rate limiting on auth endpoints
SQL injection prevention via ORM
Password hashing with bcrypt
Secure session management
Frontend
CSP headers
XSS prevention through React escaping
CSRF tokens for state-changing operations
No sensitive data in localStorage
Secure cookie attributes (HttpOnly, Secure)
Accessibility Standards
WCAG 2.1 AA Compliance
Semantic HTML elements
ARIA labels for interactive components
Color contrast ratios 4.5:1 minimum
Keyboard navigation support
Form labels and error messages
Screen reader compatibility