CloudScape Design with NextJS
Tags: cloudscape, nextjs
Published: 2022-08-23 09:57:18

As of July 19th, 2022 Amazon Web Services released their Design System as open-source along with a library of React components that implement the design system. This blog post is a quick overview of the design system and how it can be used with NextJS.

## What is Cloudscape?

[Cloudscape Design System](https://cloudscape.design/) is an open source solution for building intuitive, engaging, and inclusive user experiences at scale. Cloudscape consists of an extensive set of guidelines to create web applications, along with the design resources and front-end components to streamline implementation.
Cloudscape was built for and is used by Amazon Web Services (AWS) products and services. They created it in 2016 to improve the user experience across web applications owned by AWS services, and also to help teams implement those applications faster.

You can read more about Cloudscape [here](https://cloudscape.design/).

It's a beautiful design system and offers a lot in terms of component functionality out of the box. I would highly encourage everyone to try it out.

## Installing Cloudscape

For NextJS users, you can install Cloudscape by running the following command:

```bash
npm install @cloudscape-design/global-styles @cloudscape-design/components
```

## CloudScape Integration with NextJS

Next, we will need to integrate them into our application. First we will import the CloudScape global styles package into our app. Let's do this in our `pages/_app.{jsx,tsx}` file

```jsx
import '@cloudscape-design/global-styles'
```

After we have included our global styles, let's try to use some of the components in our application.

```jsx
import { useState } from 'react'
import Header from '@cloudscape-design/components/header'
import Container from '@cloudscape-design/components/container'
import SpaceBetween from '@cloudscape-design/components/space-between'
import Input from '@cloudscape-design/components/input'
import Button from '@cloudscape-design/components/button'

export default function Home() {
  const [value, setValue] = useState('')

  return (
    <SpaceBetween size="m">
      <Header variant="h1">Hello World!</Header>

      <Container>
        <SpaceBetween size="s">
          <span>Start editing to see some magic happen</span>
          <Input value={value} onChange={(event) => setValue(event.detail.value)} />
          <Button variant="primary">Click me</Button>
        </SpaceBetween>
      </Container>
    </SpaceBetween>
  )
}
```

Run it and see what happens.

![Error](https://www.codewithyou.com/_next/image?url=%2Fstatic%2Fimages%2Fcloudscape-design-with-nextjs%2F1.png&w=2048&q=75)

This error occurs due to NextJS implementing native CSS modules. We can fix this by use a NextJS plugin to transpile our styles into native CSS modules that NextJS can understand

```bash
npm install -D next-transpile-modules next-compose-plugins
```

After install the plugin, we need edit `next.config.js` as follows:

```js
const withTranspileModules = require('next-transpile-modules')
const withPlugins = require('next-compose-plugins')

const nextConfig = {
  // other config options
}

// Here we will add a plugin to our configuration to transpile the CloudScape components into
module.exports = withPlugins([withTranspileModules(['@cloudscape-design/components'])], nextConfig)
```

Bonus, in case you are using typescript then the file `next.config.js` should be like this

```typescript
const withTM = require('next-transpile-modules')(['@cloudscape-design/components']);

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
}

const buildConfig = _phase => {
  const plugins = [withTM]
  const config = plugins.reduce((acc, next) => next(acc), {
    ...nextConfig
  })
  return config
}

module.exports = buildConfig();
```

Restart NextJS dev server we should no longer see any error messages. You also see the following output:

![Success](https://www.codewithyou.com/_next/image?url=%2Fstatic%2Fimages%2Fcloudscape-design-with-nextjs%2F2.png&w=1920&q=75)

Wow, it seem to work! But wait a second, some error messages are still showing up in console.

```bash
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
    at InternalContainer (webpack-internal:///./node_modules/@cloudscape-design/components/container/internal.js:32:21)
    at Container (webpack-internal:///./node_modules/@cloudscape-design/components/container/index.js:24:17)
```

This is because Cloudscape uses the `useLayoutEffect` hook to render the components.
And the `useLayoutEffect` hook is not supported in the server renderer.
The Cloudscape team does not intend to Replace useLayoutEffect at the moment.
You can read more about it [here](https://github.com/cloudscape-design/components/pull/79).

To fix this issue, you can add this into `_app.js`.

```jsx
import React from 'react'
if (typeof window === 'undefined') React.useLayoutEffect = () => {}
```

That all, we are good to go! The code is now working as expected.

Thanks for reading! Hope you find this useful! :)

**Code available on [GitHub](https://github.com/buithaibinh/blog-tutorials/tree/main/cloudscape-design-with-nextjs)**