App Platform: Hosting static NextJS projects

App Platform, DigitalOcean, NextJS

App Platform has great support for static sites, building and pushing projects to over 100 points of presence around the world ensuring the fastest load times for users. NextJS is provides a great developer experience, however opinionated and can require some unique platform services to be hosted while remaining free or very low cost.

App Platform does not employ this functionality (as of today) but that's not an issue because this can be worked around!

NextJS configurations

In your next.config.js folder you're going need a couple additions:

// next.config.js
module.exports = {
    /**
     * NextJS requires serverside components to do image optimization.
     * Unfortunately, hosting via SSG/Static means you will miss out on
     * this utility which will provide appropriately sized images for
     * the devices users are accessing your app from.
     * 
     * As a side note, you can write a custom image loader which
     * reimplements this functionality but that is beyond the scope of
     * this article.
     */
    images: {
        unoptimized: true,
    },

    /**
     * Trailing slashes places the generated pages of a nextjs app
     * within a folder.
     * 
     * Eg. instead of having an `about.html` a `about/index.html` will
     * be generated.
     * 
     * This provides pretty urls, so instead of
     * `your-app.com/about.html` you'll have `your-site.com/about`.
     * 
     * This is optional.
     */
    trailingSlash: true,
}

In addition you will need to update the build command that is used to generate your app. This can be done in a few different places, I prefer to add it to my package.json:

{
    // ...
    "scripts": {
        // .../
        "build": "next build && next export -o build",
        // ...
    },
    // ...
}

Note the -o build argument, this will put your static site in a build directory. It's a good idea to add this to your .gitignore.

App Platform configurations

Create your app using the wizard in the DigitalOcean Apps cloud dashboard. Ensure that you use the appropriate build command, eg from above:

npm run build

You will need to set your catchall in Settings > <your_component> > Custom Pages. Set this value to index.html.

Some NextJS apps will require a NEXT_PUBLIC_SITE_URL environment variable. With App Platform bind variables can be used to create an environment variable for your static site component like:

NEXT_PUBLIC_SITE_URL=${APP_URL}

Note: ${APP_URL} will be auto-filled with the apps primary URL whether that is a custom URL or the provided some-value.ondigitalocean.app domain.

Finally, ensure that your output directory in the same component settings from above is set to the build directory. If you used my example above of -o build then this directory will be build.

App Platform apps are described via an app spec, here's an example app spec that is configured for a NextJS SSG project (it's this site 😉).

domains:
- domain: jonfriesen.ca
  type: PRIMARY
  zone: jonfriesen.ca
name: portfolio
region: tor
static_sites:
- build_command: npm run build
  catchall_document: index.html
  environment_slug: node-js
  envs:
  - key: NEXT_PUBLIC_SITE_URL
    scope: BUILD_TIME
    value: ${APP_URL}
  github:
    branch: main
    deploy_on_push: true
    repo: jonfriesen/jonfriesen.ca
  name: portfolio
  output_dir: build
  routes:
  - path: /
  source_dir: /