Next.js file naming conventions are checked with ESLint rules

Hiroki Ueda
3 min readJan 3, 2024

--

Photo by Mimi Thian on Unsplash

The current front-end environment has many naming conventions. For example, components should be created in Pascal case, but hooks related files should be created in Camel case, and Hooks processes should be named with use at the beginning of the file name. Example useHooks.ts. I am sure that there are implicit naming rules not only in the front-end environment, but also in your own environment.

Here is an naming conventions example. How do you control naming conventions in your project?

src
├ app // Under the app directory is kebab case.
│ ├ layout.tsx
│ ├ not-found.tsx
│ ├ page.tsx
│ └ about
│ ├ layout.tsx
│ └ page.tsx
├ components // Under the components directory is pascal case.
│ └ Button
│ ├ Button.tsx
│ ├ Button.modules.css
│ └ index.tsx
└ features
└ serach-feature
├ components
│ └ SerchField
├ hooks // Under the hooks directory is camel case. Add "use" to the filename.
│ └ useSearch.tsx
├ providers // Under the providers directory is camel case. Add "Provider" to the filename.
│ └ searchProvider.tsx
└ utils

So I came up with the idea of integrating with ESLint rules and created eslint-plugin-validate-filename which is perfect for the Next.js project. If you share the idea, please give us feedback and issues.

VSCode will display errors like this.

Install

First, install the necessary packages.

npm install --save-dev eslint-plugin-validate-filename

Next, add the ESLint configuration. The configuration files include .eslintrc and .eslint.json. validate-filename has naming-rules.

{
"plugins": ["validate-filename"],
"rules": {
"validate-filename/naming-rules": [
"error",
{
"rules": [
// add your rules here
]
}
]
}
}

Component Naming Conventions

When creating components, it’s advisable to use PascalCase for naming. This convention helps to easily distinguish between components and standard HTML elements.

The case has camel, pascal, snake, kebab, flat. and The target should be the name of the folder path. index name is ignored.

{
"case": "pascal",
"target": "**/components/**"
}

Here is an example of valid and invalid.

/components/App/App.tsx // valid
/components/App/app.tsx // invalid

The app router Naming Conventions

Under the app router directory of Next.js, it is best to create it in a kebab case. This is because the specific file names are fixed and they are all Kebab case.

The rules go like this.

{
"case": "kebab",
"target": "**/app/**",
}

Here is an example of valid and invalid.

/app/page.tsx // valid
/app/not-found.tsx //valid
/app/appRoute.tsx //invalid

If you want to restrict usage to certain filenames within the app directory, you can achieve this by setting a rule in patterns.

{
"case": "kebab",
"target": "**/app/**",
"patterns": "^(page|layout|loading|error|not-found|route|template).tsx$"
}

Hooks Naming Conventions

Under the hook directory, add the word use to the filename. By including use, it signifies that the file contains hook logic.

{
"case": "camel",
"target": "**/hooks/**",
"patterns": "^use"
}

Here is an example of valid and invalid.

/hooks/useHooks.ts // valid
/hooks/hooks.tsx // invalid

The same rules can be created for Providers subordinates.

{
"case": "camel",
"target": "**/providers/**",
"patterns": "^[a-zA-Z]*Provider"
}

Conclusion

In conclusion, implementing ESLint rules for file naming conventions will enhance the cleanliness, readability, and maintainability of the project. Given the numerous implicit naming conventions in front-end development, it’s advisable to establish rules using eslint-plugin-validate-filename

Please provide feedback and issues.

Final settings

{
"plugins": ["validate-filename"],
"rules": {
"validate-filename/naming-rules": [
"error",
{
"rules": [
{
"case": "pascal",
"target": "**/components/**"
},
{
"case": "kebab",
"target": "**/app/**",
"patterns": "^(page|layout|loading|error|not-found|route|template).tsx$"
},
{
"case": "camel",
"target": "**/hooks/**",
"patterns": "^use"
},
{
"case": "camel",
"target": "**/providers/**",
"patterns": "^[a-zA-Z]*Provider"
}
]
}
]
}
}

--

--