Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/topheman/nextjs-github-browser

Browse github through a website made in NextJS
https://github.com/topheman/nextjs-github-browser

apollo graphql nextjs react typescript

Last synced: about 2 months ago
JSON representation

Browse github through a website made in NextJS

Awesome Lists containing this project

README

        

# nextjs-github-browser

[![ci](https://github.com/topheman/nextjs-github-browser/actions/workflows/ci.yml/badge.svg)](https://github.com/topheman/nextjs-github-browser/actions/workflows/ci.yml)
[![e2e](https://github.com/topheman/nextjs-github-browser/actions/workflows/e2e.yml/badge.svg)](https://github.com/topheman/nextjs-github-browser/actions/workflows/e2e.yml)
[![nextjs-github-browser](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/6ihjj6&style=flat&logo=cypress)](https://dashboard.cypress.io/projects/6ihjj6/runs)
[![Storybook](https://img.shields.io/badge/storybook-online-ff4785.svg)](https://nextjs-github-browser.vercel.app/explore/storybook/index.html)
[![Demo](https://img.shields.io/badge/demo-online-blue.svg)](http://nextjs-github-browser.vercel.app/)

This project is a reimplementation of the main features of the [github.com](https://github.com) website in **NextJS**.

- Checkout the **demo** on **[nextjs-github-browser.vercel.app](https://nextjs-github-browser.vercel.app)**
- Browse the [online storybook](https://nextjs-github-browser.vercel.app/explore/storybook/index.html)
- Browse the [Cypress Dashboard](https://dashboard.cypress.io/projects/6ihjj6) (with the reports of the e2e tests run on CI)

## Prerequisites

- Nodejs >=14
- npm >=6

## Install

```sh
git clone https://github.com/topheman/nextjs-github-browser.git
cd nextjs-github-browser
npm install
```

## Setup

This project uses the [Github GraphQL Apis](https://docs.github.com/en/graphql). You will need to [generate a personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).

- Create a `.env.local` file
- Add `GRAPHQL_API_TOKEN=***` to the file with your own token

Create a token

## Development

```shell
npm run dev
```

This will start a development server on [http://localhost:3000](http://localhost:3000).

### Mocking

This project is shipped with built-in mocking for the graphql layer. It works for both client-side and server-side rendering.

- `MOCKS_MODE=record npm run dev` : will record any graphql request into `.tmp/mocks`
- `MOCKS_MODE=replay npm run dev` : will replay the mocks if available (if not, will let the request through)

You can use `MOCKS_MODE` with `record` / `replay` also on `npm start`.

You can override the target of the folder where the mocks are recorded by using `MOCKS_TARGET=./tmp/my/specific/folder` for example.

## Storybook

```sh
npm run storybook
```

This will start the storybook server on [http://localhost:6006](http://localhost:6006).

## Build

```sh
npm run build
```

This will build the a production version of the website in the `.next` folder.

For production, we want to expose the storybook, to do that:

```sh
npm run build:all
```

## Production

First, you need to build your project running `npm run build:all`, then:

```shell
npm start
```

This will launch a production server on [http://localhost:3000](http://localhost:3000).

You can change the port passing a `PORT` env var like: `PORT=8080 npm start`.

## Test

### Unit

The project contains unit tests run with jest (the react part is relying on [@testing-library/react](https://testing-library.com/docs/react-testing-library/intro/))

```sh
npm run test
```

### Cypress

To run the cypress end-to-end test, launch a server in a terminal (in [dev mode](#development) or [production mode](#production)).

Then start the cypress test either:

- In gui mode: `npm run cy:open`
- In headless mode: `npm run cy:run`

## Linter

Please checkout [eslintrc.js](./.eslintrc.js) for the linting configuration:

- TypeScript
- Prettier
- Next
- React
- Tailwind
- Cypress
- ...

## Continuous Integration

Each `git push` / `PR` triggers a test suite on [github/actions](https://github.com/topheman/nextjs-github-browser/actions). The following will be ran:

- linting
- type checking
- unit tests
- end to end test with cypress

The end to end test sessions are recorded, you can check them [here](https://dashboard.cypress.io/projects/6ihjj6/runs).

## FAQ

### GraphQL Schema in TypeScript

Thanks to [@octokit/graphql-schema](https://github.com/octokit/graphql-schema) and [@graphql-codegen/cli](https://www.graphql-code-generator.com), we can generate type definitions for the GraphQL queries we use.

The queries used in this project are in [src/graphql](./src/graphql).

The generated types and utils are in [src/generated/graphql.ts](./src/generated/graphql.ts).

When you modify/add a query/fragment, run `npm run graphql-codegen` to generate the types and utils.

- See [this commit for the setup](https://github.com/topheman/nextjs-github-browser/commit/4921b6b026fc34b7daeecce77858c035d619ec52)
- Thanks for the following resources:
- https://benlimmer.com/2020/05/16/adding-typescript-types-github-graphql-api/
- https://blog.logrocket.com/build-a-graphql-react-app-with-typescript/

### Http Caching

The `/api/github/graphql` handler is available by `POST` requests to both client and server (because it's needed for both SSR and some use cases where we call directly graphql from the client).

You have the following use cases:

1. full page render: browser -> nextjs(server) -> getServerSideProps -> `/api/github/graphql` -> github graphql api
- GET request issued by browser
2. partial page render: browser(onRouteChange) -> nextjs(getServerSideProps) -> `/api/github/graphql` -> github graphql api
- GET request issued by nextjs router
3. direct call to graphql from client: browser(apollo) -> `/api/github/graphql` -> github graphql api
- POST request, cache is manage client side by Apollo

I fixed the problematic of caching for the 2nd case by adding http header `Cache-Control: private, max-age=120, must-revalidate`.

You can activate it in local by using `npm run start:cache`.

A better way would be to use some database like redis and store the payloads indexed by serialized graphql variables - this is a personal project 😉.

## Resources

- Setup apollo-client in NextJS: [src/libs/apollo-client.ts](./src/libs/apollo-client.ts) (links to resources in source code)
- [Doc Apollo](https://www.apollographql.com/docs/react/performance/server-side-rendering/)
- [Github advanced search](https://github.com/search/advanced)
- [useHooks(🐠)](https://usehooks.com)
- [cypress-io/github-action](https://github.com/cypress-io/github-action)
- github actions - [Building and testing Node.js](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs)

This project is based on previous work:

- ⚛️ [topheman/nextjs-movie-browser](https://github.com/topheman/nextjs-movie-browser)
- ⚛️ [topheman/npm-registry-browser](https://github.com/topheman/npm-registry-browser)
- ️⚛️ [topheman/react-fiber-experiments](https://github.com/topheman/react-fiber-experiments)
- 📝 [Cypress.io advanced setup](http://dev.topheman.com/cypress-io-advanced-setup/)