Déploiement

Un build sitelo, ce sont de simples fichiers statiques : sitelo build écrit du HTML, du CSS et du JS dans dist/. N’importe quel hébergeur statique convient — les configurations ci-dessous supposent seulement npm run build → dist/.

Les URL propres sont des répertoires contenant un index.html (/about/index.html → /about), donc les jolies URL fonctionnent d’emblée, sans règle de redirection. Un 404.html est émis automatiquement — la convention que comprennent Netlify, Cloudflare Pages et GitHub Pages.

Des versions prêtes à copier de tout ceci sont fournies dans l’exemple de base (examples/basic dans le dépôt).

Hébergeurs statiques

Ces hébergeurs compilent le site et servent dist/ depuis leur propre CDN.

Netlify · Vercel · Cloudflare · AWS Amplify · AWS S3 + CloudFront · Azure Static Web Apps · Firebase Hosting · GitHub Pages · GitLab Pages · Render · DigitalOcean App Platform

Netlify

[build]
  command = "npm run build"
  publish = "dist"

Vercel

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "framework": null,
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "installCommand": "npm install"
}

Cloudflare

Cloudflare oriente désormais les nouveaux projets vers Workers plutôt que Pages. Avec cette configuration, npx wrangler deploy compile le site et envoie dist/ ; en connectant le dépôt dans le tableau de bord Cloudflare, la même commande tourne à chaque push. html_handling: "drop-trailing-slash" sert /about sans redirection, et les URL inconnues reçoivent 404.html.

// Cloudflare Workers
{
  "name": "my-site",
  "compatibility_date": "2026-10-01",
  "build": {
    "command": "npm run build"
  },
  "assets": {
    "directory": "./dist",
    "not_found_handling": "404-page",
    "html_handling": "drop-trailing-slash"
  }
}

Toujours sur Pages ? Indiquez la commande de build npm run build et le répertoire de sortie dist, ou envoyez un build local avec npx wrangler pages deploy dist.

AWS Amplify

# Hébergement AWS Amplify
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm install
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

AWS S3 + CloudFront

Gardez le bucket privé et placez CloudFront devant avec l’origin access control. CloudFront n’associe que / à index.html : attachez donc cette fonction aux requêtes viewer de la distribution pour servir les URL propres de sitelo.

function handler(event) {
  var request = event.request
  var uri = request.uri

  if (uri.endsWith('/')) {
    request.uri += 'index.html'
  } else if (uri.slice(uri.lastIndexOf('/') + 1).indexOf('.') === -1) {
    request.uri += '/index.html'
  }

  return request
}

Un bucket privé répond 403 quand un fichier manque : ajoutez donc des réponses d’erreur personnalisées pour 403 et 404 qui renvoient /404.html avec un statut 404. Ensuite, envoyez chaque build et videz le cache :

npm run build
aws s3 sync dist/ s3://my-bucket --delete
aws cloudfront create-invalidation --distribution-id MY_DISTRIBUTION_ID --paths "/*"

Azure Static Web Apps

Créez la Static Web App dans le portail Azure avec / comme emplacement de l’app et dist comme emplacement de sortie ; Azure ajoute au dépôt un workflow GitHub Actions qui lance npm run build. Placez ce fichier dans public/ pour que le build le copie dans dist/ — sans lui, Azure répond aux URL inconnues avec sa propre page d’erreur au lieu de 404.html.

{
  "responseOverrides": {
    "404": {
      "rewrite": "/404.html"
    }
  }
}

Firebase Hosting

Sur Firebase Hosting, choisissez un projet avec firebase use --add, puis lancez firebase deploy : le hook predeploy compile d’abord. Les URL inconnues reçoivent 404.html automatiquement, et trailingSlash: false sert /about sans redirection.

{
  "hosting": {
    "public": "dist",
    "predeploy": "npm run build",
    "trailingSlash": false
  }
}

GitHub Pages

# GitHub Pages
name: Deploy
on:
  push:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci && npm run build
      - uses: actions/upload-pages-artifact@v5
        with:
          path: dist
      - uses: actions/deploy-pages@v5

Vous déployez sous un sous-chemin (user.github.io/repo) ? Construisez avec --base /repo/.

GitLab Pages

GitLab sert 404.html et les URL de dossier tout seul : le job se contente de compiler et de publier dist/.

# GitLab Pages
deploy-pages:
  image: node:24
  script:
    - npm ci
    - npm run build
  pages:
    publish: dist
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Render

Ajoutez le Blueprint ci-dessous au dépôt, ou créez un site statique depuis le tableau de bord avec la même commande de build et le même répertoire de publication. Les URL propres et 404.html fonctionnent sans règle de redirection.

# Render
services:
  - type: web
    name: my-site
    runtime: static
    buildCommand: npm install && npm run build
    staticPublishPath: ./dist

DigitalOcean App Platform

Indiquez votre dépôt dans github.repo, puis créez l’app avec doctl apps create --spec .do/app.yaml — ou collez la spec dans le tableau de bord. App Platform résout les URL de dossier et sert 404.html par défaut.

# DigitalOcean App Platform
name: my-site
static_sites:
  - name: site
    github:
      repo: your-name/your-site
      branch: main
      deploy_on_push: true
    build_command: npm run build
    output_dir: dist

Hébergeurs de conteneurs

Ces hébergeurs exécutent un conteneur, et un seul Dockerfile les couvre tous : Node compile le site, puis Caddy sert dist/ avec des URL propres et répond aux URL inconnues avec 404.html. Caddy écoute sur PORT quand l’hébergeur le définit, et sur le port 80 sinon. Ajoutez les trois fichiers à la racine du projet.

Railway · Fly.io · Heroku · Google Cloud Run

FROM node:24-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM caddy:2-alpine
COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=build /app/dist /app/dist
node_modules
dist
.git
:{$PORT:80} {
  root * /app/dist
  encode zstd gzip
  try_files {path} {path}/index.html
  file_server
  handle_errors {
    rewrite * /{err.status_code}.html
    file_server
  }
}

Railway

Railway compile le Dockerfile dès qu’il en trouve un : il n’y a rien à régler. Sans le Dockerfile, ajoutez la variable de service RAILPACK_SPA_OUTPUT_DIR=dist et gardez le Caddyfile : Railpack sert alors dist/ à travers lui au lieu de son réglage par défaut pour les SPA, qui répond aux URL inconnues avec la page d’accueil.

Fly.io

Lancez fly launch pour créer l’app, puis fly deploy.

# Fly.io
app = "my-site"

[http_service]
  internal_port = 80
  force_https = true
  auto_stop_machines = "stop"
  auto_start_machines = true
  min_machines_running = 0

Heroku

Heroku construit le Dockerfile via heroku.yml. Passez l’app sur la stack container une fois avec heroku stack:set container, puis lancez git push heroku main.

# Heroku
build:
  docker:
    web: Dockerfile

Google Cloud Run

Lancez gcloud run deploy --source . depuis la racine du projet : Cloud Build construit le Dockerfile et Cloud Run le sert.

Votre propre serveur

Copiez le build sur le serveur avec rsync -a --delete dist/ you@server:/var/www/my-site/ et servez-le avec Caddy ou nginx — les URL propres et 404.html fonctionnent comme chez les hébergeurs ci-dessus. Caddy obtient tout seul un certificat HTTPS pour le domaine ; avec nginx, ajoutez-en un avec certbot.

example.com {
  root * /var/www/my-site
  encode zstd gzip
  try_files {path} {path}/index.html
  file_server
  handle_errors {
    rewrite * /{err.status_code}.html
    file_server
  }
}
server {
  listen 80;
  server_name example.com;
  root /var/www/my-site;

  location / {
    try_files $uri $uri/index.html =404;
  }

  error_page 404 /404.html;
}

Avant de publier