Skip to content

Statamic Guide

Statamic is a powerful flat-file CMS that’s perfect for the Webslice Serverless platform. With proper configuration, you can achieve excellent performance and keep costs low by leveraging Statamic’s built-in static caching features. This guide will walk you through deploying and optimizing your Statamic site on Webslice Serverless.

Before You Begin

This guide assumes you already have a Statamic site ready to deploy. If you’re starting fresh, check out the official Statamic documentation to get your site set up locally first.

Key Concepts for Serverless Deployments

Atomic Git Deployments

When you deploy to Webslice Serverless via git, your deployments are atomic. This means:

  • Each deployment is built in isolation and switched over instantly when ready
  • There’s no downtime during deployments
  • If a deployment fails, your previous version continues running
  • Your live site always has a complete, working codebase

This is important for Statamic because it means you can confidently deploy updates without worrying about incomplete file uploads or partial deployments interrupting your site.

Understanding Storage and Atomic Deployments

Because deployments are atomic, each deployment brings a fresh copy of your git repository. This means:

  • Your application directory is replaced entirely with each deployment
  • Any files written to your application directory during runtime (uploads, cache, logs) will be lost on the next deployment
  • Files not in your git repository won’t carry over between deployments

That’s where the /mnt/data/website/shared directory comes in – it’s a persistent directory that exists outside your application’s deployment directory and survives across all deployments. This is where you store user-generated content, uploads, caches, and anything else that needs to persist between deployments.

Configuration for Optimal Performance

Static Caching Setup

Statamic’s static caching is your best friend on a serverless platform. It pre-generates HTML files for your pages, which means:

  • Lightning-fast page loads
  • Minimal PHP execution
  • Lower costs (fewer invocations)
  • Better performance under traffic spikes

First, enable static caching in your config/statamic/static_caching.php:

config/statamic/static_caching.php
return [
'strategy' => 'full',
'strategies' => [
'full' => [
'driver' => 'file',
'path' => storage_path('statamic/static'),
'lock_hold_length' => 0,
'permissions' => [
'directory' => 0755,
'file' => 0644,
],
'warm_concurrency' => 25,
'warm_queue' => env('STATAMIC_STATIC_WARM_QUEUE'),
],
],
'servers' => [],
'invalidation' => [
'class' => null,
'rules' => 'all',
],
'ignores' => null,
'replacers' => [
'csrf' => \Statamic\StaticCaching\Replacers\CsrfTokenReplacer::class,
'nocache' => \Statamic\StaticCaching\Replacers\NoCacheReplacer::class,
],
'warm_queued' => true,
];

The key settings here are:

  • strategy set to 'full' for maximum caching
  • driver set to 'file' which works well on serverless
  • warm_concurrency at 6 for efficient cache warming

Environment Variables

Add these to your .env file:

.env
STATAMIC_STATIC_CACHING_STRATEGY=full
STATAMIC_STATIC_WARM_QUEUE=true
STATAMIC_STACHE_WATCHER=file
STATAMIC_REVISIONS_ENABLED=false

These settings optimize Statamic for serverless deployments by enabling full static caching and disabling features that work better with persistent file systems.

Persistent Storage Configuration

Directory Structure

You’ll want to store several types of data in the persistent /mnt/data/website/shared directory:

  • Directorymnt/website/shared/
    • Directoryassets/ Asset containers (images, documents, etc.)
    • Directoryforms/ Form submissions
    • Directoryglide-cache/ Image manipulation cache
    • Directorylogs/ Application logs
    • Directoryusers/ User accounts and data

To make these directories accessible to your Statamic application, you’ll create symlinks from your application to the shared directory. The best way to do this is in a deployment script.

Create a .webslice/build.sh file in your repository:

.webslice/build.sh
#!/bin/bash
# Create shared directories if they don't exist
mkdir -p /mnt/data/website/shared/assets
mkdir -p /mnt/data/website/shared/forms
mkdir -p /mnt/data/website/shared/glide-cache
mkdir -p /mnt/data/website/shared/logs
mkdir -p /mnt/data/website/shared/users
# Remove existing directories/links from the build
rm -rf storage/app/forms
rm -rf storage/app/glide
rm -rf storage/logs
rm -rf public/assets/images
# Create symlinks to persistent storage
ln -sf /mnt/data/website/shared/forms storage/app/forms
ln -sf /mnt/data/website/shared/glide-cache storage/app/glide
ln -sf /mnt/data/website/shared/logs storage/logs
ln -sf /mnt/data/website/shared/assets/images public/assets/images
ln -sf /mnt/data/website/shared/users users
echo "✓ Symlinks created successfully"

