# Pages

## Motivation

**Next.js** **has a limitation** on the project structure - all of the pages should be located in the `pages` directory. **Mosaic** **removes this limitation**, thus allowing for a modular project structure. Each Mosaic module is able to **register** its own **pages**, which will be taken into account during the build time.

## Preparations

In order to **declare a Next.js page**, some preparations are necessary. This will work only in Next.js powered by Mosaic, launched with package `@tilework/mosaic-nextjs-scripts`&#x20;

First of all, an [extension module](https://docs.mosaic.js.org/next.js-features/broken-reference) must be [created](https://docs.mosaic.js.org/develop-an-extension/anatomy-of-an-extension). You will implement your page there.

For the development purposes, it's recommended to have the under-development extension module [installed](https://docs.mosaic.js.org/install-an-extension/use-a-local-extension) into your project.

## Page type

The following page types are available:

* [SSR](https://nextjs.org/docs/basic-features/pages#server-side-rendering): server
* [Static Generation without data](https://nextjs.org/docs/basic-features/pages#static-generation-without-data): static-no-data
* [Static Generation with data](https://nextjs.org/docs/basic-features/pages#static-generation-with-data): static-with-data

## Register a page

In order to have an additional page in a Mosaic-powered Next.js application, the first step is to register this page in order to let the Mosaic build system know about the page. It should be done in the following way.

Instead of the `server` you may use one of the [values](#page-type) described above.

{% code title="@example/page-module/package.json" %}

```javascript
{
    "mosaic": {
        "nextPages": {
            "pagename": "server"
        }
    }
}
```

{% endcode %}

## See the magic

A template page, similar to the following, will be generated after the actions above. For different page types, different templates will be generated. This will cause additional [namespaces](https://docs.mosaic.js.org/develop-an-extension/namespaces) to be available for [plugins](https://docs.mosaic.js.org/develop-an-extension/plugins).&#x20;

Add functionality and contents to it with [plugins](https://docs.mosaic.js.org/develop-an-extension/plugins)!

{% tabs %}
{% tab title="server" %}

```javascript
import renderEmptyPage from '@tilework/mosaic-nextjs-scripts/lib/empty-page';

/**
 * ! This file is a "placeholder" / injection point generated,
 * ! so that the NextJS static router (and Babel plugin) would
 * ! recognize this file as a page. You can override this page
 * ! behaviour using plugin system!
 */

/** @namespace Pages/pagename/Page */
const Page = () => (
    process.env.NODE_ENV === 'production'
        ? null
        : renderEmptyPage({ ... })
);

/** @namespace Pages/pagename/getServerSideProps */
const getServerSideProps = () => ({ props: {} });

export { getServerSideProps };
export default Page;
```

{% endtab %}

{% tab title="static-no-data" %}

```javascript
import renderEmptyPage from '@tilework/mosaic-nextjs-scripts/lib/empty-page';

/**
 * ! This file is a "placeholder" / injection point generated,
 * ! so that the NextJS static router (and Babel plugin) would
 * ! recognize this file as a page. You can override this page
 * ! behaviour using plugin system!
 */

/** @namespace Pages/pagename/Page */
const Page = () => (
    process.env.NODE_ENV === 'production'
        ? null
        : renderEmptyPage({ ... })
);

export default Page;

```

{% endtab %}

{% tab title="static-with-data" %}

```javascript
import renderEmptyPage from '@tilework/mosaic-nextjs-scripts/lib/empty-page';

/**
 * ! This file is a "placeholder" / injection point generated,
 * ! so that the NextJS static router (and Babel plugin) would
 * ! recognize this file as a page. You can override this page
 * ! behaviour using plugin system!
 */

/** @namespace Pages/pagename/Page */
const Page = () => (
    process.env.NODE_ENV === 'production'
        ? null
        : renderEmptyPage({ ... })
);

/** @namespace Pages/pagename/getStaticProps */
const getStaticProps = () => ({ props: {} });

export { getStaticProps };
export default Page;

```

{% endtab %}
{% endtabs %}

## Implement the page

The code example shown below explains, how to implement the page declared above. It uses our plugin system, if you are not yet familiar to it - get acknowledged in [this guide](https://docs.mosaic.js.org/hands-on-guides/quick-start).

{% tabs %}
{% tab title="server" %}

```javascript
const serverSideProps = async ([context]) => ({ 
    props: { 
        sample: 'example for a server-side prop' 
    }
});

const page = ([{ sample }]) => <Typography content={sample} />;

export default {
    'Pages/pagename/getServerSideProps': {
        function: serverSideProps
    },
    'Pages/pagename/Page': {
        function: page
    }
}
```

{% endtab %}
{% endtabs %}
