Featured

Next.js New Project Setup: Optimal Flow and Best Practices

T
Team
·18 min read
#nextjs#react#setup#tutorial#web development#best practices

Next.js New Project Setup: Optimal Flow and Best Practices


Starting a new Next.js project can be overwhelming with all the configuration options available. This guide will walk you through the optimal setup process, from initialization to production-ready configuration.


Step 1: Project Initialization


Create New Next.js Project


Use the official Next.js CLI to create a new project:


bash
1# Create new Next.js app with TypeScript
2npx create-next-app@latest my-app --typescript --tailwind --eslint --app
3 
4# Or with JavaScript
5npx create-next-app@latest my-app --js --tailwind --eslint --app

Project Structure


After initialization, your project should have this structure:


text
1my-app/
2├── app/ # App Router (Next.js 13+)
3│ ├── layout.js # Root layout
4│ ├── page.js # Home page
5│ └── globals.css # Global styles
6├── public/ # Static assets
7├── .next/ # Build output (gitignored)
8├── node_modules/ # Dependencies (gitignored)
9├── .eslintrc.json # ESLint config
10├── .gitignore # Git ignore rules
11├── next.config.js # Next.js config
12├── package.json # Dependencies
13├── postcss.config.js # PostCSS config
14├── tailwind.config.js # Tailwind config
15└── tsconfig.json # TypeScript config (if using TS)

Step 2: Essential Configuration


Update next.config.js


Configure Next.js for optimal performance:


