Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Organize a Next.js Full Stack Project #1

Open
VienDinhCom opened this issue Jan 18, 2021 · 5 comments
Open

How to Organize a Next.js Full Stack Project #1

VienDinhCom opened this issue Jan 18, 2021 · 5 comments

Comments

@VienDinhCom
Copy link
Owner

VienDinhCom commented Jan 18, 2021

Hi there! In this article, I want to show you how I organize my Next.js Full Stack Project.

Folder Structure

First of all, you can take a look at the folder structure below. You can see that src is the root-level application project. Yes! I want to place my code into the src folder.

  • src
    • backend
      • entities
      • migrations
      • resolvers
      • services
    • frontend
      • components
      • services
    • pages
      • api
      • app
    • shared
      • schemas
      • services

Shared Folder

I often have some code that I want to use for both frontend and backend, such as schemas for typed-safe API, services for accessing environment variables or utility functions, ...

With these kinds of code, I want to place them into the shared folder.

Backend Folder

In the backend folder, I want to place my server code, such as:

  • entities is for TypeORM entities.
  • migrations is for TypeORM migrations.
  • resolvers is for resolvers of API schemas.
  • services is to place reusable code for resolvers.

Frontend Folder

In the frontend folder, I want to place my client code, such as:

  • components is for reusable components
  • services is to place reusable code for components and pages.

Pages Folder

pages is the default Next's folder for routing. Inside the pages folder, I have:

  • api is for server API handlers.
  • app is for the main authenticated app.

Setup Next.js

In this section, I will set up a Next.js application with the folder structure above.

Generate Next.js application

First, I will create a new Next.js application named next-full-stack with the command below.

yarn create next-app next-full-stack

Next, I change the working folder to next-full-stack.

cd next-full-stack

Next, I remove these Next.js default folders.

rm -rf styles pages

Next, I create a new folder named src to store all my code.

mkdir src

Finally, I change the working folder to src to ready for the next steps.

cd src

Create Folders

To organize the folder structure which we have, I will run these command to create the folders.

Create Main Folders

mkdir shared backend frontend pages

Create Shared's Sub Folders

mkdir shared/services shared/schemas

Create Backend's Sub Folders

mkdir backend/entities backend/migrations backend/resolvers backend/services

Create Frontend's Sub Folders

mkdir frontend/components frontend/services

Create Home Page

To create the home page for my project, I'll create a text file named index.tsx in the pages folder. The file will have the content below.

touch pages/index.tsx
export default function Page() {
  return <h1>Hello World!</h1>;
}

Add TypeScript Support

I'd like to work with TypeScript on this project. So I will do these steps to have TypeScript support.

yarn add --dev typescript @types/react @types/node

Run this command to let Next.js create next-env.d.ts and tsconfig.json files for TypeScript configuration.

yarn dev

Configure module aliases

Using relative import like this import mod from '../../../mod.ts' is so ugly. So I will add these lines to tsconfig.json, section compilerOptions to make my import code more beautiful.

"baseUrl": "src",
"paths": {
  "@backend/*": ["backend/*"],
  "@frontend/*": ["frontend/*"],
  "@shared/*": ["shared/*"]
}

And my new tsconfig.json will look like this.

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",

    "baseUrl": "src",
    "paths": {
      "@backend/*": ["backend/*"],
      "@frontend/*": ["frontend/*"],
      "@shared/*": ["shared/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

From now on, I can import my child modules with these lines:

import { EnvService } from '@shared/services/env.service.ts'

Or

import { UserService } from '@backend/services/user.service.ts'

Or

import { ApiService } from '@frontend/services/api.service.ts'

Demo: https://next-full-stack-git-issue-1.maxvien.vercel.app/

Source Code

You can find the source code of this tutorial in this branch: https://github.com/maxvien/next-full-stack/tree/issue-1

@bwmirek
Copy link

bwmirek commented Jun 15, 2022

Now you can create next app with typescript enabled by default via:

yarn create next-app next-full-stack --typescript

@hugocxl
Copy link

hugocxl commented Oct 2, 2022

Hi @Maxvien! This proposal is definitely a great approach to organising projects in Next.js (enforce cohesion, good discoverability and good understandability of the project). Personally, I like to follow your structure but adding an additional level of grouping within the main categories:

  • backend
    • modules
      • auth
      • ...
    • shared (reuse across backend modules)
      • lib
      • utils
      • ...
  • frontend
    • modules (or pages)
      • auth
        • Auth.tsx
        • components
        • hooks
        • ...
    • shared (reuse across frontend modules)
      • components
      • hooks
      • ...
  • pages
    • api
    • auth
    • ...
  • shared (reuse across backend/frontend)
    • utils
    • core
    • ...

@Sutherlandon
Copy link

Hey @Maxvien, my project was becoming so convoluted and it didn't feel sustainable. Thanks for posting this cause it brought a LOT more clarity to my project. The tsconfig.json was really the key that brought it all together. The only thing I changed was "client/server" instead of "frontend/backend". Thank you!

@Gerald-ux-ux
Copy link

@Maxvien I like your approach better

@Abdullah6346
Copy link

Any One can share for new Next JS 14, App Router

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants