# How to deploy Strapi with a Gatsby frontend on Upsun Fixed

Upsun Fixed maintains a [template](https://github.com/platformsh-templates/gatsby-strapi) that you can quickly deploy, and then use this guide as a reference for the Upsun Fixed specific changes that have been made to Gatsby and Strapi to make it work. 

## Shared configuration

Your local clone of the template has the following project structure:

```bash
├── .platform
│   ├── routes.yaml
│   └── services.yaml
├── strapi
│   ├── # App code
│   └── .platform.app.yaml
├── gatsby
│   ├── # App code
│   └── .platform.app.yaml
└── README.md
```

From this repository, you deploy a Gatsby app and a Strapi app.
The code for each of them resides in their own directories.
When deploying a single app project [such as Gatsby](https://fixed.docs.upsun.com/guides/gatsby/deploy.md),
the repository needs three configuration files that describe its infrastructure, described below in detail.
For [multi-app projects](https://fixed.docs.upsun.com/create-apps/multi-app.md),
two of those files remain in the project root and are shared between Gatsby and Strapi.
Each app keeps its own app configuration file (`.platform.app.yaml`) in its subdirectory.

### Service configuration

This file describes which [service containers](https://fixed.docs.upsun.com/add-services.md) (such as a database) your project should include.
Gatsby does not require services to deploy, but Strapi does.
So the following examples shows these service configurations:

```yaml {}
# The services of the project.
#
# Each service listed will be deployed
# to power your Upsun Fixed project.

dbpostgres:
    type: postgresql:12
    disk: 256

```

### Routes configuration

This [`.platform/routes.yaml`](https://fixed.docs.upsun.com/define-routes.md) file defines how requests are handled by Upsun Fixed.
The following example shows Gatsby being served from the primary domain
and Strapi being accessible from the `backend` subdomain.

```yaml {}
# The routes of the project.
#
# Each route describes how an incoming URL is going
# to be processed by Upsun Fixed.

"https://www.{default}/":
    type: upstream
    upstream: "gatsby:http"

"https://{default}/":
    type: redirect
    to: "https://www.{default}/"

"https://www.backend.{default}/":
    type: upstream
    upstream: "strapi:http"

"https://backend.{default}/":
    type: redirect
    id: 'strapi'
    to: "https://www.backend.{default}/"

```

## Strapi

The multi-app template has a single modification to Upsun Fixed's [standard Strapi template](https://github.com/platformsh-templates/strapi):
the `name` attribute in Strapi's `.platform/services.yaml` has been updated to `strapi`.
This value is used to define the [relationship between Gatsby and Strapi](#gatsby)
and in the [routes configuration](#routes-configuration).

The only additional setup required to prepare the backend is to install a package that enables GraphQL on Strapi.

In your Strapi directory, add the dependency:

```bash
yarn add strapi-plugin-graphql
```

## Gatsby

The frontend Gatsby app has a slightly different configuration from the basic [Gatsby deployment](https://fixed.docs.upsun.com/guides/gatsby/deploy.md).
Below is the `gatsby/.platform.app.yaml` file that configures the app.

```yaml {}
# .platform.app.yaml

# The name of this application, which must be unique within a project.
name: gatsby

# The type key specifies the language and version for your application.
type: 'nodejs:14'

# The hooks that will be triggered when the package is deployed.
hooks:
    # Build hooks can modify the application files on disk but not access any services like databases.
    post_deploy: |
      npm run build      
# The size of the persistent disk of the application (in MB).
disk: 1024

relationships:
   strapi: "strapi:http"

# The configuration of the application when it is exposed to the web.
web:
    locations:
        '/':
            # The public directory of the application relative to its root.
            root: 'public'
            index: ['index.html']
            scripts: false
            allow: true

mounts:
  '/.cache':
      source: local
      source_path: cache
  '/.config':
      source: local
      source_path: config
  'public':
      source: local
      source_path: public

```

In particular, notice:

- `relationships`

  Access to another service or app container in the cluster is given through [`relationships`](https://fixed.docs.upsun.com/create-apps/image-properties/relationships.md).
  In this case, one has been defined to the backend Strapi container using it's `name`.

- `post_deploy`

  Upsun Fixed containers reside in separate build containers at build time,
  before their images are moved to the final app container at deploy time.
  These build containers are isolated and so Gatsby can't access Strapi during the build hook,
  where you would normally run the [`gatsby build` command](https://github.com/platformsh-templates/gatsby/blob/master/.platform.app.yaml#L21).
  Strapi isn't available until after the deploy hook.
  So the Gatsby build is postponed until the [`post_deploy` hook](https://fixed.docs.upsun.com/create-apps/hooks/hooks-comparison.md#post-deploy-hook).

  To run `gatsby build` on-demand, or to trigger a rebuild from the backend when content is updated,
  define a [runtime operation](https://fixed.docs.upsun.com/create-apps/runtime-operations.md#build-your-app-when-using-a-static-site-generator).

- `mounts`

  There are consequences to postponing the Gatsby build,
  as you don't generally have write access to the container this late in the pipeline.
  To allow Gatsby to write to `public`, that directory has been defined as a [mount](https://fixed.docs.upsun.com/create-apps/image-properties/mounts.md).

You can then modify [gatsby-config.js](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-config/) to read from the backend Strapi container through the ``strapi`` relationship defined above to configure the ``apiURL`` attribute for ``gatsby-source-strapi``. Notice that the source plugin requires that you explicitly define the ``contentTypes`` you would like to retrieve from Strapi. At this point you have not built out the API, and the Content Types ``article`` and ``category`` are included to support the [post-install instructions](https://github.com/platformsh-templates/gatsby-strapi#user-content-post-install) outlined in the template’s README. Adjust these values to fit your current API if your are planning on migrating an existing Strapi repository.

This is facilitated by Upsun Fixed's [Config Reader library](https://github.com/platformsh/config-reader-nodejs).
So be sure to install this to the Gatsby dependencies first when replicating.
When used, Gatsby pulls the information to communicate with the Strapi container *on the current branch*.

Lastly, the Gatsby app itself needs to include [GraphQL queries](https://www.gatsbyjs.com/docs/reference/graphql-data-layer/)
to handle the data coming from Strapi and create content pages.
The most important files in the template you should consult are:

- [`gatsby/gatsby-node.js`](https://github.com/platformsh-templates/gatsby-strapi/blob/master/gatsby/gatsby-node.js)

  Dynamically creates individual pages from the data source using Gatsby's [Node API](https://www.gatsbyjs.com/docs/reference/config-files/gatsby-node/). It retrieves all of Strapi's articles and categories (see [post-install below](#deploy-and-post-install)) using the GraphQL queries `allStrapiArticle` and `allStrapiCategory` respectively. For each, a page is created (`createPage`) with an assigned `path` and formatting described by one of the template files below (`component`).

- [`gatsby/src/templates/article.js`](https://github.com/platformsh-templates/gatsby-strapi/blob/master/gatsby/src/templates/article.js)

  The template file that defines how a single Strapi article should be formatted on Gatsby, retrieving the data from that article using the `strapiArticle` GraphQL query.

- [`gatsby/src/templates/category.js`](https://github.com/platformsh-templates/gatsby-strapi/blob/master/gatsby/src/templates/category.js)

  The template file that defines how a list of articles that belong to a single Category are formatted by Gatsby. It uses the `Category` query, and then filters a specific category `id` on `allStrapiArticle`.

- [`gatsby/src/pages/index.js`](https://github.com/platformsh-templates/gatsby-strapi/blob/master/gatsby/src/pages/index.js)

  Retrieves all of Strapi's content to generate a list of articles on the homepage using the `allStrapiArticle` GraphQL query.

## Deploy and post-install

When you first deploy the template, the frontend Gatsby site will fail with a 403 error.
Visit the `backend` subdomain of your site and finish the installation of Strapi.
You don't need to set database credentials as they're already provided.

After you have deployed, you need to set up Strapi’s Admin Panel and some initial content endpoints for the Gatsby frontend to consume. Create your admin user at the ``backend`` subdomain for Strapi. You can then follow the [template’s post-install instructions](https://github.com/platformsh-templates/gatsby-strapi#user-content-post-install) to setup up some initial ``Article`` and ``Category`` content endpoints. The API you develop there is only accessible to admins by default, so be sure to adjust the permissions to public so Gatsby can access it.

Once you've finished, redeploy the project with the CLI command `platform redeploy` to view your Gatsby site,
It's now pulling its content from a backend Strapi container in the same project.

## Next steps

With Gatsby now deployed and pulling content from a backend Strapi application, there are a few things you may wish to change about your project going forward.

### Shared application configuration

You can optionally combine the application configuration (`.platform/services.yaml`) for Gatsby
and Strapi into a [single configuration file](https://fixed.docs.upsun.com/create-apps/multi-app/project-structure.md#unified-app-configuration).
Like `.platform/services.yaml` and `.platform/routes.yaml`, this file is shared across the project and resides in the `.platform` subdirectory.
You need to explicitly define the source of each application.

### Multiple content sources

Gatsby supports pulling multiple sources into its build. This can include external services like Stripe, or additional backend CMSs for different sets of content. Like shown here with Strapi, you can branch off your repository and add an additional subdirectory that contains the codebase for another frontend.

### Plan size

As mentioned previously, you should have at least a Medium
 plan for your multi-app projects.
This size gives the project enough resources for all of your containers
as well as the memory necessary to actually pull content from Strapi into Gatsby during its build.

Keep in mind that the increased plan size applies only to your production environment,
and not to preview environments (which default to Standard
).
As you continue to work with Gatsby and a backend headless CMS,
you may want to [upsize your preview environments](https://fixed.docs.upsun.com/administration/pricing.md#preview-environments).


