arch

The Perfectionist's Guide to Deploying a Statamic Website to Vercel

Note: In order to break the habit of perfectionism and ship more work, I have decided to publish drafts even if they are not fully complete. If you’re a perfectionist like me and came here because of the article’s title, maybe the joke’s on you. But try this hack and you’ll thank me at some point even if you’re cursing me right now.


I've used Statamic to build this website and Vercel to host it on the internet. Statamic is a PHP-based content management system (CMS) built on top of Laravel. Vercel, for our use-case, is a cloud platform that converts a project to static files (only HTML, CSS and JS—no server-side logic), hosts them and then distributes them over the web through its CDN.

I’m writing this article to serve as a guide for myself and others when we get stuck with the deployment process or see my Vercel builds failing in the future.

Why Vercel?

The biggest reason to use Vercel is to save time, effort and money. I did not want the overhead of running and maintaining a traditional server or a VPS. I am the only author on my website and my website doesn’t have any elements that need to communicate to a backend (like a form or an API-based fetching system). It would work perfectly well as a set of static files . Additionally, Vercel has a generous-enough free plan for non-commercial use that fits my website well.

The bigger question for me was whether to use Netlify or Vercel. Netlify is a Vercel alternative and was my first choice for hosting my website since I had used it a lot in the past to host websites built using Eleventy. However, it turned out that there was no easy way to remove trailing slashes from page URLs on Netlify and that Statamic doesn’t support trailing slashes in URLs, making it seem that Statamic and Netlify are incompatible. Vercel, on the other hand, offered a simple option to remove trailing slashes. There was no real choice.

Screenshot of Statamic's development roadmap
Support for trailing slashes is still on the roadmap for Statamic.

How to Deploy

Vercel has a build pipeline that allows projects to be converted to static files. Builds can be triggered manually as well as automatically, for example when code is pushed to a particular branch in your GitHub repository. That way, the only command you need to run to deploy the latest changes to your website would be git push. Vercel will take care of everything else.

Taking from Statamic’s Vercel deployment guide:

  • Create a script called ./build.sh and paste in the code snippet mentioned below. An aside: I personally like to organise my project meticulously and avoid storing files in the project root folder—I store them in ./server/vercel.sh.

  • Make the script an executable using chmod +x build.sh or chmod +x server/vercel.sh if you saved your file like me (assuming your terminal’s working directory is the project’s root folder).

  • Create a new site in your Vercel account.

  • Add the build command ./build.sh.

  • Set output directory to storage/app/static.

  • Add environment variable in your project settings: APP_KEY (copy & paste from dev).

Add the following snippet to build.sh file to install PHP, Composer, and run the ssg:generate command:

#!/bin/sh
 
# Install PHP & WGET
yum install -y amazon-linux-extras
amazon-linux-extras enable php8.2
yum clean metadata
yum install php php-{common,curl,mbstring,gd,gettext,bcmath,json,xml,fpm,intl,zip,imap}
yum install wget
 
# INSTALL COMPOSER
EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
 
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
    >&2 echo 'ERROR: Invalid installer checksum'
    rm composer-setup.php
    exit 1
fi
 
php composer-setup.php --quiet
rm composer-setup.php
 
# INSTALL COMPOSER DEPENDENCIES
php composer.phar install
 
# GENERATE APP KEY
php artisan key:generate
 
# BUILD STATIC SITE
php please ssg:generate

Work in Progress

This post is incomplete. I’ll add to it soon. Please feel free to bug me on Twitter (I still feel odd saying X) on @4rchi7 to take this to some level of completion.