Make the script executable:

Terminal window
chmod +x .webslice/deploy.sh

This script runs automatically during deployment and ensures your persistent data is properly linked.

Asset Container Configuration

Update your asset container configuration to use the symlinked directory. In content/assets/assets.yaml (or wherever your asset container is configured):

content/assets/assets.yaml
title: Assets
disk: assets
allow_uploads: true
allow_downloading: true
allow_renaming: true
allow_moving: true

Then ensure your config/filesystems.php has the assets disk properly configured:

config/filesystems.php
'disks' => [
'assets' => [
'driver' => 'local',
'root' => public_path('assets'),
'url' => '/assets',
'visibility' => 'public',
],
// ... other disks
],

Since public/assets is symlinked to /mnt/data/website/shared/assets, all your uploaded assets will persist across deployments.

Cache Warming for Peak Performance

Cache warming is the process of pre-generating your static cache files. This is crucial because:

  • The first visitor to a page shouldn’t have to wait for it to be cached
  • You want all pages cached before traffic hits your site
  • It ensures consistent performance from the moment you deploy

The Release Script

Create a .webslice/release.sh file to warm your cache after each deployment:

.webslice/release.sh
#!/bin/bash
echo "Starting cache warming..."
# Clear any existing cache to ensure fresh generation
php artisan cache:clear
php artisan statamic:stache:clear
php artisan statamic:static:clear
# Warm the static cache
php artisan statamic:static:warm --queue
echo "✓ Cache warming initiated"
echo "✓ Release complete"

Make it executable:

Terminal window
chmod +x .webslice/release.sh

This script runs after your deployment goes live. The --queue flag means the warming happens in the background, so your deployment completes quickly, but your cache gets fully warmed shortly after.

Manual Cache Warming

You can also manually warm your cache at any time using the Statamic CLI:

Terminal window
php artisan statamic:static:warm

Or from the Statamic Control Panel, navigate to Utilities → Static Caching and click “Warm Cache”.

Forms and Submissions

If you’re using Statamic’s built-in forms, you need to ensure submissions are stored in persistent storage.

In your config/statamic/forms.php:

config/statamic/forms.php
return [
'default' => 'file',
'drivers' => [
'file' => [
'storage' => 'forms',
],
],
];

And in config/filesystems.php, add a forms disk:

config/filesystems.php
'disks' => [
'forms' => [
'driver' => 'local',
'root' => storage_path('app/forms'),
],
// ... other disks
],

Since we symlinked storage/app/forms to /mnt/data/website/shared/forms in our deploy script, all form submissions will be preserved across deployments.

Image Manipulation (Glide)

Statamic uses Glide for on-the-fly image manipulation. To prevent regenerating these cached images on every deployment:

In your config/statamic/assets.php:

config/statamic/assets.php
return [
'image_manipulation' => [
'driver' => 'gd', // or 'imagick' if available
'cache' => true,
'cache_path' => storage_path('app/glide'),
'presets' => [
// Your image presets
],
],
];

The storage/app/glide directory is symlinked to /mnt/data/website/shared/glide-cache, so transformed images persist across deployments.

Git Ignore Configuration

Since we’re storing certain directories in persistent storage, you should ensure they’re in your .gitignore:

