This guide covers everything you need to install and configure the WhatsApp Chat application, from initial setup to understanding the complete dependency tree.
System requirements
Before installing, verify your system meets these requirements:
Node.js 20.0.0 or higher
npm 10+ / yarn 1.22+ / pnpm 8+
Operating system : macOS, Windows, or Linux
Memory : 4GB RAM minimum (8GB recommended)
Disk space : 500MB for dependencies
Quick installation
Get started in three commands:
Clone or create project
If starting fresh, create a new directory: mkdir whatsapp-chat
cd whatsapp-chat
Install dependencies
Choose your package manager: This installs all packages defined in package.json.
Package overview
The application uses these core dependencies:
Framework & runtime
{
"dependencies" : {
"next" : "15.5.4" ,
"react" : "19.1.0" ,
"react-dom" : "19.1.0"
}
}
Next.js 15 – React framework with App Router, Server Components, and Turbopack
React 19 – Latest React with improved hooks and concurrent features
React DOM 19 – React renderer for web browsers
State management
{
"dependencies" : {
"zustand" : "^5.0.8"
}
}
Zustand – Lightweight state management with localStorage persistence
Used for managing chats, messages, contacts, drafts, and typing indicators:
import { create } from 'zustand'
import { persist , createJSONStorage } from 'zustand/middleware'
const useChatStore = create < ChatStore >()( persist (
( set , get ) => ({
chats: {},
messages: {},
contacts: {},
sendMessage : ( chatId , payload ) => { /* ... */ },
}),
{
name: 'chat-store' ,
storage: createJSONStorage (() => localStorage )
}
))
UI components
{
"dependencies" : {
"@radix-ui/react-avatar" : "^1.1.10" ,
"@radix-ui/react-dialog" : "^1.1.15" ,
"@radix-ui/react-dropdown-menu" : "^2.1.16" ,
"@radix-ui/react-popover" : "^1.1.15" ,
"@radix-ui/react-scroll-area" : "^1.2.10" ,
"@radix-ui/react-separator" : "^1.1.7" ,
"@radix-ui/react-slot" : "^1.2.3" ,
"@radix-ui/react-tooltip" : "^1.2.8"
}
}
Radix UI – Unstyled, accessible component primitives
All components follow WAI-ARIA patterns for keyboard navigation and screen readers
{
"dependencies" : {
"@phosphor-icons/react" : "^2.1.10" ,
"@emoji-mart/react" : "^1.1.1" ,
"@emoji-mart/data" : "^1.2.1" ,
"lucide-react" : "^0.544.0"
}
}
Phosphor Icons – Primary icon set with 6,000+ icons
Emoji Mart – Emoji picker with search and categories
Lucide React – Additional icon alternatives
Example usage:
import { PaperPlaneTilt , Paperclip , Smiley } from '@phosphor-icons/react'
< Button >
< PaperPlaneTilt className = "h-5 w-5" weight = "fill" />
Send
</ Button >
File handling
{
"dependencies" : {
"react-dropzone" : "^14.3.8"
}
}
react-dropzone – Drag-and-drop file uploads with validation
Implemented in the message composer:
import { useDropzone } from 'react-dropzone'
const { getRootProps , getInputProps , isDragActive } = useDropzone ({
onDrop : ( files ) => {
const media = files . map ( file => ({
id: `upload- ${ file . name } ` ,
type: 'image' ,
url: URL . createObjectURL ( file ),
sizeInBytes: file . size
}))
setAttachments ( prev => [ ... prev , ... media ])
},
accept: { 'image/*' : [] },
multiple: true
})
{
"dependencies" : {
"date-fns" : "^4.1.0"
}
}
date-fns – Modern date utility library
Used for message timestamps and activity formatting:
import { format , formatDistanceToNow , isToday } from 'date-fns'
const timeLabel = format ( new Date ( message . createdAt ), 'HH:mm' )
const lastSeen = formatDistanceToNow ( new Date ( contact . lastSeenAt ), {
addSuffix: true
})
Styling
{
"dependencies" : {
"tailwindcss" : "^4" ,
"class-variance-authority" : "^0.7.1" ,
"tailwind-merge" : "^3.3.1" ,
"clsx" : "^2.1.1"
},
"devDependencies" : {
"@tailwindcss/postcss" : "^4" ,
"tw-animate-css" : "^1.4.0"
}
}
Tailwind CSS v4 – Utility-first CSS framework with custom theming
CVA – Component variant utilities
tailwind-merge – Merge Tailwind classes without conflicts
clsx – Conditional className builder
The app uses custom color tokens for WhatsApp-like theming:
:root {
--bubble-outgoing : oklch ( 0.92 0.04 145 );
--bubble-incoming : oklch ( 0.995 0.015 95 );
--status-sent : oklch ( 0.65 0.02 140 );
--status-delivered : oklch ( 0.55 0.18 145 );
--status-read : oklch ( 0.6 0.2 210 );
--sidebar : oklch ( 0.992 0.004 140 );
}
{
"dependencies" : {
"react-hook-form" : "^7.63.0" ,
"@hookform/resolvers" : "^5.2.2" ,
"zod" : "^4.1.11"
}
}
React Hook Form – Performant form state management
Zod – TypeScript-first schema validation
Additional UI utilities
{
"dependencies" : {
"react-virtuoso" : "^4.14.1" ,
"react-resizable-panels" : "^3.0.6" ,
"sonner" : "^2.0.7" ,
"vaul" : "^1.1.2"
}
}
react-virtuoso – Virtual scrolling for large message lists
react-resizable-panels – Resizable split layouts
sonner – Toast notifications
vaul – Drawer/bottom sheet component
Configuration files
TypeScript configuration
The project uses strict TypeScript with path aliases:
{
"compilerOptions" : {
"target" : "ES2017" ,
"lib" : [ "dom" , "dom.iterable" , "esnext" ],
"allowJs" : true ,
"skipLibCheck" : true ,
"strict" : true ,
"noEmit" : true ,
"esModuleInterop" : true ,
"module" : "esnext" ,
"moduleResolution" : "bundler" ,
"resolveJsonModule" : true ,
"isolatedModules" : true ,
"jsx" : "preserve" ,
"incremental" : true ,
"paths" : {
"@/*" : [ "./*" ]
}
},
"include" : [ "next-env.d.ts" , "**/*.ts" , "**/*.tsx" ],
"exclude" : [ "node_modules" ]
}
Path aliases allow clean imports:
import { useChatStore } from '@/lib/chat/state'
import { ChatApp } from '@/components/chat/chat-app'
import { Button } from '@/components/ui/button'
Next.js configuration
import type { NextConfig } from "next" ;
const nextConfig : NextConfig = {
// Configuration options
};
export default nextConfig ;
Component library setup
The project uses shadcn/ui component patterns:
{
"$schema" : "https://ui.shadcn.com/schema.json" ,
"style" : "default" ,
"rsc" : true ,
"tsx" : true ,
"tailwind" : {
"config" : "tailwind.config.ts" ,
"css" : "app/globals.css" ,
"baseColor" : "slate" ,
"cssVariables" : true
},
"aliases" : {
"components" : "@/components" ,
"utils" : "@/lib/utils"
}
}
Build commands
Available npm scripts:
Development
Starts the Next.js development server with Turbopack for fast refresh. Hot Module Replacement (HMR) automatically updates the browser when you edit files.
Production build
Creates an optimized production build with:
Static page generation for better performance
Tree shaking to remove unused code
Code splitting for smaller bundle sizes
Image optimization
Production server
Serves the production build. Run npm run build first.
Linting
Runs ESLint to check code quality and catch errors.
Troubleshooting
Port already in use
If port 3000 is occupied, specify a different port:
Clear node_modules
If you encounter dependency issues:
rm -rf node_modules package-lock.json
npm install
TypeScript errors
Regenerate TypeScript definitions:
npm run dev
# Wait for the server to start, then stop it
# Next.js will regenerate .next/types
Build errors
Check Node.js version:
node --version
# Should be v20.0.0 or higher
Next steps
Quickstart Build your first chat feature in 5 minutes
Project structure Explore the codebase organization and architecture
Components Learn about the UI component library
State management Deep dive into Zustand store patterns
Development tip : Use pnpm for faster installs and better disk space efficiency compared to npm or yarn.