• Быстрый старт
    • Доступ и токен
  • СУЩНОСТИ
    • Страницы
      • Markdown
      • Аналитика страниц
    • Фреймы
      • Блоки
      • Бинды data-op-bind
      • Повторитель onpress/repeat
      • Сборка и копии
      • Фреймы в Markdown
      • Фреймы с данными
      • Готовые фреймы
    • Данные
    • Медиа
  • УСТРОЙСТВО САЙТА
    • Сайты
    • Настройки сайта
    • Меню
    • Языки и переводы
    • Стили и оформление
  • УПРАВЛЕНИЕ
    • Домены
    • Соцсети и контакты
    • SEO
    • Аналитика
    • Кэш
    • Дашборд и вход
    • Пользователи и профиль
    • Сайдбар документации
    • Ошибки и проблемы
  • КЕЙСЫ
    • Создание сайтов
    • Работа с контентом
    • Фреймы и данные
    • Настройка сайта
    • Перевод страницы
  • ПРИЛОЖЕНИЯ
    • Приложения
      • Закрытый доступ
      • Данные приложения
      • Внешние данные
      • Демо
    • Быстрый старт
    • Доступ и токен
  • СУЩНОСТИ
    • Страницы
    • Фреймы
    • Данные
    • Медиа
  • УСТРОЙСТВО САЙТА
    • Сайты
    • Настройки сайта
    • Меню
    • Языки и переводы
    • Стили и оформление
  • УПРАВЛЕНИЕ
    • Домены
    • Соцсети и контакты
    • SEO
    • Аналитика
    • Кэш
    • Дашборд и вход
    • Пользователи и профиль
    • Сайдбар документации
    • Ошибки и проблемы
    • Редиректы
    • Кредиты и автоматизация
    • Входящие
    • Кросспостинг
OnPress OnPress
  • Документация
  • Контакты
Войти
Обзор Справочник API
    • Быстрый старт
    • Доступ и токен
  • СУЩНОСТИ
    • Страницы
      • Markdown
      • Аналитика страниц
    • Фреймы
      • Блоки
      • Бинды data-op-bind
      • Повторитель onpress/repeat
      • Сборка и копии
      • Фреймы в Markdown
      • Фреймы с данными
      • Готовые фреймы
    • Данные
    • Медиа
  • УСТРОЙСТВО САЙТА
    • Сайты
    • Настройки сайта
    • Меню
    • Языки и переводы
    • Стили и оформление
  • УПРАВЛЕНИЕ
    • Домены
    • Соцсети и контакты
    • SEO
    • Аналитика
    • Кэш
    • Дашборд и вход
    • Пользователи и профиль
    • Сайдбар документации
    • Ошибки и проблемы
  • КЕЙСЫ
    • Создание сайтов
    • Работа с контентом
    • Фреймы и данные
    • Настройка сайта
    • Перевод страницы
  • ПРИЛОЖЕНИЯ
    • Приложения
      • Закрытый доступ
      • Данные приложения
      • Внешние данные
      • Демо
    • Быстрый старт
    • Доступ и токен
  • СУЩНОСТИ
    • Страницы
    • Фреймы
    • Данные
    • Медиа
  • УСТРОЙСТВО САЙТА
    • Сайты
    • Настройки сайта
    • Меню
    • Языки и переводы
    • Стили и оформление
  • УПРАВЛЕНИЕ
    • Домены
    • Соцсети и контакты
    • SEO
    • Аналитика
    • Кэш
    • Дашборд и вход
    • Пользователи и профиль
    • Сайдбар документации
    • Ошибки и проблемы
    • Редиректы
    • Кредиты и автоматизация
    • Входящие
    • Кросспостинг
Создание сайтов
Markdown
Открыть в ИИ
  • Открыть в ChatGPT
  • Открыть в Claude
  • Открыть в Gemini
  • Открыть в Perplexity
  • Открыть в Grok
  • Открыть в DeepSeek

Сайт с нуля

Результат: сайт с шапкой и подвалом, меню, главной, страницами «О компании» и «Контакты», оформленной страницей 404 и своими цветами. Всё — запросами к API, файлы лежат рядом в рабочем каталоге.

0. Сайт

Если сайт уже есть — возьмите его site_id (доступ) и переходите к шагу 1. Новый сайт создайте через POST /sites; с "empty": true он придёт без демо-контента:

