Перейти к содержимому

Схема контента

Схема — единственное описание контента сайта. По ней CMS строит форму правки и проверяет каждое сохранение, а сайт получает типы своего контента: ContentOf<typeof schema>. Порядок полей в схеме — порядок полей в форме.

import { defineSchema, text } from "@seamlet/astro/schema";
export const schema = defineSchema({
title: text({ label: "Заголовок" }),
});

У каждого поля есть label — его название в редакторе, по-русски, так, как его поймёт владелец сайта.

text({ label: "Подзаголовок", multiline: true, maxLength: 200 });
Настройка Что делает
multiline Многострочный текст: в форме — поле на несколько строк.
maxLength Не длиннее стольких символов — так, как их видит человек (эмодзи — один).

Значение — строка, пустая строка "", если текст не заполнен.

number({ label: "Цена, ₽", min: 0 });

Настройки min и max — границы значения. Значение — number или null, если не заполнено.

date({ label: "День события" });

Дата без времени, строка "2026-10-24", или null. Как её показать посетителю, решает сайт.

image({ label: "Фото первого экрана" });

Значение — { src, alt } или null. src — адрес фото, загруженного в CMS (/media/<сайт>/<файл>.webp), или любой другой адрес. alt — что на фото, для тех, кто его не видит. CMS сама поворачивает загруженные фото, уменьшает до 2560 px по длинной стороне, сохраняет в WebP и убирает метаданные (место съёмки с телефона).

link({ label: "Кнопка «Записаться»" });

Значение — { text, href } или null. Ведёт на страницу сайта (/menu), другой сайт (https://…), телефон (tel:) или почту (mailto:). Другое, например javascript:, CMS не сохранит. Как ссылка выглядит — кнопкой или текстом — решает сайт.

group({
label: "Контакты",
fields: {
address: text({ label: "Адрес" }),
phone: text({ label: "Телефон" }),
},
});

Поля, которые показываются и хранятся вместе, например первый экран страницы. Значение — объект с полями группы.

collection({
label: "Меню",
itemTitle: "name",
item: {
name: text({ label: "Название" }),
price: number({ label: "Цена, ₽", min: 0 }),
},
});

Список записей одного вида: блюда меню, отзывы, сотрудники. Владелец добавляет, удаляет и переставляет записи прямо на странице. itemTitle — поле, по которому запись называется в редакторе («Эспрессо» вместо «Запись 1»): текстовое или ссылка (по её тексту). Значение — массив объектов.

Пока сайт не опубликован, он показывает свой начальный контент. ContentOf проверяет его на этапе сборки:

src/initial-content.ts
import type { Content } from "./schema";
export const initialContent: Content = {
title: "Кофейня «Зерно»",
};

Новое поле в схеме у уже сохранённого контента получает пустое значение по умолчанию, ничего не ломается. Переименование поля для CMS — это удаление старого и добавление нового: прежнее значение пропадёт из формы, поэтому переименовывайте осознанно.