Quick Start - Deploy Your Site
s:CMS can be deployed to any static hosting platform. Choose your preferred option below.
GitHub Pages
Option 1: GitHub Actions (Recommended)
The template already ships a working workflow at .github/workflows/deploy.yml (Node 22, builds with npm run build, deploys dist/ via actions/deploy-pages). You normally only need to:
-
Configure your site URL in
src/user.config.mjs:export const userConfig = {site: 'https://username.github.io/repo-name',base: '/repo-name', // omit if deploying to a custom domain or a user/org root site} -
Enable GitHub Pages in repo settings:
- Settings → Pages → Source: GitHub Actions
-
Push to GitHub - automatic deployment on every push
If you need to customize the workflow (different Node version, extra build steps, environment secrets), edit .github/workflows/deploy.yml directly — it’s a normal file in your repo, nothing special touches it.
Option 2: Manual Build & Deploy
npm run build# Upload dist/ folder to GitHub Pages via gh-pages branchnpx gh-pages -d distNetlify
- Connect your GitHub repository
- Build settings:
- Build command:
npm run build - Publish directory:
dist
- Build command:
- Deploy
With Environment Variables:
[build] command = "npm run build" publish = "dist"
[build.environment] NODE_VERSION = "20"
# Optional: Set environment variables# DIRECTUS_URL = "https://your-directus.com"# DIRECTUS_TOKEN = "your-token"Vercel
- Import your GitHub repository
- Framework Preset: Astro
- Deploy
With Environment Variables:
{ "buildCommand": "npm run build", "outputDirectory": "dist", "framework": "astro"}Add secrets in Vercel dashboard: Settings → Environment Variables
Cloudflare Pages
- Connect your GitHub repository
- Build settings:
- Build command:
npm run build - Build output directory:
dist
- Build command:
- Deploy
With Environment Variables: Add in Cloudflare dashboard: Settings → Environment variables
Traditional Hosting (FTP/SSH)
# Build locallynpm run build
# Upload dist/ folder to your server# Via FTP, rsync, or your hosting panelManaging Secrets & Environment Variables
If your site uses Directus, external APIs, or other services requiring credentials, never commit secrets to your repository.
Local Development
Create .env file (gitignored by default):
DIRECTUS_URL=https://your-directus-instance.comDIRECTUS_TOKEN=your_secret_tokenPUBLIC_SITE_URL=http://localhost:4321Access in your code:
import.meta.env.DIRECTUS_URLimport.meta.env.DIRECTUS_TOKENimport.meta.env.PUBLIC_SITE_URL // Available in client codeDeployment Platform Setup
GitHub Actions:
Add secrets to your repository:
- Go to: Settings → Secrets and variables → Actions
- Click “New repository secret”
- Add your secrets (e.g.,
DIRECTUS_TOKEN)
Update your GitHub Actions workflow to use secrets:
jobs: build: runs-on: ubuntu-latest steps: # ... other steps ...
- name: Build with Astro run: npm run build env: DIRECTUS_URL: ${{ secrets.DIRECTUS_URL }} DIRECTUS_TOKEN: ${{ secrets.DIRECTUS_TOKEN }} PUBLIC_SITE_URL: ${{ vars.PUBLIC_SITE_URL }}Note: Use secrets for sensitive data, vars for non-sensitive configuration.
Platform-Specific Secrets
Netlify:
- Dashboard → Site settings → Environment variables
- Or via
netlify.toml:
[context.production.environment] PUBLIC_SITE_URL = "https://yourdomain.com"Vercel:
- Dashboard → Project Settings → Environment Variables
- Set for: Production, Preview, Development
Cloudflare Pages:
- Dashboard → Settings → Environment variables
- Separate settings for Production and Preview
Security Best Practices
- ✅ Never commit
.envfiles - Already in.gitignore - ✅ Use
PUBLIC_prefix for client-side variables only - ✅ Rotate secrets regularly - Especially after team changes
- ✅ Use different secrets per environment - Production vs. Preview
- ❌ Don’t log secrets - Be careful with console.log in production
- ❌ Don’t expose server-side secrets - Keep them in
.env, not in public code
Example: Directus Integration with Secrets
src/content.config.ts:
import { defineCollection } from 'astro:content';import { directusLoader } from '@lad-sapienza/scms-core/integrations/directusLoader';
const articlesCollection = defineCollection({ loader: directusLoader({ url: import.meta.env.DIRECTUS_URL, token: import.meta.env.DIRECTUS_TOKEN, collection: 'articles', }),});
export const collections = { articles: articlesCollection,};Required secrets:
DIRECTUS_URL- Your Directus instance URLDIRECTUS_TOKEN- Static token with read permissions
Custom Build Scripts
Add to package.json:
{ "scripts": { "build:prod": "astro check && astro build", "build:preview": "astro build --mode preview", "deploy": "npm run build && npx gh-pages -d dist" }}Continuous Deployment Options
Option 1: Direct Git Push
- GitHub Pages, Netlify, Vercel auto-deploy on git push
Option 2: GitHub Actions (Custom)
Create .github/workflows/deploy.yml with your platform-specific deployment
Option 3: Platform CLI
# Netlifynpm install -g netlify-clinetlify deploy --prod
# Vercelnpm install -g vercelvercel --prodTroubleshooting Deployment
Build Fails
Check Node version:
- name: Setup Node uses: actions/setup-node@v4 with: node-version: "20" # Match your local versionCheck dependencies:
rm -rf node_modules package-lock.jsonnpm installnpm run buildSite Shows 404
For GitHub Pages project sites, set base in astro.config.mjs:
export default { site: 'https://username.github.io', base: '/repo-name',}For custom domains, no base needed:
export default { site: 'https://yourdomain.com',}Environment Variables Not Working
- ✅ Restart dev server after adding
.env - ✅ Use
PUBLIC_prefix for client-side access - ✅ Check variable names match exactly (case-sensitive)
- ✅ Verify secrets are set in deployment platform
Images Not Loading
Check image paths:
- Use
/images/photo.jpgfor files inpublic/images/ - Use relative paths
./photo.jpgfor images next to content - Astro optimizes images automatically
Performance Optimization
Build Optimization
export default { build: { inlineStylesheets: 'auto', }, image: { service: { entrypoint: 'astro/assets/services/sharp', }, },}Caching Strategy
For GitHub Actions:
- name: Setup Node uses: actions/setup-node@v4 with: node-version: "20" cache: npm # Caches node_modulesFor Netlify/Vercel:
- Built-in caching enabled automatically
- Clear cache in settings if needed
Keeping s:CMS Up-to-Date
The s:CMS framework layer is the @lad-sapienza/scms-core npm package — updating it is an ordinary dependency update, not a custom script.
npm update @lad-sapienza/scms-coreYour content and customizations in src/ are never touched, because the framework was never part of this repository to begin with — it lives entirely in node_modules. See Updating for checking what’s new before you update.
Best Practices
- Update regularly - Smaller updates are easier to review
- Test locally - Always run
npm run devafter updating - Read changelogs - Review what’s changing in each release
Need help? Check out docs/UPDATING.md for detailed instructions!