import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Guides/Installation/SSR/Next.js pages router" />

# Installation: Next.js pages router

This guide assumes you have read and followed the steps in the [Installation: Applications](/story/guides-installation-applications--page) guide.

## Packages

You will need to install one extra package. `@preply/ds-web-core`, which provides you with everything you need to collect stylesheets and CSS classes during SSR time.

```
yarn add @preply/ds-web-core
```

## Instruct `RootProvider` to NOT render any CSS classes

In the case of SSR, `document.body` is not available during SSR, so you will need to provide `target="none"` instead.

```tsx
import { RootProvider } from '@preply/ds-web-root';

export const wrapWithProviders = () => (values: ContextValues) => {
    return (elements: React.ReactNode) => (
        ...
        <NextRouter.Provider value={values.nextRouter}>
            ...
            <RootProvider target="none" theme="tokyo-ui">{elements}</RootProvider>
            ...
        </NextRouter.Provider>
        ...
    );
};
```

## Add the global styles

In the component that renders your application's HTML document, as close as possible to the start of the `<head>` tag, add:

```tsx
import { GlobalStyle } from '@preply/ds-web-root';

...
    return (
        <html>
            <head>
                <link rel="preconnect" href="https://static.preply.com" />
                <GlobalStyle />
                ...
```

## Setup SSRProvider - DS context for SSR time

Wrap your SSR application with `SSRProvider` in order to provide a `hostname` context and collect the "critical" CSS class names and style blocks.

For more information on this provider visit [API / ds-web-root / providers / SSRProvider](/story/api-ds-web-root-providers-ssrprovider--page) reference page.

The following code is taken from a `Next.js` application.

1. merge `{ classNames: string }` with the `Document` props
2. create an instance of this class to collect CSS class names and `<style>` blocks
3. wrap SSR rendering with the `SSRProvider`
4. expose CSS class names and the `<style>` element
5. and render the CSS classes in the `<body>` tag

```tsx
// _document.tsx
import { ServerStyleSheet } from '@preply/ds-web-core';
import { SSRProvider } from '@preply/ds-web-root';

// 1
class MyDocument extends Document<Request & { classNames: string }> {
    static async getInitialProps(ctx: DocumentContext}) {

        // 2
        const stylesheet = new ServerStyleSheet();

        // 3
        const originalRenderPage = ctx.renderPage
        ctx.renderPage = () =>
            originalRenderPage({
                enhanceApp: (App) => props => (
                    <SSRProvider stylesheet={stylesheet} hostname={hostname}>
                        <App {...props} />
                    </SSRProvider>
                ),
            });

        // 4
        const initialProps = await Document.getInitialProps(ctx);
        return {
            ...initialProps,
            classNames : stylesheet.getClassName(),
            styles: stylesheet.getStyleElement()
        };
    }

    render() {
        const { classNames } = this.props;
        // 5
        return (
            <Html>
                <body className={`other-classes ${classNames}`}>
                    ...
                </body>
            </Html>
        );
    }
}
```

See also [Next.js official docs](https://nextjs.org/docs/advanced-features/custom-document).