curl -s -X POST "$API/sites" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "acme", "title": "Acme", "empty": true, "public": false}' \
  | jq '{site_id, blog_id, domain}'

export SITE=…   # site_id из ответа

public: false закрывает сайт от поисковиков до запуска (в конце откроем). Подробности — сайты и домены.

1. Язык

curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/languages" | jq '{default, languages: [.languages[].slug]}'

Дальше во всех страницах lang — язык из default. Здесь — ru. Нужен другой основной язык — языки сайта.

2. Фреймы

Три файла.

site__header.html:

<header class="site-header">
  <a class="site-header__logo" data-op-bind='{"href":"site.home_url","text":"site.name"}'></a>
  <nav class="site-header__nav"><!-- frame/menu {"place":"header","depth":1} /--></nav>
  <!-- frame/lang-switcher--dropdown /-->
</header>

site__footer.html:

<footer class="site-footer">
  <!-- frame/footer-columns /-->
  <p class="site-footer__copy"><!-- frame/copyright /--></p>
</footer>

article.html — оболочка страницы, которая вкладывает шапку и подвал:

<!-- frame/site__header /-->
<main class="article">
  <h1 class="article__title" data-op-bind='{"text":"page.title"}'></h1>
  <p class="article__lead" data-op-bind='{"text":"page.description"}'></p>
  <div class="article__body"><!-- onpress/content /--></div>
</main>
<!-- frame/site__footer /-->

Меню, переключатель языков, колонки подвала и копирайт выводят системные фреймы библиотеки. Поставьте их на сайт, если их там нет:

for f in menu lang-switcher--dropdown footer-columns copyright; do
  curl -s -X POST "$API/site/$SITE/frames/system/$f/install" \
    -H "Authorization: Bearer $OP_TOKEN"
done

Загрузите — сначала вложенные, потом оболочку, чтобы ссылки сразу находили фреймы:

for f in site__header site__footer article; do
  curl -s -X POST "$API/site/$SITE/frames" \
    -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
    -d "$(jq -n --arg slug "$f" --rawfile html "$f.html" '{slug: $slug, html: $html}')" \
    | jq -c '{slug: .frame.slug, renders_on_request, warnings}'
done
{"slug":"site__header","renders_on_request":true,"warnings":[]}
{"slug":"site__footer","renders_on_request":false,"warnings":[]}
{"slug":"article","renders_on_request":true,"warnings":[]}

Подвал от страницы не зависит. Шапка зависит от нее через переключатель языков (pages.translations), оболочка — через onpress/content и page.title, поэтому платформа собирает их страницы на запросе. Если слаг занят (409 slug_taken) — фрейм уже есть: замените разметку тем же телом через PUT $API/site/$SITE/frames/<слаг>.

3. Страницы

Четыре файла. home.md:

---
name: "Acme"
slug: "home"
url: "/home/"
lang: "ru"
frame: "article"
excerpt: "Мы делаем сайты, которыми управляют через API."
seo_title: "Acme — сайты через API"
seo_description: "Acme делает сайты на OnPress: страницы из markdown, оформление фреймами, всё через API."
---

## Что мы делаем

Сайты, где страницы публикуются запросом, а вид задаётся фреймами.

## Как с нами связаться

Все способы — на странице [Контакты](/kontakty/).

o-kompanii.md:

---
name: "О компании"
slug: "o-kompanii"
url: "/o-kompanii/"
lang: "ru"
frame: "article"
excerpt: "Кто мы и чем занимаемся."
---

Текст о компании.

kontakty.md:

---
name: "Контакты"
slug: "kontakty"
url: "/kontakty/"
lang: "ru"
frame: "article"
---

Почта: hello@example.com

404.md — ответ «не найдено» для всего сайта:

---
name: "Страница не найдена"
slug: "404"
url: "/404/"
lang: "ru"
frame: "article"
---

Такой страницы нет. Начните с [главной](/).

Опубликуйте:

for p in home o-kompanii kontakty 404; do
  curl -s -X POST "$API/site/$SITE/pages/markdown" \
    -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
    -d "$(jq -n --rawfile md "$p.md" '{markdown: $md}')" \
    | jq -c '{id, url, link, how: .printed.how, warnings}'
done

У каждой страницы в ответе how: "on_request" и пустые warnings. Страница со слагом 404 собирает ответ сайта на любой несуществующий адрес.

4. Меню

Шапка — одним запросом: создать, поставить в область, наполнить.

