Разработка кастомных Contentful Apps (расширений)
Contentful Apps — механизм расширения интерфейса редактора через iframe-приложения, которые монтируются в поля, боковую панель или целые экраны. Это не просто UI-виджеты: через Contentful App SDK приложение получает доступ к Entry API, Space API и может запускать App Actions — серверные функции, исполняемые в контексте Contentful.
Архитектура Contentful App
Каждое приложение состоит из двух частей: frontend (React/Vue/Vanilla JS, размещается на любом хостинге) и опциональный App Backend (AWS Lambda или любой HTTP-эндпоинт для App Actions и Events). Оба регистрируются в App Definition через Contentful Management API или Web App.
App Definition
├── Locations: field, sidebar, entry-editor, page, home
├── Parameters: instance params (per-field) + installation params (per-space)
└── App Actions: serverless functions callable from UI or API
Типичные сценарии:
- Кастомный field editor — например, цветовой пикер, связанный с дизайн-токенами из Figma
- Sidebar extension — панель SEO-анализа, которая читает поля Entry в реальном времени
- Page location — полноэкранный Asset Manager с интеграцией Cloudinary
- App Actions — генерация AI-описаний через OpenAI при сохранении Entry
Разработка Field Extension
Инициализация SDK:
import { init, FieldExtensionSDK } from '@contentful/app-sdk';
init((sdk: FieldExtensionSDK) => {
// Читаем текущее значение поля
const value = sdk.field.getValue();
// Подписываемся на изменения из внешних источников
sdk.field.onValueChanged((newValue) => {
setFieldValue(newValue);
});
// Обновляем значение
sdk.field.setValue({ color: '#ff5500', token: 'brand-primary' });
// Авторесайз iframe под контент
sdk.window.startAutoResizer();
});
Для React-приложений удобнее @contentful/react-apps-toolkit:
import { useSDK, useFieldValue } from '@contentful/react-apps-toolkit';
const ColorPickerField = () => {
const sdk = useSDK<FieldExtensionSDK>();
const [value, setValue] = useFieldValue<string>();
return (
<ColorPicker
value={value}
onChange={(color) => setValue(color.hex)}
tokens={sdk.parameters.installation.designTokens}
/>
);
};
App Actions (серверная логика)
App Actions позволяют запускать серверный код из интерфейса Contentful без кастомного бэкенда — Contentful проксирует вызов на зарегистрированный endpoint:
// Регистрация App Action в App Definition (через CMA)
// callType: "request" | "event"
// url: https://your-backend.com/actions/generate-seo
// Вызов из frontend приложения
const result = await sdk.cma.appAction.callById({
spaceId: sdk.ids.space,
environmentId: sdk.ids.environment,
appDefinitionId: sdk.ids.app,
appActionId: 'generate-seo',
parameters: {
entryId: sdk.ids.entry,
locale: sdk.locales.default,
},
});
На стороне сервера (Node.js/Express):
app.post('/actions/generate-seo', async (req, res) => {
// Верифицируем подпись Contentful
verifySignature(req.headers['x-contentful-signature'], req.body);
const { entryId, locale } = req.body.parameters;
const entry = await cma.entry.get({ entryId });
const seoData = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: buildSeoPrompt(entry, locale) }],
});
res.json({ result: { seoTitle: seoData.choices[0].message.content } });
});
Installation Parameters и конфигурация
Параметры установки задаются один раз при инсталляции приложения в Space. Через них передаются API-ключи, токены, конфиги — без хардкода в коде приложения:
// Экран настроек приложения
const ConfigScreen = () => {
const sdk = useSDK<AppExtensionSDK>();
const [params, setParams] = useState(sdk.parameters.installation);
sdk.app.onConfigure(() => ({
parameters: params,
targetState: {
EditorInterface: {
// Автоматически подключить к полям типа Symbol
controls: [{ fieldId: 'seoTitle', widgetId: sdk.ids.app }],
},
},
}));
};
Сборка и деплой
Contentful предоставляет CLI для локальной разработки и деплоя:
# Создание нового приложения по шаблону
npx create-contentful-app@latest my-app --template typescript
# Локальная разработка с туннелем
npm run start # запускает на localhost:3000
contentful-app-scripts activate # временно регистрирует localhost в App Definition
# Деплой на Contentful-хостинг (бесплатно для Apps)
npm run build
contentful-app-scripts upload # загружает dist/ в Contentful CDN
Сроки и объём работ
| Тип расширения | Сложность | Время разработки |
|---|---|---|
| Простой field editor (пикер, слайдер) | Низкая | 1–2 дня |
| Sidebar с внешним API | Средняя | 3–5 дней |
| Page location (полный экран) | Высокая | 1–2 недели |
| App Actions + серверный бэкенд | Высокая | 1–2 недели |
| Полноценное приложение с конфиг-экраном | Высокая | 2–3 недели |
При разработке обязательно покрываем тестами с @contentful/app-sdk mock-объектами и настраиваем CI для автоматического деплоя через contentful-app-scripts upload.







