Базовый сайт

Самый маленький полезный сайт на sitelo: одна страница, одна таблица стилей и конфигурации хостингов, публикующие dist/. Скопируйте конфигурации в любой проект sitelo — они предполагают только npm run build → dist/.

Рабочая копия лежит в репозитории sitelo, в examples/basic/.

Что вы получаете

Структура проекта

my-site/
  sitelo.config.js
  netlify.toml           # Netlify
  vercel.json            # Vercel
  wrangler.jsonc         # Cloudflare Workers
  amplify.yml            # AWS Amplify
  cloudfront-function.js # AWS S3 + CloudFront
  firebase.json          # Firebase Hosting
  .gitlab-ci.yml         # GitLab Pages
  render.yaml            # Render
  .do/app.yaml           # DigitalOcean App Platform
  Caddyfile              # Railway, Fly.io, Heroku, Cloud Run
  Dockerfile             # Railway, Fly.io, Heroku, Cloud Run
  .dockerignore          # Railway, Fly.io, Heroku, Cloud Run
  fly.toml               # Fly.io
  heroku.yml             # Heroku
  nginx.conf             # Your own server
  package.json
  public/
    staticwebapp.config.json  # Azure Static Web Apps
  src/
    index.ht.js
    css/
      styles.css
import { html, head, title, link, body, h1 } from 'javascript-to-html'

export default () =>
  html({ lang: 'ru' },
    head(
      title('sitelo — базовый пример'),
      link({ rel: 'stylesheet', href: '/styles.css' }),
    ),
    body(h1('Привет от sitelo')),
  )

Сборка

npm install
npm run build

Развёртывание

Из монорепозитория sitelo укажите корневой или базовый каталог платформы как examples/basic.

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"
}

Развернуть на Vercel · Развернуть на Netlify (когда спросят, укажите базовый каталог examples/basic).

Cloudflare

Для новых проектов Cloudflare теперь рекомендует Workers. npx wrangler deploy собирает и загружает dist/, либо подключите репозиторий в панели Cloudflare. На Pages укажите команду сборки npm run build и каталог вывода dist.

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

AWS Amplify

Подключите репозиторий в Amplify Hosting.

version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm install
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*

AWS S3 + CloudFront

Привяжите cloudfront-function.js к viewer-запросам дистрибуции и добавьте пользовательские ответы на ошибки 403 и 404, которые возвращают /404.html со статусом 404. Затем загружайте каждую сборку:

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
}
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

Создайте Static Web App с расположением приложения / и расположением вывода dist. sitelo копирует public/staticwebapp.config.json в dist/, где Azure его читает и отдаёт 404.html для неизвестных URL.

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

Google Cloud

Firebase Hosting: выберите проект командой firebase use --add, затем firebase deploy соберёт и загрузит сайт. Для Cloud Run команда gcloud run deploy --source . собирает Dockerfile ниже.

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

GitLab Pages

Скопируйте .gitlab-ci.yml в корень репозитория GitLab; задача соберёт и опубликует dist/.

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

Render

Создайте Blueprint из render.yaml или укажите те же команду сборки и каталог публикации у нового статического сайта. Чистые URL и 404.html работают без правил.

services:
  - type: web
    name: sitelo-basic
    runtime: static
    buildCommand: npm install && npm run build
    staticPublishPath: ./dist

DigitalOcean App Platform

Укажите свой репозиторий в github.repo, затем выполните doctl apps create --spec .do/app.yaml.

name: sitelo-basic
static_sites:
  - name: site
    github:
      repo: your-name/your-site
      branch: main
      deploy_on_push: true
    build_command: npm run build
    output_dir: dist

Railway

Railway собирает Dockerfile (см. Fly.io ниже), так что настраивать ничего не нужно. В проекте без него добавьте вместо этого переменную сервиса RAILPACK_SPA_OUTPUT_DIR=dist: тогда Railpack раздаёт dist/ через Caddyfile, который отвечает на неизвестные URL страницей 404.html.

:{$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
  }
}

Fly.io

Dockerfile собирает сайт в Node и раздаёт dist/ через Caddy. Создайте приложение командой fly launch, затем выполните fly deploy.

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
app = "sitelo-basic"

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

Heroku

Один раз выполните heroku stack:set container, затем git push heroku main: Heroku собирает Dockerfile и задаёт PORT для Caddy.

build:
  docker:
    web: Dockerfile

Свой сервер

Скопируйте сборку на сервер командой rsync -a --delete dist/ you@server:/var/www/my-site/ и раздавайте её через nginx.conf — или через Caddyfile выше, заменив :{$PORT:80} на свой домен, а /app/dist на каталог.

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;
}

Render, Railway, Fly.io, Heroku и Cloud Run видят только развёртываемую папку, поэтому ссылка file:../.. из примера на sitelo там не разрешится — разверните копию, которая ставит sitelo из npm.

Работаете с Cursor, Copilot или другим агентом? Скопируйте AGENTS.md из этого примера (или см. Разработку с ИИ), чтобы инструменты не выдумывали паттерны React/Next.

Начало работы · Разработка с ИИ · Список задач · Пример серверных островов