curl -s -X POST "$API/site/$SITE/menus" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Шапка", "location": "header", "lang": "ru", "items": [
        {"page": "/o-kompanii/"},
        {"page": "/kontakty/"}
      ]}' | jq -c '{menu, invalid, rebaked: .rebaked.status}'

Подвал — две колонки:

curl -s -X POST "$API/site/$SITE/menus" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Компания", "location": "footer_1", "lang": "ru", "items": [{"page": "/o-kompanii/"}, {"page": "/kontakty/"}]}' | jq -c .menu

curl -s -X POST "$API/site/$SITE/menus" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Мы в сети", "location": "footer_2", "lang": "ru", "items": [{"url": "https://t.me/acme", "title": "Telegram", "target": "_blank"}]}' | jq -c .menu

Имя меню подвала становится заголовком колонки во фрейме footer-columns.

5. Главная

curl -s -X PUT "$API/site/$SITE/data/site.front_page" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"page": "/home/"}' | jq '{changed, page_on_front, front_pages}'

Теперь / отдаёт страницу home, а её собственный адрес /home/ уводит на корень.

6. Название и видимость

curl -s -X PATCH "$API/site/$SITE/settings" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"blogname": "Acme", "blogdescription": "Сайты через API"}' | jq '{changed}'

blog_public: 1 откроет сайт поисковикам — сделайте это в самом конце, когда всё проверено.

7. Оформление

Цвет бренда — CSS-переменной, раскладка фреймов — собственным CSS:

curl -s -X PATCH "$API/site/$SITE/data/css.variables" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"variables": {"color.primary": "#16a34a", "radius.default": "8px"}}' | jq -c '[.changed[].variable]'

site.css:

.site-header{display:flex;align-items:center;gap:24px;padding:16px 24px;border-bottom:1px solid var(--line-color)}
.site-header__logo{font-weight:700;color:var(--primary-color);text-decoration:none}
.site-header__menu{display:flex;gap:16px;list-style:none;margin:0;padding:0}
.article{max-width:760px;margin:0 auto;padding:40px 24px}
.article__lead{color:var(--font-second-color)}
.article__lead:empty{display:none}
.site-footer{display:flex;justify-content:space-between;padding:32px 24px;border-top:1px solid var(--line-color)}
curl -s -X PUT "$API/site/$SITE/data/css" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d "$(jq -n --rawfile css site.css '{css: $css}')" | jq -c '{applied, bytes, stripped, cache: .cache.status}'

Если на сайте уже есть свой CSS, не затирайте его: прочитайте GET /data/css, добавьте свой кусок и залейте лист целиком (стили).

8. Проверка

DOMAIN=$(curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/settings" | jq -r .settings.domain)
for u in / /o-kompanii/ /kontakty/ /net-takoj-stranicy/; do
  printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' "https://$DOMAIN$u")" "$u"
done
200 /
200 /o-kompanii/
200 /kontakty/
404 /net-takoj-stranicy/

Несуществующий адрес отвечает 404, но с вашей страницей «не найдено» внутри шапки и подвала. Проверьте SEO-обход: GET $API/site/$SITE/seo/pages — на страницах не должно быть many_h1 (заголовок выводит фрейм, в теле # не нужен) и пропущенных описаний.

9. Открыть сайт

curl -s -X PATCH "$API/site/$SITE/settings" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"blog_public": 1}' | jq '{changed}'

Свой домен вместо acme.onpress.pro подключается в разделе «Домен» дашборда.

Что дальше

  • Раздел документации или лендинг рядом с основными страницами.
  • FAQ на страницах.
  • Второй язык.
arrow_backНазад
Создание сайтов
Далееarrow_forward
Раздел документации
На этой странице
  • 0. Сайт
    • 1. Язык
      • 2. Фреймы
        • 3. Страницы
          • 4. Меню
            • 5. Главная
              • 6. Название и видимость
                • 7. Оформление
                  • 8. Проверка
                    • 9. Открыть сайт
                      • Что дальше
                      1. Главная
                      2. Docs
                      3. Документация OnPress v2
                      4. Обзор
                      5. Создание сайтов
                      6. Сайт с нуля
                      OnPress
                      OnPress
                      ИП Зуев И.В. ИНН: 360408359441
                      info@onpress.pro
                      © 2026
                      политика конфиденциальности публичная оферта
                      • visa
                      • mastercard
                      • sber
                      • tpay