Skip to content

A simple app to demonstrate basic API functions built with REST and GraphQL

Notifications You must be signed in to change notification settings

codica2/nextjs-graphql-sample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

24 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Next.js project example with TypeScript & GraphQl

Description

This is an example/boilerplate of a nextjs project using Typescript and Apollo.

The main idea behind the example is to show the best typescript and GraphQL usage by integration of the Apollo client and types generating using GraphQL Code Generator.

Moreover, for writing styles it suggests no less interesting approach with combining styled-components and styled-system Read more. πŸ˜ƒ

In this example, Apollo is integrated by wrapping our pages with HOC. Using the HOC pattern we're able to pass down a central store of query result data created by Apollo into our React component hierarchy defined inside each page of our Next application.

Table of Contents

Usage

Install it and run:

npm install
npm run dev

# or

yarn
yarn dev

File structure

    .
    β”œβ”€β”€ ...
    β”œβ”€β”€ generated/             # generated graphql types
    β”œβ”€β”€ graphql/               # graphql queries and mutations splitted by entities
    β”œβ”€β”€ interfaces/            # custom ts interfaces
    β”œβ”€β”€ utils/                 # app utilities
    β”œβ”€β”€ pages/                 # next.js pages
    β”œβ”€β”€ server/                # custom server
    β”œβ”€β”€ views
    β”‚   β”œβ”€β”€ components/        # components
    β”‚   β”œβ”€β”€ layouts/           # application layouts
    β”‚   β”œβ”€β”€ styled/            # styled components + styled system types
    β”‚   └── ui/                # ui components(Button, Inputs, etc.)
    └── ...

Configuration

Also, this example is easily configurable. The main config file next.config.js is placed in the root. You can engage all the needed plugins there. Next-compose-plugins is used for composing all the plugins together, It provides a cleaner API for enabling and configuring plugins.

const withPlugins = require("next-compose-plugins");
const withTypescript = require("@zeit/next-typescript");
const withLess = require("@zeit/next-less");

module.exports = withPlugins(
  [
    // add a plugin without a configuration
    withTypescript,

    // add a plugin with specific configuration
    [
      withLess,
      {
        lessLoaderOptions: {
          javascriptEnabled: true
        }
      }
    ]
  ],
  nextConfig // next.js configuration
);

Making GraphQl queries and mutations

In order to make a GraphQL query or request, firstly we should describe the schemas, all of them should be placed in the graphql folder, we actually splitted them by entities for convenience of use.

Then we must generate typescript types read more. After this, you could use these generated components:

<LoginComponent>
{(<LoginMutation>, <LoginVariables>) => (
  ...code
)}
</LoginComponent>

Styling

This exapmle uses styled-components along with styled-system approach.

Styled-components is a CSS-in-JS library which allows you to write actual CSS code to style your components.

Styled-System provides you with a set of utilities that map props to your design system. It uses the concept of style functions. Each style function exposes its own set of props that style elements based on values defined in your design system theme. It has a rich API with functions for most CSS properties.

The Design Styled System theme object is intended to be a general purpose format for storing design system style values and scales:

const theme = {
  breakpoints: [32, 48, 64],
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
  fontSizes: [12, 14, 16, 20, 24, 36, 48, 80, 96],
  fontWeights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
  colors: {
    primary: "#000",
    secondary: "#ccc",
    ...
  },
   buttonSizes: {
    xs: `
      height: 16px;
      padding: 0 16px;
      font-size: 10px;
    `,
    sm: `
      height: 24px;
      padding: 0 24px;
      font-size: 13px;
    `,
    md: `
      height: 34px;
      padding: 0 34px;
      font-size: 14px;
      letter-spacing: 0.4px;
    `
  ...

Our styled components utilize what we call system props to apply a custom set of props to a component. We adopted this approach by creating seperate types like layout, typography, flexbox, and others. This means that every component is guaranteed to have the same API.

Here is an example of the common type, we use the compose utility to create custom type that each new component can use.

import * as SS from "styled-system";

// typescript type
export type CommonProps = SS.SpaceProps &
  SS.WidthProps &
  SS.HeightProps &
  SS.ColorProps &
  SS.FontSizeProps;

// common type
export default SS.compose(
  SS.space,
  SS.width,
  SS.height,
  SS.color,
  SS.fontSize
);

This is a component for styling headings, here we import our custom common and typography functions, moreover, we could extend it with our custom css styles. Also, we add some default styled-system props.

import styled, { StyledComponent } from "styled-components";
import { borders, BordersProps } from "styled-system";

import common, { CommonProps } from "./types/common";
import typography, { TypographyProps } from "./types/typography";

type Props = CommonProps & TypographyProps & BordersProps;

const Heading: StyledComponent<Props> = styled("h1")(
  { margin: "0 0 20px" },

  common,
  borders,
  typography
);

Heading.defaultProps = {
  fontSize: [2, 3, 4],
  fontWeight: 5,
  color: "primary"
};

Heading.displayName = "Heading";

export default Heading;

Eventually, we can easily reuse this styled component adding different props.

// (theme.fontSizes[4])
<Heading fontSize={4} />

// (theme.space[3])
<Heading m={2} />

// (theme.colors.blacks[0])
<Heading color="blacks.3" />

Features

GraphQL types

To generate GraphQL types out of GraphQL schemas we use GraphQL Code Generator, it takes all our GraphQL queries and mutations from graphql/**/* and generates typescript components into a generated/apolloComponents.tsx file, so after you could use it inside your components. In order to generate it run npm run generate or yarn generate command. You should regenerate types every time any graphql mutation or query changes ❗

Protected routes

For catching authentication errors we use HOC, it makes an initial GraphQL query to get the authenticated. If there is no authenticated user it redirects to the login page.

export const withAuth = <T extends object>(
  C: React.ComponentClass<T> | React.FC
) => {
  return class AuthComponent extends React.Component<T> {
    static async getInitialProps({
      apolloClient,
      ...ctx
    }: NextContextWithApollo) {
      const response = await apolloClient.query<MeQuery>({ query: meQuery });
      if (!response || !response.data || !response.data.me) {
        redirect(ctx, "/login");

        return {
          me: null
        };
      }

      return {
        me: response.data.me
      };
    }

    render() {
      return <C {...this.props} />;
    }
  };
};

License

nextjs-graphql-sample is Copyright Β© 2015-2019 Codica. It is released under the MIT License.

About Codica

Codica logo

We love open source software! See our other projects or hire us to design, develop, and grow your product.

About

A simple app to demonstrate basic API functions built with REST and GraphQL

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published