Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/liinkiing/next-ts-graphql-apollo-starter
An opiniated Next powered starter which include support for Apollo with GraphQL SSR support, codegen, styled component / system, framer motion and Cypress
https://github.com/liinkiing/next-ts-graphql-apollo-starter
apollo codegen cypress framer-motion graphql next react ssr starter styled-component styled-system template typescript
Last synced: 5 days ago
JSON representation
An opiniated Next powered starter which include support for Apollo with GraphQL SSR support, codegen, styled component / system, framer motion and Cypress
- Host: GitHub
- URL: https://github.com/liinkiing/next-ts-graphql-apollo-starter
- Owner: Liinkiing
- Created: 2020-04-15T00:20:17.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2022-06-08T21:27:10.000Z (over 2 years ago)
- Last Synced: 2023-03-04T00:18:57.506Z (almost 2 years ago)
- Topics: apollo, codegen, cypress, framer-motion, graphql, next, react, ssr, starter, styled-component, styled-system, template, typescript
- Language: TypeScript
- Homepage:
- Size: 811 KB
- Stars: 17
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Next GraphQL Apollo Starter
A starter to bootstrap your **Next** application (nice pun gg) with some noice GraphQL
(**🎊 With SSR support 🎊**) with Apollo and [GraphQL code generator](https://graphql-code-generator.com/)## Usage
```bash
$ yarn
# install dependencies$ yarn dev
# launch concurrently gql-gen:watch and dev:next$ yarn gql-gen
# launch GraphQL code generation based on codegen.yaml$ yarn gql-gen:watch
# same as above, with watch mode$ yarn dev:next
# launch Next dev script$ yarn build
# launch Next build script$ yarn start
# launch Next start script$ yarn test
# launch test suite$ yarn cy:open
# open cypress (you first need to install deps in cypress folder)$ yarn ts:check
# check TypeScript$ yarn lint
# run ESLint
```## GraphQL support
The starter comes by default with Apollo@3. All Apollo related code and config is located under `~/apollo` folder.
It uses environment variables to define the API endpoint, so you have to copy/paste the `.env.sample`
file and rename it to `.env` (not committed). The variable name is `NEXT_PUBLIC_GRAPHQL_API`To make the codegen work, you must have a `schema.graphql` at the root (can be
modified in the `codegen.yaml`, see [the configuration reference](https://graphql-code-generator.com/docs/getting-started/codegen-config)).
Based on this and your \*.graphql files in `~/graphql/**`, it will auto generate
corresponding hooks.When writing \*.graphql files, you can also import other \*.graphql files by using
comments, but this is no longer necessary because last versions of graphql codegen inline
\*.graphql docs.`~/graphql/fragments/ProjectCard_project.graphql`
```graphql
fragment ProjectCard_project on Project {
title
body
}
````~/graphql/queries/Projects.graphql`
```graphql
query Projects {
projects {
id
...ProjectCard_project
}
}
```### Using Apollo in server side
If you want to fetch your data with Apollo from your server, you must use the
provided functions `initializeApollo` and `addApolloState`. They are used to
get apollo either from an already initialized client or a new one. They are
also responsible for populating the Apollo store and restore it on the client side.Here is an example on how to use it
```tsx
import { gql } from '@apollo/client'
import type { GetServerSideProps, NextPage } from 'next'
import { useHelloQuery } from '~/__generated__/graphql'
import { addApolloState, initializeApollo } from '~/apollo/client'
const Page: NextPage = () => {
data will already be available on first render
// be
se it has been fetched on your server side and been
// po
ated into the apollo cache store.
const
const { data } = useHelloQuery()
return{data.hello}
}
export const getServerSideProps: GetServerSideProps = async ctx => {
const client = initializeApollo()
const { data } = await client.query({
query: gql`
query Hello {
hello
}
`,
})
if (!data.hello) {
return { notFound: true }
}
return addApolloState(client, { props: {} })
}
```You can also use the provided hook `useApollo` to get your apollo client instance with the
correct store cache if you made a query on your server side.### Configuration
All configuration related files are located in the `codegen.yaml` file ([more informations here](https://graphql-code-generator.com/docs/getting-started/codegen-config))
A `.graphqlconfig` file is also provided, if you use a GraphQL extension in your IDE, it will allow you
to introspect the schema of a given endpoint and writing it in a `schema.graphql` file.
You must enter your API url here### Examples
Example usage for a given query
```graphql
query Projects {
projects {
id
title
body
}
}
```which generate a hook and a component and could be used like this :
```typescript jsx
import React, { FC } from 'react'
import { useProjectsQuery } from '~/__generated__/graphql'
file is generated by gql-codegenconst
const Projects: FC = () => {
const { data, loading, error } = useHelloQuery()
if (error) {
returnError
}
if (loading) {
returnLoading...
}
if (data.projects) {
}
}
return null
}
const App: FC = () => {
return (
)
}
export default App
```and you get all the nice **autocompletion** from your IDE thanks to Typescript!
And if you change any of \*.graphql files to add a new field for a GraphQL query,
it will be automatically generated and you will be always in sync with your GraphQL files!## Next config
It comes already configured with some nice plugin. You can see in `next.config.js` what is
used. In short, it allows support of importing images files and fonts within webpack.
It also comes with **NProgress** support, by default so it shows a small loading bar in top of
the page when loading. You can find the component in `~/components/NProgress.tsx`, and it is used in the
custom `_app.tsx`## Styled component
The template comes with [styled-components](https://github.com/styled-components/styled-components).
Again, you can either choose to not use it, this is a personal choice.
You can also find a `styles` folder, which contains many related
styled-components files to keep things organized. It's also includes all themes-related stuff in here.
It's again a personal convention that I follow, feel free to annihilate this directory if you want 😢## Styled system
It also comes with [styled-system](https://github.com/styled-system/styled-system). It is a great way to
build reusable UI blocks with a great props API and consistent spaces / typography.
A lot comes from the theme, provided in `~/styles/themes/base.ts` where we define some
breakpoints, spacings and typography stuff. It allows then the custom `AppBox` component (`~/ui/AppBox`)
to be aware of your theme and then build something amazing with the primitives.
By default, this starter provides some basic examples components that uses this pattern, for
example the `AppNav` component (`~/components/layout/AppNav`).🔥 It also supports and provides autocomplete for props that takes source from the theme (e.g `bg`, `zIndex`, `border`...). 🔥
**TypeScript > 4.1** is mandatory because I'm using the new [Template Litteral Types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types) to
provide autocompletion of the color prop based of the nested `colors` object, so when using
`bg` prop for exemple, you should have autocompletion for `red.xxx, blue.xxx` or anything defined in your `colors.ts`.
It supports nested elements with a dot notation! (that's why TS 4.1 is required)## Framer motion
Again, personal preference here, but the starter comes with framer motion already configured
to handle Next pages changes and enable some smooth transitions when navigating. You
can find the default variant used for the page transitions in `~/common/framer.ts`.## Testing
[Jest](https://github.com/facebook/jest) and [@testing-library/react](https://github.com/testing-library/react-testing-library) is used to run your tests. It comes preconfigured
with [ts-jest](https://github.com/kulshekhar/ts-jest) so your tests also checks your types.
You can look the **jest.config.js** and the file **setupTest.ts** to see what's in there.
[jest-styled-components](https://github.com/styled-components/jest-styled-components) is also used to have deterministic classNames
within your styled components that you are testing.
[Cypress](https://cypress.io) starter for e2e tests. Take a look at Cypress config file **cypress.json**### Cypress
This starter comes by default with [Cypress](https://cypress.io) and some sensible defaults and a custom plugin which enable you to
inject your .env\* files in the Cypress.env helper. It also add support for a per-environment configuration file.
Just add a cypress..json. It uses by default the `cypress.json` and then extend the configuration if you have
a `cypress..json`. Take a look at the various configuration file in the `cypress` folder and the custom plugin in `cypress/plugins/index.ts`.
This folder is independant and lives by itself, so it has his own dependencies / scripts / tsconfig and do not pollute the
global namespace. [See why an isolated folder](https://basarat.gitbook.io/typescript/intro-1/cypress#tip-creating-page-objects)It also have an opiniated way of interacting with some of your webpages in Cypress. As your application
will grow (and pages would become complex), it's recommended to have some sort of "Page objects" which allows
you to work in a more conveniant way for some complex page. See more here https://basarat.gitbook.io/typescript/intro-1/cypress#tip-creating-page-objects.It also comes with two custom commands (`cypress/support/commands.ts`) that are autocompleted (see `cypress/@types/index.d.ts`)
```typescript
cy.server() // start mocking the calls made to the server, needed to mock later the queries
cy.mockGraphQL() // in your test, allow to start intercepting requests made to your /graphql/ endpoint
cy.mockGraphQLOperation('ViewerQuery') // internally alias the request, so you can do later in your test cy.wait
// your test ...
cy.wait('@ViewerQuery') // waits for the graphql operation to succeed
```## Aliases
It includes by default support for aliases in `tsconfig.json`.
They are 1 defaulted alias, ready to use :```typescript
// ~ refers to src folder
import { something } from '~/file'
```You can also use for your convenience the global `__DEV__` variable, which is
injected by webpack with the DefinePlugin (see **next.config.js**).## @types and extending modules
It also includes a `@types` directory under **src**, so you can easily
separate your types or extends some external modules. They are also included in the `tsconfig.json`
For example, if some package named `foo` does not have any types in [DefinitelyTyped](https://definitelytyped.org/), you could
add a `index.d.ts` under `src/@types/foo/index.d.ts`. It is just my personal convention, so do as you want!```typescript
// src/@types/foo/index.d.ts// to make sure Typescript get the original types from the module (if any
import * as foo from 'foo'declare module 'foo' {
declare function foo(bar: string): boolean
}
```Because the `@types` directory is declared in `typeRoots`, Typescript will no longer complain if you imported your package with missing types
## Tooling
The template includes [Prettier](https://prettier.io/), [ESLint](https://eslint.org/) (with [Typescript-eslint](https://github.com/typescript-eslint/typescript-eslint)), [Babel](https://babeljs.io/) and [lint-staged](https://github.com/okonet/lint-staged).
All their related configurations are in the `*rc` files (except for lint-staged, which is located in the `package.json`).