Published on

SvelteKit Hosting Setup with WPEngine Atlas

Authors

Overview

This is a quick tutorial that documents how I was able to get a SvelteKit headless Wordpress site running on WPEngine's Atlas hosting platform. As of this writing, I was implementing things with SvelteKit at version 1.0.0-next.288. It should be noted that SvelteKit is moving at breakneck speed, and many of the details here will likely become irrelevant at some future point.

Motivation

I struggled to find many good hosting setup walkthroughs with SvelteKit and stumbled through several issues to get this working myself. It seemed like a worthy topic to document. I did benefit from Nostro's article on getting SvelteKit running on Heroku. (Which I used initially before moving to Atlas)

Why WPEngine Atlas?

WPEngine is one of the leading Wordpress hosts today. I prefer managed service providers for hosting, especially for client work. Atlas is their relatively new service for running headless Wordpress websites. It is essentially a node runtime environment that sits alongside the Wordpress installation, all wrapped up in one neat hosting package. For the purposes of this article I am focusing on just the hosting configuration setup and a few gotchas I ran into. I'll save the headless configuration bits for another post.

Lack of Subdirectory Support

Right off the bat Atlas does not support repositories that have a nested web project root which was the case for my project. This is something their team has on the roadmap but for now I needed to hack around this. The structure of my repository looks like this:

www - SvelteKit project root sits here
cms - Wordpress specific files live in here

On Heroku you can configure a subdirectory with a subdirectory module and Vercel just has a simple setting for this which is the way I hope WPEngine supports it with Atlas. So we need to get this working, my method is to simple copy everything up a level after the build is run.

In our root of the project we have a package.json that looks like this:

{
    "name": "SvelteKit Headless Site",
    "version": "0.0.1",
    "engines": {
        "node": "=16.14.2"
    },
    "scripts": {
        "wpe-build": "cd www && npm install && npm run build-for-containers",
        "start": "npm start"
    },
    "dependencies": {
        "fs-extra": "10.0.1"
    }
}

wpe-build is a special script that Atlas looks for to kick things off after it runs a npm install. We go into our www directory and kick off the build process. Here we have the full project package.json but the important bits for this article happen in the scripts section:

{
  "name": "SvelteKit Headless Site",
  "version": "0.0.1",
  "engines": {
    "node": "=16.14.2"
  },
  "volta": {
    "node": "16.14.2"
  },
  "type": "module",
  "scripts": {
    "dev": "concurrently \"npm run compile:sass:watch\" \"svelte-kit dev --https -o\"",
    "build": "sass ./src/styles/scss/application.scss ./src/styles/application.css && svelte-kit build",
    "build-for-containers": "sass ./src/styles/scss/application.scss ./src/styles/application.css && svelte-kit build && cd ../ && node move-www-to-root.cjs",
    "start": "node build/index.js",
    "package": "svelte-kit package",
    "preview": "svelte-kit preview",
    "check": "svelte-check --tsconfig ./tsconfig.json",
    "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
    "lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
    "format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. .",
    "compile:sass": "sass ./src/styles/scss/application.scss ./src/styles/application.css",
    "compile:sass:watch": "sass --watch ./src/styles/scss/application.scss ./src/styles/application.css"
  },
  "dependencies": {
    "classnames": "2.3.1",
    "concurrently": "7.0.0",
    "qs": "6.10.3",
    "seedrandom": "3.0.5",
    "stackblur-canvas": "2.5.0",
    "svelte-inview": "3.0.0",
    "url-parse": "1.5.10"
  },
  "devDependencies": {
    "@fullhuman/postcss-purgecss": "4.1.3",
    "@sveltejs/adapter-node": "1.0.0-next.70",
    "@sveltejs/kit": "1.0.0-next.288",
    "@typescript-eslint/eslint-plugin": "5.10.1",
    "@typescript-eslint/parser": "5.10.1",
    "autoprefixer": "10.4.2",
    "cssnano": "5.1.0",
    "eslint": "7.32.0",
    "eslint-config-prettier": "8.3.0",
    "eslint-plugin-svelte3": "3.2.1",
    "fs": "0.0.1-security",
    "postcss": "8.4.8",
    "postcss-load-config": "3.1.3",
    "prettier": "2.5.1",
    "prettier-plugin-svelte": "2.5.0",
    "sass": "1.49.9",
    "svelte": "3.44.0",
    "svelte-check": "2.2.6",
    "svelte-preprocess": "4.10.1",
    "tslib": "2.3.1",
    "typescript": "4.5.4"
  }
}

build-for-containers here is a separate build script here that contains a call to copy the build directory up to the root after the build completes. You'll want the details of this script as well:

const fs = require('fs-extra');

fs.copy('./www', './', { overwrite: true }, err => {
  if(err) return console.error(err);
  console.log("success, www folder moved to root!")
});

Yeah, this is really hack, but it actually works and doesn't disrupt local development or the existing project structure.

SvelteKit Specific bits

For the most part everything with SvelteKit worked. The important parts to call out where I stumbled, is around the adapters. @sveltejs/adapter-node is very important versus the auto adapter you'll probably encounter in most tutorials. Pay close attention to versions here. The version combination above in my package files worked for me, but it took some alignment to get around a few known issues that the SvelteKit team seems to be working actively on.

Envirionment Variables

With this basic headless site there are only 2 environment variables configured in Atlas, pretty simple. The first is a graphql endpoint for the Wordpress content data. The second is the base URL stored in VITE_PUBLIC_BASE_PATH (which should be set to your domain - e.g. https://www.jimmysquires.com)

That's it! Hopefully at this point you should have a site running on WPEngine Atlas. The directory copy is pretty hack I admin, but a nice quick workaround.