javascript(62 lines, showing 15)
1/** @type {import('next').NextConfig} */
2const nextConfig = {
3 // Enable React strict mode
4 reactStrictMode: true,
5
6 // Optimize images
7 images: {
8 domains: ['example.com'],
9 formats: ['image/avif', 'image/webp'],
10 },
11
12 // Compress output
13 compress: true,
14
15 // Enable standalone output for Docker

Step 3: Optimal Folder Structure


Organize your project with this structure:


text(43 lines, showing 15)
1my-app/
2├── app/
3│ ├── (auth)/ # Route group for auth pages
4│ │ ├── login/
5│ │ └── register/
6│ ├── (dashboard)/ # Route group for dashboard
7│ │ ├── layout.js
8│ │ └── page.js
9│ ├── api/ # API routes
10│ │ └── users/
11│ │ └── route.js
12│ ├── layout.js # Root layout
13│ ├── page.js # Home page
14│ └── globals.css
15├── components/

Step 4: Install Essential Dependencies


Core Dependencies


bash(17 lines, showing 15)
1# Form handling
2npm install react-hook-form zod @hookform/resolvers
3 
4# State management
5npm install zustand # or redux toolkit
6 
7# HTTP client
8npm install axios
9 
10# Date handling
11npm install date-fns
12 
13# Icons
14npm install react-icons
15 

Development Dependencies


bash
1# Code formatting
2npm install -D prettier prettier-plugin-tailwindcss
3 
4# Additional linting
5npm install -D @typescript-eslint/eslint-plugin
6 
7# Testing
8npm install -D jest @testing-library/react @testing-library/jest-dom
9 
10# Type checking (if using TypeScript)
11npm install -D typescript @types/node @types/react

Step 5: Environment Variables Setup


Create environment variable files:


.env.local (for local development):

bash
1# Database
2DATABASE_URL=postgresql://user:password@localhost:5432/mydb
3 
4# API
5NEXT_PUBLIC_API_URL=http://localhost:3000/api
6 
7# Authentication
8NEXTAUTH_URL=http://localhost:3000
9NEXTAUTH_SECRET=your-secret-key
10 
11# Third-party services
12STRIPE_PUBLIC_KEY=pk_test_...
13GOOGLE_CLIENT_ID=...

.env.example (template for team):

bash
1DATABASE_URL=
2NEXT_PUBLIC_API_URL=
3NEXTAUTH_URL=
4NEXTAUTH_SECRET=

Step 6: Configure ESLint and Prettier


.eslintrc.json


json
1{
2 "extends": [
3 "next/core-web-vitals",
4 "prettier"
5 ],
6 "rules": {
7 "react/no-unescaped-entities": "off",
8 "@next/next/no-img-element": "warn"
9 }
10}

.prettierrc


json
1{
2 "semi": false,
3 "singleQuote": true,
4 "tabWidth": 2,
5 "trailingComma": "es5",
6 "printWidth": 100,
7 "plugins": [
8 "prettier-plugin-tailwindcss"
9 ]
10}

.prettierignore


text
1.next
2node_modules
3public
4*.min.js

Step 7: Set Up Root Layout


Update app/layout.js:


javascript(26 lines, showing 15)
1import { Inter } from 'next/font/google'
2import './globals.css'
3import Header from '@/components/layout/Header'
4import Footer from '@/components/layout/Footer'
5 
6const inter = Inter({ subsets: ['latin'] })
7 
8export const metadata = {
9 title: 'My App',
10 description: 'Description of my app',
11 keywords: ['nextjs', 'react', 'web development'],
12}
13 
14export default function RootLayout({ children }) {
15 return (

Step 8: Create Utility Functions


Create lib/utils.js:


javascript(26 lines, showing 15)
1// Format date
2export function formatDate(date) {
3 return new Date(date).toLocaleDateString('en-US', {
4 year: 'numeric',
5 month: 'long',
6 day: 'numeric',
7 })
8}
9 
10// Debounce function
11export function debounce(func, wait) {
12 let timeout
13 return function executedFunction(...args) {
14 const later = () => {
15 clearTimeout(timeout)

Step 9: Set Up API Routes


Create API route example app/api/users/route.js:


javascript(26 lines, showing 15)
1import { NextResponse } from 'next/server'
2 
3export async function GET(request) {
4 try {
5 const users = await fetchUsers() // Your data fetching logic
6 return NextResponse.json({ users })
7 } catch (error) {
8 return NextResponse.json(
9 { error: 'Failed to fetch users' },
10 { status: 500 }
11 )
12 }
13}
14 
15export async function POST(request) {

Step 10: Development Workflow


Package.json Scripts


Update package.json scripts:


json
1{
2 "scripts": {
3 "dev": "next dev",
4 "build": "next build",
5 "start": "next start",
6 "lint": "next lint",
7 "format": "prettier --write .",
8 "format:check": "prettier --check .",
9 "type-check": "tsc --noEmit",
10 "test": "jest",
11 "test:watch": "jest --watch"
12 }
13}

Git Workflow


1. Create feature branch: git checkout -b feature/new-feature

2. Make changes: Write code, add tests

3. Format code: npm run format

4. Lint code: npm run lint

5. Commit: git commit -m "feat: add new feature"

6. Push: git push origin feature/new-feature

7. Create PR: Open pull request on GitHub


Step 11: Performance Optimization


Image Optimization


javascript
1import Image from 'next/image'
2 
3export default function MyComponent() {
4 return (
5 <Image
6 src="/image.jpg"
7 alt="Description"
8 width={500}
9 height={300}
10 priority // For above-the-fold images
11 placeholder="blur" // Optional
12 />
13 )
14}

Font Optimization


javascript
1import { Inter } from 'next/font/google'
2 
3const inter = Inter({
4 subsets: ['latin'],
5 display: 'swap',
6 variable: '--font-inter',
7})

Code Splitting


Use dynamic imports for large components:


javascript
1import dynamic from 'next/dynamic'
2 
3const HeavyComponent = dynamic(() => import('@/components/HeavyComponent'), {
4 loading: () => <p>Loading...</p>,
5 ssr: false, // Disable SSR if needed
6})

Step 12: Testing Setup


Jest Configuration


Create jest.config.js:


javascript
1const nextJest = require('next/jest')
2 
3const createJestConfig = nextJest({
4 dir: './',
5})
6 
7const customJestConfig = {
8 setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
9 testEnvironment: 'jest-environment-jsdom',
10}
11 
12module.exports = createJestConfig(customJestConfig)

Example Test


javascript
1import { render, screen } from '@testing-library/react'
2import Home from '@/app/page'
3 
4describe('Home', () => {
5 it('renders heading', () => {
6 render(<Home />)
7 const heading = screen.getByRole('heading', {
8 name: /welcome/i,
9 })
10 expect(heading).toBeInTheDocument()
11 })
12})

Best Practices Summary


1. **Use TypeScript**

TypeScript catches errors early and improves developer experience.


2. **Follow File Naming Conventions**

  • Components: PascalCase (`Button.jsx`)
  • Utilities: camelCase (`utils.js`)
  • Constants: UPPER_SNAKE_CASE (`API_URL`)

  • 3. **Optimize Images**

    Always use Next.js Image component for better performance.


    4. **Use Server Components**

    Prefer Server Components when possible for better performance.


    5. **Implement Error Boundaries**

    Handle errors gracefully with error boundaries.


    6. **Add Loading States**

    Use loading.tsx files for better UX.


    7. **Environment Variables**

    Never commit sensitive data. Use .env.local for secrets.


    8. **Code Organization**

    Keep components small and focused. Use feature-based folder structure.


    Conclusion


    Following this setup guide will give you a solid foundation for your Next.js project. Remember to:


  • Start simple - Don't over-engineer initially
  • Iterate - Add features as needed
  • Follow conventions - Stick to Next.js best practices
  • Optimize gradually - Focus on performance as you scale

  • Your Next.js project is now ready for development!


    Enjoyed this article?

    Support our work and help us create more free content for developers.

    Stay Updated

    Get the latest articles and updates delivered to your inbox.