Next.js template
Tags: typescript, react, nextjs, graphql
Published: 2022-11-08 12:44:46

https://github.com/akira-toriyama/next.js-tpl


# Next.js template

[App](https://next-js-tpl-62l80d57r-akira-toriyama.vercel.app/)  
Displays the data registered in **Hygraph**.

[Design system](https://next-js-tpl-designsystem-1cq9u10a7-akira-toriyama.vercel.app)  
This is a design system, but it does not use styles.  
**React** has various ways to apply styles, such as **css in js**, **css module**, **comport library**, etc., and there is no best practice. Please consider the style in consideration of the contents of your application.

## How to use

### Required libraries

- [asdf](https://github.com/asdf-vm/asdf)
- [docker](https://docs.docker.com)

### First.

Prepare environment variables and schema for mock.
The `SCHEMA_DOWNLOAD_URL` in `.env.example` is the URL of the **Hygraph** resource. Please prepare it by yourself at the time of development. It is released to the public for operation check.


```bash
yarn mockServer
yarn generate:fromGQL
yarn dev

open "http://localhost:4000/graphql"
open "http://localhost:4000/voyager"
open "http://localhost:3000"
```

### Development

During development, develop while communicating with the mock server.


```bash
yarn mockServer
yarn generate:fromGQL
yarn dev

open "http://localhost:4000/graphql"
open "http://localhost:4000/voyager"
open "http://localhost:3000"
```

### design system

`storybook` is well known, but we use `ladle`.

```bash
yarn designSystem
open "http://localhost:6006"
```

### comport generation

Generate comport with `hygen`.

```bash
# Please git commit in advance.

yarn generate:ui/general
yarn generate:ui/domain
```

### Snapshot update

Update snapshot when adding or updating `stories.tsx`.

```bash
# It takes time.

yarn updateSnapshot
```

## directory structure.

```bash
src
├── env.ts
├── infra
│  └── graphql
│     ├── client.ts
│     ├── types.ts
│     └── util
│        ├── index.ts
│        ├── util.test.ts
│        └── util.ts
└── ui
   ├── domain
   │  └── item
   │     ├── Item
   │     │  ├── coLocation
   │     │  │  ├── dao.ts
   │     │  │  ├── Item.gql.generated.ts
   │     │  │  └── Item.gql.ts
   │     │  ├── component
   │     │  │  ├── index.ts
   │     │  │  ├── Item.stories.tsx
   │     │  │  ├── Item.test.tsx
   │     │  │  └── Item.tsx
   │     │  ├── hook
   │     │  │  ├── index.ts
   │     │  │  ├── item.hook.test.ts
   │     │  │  ├── item.hook.ts
   │     │  │  └── service
   │     │  │     ├── index.ts
   │     │  │     ├── service.test.ts
   │     │  │     └── service.ts
   │     │  ├── index.ts
   │     │  └── Item.type.ts
   │     └── Items
   │        ├── coLocation
   │        │  ├── dao.ts
   │        │  ├── Items.gql.generated.ts
   │        │  └── Items.gql.ts
   │        ├── component
   │        │  ├── index.ts
   │        │  ├── Items.stories.tsx
   │        │  ├── Items.test.tsx
   │        │  └── Items.tsx
   │        ├── hook
   │        │  ├── index.ts
   │        │  ├── items.hook.test.ts
   │        │  ├── items.hook.ts
   │        │  └── service
   │        │     ├── index.ts
   │        │     ├── service.test.ts
   │        │     └── service.ts
   │        ├── index.ts
   │        └── Items.type.ts
   ├── general
   │  ├── Card
   │  │  ├── Card.stories.tsx
   │  │  ├── Card.test.tsx
   │  │  ├── Card.tsx
   │  │  └── index.ts
   │  └── List
   │     ├── index.ts
   │     ├── List.stories.tsx
   │     ├── List.test.tsx
   │     └── List.tsx
   ├── provider
   │  ├── ErrorBoundary.tsx
   │  ├── ReactQuery.tsx
   │  └── Wrapper.tsx
   └── util
      └── tag
         ├── index.ts
         ├── tag.test.ts
         └── tag.ts
```

## Development flow.

GithubActions is executed when you submit a pull request on **main** branch. ([example](https://github.com/akira-toriyama/next.js-tpl/pull/883))  
GithubActions executes type checking, lint, unused code detection, snapshotting, etc. App and Design system are also published by pull requests.

## Implementation policy

### Directory structure

The directory structure directly under src/ is based on the layered architecture. Please be aware of where to implement this process.
Avoid using src/graphql, src/component, etc., as it will result in a technology-driven structure.

### mock server

During development, it is not necessary to communicate with the actual resource. Prepare a [mock](https://www.the-guild.dev/graphql/tools/docs/mocking) that returns convenient data in \_server/grphqlServer/mocks.ts.

### Template.

Use `yarn generate:ui/general`, `yarn generate:ui/domain` to align the basic implementation.

### domain component

In SPA, UI and logic and UI and storage are tightly coupled. Please do not prepare directories with the same name, but use extensions and directory structure to express the roles.

```
# Bad

src/graphql/animal/cat.gql.ts
src/component/animal/Cat.tsx
```

```
# Good

src/ui/domain/animal/cat/coLocation/cat.gql.ts
src/ui/domain/animal/cat/component/Cat.tsx
```

Not everything fits this rule, but implement everything of interest in src/ui/domain/.

### tsx

Do not implement non-testable components.
Please refer to [eslint-plugin-use-encapsulation](https://github.com/kyleshevlin/eslint-plugin-use-encapsulation).

```tsx
# Bad

const Cat: React.FC = () => {
  const [v, setV] = useState("Tama");

  return <>name of the cat {v}</>;
};
```

```tsx
# Good

const useCat = () => {
  const [v, setV] = useState("Tama");

  return {
    name: v,
  };
};

const Cat: React.FC = () => {
  const cat = useCat();

  return <>cat's name {cat.name}</>;
};
```

### Testing

Please write unit tests well. Don't write tests knowing too much about the processing of the file you are ``importing``.

### state.

[ts-pattern](https://github.com/gvergnaud/ts-pattern), type refinement, more state, etc. `__tag` is better than `isXxx`.
[example](https://www.typescriptlang.org/play?ssl=32&ssc=1&pln=33&pc=1#code/C4TwDgpgBAQghgEwAoCcD2YDOUC8UDeAUFFAJaYAyaipAdgOYBcUARmmgDYRy0DcxZTAGUArgGMxETJmZtO3PgIRxgcZpmAo69KAB8otERw78Avv0Ji0tDa0QAxWrigAKMM3jJ0WAJS4AfAQCpABmrmAAdORUNAx+RCQkAPRJJAAqABYQKNCYGWhGCAZowKzQyqoRAsmpMCKlGloMegZGHNVQkRVw-IlQKVAAegD8AqaEwWFuUcLiktLxHQOZ2bn5hWVQ3VV9A3UNmtothsYdXSo9S6kjY4TmE6CQUADi7F4Y2DgC+gl9UAD6-1UTCgACIONQENpQb0-t1mCcTB1xiQfh0SIDgcxQZg5lJMDD0VsLupDgxYSR7pZrLZ6G9HM43MxXmh3r4AkESKFwhFMXAdDhBWCIbF6KDFrtUt1BK1Tn1zqoKf1rqNKRMuVNInyBUKcXjpOLOYkBtLyFBGtozhFukqBjc1fcgA)