Skip Main Navigation
Ben IlegboduBen Ilegbodu

Putting test files in the pages folder in a Next.js app

How to include test and other non-page files next to page components and API routes within the pages directory in a Next.js application

Sunday, February 13, 2022 Β· 3 min read

When developing Next.js apps I want to be able to include other files within the src/pages directory besides the page React components or API routes. I'm perfectly fine putting components in src/components and helper functions in src/utils. But I like to co-locate other files with my pages and API routes.

Instead of creating a parallel __tests__ folder, I like putting my *.test.ts or *.test.tsx Jest unit tests next to whatever it is that I'm testing. That works great in src/components, src/utils or any other location outside of src/pages. Similarly, I like putting my Storybook stories (*.stories.tsx) next to my React components, including my page components (made possible by Storybook Addon Next Router).

But when I add these files within src/pages or src/pages/api and run next build, I get the following error:

Build error occurred

Error: Build optimization failed: found page without a
React Component as default export in

pages/my/plan.stories

See https://nextjs.org/docs/messages/page-without-valid-component
for more info.

It's pretty nice that the error leads me to a place where I can find more info. I love when frameworks do this. But when I visit the Page Without Valid React Component page it gives a rather short explanation as to why the error ocurred, and some possible ways to fix it. The problem is that all the possible ways to fix it assume I somehow screwed up! 😒

I mean I guess I did screw up by putting other files in the src/pages folder, but it seems like something that should be allowed! Why is Next.js so picky about what files go in there? I guess since Next uses page-based routing it makes sense that it will have no way of interpreting page component files from test files or Storybook stories.

So for the longest I just accepted my fate and put my stories in a sibling src/page-stories directory and just avoided writing unit tests, moving nearly everything into src/utils. But it felt a bit clunky.

Then a coworker showed me a workaround! The pageExtensions configuration allows us to alter the default list of valid page extensions (.tsx, .ts, .jsx, and .js). The config option is aimed at tools like @next/mdx, which have files that end in .mdx. But we can take advantage of it to let us put non-page files in the src/pages folder as well. And it's right there in the docs.

We add special extensions for the page components and API routes to help Next.js distinguish them from all of the other files.

module.exports = {
  pageExtensions: [
    // `.page.tsx` for page components
    'page.tsx',
    // `.api.ts` for API routes
    'api.ts',
  ],
}

Because I exclusively develop in TypeScript, I only have TypeScript extensions. So all of my pages end in .page.tsx, such as src/pages/my/plan.page.tsx. And any of my API routes end in .api.ts, such as src/pages/api/client/auth.api.ts. I give the API routes their own extension, just for added clarity. And because page components will always have JSX, there's no need for .page.ts. Likewise, since API routes should never have JSX, there's no need for .api.tsx.

Now I can have plan.page.tsx, plan.test.tsx and plan.stories.tsx all in the same src/pages/my folder! And the cool thing is if I want to add a utils.ts or constants.ts in the src/pages folder, it will also work. Who knew something so simple could be so exciting? πŸ˜‚

Keep in mind, though, that this change also has to apply to any Custom App (src/pages/_app.tsx), Custom Document (src/pages/_document.tsx), and Custom Error Pages (src/pages/404.tsx & src/pages/500.tsx) that we've defined. They'll all need the .pages.tsx extension.


While I'd love for everyone to find my blog post to get their answer, the Page Without Valid React Component error page is slightly more discoverable. πŸ˜… So I submitted a pull request to add a link to the Custom Page Extensions page. As of writing, there are 194 open pull requests on the Next.js repo. So it may take a while to merge, if ever. Until then, I'll rake in the page views! 🀣

If you've got any questions or suggestions, feel free to reach out to me on Twitter at @benmvp.

Keep learning my friends. πŸ€“

Subscribe to the Newsletter

Get notified about new blog posts, minishops & other goodies

​
​

Hi, I'm Ben Ilegbodu. πŸ‘‹πŸΎ

I'm a Christian, husband, and father of 3, with 15+ years of professional experience developing user interfaces for the Web. I'm a Google Developer Expert Frontend Architect at Stitch Fix, and frontend development teacher. I love helping developers level up their frontend skills.

Discuss on Twitter // Edit on GitHub