> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 4 days, 4 languages, 4 frameworks, Day 3: GatsbyJS

> Explore how to run GatsbyJS, a Progressive Web App (PWA), on Platform.sh. Learn about JAMstack architecture and deploy your Gatsby site easily.

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["upsun"], date: "2019-02-28", image: "/images/posts/unknown/four-days-four-languages-four-frameworks-day-3-gatsbyjs-the-reactbased-static-site-generator/four-days-four-languages-four-frameworks-day-3-gatsbyjs-the-reactbased-static-site-generator.webp" }} />

<Tip>
  This post was originally published on the Platform.sh blog and reflects information from the time of publication.
</Tip>

It's day three of our four-part series of posts about running Static Site Generators (SSGs) and alternative Content Management Systems on Platform.sh. Today, we're looking at [GatsbyJS](https://gatsbyjs.org), an SSG publishing framework built on top of [React](https://reactjs.org) Facebook's Javascript library. What makes Gatsby unique and interesting is that it's written as a [Progressive Web App](https://en.wikipedia.org/wiki/Progressive_web_applications) (PWA).

Gatsby and other PWAs use a combination of client-side (Javascript) and server-side components, which can be both static assets and dynamic APIs. This gets to our third, three-letter-acronym: JAM or [JAMstack](https://jamstack.org/)—an architecture built on client-side Javascript, APIs, and Markup, as opposed to the LAMP (Linux, Apache, MySQL, PHP) server-side stack we know so well from Drupal, WordPress, and so on.

While Gatsby uses a different language (Javascript) and server-side framework (Node) than the other SSGs we're demonstrating, setting it up on Platform.sh is very similar to [how we ran Hugo](/posts/unknown/four-days-four-languages-four-frameworks-day-2-running-hugo), the Go-based SSG.

## Let's run GatsbyJS on Platform.sh

We'll start as we have before with a local version of our application. Since we're starting from scratch, we need a few prerequisites installed on our machine. If you have an existing Gatsby app, you can [skip ahead](#newproject). You can also download a [ready-to-run copy of a Gatsby](https://github.com/platformsh-templates/gatsby) project for Platform.sh, if that's more your speed.

### 1. Set up your local machine

You'll need four tools to deploy your Gatsby site on Platform.sh:

* Git: [install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) if it's not already on your machine
* Node 8+: [install node](https://nodejs.org/en/)
* npx: `sudo npm install -g npx`
* Optional (but really, you should): [the platform.sh cli tool](https://docs.platform.sh/gettingstarted/cli.html)

For each of these tools, please refer to their own install pages.

### 2. Bootstrap your GatsbyJS project

You need to create a new GatsbyJS folder from a template:

```sh theme={null}
$ npx gatsby new gatsby-hello https://github.com/gatsbyjs/gatsby-starter-blog
npx: installed 1384 in 33.248s
info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-blog.git
Cloning into 'gatsby-hello'...

...... (Lots of output here)

Initialized empty Git repository in /media/psh/customers/gatsby-hello/.git/
info Create initial git commit in gatsby-hello
```

You can now run the local development server:

```sh theme={null}
$ cd gatsby-hello && npm run develop

> gatsby-starter-blog@0.1.0 develop /media/psh/customers/gatsby-hello
> gatsby develop

... (Lots of output here)

You can now view Gatsby-starter-blog in the browser.

  http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema.

  http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use npm run build.

ℹ ｢wdm｣:
ℹ ｢wdm｣: Compiled successfully.
```

Browse [http://localhost:8000/](http://localhost:8000/) to check that everything is working as expected.

The `npx` template already creates a basic Git repository:

```
$ git log
commit cd34e2366e6c28de7e0db53b527d6d4ddb1b7952 (HEAD -> master)
Author: Guillaume Moigneu <***@platform.sh>
Date:   Mon Feb 18 12:33:26 2019 +0100

    Initial commit from Gatsby: (https://github.com/gatsbyjs/gatsby-starter-blog.git)
```

## <a name="#newproject"> </a>3. Create your Platform.sh project

Create a Platform.sh project by signing to [a trial account](https://auth.api.platform.sh/register?trial_type=general) or log in to your account.

Select a `Standard` project, then choose the region you want your project to be hosted in.

Review and validate. You can now access your newly provisioned project. On the wizard, click `Git remote` and copy it.

Add the remote to your local project:

```sh theme={null}
git remote add platform <project ID>@git.<region>.platform.sh:<project ID>.git
```

**Don't push anything for now**. You still need to add the Platform.sh configuration.

## 4. Set up the `.platform.app.yaml` configuration

Platform.sh relies on <a href="https://docs.platform.sh/overview/yaml/what-is-yaml.html">`yaml` configurations</a> to configure the different containers to deploy.
Create the `.platform.app.yaml` file at the root of your project, and add the following code:

```yaml theme={null}
# .platform.app.yaml

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

# The type key specifies the language and version for your application.
type: "nodejs:8.9"

# 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.
  build: |
    npm run build

# The size of the persistent disk of the application (in MB).
disk: 256

# The configuration of the application when it's exposed to the web.
web:
  commands:
    start: sleep infinity
  locations:
    "/":
      # The public directory of the application relative to its root.
      root: "public"
      index: ["index.html"]
      scripts: false
      allow: true
```

The `web` section is nearly identical to the [Hugo version](/posts/unknown/four-days-four-languages-four-frameworks-day-2-running-hugo). Really, serving any static site on Platform.sh is the same at runtime. The build hook is a bit simpler in this case as it need only run `npm run build` to compile Gatsby.

Because the container `type` is NodeJS, and the build flavor is left at the default, Platform.sh will automatically run `npm install` before the build hook automatically to ensure all dependencies are available.

We need also two other files: `routes.yaml` and `services.yaml`. `services.yaml` is used to configure additional services like databases, so we don't need it for that project. Just create the file:

```sh theme={null}
mkdir .platform
touch services.yaml
```

Add `routes.yaml` in the `.platform` folder, and add the following configuration:

```yaml theme={null}
"https://{default}/":
  type: upstream
  upstream: "gatsbyjs:http"
```

This file tells the Platform.sh router to direct all incoming requests to our `gatsbyjs` container. Commit these new files:

```sh theme={null}
git add .platform.app.yaml .platform
git commit -m "Add platform.sh configuration"
```

## 5. Test and deploy

You're now ready to deploy the project on Platform.sh. Push the repository to the new remote:

```sh theme={null}
git push platform master
```

Platform.sh will then build and deploy your Gatsby application, with the following output:

<div style={{overflowY: 'scroll', height: '5em'}}>
  ```sh theme={null}

  Counting objects: 44, done.
  Delta compression using up to 4 threads.
  Compressing objects: 100% (38/38), done.
  Writing objects: 100% (44/44), 1.04 MiB | 16.98 MiB/s, done.
  Total 44 (delta 2), reused 0 (delta 0)

  Validating submodules

  Validating configuration files

  Building application 'gatsbyjs' (runtime type: nodejs:8.9, tree: fafb3d4)
        Generating runtime configuration.

        Building a NodeJS application, let's make it fly.
        Found a `package.json`, installing dependencies.

          > sharp@0.21.3 install node_modules/sharp
          > (node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)
          ...
          up to date in 14.102s

          success open and validate gatsby-configs — 0.009 s
          success load plugins — 0.325 s
          success onPreInit — 0.895 s
          success delete html and css files from previous builds — 0.096 s
          success initialize cache — 0.016 s
          success copy gatsby files — 0.024 s
          success onPreBootstrap — 0.006 s
          success source and transform nodes — 0.104 s
          success building schema — 0.326 s
          success createPages — 0.056 s
          success createPagesStatefully — 0.032 s
          success onPreExtractQueries — 0.004 s
          success update schema — 0.185 s
          success extract queries from components — 0.134 s

          success run graphql queries — 0.694 s — 9/9 13.00 queries/second
          success write out page data — 0.012 s
          success write out redirect data — 0.001 s

          info bootstrap finished - 5.674 s

          done generating icons for manifest
          success onPostBootstrap — 0.287 s
          success Building production JavaScript and CSS bundles — 11.784 s
          success Building static HTML for pages — 0.844 s — 7/7 28.27 pages/second
          Generated public/sw.js, which will precache 11 files, totaling 283621 bytes.
          info Done building in 18.685 sec

           Executing pre-flight checks...

        Compressing application.
        Beaming package to its final destination.

      W: Route '{default}' doesn't map to a domain of the project, mangling the route.

      Provisioning certificates
        Validating 1 new domain
        Provisioned new certificate for 1 domains of this environment
        (Next refresh will be at 2019-04-20 20:19:01+00:00.)
        Environment certificates
        - certificate 18bf626: expiring on 2019-05-18 20:19:01+00:00, covering master-7rqtwti-<project ID>.<region>.platformsh.site

      Creating environment <project ID>-master-7rqtwti
        Environment configuration
          gatsbyjs (type: nodejs:8.9, size: M, disk: 5120)

        Environment routes
          http://master-7rqtwti-<project ID>.<region>.platformsh.site/ redirects to https://master-7rqtwti-<project ID>.<region>.platformsh.site/
          https://master-7rqtwti-<project ID>.<region>.platformsh.site/ is served by application `gatsbyjs`
  ```
</div>

Let's review the output of your `push`. After a basic Git push output, Platform.sh kicks in and runs the build script. Under where it says `Executing build hook` you can see it downloading npm packages and then running Gatsby.

```sh theme={null}
Building application 'gatsbyjs' (runtime type: nodejs:8.9, tree: fafb3d4)
      Generating runtime configuration.

      Building a NodeJS application, let's make it fly.
      Found a `package.json`, installing dependencies.

        > sharp@0.21.3 install node_modules/sharp
        > (node install/libvips && node install/dll-copy && prebuild-install) || (node-gyp rebuild && node install/dll-copy)
        ...
        up to date in 14.102s

        success open and validate gatsby-configs — 0.009 s
        success load plugins — 0.325 s
        success onPreInit — 0.895 s
        success delete html and css files from previous builds — 0.096 s
        success initialize cache — 0.016 s
        success copy gatsby files — 0.024 s
        success onPreBootstrap — 0.006 s
        success source and transform nodes — 0.104 s
        success building schema — 0.326 s
        success createPages — 0.056 s
        success createPagesStatefully — 0.032 s
        success onPreExtractQueries — 0.004 s
        success update schema — 0.185 s
        success extract queries from components — 0.134 s

        success run graphql queries — 0.694 s — 9/9 13.00 queries/second
        success write out page data — 0.012 s
        success write out redirect data — 0.001 s

        info bootstrap finished - 5.674 s

        done generating icons for manifest
        success onPostBootstrap — 0.287 s
        success Building production JavaScript and CSS bundles — 11.784 s
        success Building static HTML for pages — 0.844 s — 7/7 28.27 pages/second
        Generated public/sw.js, which will precache 11 files, totaling 283621 bytes.
        info Done building in 18.685 sec
```

(It's not as fast as Hugo, but still decently fast.)

Platform.sh then checks that everything seems correct and deploys the container to a host. Again, it generates Let's Encrypt TLS certificates for every route automatically and ends with the URLs of the application:

```sh theme={null}
      Environment routes
        http://master-7rqtwti-<project ID>.<region>.platformsh.site/ redirects to https://master-7rqtwti-<project ID>.<region>.platformsh.site/
        https://master-7rqtwti-<project ID>.<region>.platformsh.site/ is served by application `gatsbyjs`
```

The last output is your application's new URL. You can also check that the project has been successfully deployed on the web interface. If you've got the Platform.sh CLI installed, jumping to the web interface from your project is simple; no need to remember project IDs, just type `platform web`.

Now your basic GatsbyJS site is up and running!

As a side note, we've been focused this week on showing how you can run alternate frameworks and a variety of languages on Platform.sh. Did you know that you can run multiple applications inside the same project? This [multi-app setup](https://docs.platform.sh/configuration/app/multi-app.html#multiple-applications) is a subject for another post, however it's worth noting that combining purpose-built services, like a site built with an SSG, with a blog powered by WordPress, or a headless e-commerce back end powered by Magento or Drupal Commerce, is quite straightforward. Gatsby makes it especially easy, since it's client-side framework was designed to consume APIs directly.

**Tomorrow**, we'll take a look at our final SSG, and the most popular, [Jekyll](https://jekyllrb.com/) a SSG written in Ruby.

Read the series: *Four days, four languages, four frameworks*

1. Day 1, Java: [Running Brightspot CMS on Platform.sh](/posts/unknown/four-days-four-languages-four-frameworks-on-platformsh)
2. Day 2, Go: [Hugo, a fast static site generator](/posts/unknown/four-days-four-languages-four-frameworks-day-2-running-hugo)
