Next.js Best Practices Documentation

May 7, 2025

I was asked to research best practices in Next.js and compile a list for our upcoming project at ISACA. This documentation was compiled from various sources like Vercel and Bulletproof React and agreed upon by the development team.

  1. Starting a New Project
  2. Tooling
  3. Versioning and DevOps
  4. Project Structure
  5. Imports
  6. Routing
  7. Layouts
  8. Components
  9. Errors
  10. Coding Standards
  11. Naming Conventions
  12. Performance
  13. Security
  14. References

Starting a New Project

Use the default Next.js app template for new projects. The command for creating an app is:

npx create-next-app@latest

Rationale

Projects created with a common app template will be easier to maintain, share, and understand. Vercel created and maintains NextJS and has setup the create-next-app template with best practices and standards.

Tooling

Next.js sites should use the following tools at a minimum:

  • Node
  • React
  • ReactDOM
  • TypeScript
  • ESLint
  • Tailwind

Rationale

Next.js is a React framework that requires Node, React, and ReactDOM. Node is the JavaScript runtime environment. React is the main JavaScript library for development. ReactDom adds DOM specific methods for rendering and manipulating the browsers DOM.

TypeScript is a strongly-typed programming language that builds on JavaScript and adds additional tooling. It improves error checking, maintainability, scalability, and collaboration on JavaScript projects.

ESLint is an ECMAscript linter that works with TypeScript or JavaScript and checks for functional and style errors while developing in an editor or in DevOps processes. It can be configured to enforce project or company specific coding standards.

Tailwind is a CSS framework that provides succinct, extensible utility classes for most style rules. Combined with Next.js, the styles for a component are dynamically built and delivered within the page to maximize page performance and minimize CLS.

Versioning and DevOps

Next.js sites should use Git and Github.

Rationale

Git is the most popular version control system and works with Azure DevOps. We already use Github for other projects. New projects built within Github increase maintainability, ease of use, and the ability to re-use resources.

Project Structure

Next.js has certain conventions for project structure that should be followed (folders like app, src, and public have special behaviors - see the Project Structure documentation).

Beyond these, use common naming conventions for source code folders:

Recommended Project Folder Structure

Feature folders can help organize code like Sitecore’s Helix pattern. When using feature folders, enforce dependency flow from Shared → Features → Application:

Dependencies with Feature Folders

Rationale

Following Next.js and common naming conventions make code more maintainable and easier to understand.

Using feature folders and dependency conventions allow you to separate feature-only code but continue to ensure collaboration, readability, and scalability in the project.

Imports

Use absolute imports to make it easier to more files or locate references. Use a single import path for @ that is mapped to the src folder like:

"compilerOptions": {"baseUrl": ".", "paths": {"@/*": ["./src/*"]}}

Rationale

Code is easier to read and maintain when you have imports like:

import MyComponent from '@/features/MyComponent';

Instead of:

import MyComponent from '../../../features/MyComponent';

Routing

Use the default file-system based routing available in the app folder. Leverage dynamic route segments where possible. Leverage the default redirects function if necessarry.

Rationale

The app folder routing has a large number of features that should cover all of our page-based routing needs. Using the default functionality requires less configuration and improves readability and maintainability.

Dynamic Route Segments re-use the same page for all matching routes and reduce the amount of files/code needed which improves maintainability.

The Next.js Redirects Function is standard functionality that requires less configuration and improves readability and maintainability.

Layouts

Use shared layout files for the UI shared between multiple pages. Use nested layouts to encapsulate UI shared between a subset of pages.

Rationale

Layouts improve reusability and maintainability by removing duplicate code from dependent pages.

Components

Use Static Rendering Server Components whenever possible. Use feature folders and colocate dependencies where appropriate. Simplify components by refactoring large components into smaller components and limiting the number of input props.

Rationale

Static Rendering Server Components can be exported to static files that can be hosted on a CDN for optimal performance.

Colocating dependencies makes features easier to understand and improves maintainability.

Simplifying components improves readability and maintainability.

Error Handling

Create user-friendly error pages following Next.js conventions for common errors like 404 not found. Use error boundaries for handling uncaught errors within a page or layout. Use try-catch blocks around code that can error (ex. code that relies on server data fetching). Handle errors gracefully and provide reset functions when possible to allow the customer to recover from an error. Use tracing or logging tools that save errors so that they can be used for debugging and diagnostics.

Rationale

User-friendly error pages improve the user experience and trust of a site and can make it easier for customers to understand and recover from an error.

Coding Standards

Leverage existing company coding standards like the JavaScript Best Practices documentation. Use industry standards and best practices for any languages / situation not covered by company or team coding standards. Incorporate standards into ESLint configuration to enforce standards as developers code.

Rationale

Coding standards reduce bugs and improve consistency, maintainability, and readability.

Naming Conventions

Use lowercase kebab-case for folder/file names (ex. /app/product-bundles/super-special-offer.tsx) and CSS class names. Use PascalCase for component names and CamelCase for function, variable, and property names. Use SCREAMING_SNAKE_CASE for constants, enumeration properties, and global variables.

Rationale

Lowercase kebab-case for folder / file names is cross-platform compatible which is important when code is developed on Windows but hosted on Linux. It also follows common URL conventions.

PascalCase for component names follows common React coding conventions and improves readability.

CamelCase for function, variable, and property names follow common React coding conventions and improves readability.

SCREAMING_SNAKE_CASE for constants, enumeration properties, and global variables follow React coding conventions and improves readability.

Performance

Next.js is designed to deliver performant and scalable React websites. Leverage the default features available whenever possible. This includes:

  • Avoid or minimize global css and instead leverage Tailwind CSS and component level styling
  • Use Next.js Image and Font optimizations
  • Leverage ISR to build static page assets that can be distributed to a global CDN
  • Minimize client-side requests and CLS
  • When necessary, use suspended content sections and streaming for small sections of a page that require separate client-side requests.

Rationale

Leveraging default features improves readability and maintainability and requires less configuration.

Security

Secrets should be stored in an environment file that is not added to the repository.

Rationale

Environment files are easier to secure and different environments can more easily replace secrets to connect to different services.

References