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)
-
Configure your site URL in
usr/user.config.mjs:export const siteMetadata = {siteUrl: 'https://username.github.io/repo-name',} -
Create GitHub Actions workflow: Create
.github/workflows/deploy.yml:name: Deploy to GitHub Pageson:# Runs on pushes targeting the default branchpush:branches: ["main"]# Allows you to run this workflow manually from the Actions tabworkflow_dispatch:# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pagespermissions:contents: readpages: writeid-token: write# Allow only one concurrent deploymentconcurrency:group: "pages"cancel-in-progress: falsejobs:build:runs-on: ubuntu-lateststeps:- name: Checkoutuses: actions/checkout@v4- name: Setup Nodeuses: actions/setup-node@v4with:node-version: "20"cache: npm- name: Install dependenciesrun: npm ci- name: Build with Astrorun: npm run build- name: Upload artifactuses: actions/upload-pages-artifact@v3with:path: ./distdeploy:environment:name: github-pagesurl: ${{ steps.deployment.outputs.page_url }}runs-on: ubuntu-latestneeds: buildsteps:- name: Deploy to GitHub Pagesid: deploymentuses: actions/deploy-pages@v4 -
Enable GitHub Pages in repo settings:
- Settings → Pages → Source: GitHub Actions
-
Push to GitHub - automatic deployment on every push
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
usr/content/config.ts:
import { defineCollection } from 'astro:content';import { directusLoader } from '@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 inusr/public/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
s:CMS uses a core/usr architecture that keeps framework updates separate from your content.
First Time Setup
After creating your site from the template:
npm run setup-upstreamThis configures the connection to receive s:CMS updates.
Updating to Latest Version
npm run update-coreThis script will:
- Create a backup of your current code
- Fetch the latest s:CMS version
- Merge updates while protecting your
usr/folder - Install new dependencies if needed
Your content and customizations in usr/ are never overwritten! 🛡️
What Gets Updated
| Path | Status | Description |
|---|---|---|
core/** | ✅ Updated | Framework components & utilities |
usr/** | 🛡️ Protected | Your content & customizations |
package.json | ⚠️ Review | May need manual dependency merge |
astro.config.mjs | ✅ Auto-merges | Uses coreConfig + userConfig pattern |
Detailed Documentation
For complete update instructions, troubleshooting, and conflict resolution:
Best Practices
- Update regularly - Smaller updates are easier to merge
- Test locally - Always run
npm run devafter updating - Read changelogs - Review what’s changing in each release
- Don’t edit core/ - Make all customizations in
usr/
Need help? Check out docs/UPDATING.md for detailed instructions!