.gitignore
/vendor
/node_modules
.env
.DS_Store
# Persistent storage directories (handled via symlinks)
/public/assets/*
!/public/assets/.gitkeep
/storage/app/forms
/storage/app/glide
/storage/logs/*
!/storage/logs/.gitkeep
/users/*
!/users/.gitkeep
# Statamic caches
/storage/statamic/*
!/storage/statamic/.gitkeep

You can include .gitkeep files to maintain the directory structure in git without committing the contents.

Deployment Checklist

When deploying your Statamic site to Webslice Serverless, follow these steps:

  1. Configure static caching in config/statamic/static_caching.php with the full strategy

  2. Create deployment script at .webslice/deploy.sh to set up symlinks to /mnt/data/website/shared

  3. Create release script at .webslice/release.sh to warm your static cache

  4. Make scripts executable with chmod +x .webslice/deploy.sh .webslice/release.sh

  5. Update asset containers to use the symlinked directories

  6. Configure forms to store in persistent storage if using Statamic forms

  7. Set up Glide cache in persistent storage for image transformations

  8. Update .gitignore to exclude symlinked directories

  9. Test locally to ensure symlinks work and cache warms correctly

  10. Deploy and monitor the first deployment to ensure cache warming completes

Performance Tips

Maximize Static Caching

The more pages you can statically cache, the better your performance and lower your costs. Consider:

  • Caching all public-facing pages
  • Using AJAX for dynamic elements on otherwise static pages
  • Leveraging the nocache tag for small dynamic sections within cached pages

Example using the nocache tag:

templates/blog/show.antlers.html
{{ nocache }}
<p>You are visitor number {{ visits }} to this page</p>
{{ /nocache }}
<article>
<!-- Rest of your cached content -->
</article>

Optimize Assets

Since serverless environments bill by execution time:

  • Use responsive images to serve appropriately-sized files
  • Implement lazy loading for images below the fold
  • Consider using a CDN for assets (though static caching helps significantly)

Monitor Cache Hit Rates

Keep an eye on how well your static cache is performing. You can add custom logging to track cache hits vs. misses and optimize accordingly.

Troubleshooting

Cache Not Warming

If your static cache isn’t warming:

  1. Check that .webslice/release.sh is executable
  2. Review deployment logs for errors during the release phase
  3. Try manually warming: php artisan statamic:static:warm
  4. Check that your routes are discoverable (Statamic crawls from the homepage)

Files Not Persisting

If uploads or form submissions aren’t persisting:

  1. Verify symlinks are pointing to /mnt/data/website/shared/*
  2. Check file permissions: ls -la /mnt/data/website/shared/
  3. Ensure directories exist before symlinking in your deploy script

Advanced Configuration

Then in your environment variables:
```bash title=".env.production"
STATAMIC_STATIC_CACHING_STRATEGY=full
STATAMIC_WARM_CONCURRENCY=50
.env.staging
STATAMIC_STATIC_CACHING_STRATEGY=half
STATAMIC_WARM_CONCURRENCY=10

Custom Cache Warming

For large sites, you might want more control over cache warming. Create a custom command:

app/Console/Commands/WarmStaticCacheSelectively.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Statamic\Facades\Entry;
class WarmStaticCacheSelectively extends Command
{
protected $signature = 'custom:warm-cache';
protected $description = 'Warm static cache for high-priority pages first';
public function handle()
{
$this->info('Warming high-priority pages...');
// Warm homepage and main pages first
$priorityUrls = ['/', '/blog', '/about', '/contact'];
foreach ($priorityUrls as $url) {
\Artisan::call('statamic:static:warm', [
'--url' => $url,
]);
}
$this->info('High-priority pages warmed.');
// Then warm all blog posts
$this->info('Warming blog posts...');
Entry::query()
->where('collection', 'blog')
->get()
->each(function ($entry) {
\Artisan::call('statamic:static:warm', [
'--url' => $entry->url(),
]);
});
$this->info('Cache warming complete!');
}
}

Then call this from your .webslice/release.sh:

.webslice/release.sh
#!/bin/bash
echo "Starting selective cache warming..."
php artisan custom:warm-cache
echo "✓ Release complete"

Conclusion

With proper configuration, Statamic runs beautifully on Webslice Serverless. The combination of:

  • Static caching for performance
  • Persistent storage for user data
  • Atomic deployments for reliability
  • Cache warming for consistent speed

…gives you a fast, cost-effective, and robust hosting solution for your Statamic sites.

The key is embracing the serverless model: keep your application code ephemeral and stateless, store persistent data in /mnt/data/website/shared, and leverage static caching to minimize PHP execution. Follow these patterns, and you’ll have a Statamic site that’s both performant and economical to run.