From 3e789d688720e913f197ffe9b7ee40b4b4e5a97d Mon Sep 17 00:00:00 2001 From: dcconstructions Date: Thu, 25 Jun 2026 23:50:24 +0300 Subject: [PATCH] Split product system into editable sections --- admin/admin.js | 16 +- content/pages/home.json | 1102 ++++++++++++++++- templates/pages/home/blocks/ai-modes.html | 1 + .../pages/home/blocks/component-library.html | 1 + templates/pages/home/blocks/faq.html | 1 + .../pages/home/blocks/pricing-table.html | 1 + .../pages/home/blocks/product-system.html | 1 - templates/pages/home/blocks/publish-cta.html | 1 + tools/extract-home-blocks.mjs | 360 +++++- 9 files changed, 1469 insertions(+), 15 deletions(-) create mode 100644 templates/pages/home/blocks/ai-modes.html create mode 100644 templates/pages/home/blocks/component-library.html create mode 100644 templates/pages/home/blocks/faq.html create mode 100644 templates/pages/home/blocks/pricing-table.html delete mode 100644 templates/pages/home/blocks/product-system.html create mode 100644 templates/pages/home/blocks/publish-cta.html diff --git a/admin/admin.js b/admin/admin.js index 866e119..8c1e4c5 100644 --- a/admin/admin.js +++ b/admin/admin.js @@ -123,11 +123,17 @@ const GROUP_COPY = { "Юридический блок": "Политики, права и нижний текст формы.", "Видео-окно": "Окно демо-видео и подключенный медиа-файл.", Пункты: "Текстовые пункты внутри секции.", + Слайдер: "Видео-превью и подписи карточек внутри горизонтального слайдера.", + "Один клик": "Подблок про быстрое добавление и настройку компонентов.", + MCP: "Подблок про MCP-сервер и контекст Webflow.", + FAQ: "Список вопросов и тексты ответов в mail-интерфейсе.", + CTA: "Финальный призыв к действию: заголовок, пояснение, кнопка и ссылка.", + Тарифы: "Верхняя часть тарифной таблицы: заголовки, планы, цены, кнопки и примечания.", Контент: "Остальные typed-поля выбранного блока.", }; -function field(path, label, kind = "text", renderAs = kind === "html" ? "html" : "text", group = null) { - return { path, label, kind, renderAs, group: group || inferFieldGroup(path) }; +function field(path, label, kind = "text", renderAs = kind === "html" ? "html" : "text", group = null, options = {}) { + return { path, label, kind, renderAs, group: group || inferFieldGroup(path), ...options }; } function setStatus(message) { @@ -171,6 +177,12 @@ function inferFieldGroup(path) { if (path === "content.legalHtml") return "Юридический блок"; if (path === "content.windowTitle" || path === "content.videoSrc") return "Видео-окно"; if (path.startsWith("content.features.")) return "Пункты"; + if (path.startsWith("content.sliderItems.")) return "Слайдер"; + if (path.startsWith("content.oneClick.")) return "Один клик"; + if (path.startsWith("content.mcp.")) return "MCP"; + if (path.startsWith("content.faq.")) return "FAQ"; + if (path.startsWith("content.cta.")) return "CTA"; + if (path.startsWith("content.plans.") || path.startsWith("content.pricing.")) return "Тарифы"; if (path.startsWith("content.heading.") || path === "content.introHtml") return "Заголовок"; return "Контент"; } diff --git a/content/pages/home.json b/content/pages/home.json index af3b4d1..05f7490 100644 --- a/content/pages/home.json +++ b/content/pages/home.json @@ -695,11 +695,1105 @@ "blocks": [ { "region": "cViz", - "id": "product-system", - "type": "staticHtml", - "template": "product-system.html", - "adminLabel": "Компоненты, режимы, FAQ и тарифная таблица", + "id": "component-library", + "type": "componentLibrary", + "template": "component-library.html", + "adminLabel": "Компонентная библиотека и MCP", "anchor": null, + "content": { + "heading": { + "muted": "Агентная", + "middle": "Компонентная", + "main": "библиотека." + }, + "introHtml": "Готовая к работе с агентами компонентная библиотека: добавление в один клик через приложение NODE.DC для Webflow и дальнейшая настройка под проект.", + "sliderItems": [ + { + "videoSrc": "./assets/media/various-modes.mp4", + "title": "Переключение режимов ИИ" + }, + { + "videoSrc": "./assets/media/project-flow.mp4", + "title": "Создание нового проекта" + }, + { + "videoSrc": "./assets/media/ai-dock-mode.mp4", + "title": "ИИ-док" + }, + { + "videoSrc": "./assets/media/account.mp4", + "title": "Аккаунт" + }, + { + "videoSrc": "./assets/media/code-edits.mp4", + "title": "Редактирование кода с ИИ" + }, + { + "videoSrc": "./assets/media/dev-server.mp4", + "title": "Dev-сервер с ИИ" + }, + { + "videoSrc": "./assets/media/webflow-mcp.mp4", + "title": "Webflow MCP" + }, + { + "videoSrc": "./assets/media/publish-flow.mp4", + "title": "Публикация" + } + ], + "oneClick": { + "heading": { + "muted": "Один", + "middle": "клик", + "main": "добавления." + }, + "introHtml": "С помощью расширения NODE.DC для Webflow. ", + "items": [ + { + "eyebrow": "Понимание компонентов", + "bodyHtml": "Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность." + }, + { + "eyebrow": "Быстрый старт", + "bodyHtml": "Используйте быстрые Bun сборки и автообновление для вашего кастомного кода." + } + ] + }, + "mcp": { + "heading": { + "muted": "Получите", + "middle": "более сильный", + "main": "MCP." + }, + "introHtml": "Полностью переработанный и более быстрый MCP-сервер. ", + "items": [ + { + "eyebrow": "Понимание Webflow", + "bodyHtml": "Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность." + } + ] + } + }, + "editableFields": [ + { + "path": "content.heading.muted", + "label": "Заголовок: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.heading.middle", + "label": "Заголовок: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.heading.main", + "label": "Заголовок: основная строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.introHtml", + "label": "Вводный текст", + "kind": "html", + "renderAs": "html", + "group": "Заголовок" + }, + { + "path": "content.sliderItems.0.videoSrc", + "label": "Слайд 1: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.0.title", + "label": "Слайд 1: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.1.videoSrc", + "label": "Слайд 2: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.1.title", + "label": "Слайд 2: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.2.videoSrc", + "label": "Слайд 3: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.2.title", + "label": "Слайд 3: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.3.videoSrc", + "label": "Слайд 4: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.3.title", + "label": "Слайд 4: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.4.videoSrc", + "label": "Слайд 5: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.4.title", + "label": "Слайд 5: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.5.videoSrc", + "label": "Слайд 6: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.5.title", + "label": "Слайд 6: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.6.videoSrc", + "label": "Слайд 7: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.6.title", + "label": "Слайд 7: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.7.videoSrc", + "label": "Слайд 8: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.7.title", + "label": "Слайд 8: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.oneClick.heading.muted", + "label": "Один клик: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "Один клик" + }, + { + "path": "content.oneClick.heading.middle", + "label": "Один клик: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "Один клик" + }, + { + "path": "content.oneClick.heading.main", + "label": "Один клик: основная строка", + "kind": "text", + "renderAs": "text", + "group": "Один клик" + }, + { + "path": "content.oneClick.introHtml", + "label": "Один клик: вводный текст", + "kind": "html", + "renderAs": "html", + "group": "Один клик" + }, + { + "path": "content.oneClick.items.0.eyebrow", + "label": "Один клик: пункт 1, подпись", + "kind": "text", + "renderAs": "text", + "group": "Один клик" + }, + { + "path": "content.oneClick.items.0.bodyHtml", + "label": "Один клик: пункт 1, текст", + "kind": "html", + "renderAs": "html", + "group": "Один клик" + }, + { + "path": "content.oneClick.items.1.eyebrow", + "label": "Один клик: пункт 2, подпись", + "kind": "text", + "renderAs": "text", + "group": "Один клик" + }, + { + "path": "content.oneClick.items.1.bodyHtml", + "label": "Один клик: пункт 2, текст", + "kind": "html", + "renderAs": "html", + "group": "Один клик" + }, + { + "path": "content.mcp.heading.muted", + "label": "MCP: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "MCP" + }, + { + "path": "content.mcp.heading.middle", + "label": "MCP: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "MCP" + }, + { + "path": "content.mcp.heading.main", + "label": "MCP: основная строка", + "kind": "text", + "renderAs": "text", + "group": "MCP" + }, + { + "path": "content.mcp.introHtml", + "label": "MCP: вводный текст", + "kind": "html", + "renderAs": "html", + "group": "MCP" + }, + { + "path": "content.mcp.items.0.eyebrow", + "label": "MCP: пункт 1, подпись", + "kind": "text", + "renderAs": "text", + "group": "MCP" + }, + { + "path": "content.mcp.items.0.bodyHtml", + "label": "MCP: пункт 1, текст", + "kind": "html", + "renderAs": "html", + "group": "MCP" + } + ], + "enabled": true + }, + { + "region": "cViz", + "id": "ai-modes", + "type": "aiModes", + "template": "ai-modes.html", + "adminLabel": "Гибкие режимы ИИ", + "anchor": null, + "content": { + "heading": { + "muted": "Гибкие", + "main": "режимы ИИ." + }, + "introHtml": "Разные режимы и модели для разных задач.", + "sliderItems": [ + { + "videoSrc": "./assets/media/various-modes.mp4", + "title": "Переключение режимов ИИ" + }, + { + "videoSrc": "./assets/media/project-flow.mp4", + "title": "Создание нового проекта" + }, + { + "videoSrc": "./assets/media/ai-dock-mode.mp4", + "title": "ИИ-док" + }, + { + "videoSrc": "./assets/media/account.mp4", + "title": "Аккаунт" + }, + { + "videoSrc": "./assets/media/code-edits.mp4", + "title": "Редактирование кода с ИИ" + }, + { + "videoSrc": "./assets/media/dev-server.mp4", + "title": "Dev-сервер с ИИ" + }, + { + "videoSrc": "./assets/media/webflow-mcp.mp4", + "title": "Webflow MCP" + }, + { + "videoSrc": "./assets/media/publish-flow.mp4", + "title": "Публикация" + } + ] + }, + "editableFields": [ + { + "path": "content.heading.muted", + "label": "Заголовок: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.heading.main", + "label": "Заголовок: основная строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.introHtml", + "label": "Вводный текст", + "kind": "html", + "renderAs": "html", + "group": "Заголовок" + }, + { + "path": "content.sliderItems.0.videoSrc", + "label": "Слайд 1: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.0.title", + "label": "Слайд 1: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.1.videoSrc", + "label": "Слайд 2: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.1.title", + "label": "Слайд 2: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.2.videoSrc", + "label": "Слайд 3: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.2.title", + "label": "Слайд 3: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.3.videoSrc", + "label": "Слайд 4: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.3.title", + "label": "Слайд 4: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.4.videoSrc", + "label": "Слайд 5: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.4.title", + "label": "Слайд 5: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.5.videoSrc", + "label": "Слайд 6: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.5.title", + "label": "Слайд 6: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.6.videoSrc", + "label": "Слайд 7: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.6.title", + "label": "Слайд 7: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.7.videoSrc", + "label": "Слайд 8: видео", + "kind": "media", + "renderAs": "attr", + "group": "Слайдер" + }, + { + "path": "content.sliderItems.7.title", + "label": "Слайд 8: подпись", + "kind": "text", + "renderAs": "text", + "group": "Слайдер" + } + ], + "enabled": true + }, + { + "region": "cViz", + "id": "faq", + "type": "faqSection", + "template": "faq.html", + "adminLabel": "Частые вопросы и ответы", + "anchor": null, + "content": { + "heading": { + "muted": "Частые", + "middle": "вопросы", + "main": "и ответы" + }, + "introHtml": "Подробный обзор возможностей, логики работы и внутреннего устройства.", + "docsHref": "https://docs.ssscript.app/", + "docsLabel": "Полная документация", + "windowTitle": "FAQ", + "faq": [ + { + "question": "Это влияет на производительность?", + "answerHtml": "

Как и любой кастомный код, это добавляет только ту нагрузку, которую несёт сам код.

Все файлы собираются, минифицируются и сжимаются, чтобы минимально влиять на проект и не плодить внешние библиотеки и CDN-скрипты.

" + }, + { + "question": "Где размещаются мои файлы?", + "answerHtml": "

После сборки файлы загружаются в Cloudflare R2 и отдаются через CDN-ссылку на выделенном домене проекта, чтобы получить быстрый и совместимый с Webflow результат.

" + }, + { + "question": "Что делать, если я опубликовал не те файлы?", + "answerHtml": "

В панели деплоя есть мгновенный откат.

Нажмите откат, верните предыдущую рабочую версию, исправьте локально и опубликуйте заново.

" + }, + { + "question": "Что такое ИИ-агент Webflow?", + "answerHtml": "

Помимо @plan, @build и @explore стандартных режимов агентов мы готовим @webflow режим, специально заточенный под Webflow: структуру проекта, взаимодействие с ним и эффективную разработку.

" + }, + { + "question": "Что такое собственная база знаний?", + "answerHtml": "

Основано на многолетнем опыте написания кастомного кода для Webflow-анимаций.

WebGL, Three.js, GSAP и кастомная функциональность собраны в набор практик, пайплайнов и модульную систему, чтобы всё работало согласованно.

Также доступна библиотека компонентов: выберите компонент, добавьте в проект и попросите ИИ адаптировать его под задачу.

" + }, + { + "question": "Как использовать это с Webflow?", + "answerHtml": "

При запуске NODE.DC доступна отдельная вкладка для встраивания.

В зависимости от задачи можно получить скрипты для конкретной страницы или единый app.js для всего проекта.

Сгенерированная ссылка содержит и продакшен-версию, следующую за URL деплоя, и локальную версию для предпросмотра без влияния на посетителей сайта.

" + }, + { + "question": "Какие ИИ-модели доступны?", + "answerHtml": "

Мы используем основные доступные модели: OpenAI до Claude до Gemini.

Оркестратор выбирает модель под задачу автоматически, но вы можете вручную переключиться на нужную модель.

" + }, + { + "question": "Как это работает?", + "answerHtml": "

Во время работы NODE.DC выполняет две задачи параллельно.

Поднимает локальную среду разработки на Bun, синхронизирует JavaScript и TypeScript, включает HMR и держит webhook для автоматического обновления сайта при изменениях.

Одновременно работает оркестратор ИИ-агентов: обрабатывает запросы, меняет код, проверяет состояние сборки и при необходимости обновляет проект Webflow.

" + }, + { + "question": "Как работает публикация?", + "answerHtml": "

Процесс многоэтапный: сначала Bun собирает, сжимает, минифицирует и подготавливает проект вместе с библиотеками.

Затем файлы отправляются в CDN: cdn.node.dc/{USERNAME}/{PROJECT-NAME}. Ссылка уже содержит нужную структуру: вы видите локальную версию, а пользователи получают опубликованный скрипт.

" + }, + { + "question": "Это работает с MCP?", + "answerHtml": "

Система изначально рассчитана на работу с Webflow MCP.

Подключите проект и авторизацию, чтобы ИИ-агенты получили доступ к Webflow-сборке. Подключение приложения в Webflow Designer даёт агентам доступ к контенту, элементам, стилям и CSS, а кастомный код получает полный контекст проекта.

" + } + ] + }, + "editableFields": [ + { + "path": "content.heading.muted", + "label": "Заголовок: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.heading.middle", + "label": "Заголовок: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.heading.main", + "label": "Заголовок: основная строка", + "kind": "text", + "renderAs": "text", + "group": "Заголовок" + }, + { + "path": "content.introHtml", + "label": "Вводный текст", + "kind": "html", + "renderAs": "html", + "group": "Заголовок" + }, + { + "path": "content.docsHref", + "label": "Документация: ссылка", + "kind": "url", + "renderAs": "attr", + "group": "Контент" + }, + { + "path": "content.docsLabel", + "label": "Документация: кнопка", + "kind": "text", + "renderAs": "text", + "group": "Контент" + }, + { + "path": "content.windowTitle", + "label": "Окно: название", + "kind": "text", + "renderAs": "text", + "group": "Видео-окно" + }, + { + "path": "content.faq.0.question", + "label": "FAQ 1: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.0.answerHtml", + "label": "FAQ 1: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.1.question", + "label": "FAQ 2: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.1.answerHtml", + "label": "FAQ 2: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.2.question", + "label": "FAQ 3: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.2.answerHtml", + "label": "FAQ 3: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.3.question", + "label": "FAQ 4: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.3.answerHtml", + "label": "FAQ 4: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.4.question", + "label": "FAQ 5: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.4.answerHtml", + "label": "FAQ 5: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.5.question", + "label": "FAQ 6: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.5.answerHtml", + "label": "FAQ 6: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.6.question", + "label": "FAQ 7: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.6.answerHtml", + "label": "FAQ 7: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.7.question", + "label": "FAQ 8: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.7.answerHtml", + "label": "FAQ 8: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.8.question", + "label": "FAQ 9: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.8.answerHtml", + "label": "FAQ 9: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + }, + { + "path": "content.faq.9.question", + "label": "FAQ 10: вопрос", + "kind": "text", + "renderAs": "text", + "group": "FAQ", + "replaceAll": true + }, + { + "path": "content.faq.9.answerHtml", + "label": "FAQ 10: ответ", + "kind": "html", + "renderAs": "html", + "group": "FAQ" + } + ], + "enabled": true + }, + { + "region": "cViz", + "id": "publish-cta", + "type": "publishCta", + "template": "publish-cta.html", + "adminLabel": "Финальный CTA перед тарифами", + "anchor": "hero", + "content": { + "cta": { + "heading": { + "muted": "Подключить.", + "middle": "Поставить задачу.", + "main": "Опубликовать." + }, + "intro": "Единый путь от разработки до продакшена.", + "detailHtml": "Настройка примерно в 12 кликов: от скачивания приложения до запуска в проекте.", + "href": "index.html#hero", + "buttonLabel": "Встать в лист ожидания" + } + }, + "editableFields": [ + { + "path": "content.cta.heading.muted", + "label": "CTA: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "CTA" + }, + { + "path": "content.cta.heading.middle", + "label": "CTA: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "CTA" + }, + { + "path": "content.cta.heading.main", + "label": "CTA: основная строка", + "kind": "text", + "renderAs": "text", + "group": "CTA" + }, + { + "path": "content.cta.intro", + "label": "CTA: вводный текст", + "kind": "text", + "renderAs": "text", + "group": "CTA" + }, + { + "path": "content.cta.detailHtml", + "label": "CTA: пояснение", + "kind": "html", + "renderAs": "html", + "group": "CTA" + }, + { + "path": "content.cta.href", + "label": "CTA: ссылка", + "kind": "url", + "renderAs": "attr", + "group": "CTA" + }, + { + "path": "content.cta.buttonLabel", + "label": "CTA: кнопка", + "kind": "text", + "renderAs": "text", + "group": "CTA" + } + ], + "enabled": true + }, + { + "region": "cViz", + "id": "pricing-table", + "type": "pricingTable", + "template": "pricing-table.html", + "adminLabel": "Тарифная таблица", + "anchor": "pricing-wrap", + "content": { + "pricing": { + "eyebrow": "Тарифы", + "heading": { + "muted": "Код", + "middle": "для No-Code,", + "main": "усиленный ИИ." + }, + "introHtml": "Подписки на приложение с
включённым объёмом в каждом тарифе.
", + "tokenBillingHtml": "Токенная оплата сверх лимитов.", + "founderLimitHtml": "200 Founder мест с фиксированной ценой на первый год.", + "windowTitle": "Тарифы.app", + "discountLabel": "Скидка 50%", + "betaHref": "beta-apply.html", + "founderHref": "founders.html", + "betaButtonLabel": "Подать заявку в бету", + "founderButtonLabel": "Оформить Founder-доступ", + "basicButtonLabel": "Выбрать Basic", + "advancedButtonLabel": "Выбрать Advanced", + "noteHtml": "(*) Условия могут меняться по ходу тестирования, но мы постараемся сохранить заявленные обещания.", + "enterpriseNoteHtml": "Enterprise BYOK-тарифы будут доступны с сентября 2026." + }, + "plans": [ + { + "name": "Бета", + "priceHtml": "Бесплатно", + "period": "1 месяц" + }, + { + "name": "Founder ", + "priceHtml": "310", + "period": "/ год, навсегда" + }, + { + "name": "Basic", + "priceHtml": "20", + "period": "/ месяц" + }, + { + "name": "Advanced", + "priceHtml": "50", + "period": "/ месяц" + } + ] + }, + "editableFields": [ + { + "path": "content.pricing.eyebrow", + "label": "Тарифы: надзаголовок", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.heading.muted", + "label": "Тарифы: приглушённая строка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.heading.middle", + "label": "Тарифы: средняя строка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.heading.main", + "label": "Тарифы: основная строка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.introHtml", + "label": "Тарифы: вводный текст", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.pricing.tokenBillingHtml", + "label": "Тарифы: оплата сверх лимитов", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.pricing.founderLimitHtml", + "label": "Тарифы: Founder-лимит", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.pricing.windowTitle", + "label": "Окно: название", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.discountLabel", + "label": "Founder: бейдж скидки", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.0.name", + "label": "Бета: название", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.0.priceHtml", + "label": "Бета: цена", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.plans.0.period", + "label": "Бета: период", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.1.name", + "label": "Founder: название", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.1.priceHtml", + "label": "Founder: цена", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.plans.1.period", + "label": "Founder: период", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.2.name", + "label": "Basic: название", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.2.priceHtml", + "label": "Basic: цена", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.plans.2.period", + "label": "Basic: период", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.3.name", + "label": "Advanced: название", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.plans.3.priceHtml", + "label": "Advanced: цена", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.plans.3.period", + "label": "Advanced: период", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.betaHref", + "label": "Бета: ссылка", + "kind": "url", + "renderAs": "attr", + "group": "Тарифы" + }, + { + "path": "content.pricing.founderHref", + "label": "Founder: ссылка", + "kind": "url", + "renderAs": "attr", + "group": "Тарифы" + }, + { + "path": "content.pricing.betaButtonLabel", + "label": "Бета: кнопка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.founderButtonLabel", + "label": "Founder: кнопка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.basicButtonLabel", + "label": "Basic: кнопка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.advancedButtonLabel", + "label": "Advanced: кнопка", + "kind": "text", + "renderAs": "text", + "group": "Тарифы" + }, + { + "path": "content.pricing.noteHtml", + "label": "Тарифы: примечание", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + }, + { + "path": "content.pricing.enterpriseNoteHtml", + "label": "Тарифы: Enterprise-примечание", + "kind": "html", + "renderAs": "html", + "group": "Тарифы" + } + ], "enabled": true }, { diff --git a/templates/pages/home/blocks/ai-modes.html b/templates/pages/home/blocks/ai-modes.html new file mode 100644 index 0000000..a8ad97d --- /dev/null +++ b/templates/pages/home/blocks/ai-modes.html @@ -0,0 +1 @@ +

{{text:content.heading.muted}}{{text:content.heading.main}}

{{html:content.introHtml}}

{{text:content.sliderItems.0.title}}

{{text:content.sliderItems.1.title}}

{{text:content.sliderItems.2.title}}

{{text:content.sliderItems.3.title}}

{{text:content.sliderItems.4.title}}

{{text:content.sliderItems.5.title}}

{{text:content.sliderItems.6.title}}

{{text:content.sliderItems.7.title}}

\ No newline at end of file diff --git a/templates/pages/home/blocks/component-library.html b/templates/pages/home/blocks/component-library.html new file mode 100644 index 0000000..6563f84 --- /dev/null +++ b/templates/pages/home/blocks/component-library.html @@ -0,0 +1 @@ +

{{text:content.heading.muted}}{{text:content.heading.middle}}{{text:content.heading.main}}

{{html:content.introHtml}}

{{text:content.sliderItems.0.title}}

{{text:content.sliderItems.1.title}}

{{text:content.sliderItems.2.title}}

{{text:content.sliderItems.3.title}}

{{text:content.sliderItems.4.title}}

{{text:content.sliderItems.5.title}}

{{text:content.sliderItems.6.title}}

{{text:content.sliderItems.7.title}}

{{text:content.oneClick.heading.muted}}{{text:content.oneClick.heading.middle}}{{text:content.oneClick.heading.main}}

{{html:content.oneClick.introHtml}}
{{text:content.oneClick.items.0.eyebrow}}
{{html:content.oneClick.items.0.bodyHtml}}
{{text:content.oneClick.items.1.eyebrow}}
{{html:content.oneClick.items.1.bodyHtml}}

{{text:content.mcp.heading.muted}}{{text:content.mcp.heading.middle}}{{text:content.mcp.heading.main}}

{{html:content.mcp.introHtml}}
{{text:content.mcp.items.0.eyebrow}}
{{html:content.mcp.items.0.bodyHtml}}
\ No newline at end of file diff --git a/templates/pages/home/blocks/faq.html b/templates/pages/home/blocks/faq.html new file mode 100644 index 0000000..d9146ad --- /dev/null +++ b/templates/pages/home/blocks/faq.html @@ -0,0 +1 @@ +

{{text:content.heading.muted}}{{text:content.heading.middle}}{{text:content.heading.main}}

{{html:content.introHtml}}
{{text:content.windowTitle}}
NODE.DC
{{text:content.faq.0.question}}
NODE.DC
{{text:content.faq.1.question}}
NODE.DC
{{text:content.faq.2.question}}
NODE.DC
{{text:content.faq.3.question}}
NODE.DC
{{text:content.faq.4.question}}
NODE.DC
{{text:content.faq.5.question}}
NODE.DC
{{text:content.faq.6.question}}
NODE.DC
{{text:content.faq.7.question}}
NODE.DC
{{text:content.faq.8.question}}
NODE.DC
{{text:content.faq.9.question}}
NODE.DC
Ответить
{{text:content.faq.0.question}}
{{html:content.faq.0.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.1.question}}
{{html:content.faq.1.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.2.question}}
{{html:content.faq.2.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.3.question}}
{{html:content.faq.3.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.4.question}}
{{html:content.faq.4.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.5.question}}
{{html:content.faq.5.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.6.question}}
{{html:content.faq.6.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.7.question}}
{{html:content.faq.7.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.8.question}}
{{html:content.faq.8.answerHtml}}
Отправлено с iPhone
NODE.DC
Ответить
{{text:content.faq.9.question}}
{{html:content.faq.9.answerHtml}}
Отправлено с iPhone
\ No newline at end of file diff --git a/templates/pages/home/blocks/pricing-table.html b/templates/pages/home/blocks/pricing-table.html new file mode 100644 index 0000000..381a1b3 --- /dev/null +++ b/templates/pages/home/blocks/pricing-table.html @@ -0,0 +1 @@ +
{{text:content.pricing.eyebrow}}

{{text:content.pricing.heading.muted}}{{text:content.pricing.heading.middle}}{{text:content.pricing.heading.main}}

{{html:content.pricing.introHtml}}
{{html:content.pricing.tokenBillingHtml}}
{{html:content.pricing.founderLimitHtml}}
{{text:content.pricing.windowTitle}}

{{text:content.plans.0.name}}

{{html:content.plans.0.priceHtml}}
{{text:content.plans.0.period}}

{{text:content.plans.1.name}}

{{html:content.plans.1.priceHtml}}
{{text:content.plans.1.period}}
{{text:content.pricing.discountLabel}}

{{text:content.plans.2.name}}

{{html:content.plans.2.priceHtml}}
{{text:content.plans.2.period}}

{{text:content.plans.3.name}}

{{html:content.plans.3.priceHtml}}
{{text:content.plans.3.period}}
Старт
Старт
Старт
Всего доступно
Расширение (20M)
Расширение (10M)
Глубина рассуждения
Базовый интеллект
Рабочее пространство
Объём токенов
Старт
Объём токенов
Объём токенов
Рабочее пространство
Всего доступно
Расширение (20M)
Расширение (10M)
Глубина рассуждения
Базовый интеллект
Рабочее пространство
Базовый интеллект
Глубина рассуждения
Расширение (10M)
Расширение (20M)
Всего доступно
Июнь 2026
Июнь 2026
Июнь 2026
Июнь 2026
Кредиты тарифа
Без ограничений
40 000 включено
12 000 включено
40 000 включено
Рабочее пространство
Без ограничений
Без ограничений
10 проектов
Без ограничений
Базовый интеллект
Все модели
Все быстрые
Все быстрые
Все быстрые
Глубина рассуждения
Полный
Полный
Ограниченный
Полный
Расширение SM 10€
Обновления без лимита
+ 10 000 кредитов
+ 8 000 кредитов
+ 10 000 кредитов
Расширение MD 20€
Обновления без лимита
+ 26 000 кредитов
+ 20 000 кредитов
+ 26 000 кредитов
Всего доступно
40 тестировщиков
200 мест
--
--
{{text:content.pricing.betaButtonLabel}}
{{text:content.pricing.founderButtonLabel}}
{{html:content.pricing.noteHtml}}
{{html:content.pricing.enterpriseNoteHtml}}
публикация-в-один-клик.png
Иконка MOV-файла.
публикация-в-один-клик.png
полноценный-редактор-кода.webp
Иконка MOV-файла.
полноценный-редактор-кода.webp
ИИ-док-режим.jpg
Иконка MOV-файла.
ИИ-док-режим.jpg
глубокая-интеграция-webflow.webp
Иконка MOV-файла.
глубокая-интеграция-webflow.webp
установка-настройка-запуск.jpg
Иконка MOV-файла.
установка-настройка-запуск.jpg
\ No newline at end of file diff --git a/templates/pages/home/blocks/product-system.html b/templates/pages/home/blocks/product-system.html deleted file mode 100644 index fc14785..0000000 --- a/templates/pages/home/blocks/product-system.html +++ /dev/null @@ -1 +0,0 @@ -

АгентнаяКомпонентнаябиблиотека.

Готовая к работе с агентами компонентная библиотека: добавление в один клик через приложение NODE.DC для Webflow и дальнейшая настройка под проект.

Переключение режимов ИИ

Создание нового проекта

ИИ-док

Аккаунт

Редактирование кода с ИИ

Dev-сервер с ИИ

Webflow MCP

Публикация

Одинкликдобавления.

С помощью расширения NODE.DC для Webflow.
Понимание компонентов
Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность.
Быстрый старт
Используйте быстрые Bun сборки и автообновление для вашего кастомного кода.

Получитеболее сильныйMCP.

Полностью переработанный и более быстрый MCP-сервер.
Понимание Webflow
Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность.

Гибкиережимы ИИ.

Разные режимы и модели для разных задач.

Переключение режимов ИИ

Создание нового проекта

ИИ-док

Аккаунт

Редактирование кода с ИИ

Dev-сервер с ИИ

Webflow MCP

Публикация

Частыевопросыи ответы

Подробный обзор возможностей, логики работы и внутреннего устройства.
FAQ
NODE.DC
Это влияет на производительность?
NODE.DC
Где размещаются мои файлы?
NODE.DC
Что делать, если я опубликовал не те файлы?
NODE.DC
Что такое ИИ-агент Webflow?
NODE.DC
Что такое собственная база знаний?
NODE.DC
Как использовать это с Webflow?
NODE.DC
Какие ИИ-модели доступны?
NODE.DC
Как это работает?
NODE.DC
Как работает публикация?
NODE.DC
Это работает с MCP?
NODE.DC
Ответить
Это влияет на производительность?

Как и любой кастомный код, это добавляет только ту нагрузку, которую несёт сам код.

Все файлы собираются, минифицируются и сжимаются, чтобы минимально влиять на проект и не плодить внешние библиотеки и CDN-скрипты.

Отправлено с iPhone
NODE.DC
Ответить
Где размещаются мои файлы?

После сборки файлы загружаются в Cloudflare R2 и отдаются через CDN-ссылку на выделенном домене проекта, чтобы получить быстрый и совместимый с Webflow результат.

Отправлено с iPhone
NODE.DC
Ответить
Что делать, если я опубликовал не те файлы?

В панели деплоя есть мгновенный откат.

Нажмите откат, верните предыдущую рабочую версию, исправьте локально и опубликуйте заново.

Отправлено с iPhone
NODE.DC
Ответить
Что такое ИИ-агент Webflow?

Помимо @plan, @build и @explore стандартных режимов агентов мы готовим @webflow режим, специально заточенный под Webflow: структуру проекта, взаимодействие с ним и эффективную разработку.

Отправлено с iPhone
NODE.DC
Ответить
Что такое собственная база знаний?

Основано на многолетнем опыте написания кастомного кода для Webflow-анимаций.

WebGL, Three.js, GSAP и кастомная функциональность собраны в набор практик, пайплайнов и модульную систему, чтобы всё работало согласованно.

Также доступна библиотека компонентов: выберите компонент, добавьте в проект и попросите ИИ адаптировать его под задачу.

Отправлено с iPhone
NODE.DC
Ответить
Как использовать это с Webflow?

При запуске NODE.DC доступна отдельная вкладка для встраивания.

В зависимости от задачи можно получить скрипты для конкретной страницы или единый app.js для всего проекта.

Сгенерированная ссылка содержит и продакшен-версию, следующую за URL деплоя, и локальную версию для предпросмотра без влияния на посетителей сайта.

Отправлено с iPhone
NODE.DC
Ответить
Какие ИИ-модели доступны?

Мы используем основные доступные модели: OpenAI до Claude до Gemini.

Оркестратор выбирает модель под задачу автоматически, но вы можете вручную переключиться на нужную модель.

Отправлено с iPhone
NODE.DC
Ответить
Как это работает?

Во время работы NODE.DC выполняет две задачи параллельно.

Поднимает локальную среду разработки на Bun, синхронизирует JavaScript и TypeScript, включает HMR и держит webhook для автоматического обновления сайта при изменениях.

Одновременно работает оркестратор ИИ-агентов: обрабатывает запросы, меняет код, проверяет состояние сборки и при необходимости обновляет проект Webflow.

Отправлено с iPhone
NODE.DC
Ответить
Как работает публикация?

Процесс многоэтапный: сначала Bun собирает, сжимает, минифицирует и подготавливает проект вместе с библиотеками.

Затем файлы отправляются в CDN: cdn.node.dc/{USERNAME}/{PROJECT-NAME}. Ссылка уже содержит нужную структуру: вы видите локальную версию, а пользователи получают опубликованный скрипт.

Отправлено с iPhone
NODE.DC
Ответить
Это работает с MCP?

Система изначально рассчитана на работу с Webflow MCP.

Подключите проект и авторизацию, чтобы ИИ-агенты получили доступ к Webflow-сборке. Подключение приложения в Webflow Designer даёт агентам доступ к контенту, элементам, стилям и CSS, а кастомный код получает полный контекст проекта.

Отправлено с iPhone

Подключить.Поставить задачу.Опубликовать.

Единый путь от разработки до продакшена.
Настройка примерно в 12 кликов: от скачивания приложения до запуска в проекте.
Встать в лист ожидания
Тарифы

Коддля No-Code,усиленный ИИ.

Подписки на приложение с
включённым объёмом в каждом тарифе.
Токенная оплата сверх лимитов.
200 Founder мест с фиксированной ценой на первый год.
Тарифы.app

Бета

Бесплатно
1 месяц

Founder

310
/ год, навсегда
Скидка 50%

Basic

20
/ месяц

Advanced

50
/ месяц
Старт
Старт
Старт
Всего доступно
Расширение (20M)
Расширение (10M)
Глубина рассуждения
Базовый интеллект
Рабочее пространство
Объём токенов
Старт
Объём токенов
Объём токенов
Рабочее пространство
Всего доступно
Расширение (20M)
Расширение (10M)
Глубина рассуждения
Базовый интеллект
Рабочее пространство
Базовый интеллект
Глубина рассуждения
Расширение (10M)
Расширение (20M)
Всего доступно
Июнь 2026
Июнь 2026
Июнь 2026
Июнь 2026
Кредиты тарифа
Без ограничений
40 000 включено
12 000 включено
40 000 включено
Рабочее пространство
Без ограничений
Без ограничений
10 проектов
Без ограничений
Базовый интеллект
Все модели
Все быстрые
Все быстрые
Все быстрые
Глубина рассуждения
Полный
Полный
Ограниченный
Полный
Расширение SM 10€
Обновления без лимита
+ 10 000 кредитов
+ 8 000 кредитов
+ 10 000 кредитов
Расширение MD 20€
Обновления без лимита
+ 26 000 кредитов
+ 20 000 кредитов
+ 26 000 кредитов
Всего доступно
40 тестировщиков
200 мест
--
--
Подать заявку в бету
Оформить Founder-доступ
(*) Условия могут меняться по ходу тестирования, но мы постараемся сохранить заявленные обещания.
Enterprise BYOK-тарифы будут доступны с сентября 2026.
публикация-в-один-клик.png
Иконка MOV-файла.
публикация-в-один-клик.png
полноценный-редактор-кода.webp
Иконка MOV-файла.
полноценный-редактор-кода.webp
ИИ-док-режим.jpg
Иконка MOV-файла.
ИИ-док-режим.jpg
глубокая-интеграция-webflow.webp
Иконка MOV-файла.
глубокая-интеграция-webflow.webp
установка-настройка-запуск.jpg
Иконка MOV-файла.
установка-настройка-запуск.jpg
\ No newline at end of file diff --git a/templates/pages/home/blocks/publish-cta.html b/templates/pages/home/blocks/publish-cta.html new file mode 100644 index 0000000..dc7e151 --- /dev/null +++ b/templates/pages/home/blocks/publish-cta.html @@ -0,0 +1 @@ +

{{text:content.cta.heading.muted}}{{text:content.cta.heading.middle}}{{text:content.cta.heading.main}}

{{text:content.cta.intro}}
{{html:content.cta.detailHtml}}
{{text:content.cta.buttonLabel}}
\ No newline at end of file diff --git a/tools/extract-home-blocks.mjs b/tools/extract-home-blocks.mjs index 88850c8..c0234ff 100644 --- a/tools/extract-home-blocks.mjs +++ b/tools/extract-home-blocks.mjs @@ -38,6 +38,17 @@ const waitlistFilesStart = findRequired(marker.waitlistFiles, pricingIntroStart) const demoVideoFolderStart = findRequired(marker.demoVideoFolder, waitlistFilesStart); const footerStart = findRequired(marker.footer, demoVideoFolderStart); const footerEnd = findRequired("", footerStart) + "".length; +const productSystemHtml = html.slice(cVizOpenEnd, pricingIntroStart); +const productSectionStarts = [...productSystemHtml.matchAll(/ match.index); + +if (productSectionStarts.length < 5) { + throw new Error(`Expected at least 5 product-system sections, found ${productSectionStarts.length}`); +} + +const productSections = productSectionStarts.map((start, index) => { + const end = productSectionStarts[index + 1] ?? productSystemHtml.length; + return productSystemHtml.slice(start, end); +}); let shell = [ html.slice(0, heroStart), @@ -68,12 +79,48 @@ const blocks = [ }, { region: "cViz", - id: "product-system", + id: "component-library", type: "staticHtml", - template: "product-system.html", - adminLabel: "Компоненты, режимы, FAQ и тарифная таблица", + template: "component-library.html", + adminLabel: "Компонентная библиотека и MCP", anchor: null, - html: html.slice(cVizOpenEnd, pricingIntroStart), + html: productSections[0], + }, + { + region: "cViz", + id: "ai-modes", + type: "staticHtml", + template: "ai-modes.html", + adminLabel: "Гибкие режимы ИИ", + anchor: null, + html: productSections[1], + }, + { + region: "cViz", + id: "faq", + type: "staticHtml", + template: "faq.html", + adminLabel: "Частые вопросы и ответы", + anchor: null, + html: productSections[2], + }, + { + region: "cViz", + id: "publish-cta", + type: "staticHtml", + template: "publish-cta.html", + adminLabel: "Финальный CTA перед тарифами", + anchor: "hero", + html: productSections[3], + }, + { + region: "cViz", + id: "pricing-table", + type: "staticHtml", + template: "pricing-table.html", + adminLabel: "Тарифная таблица", + anchor: "pricing-wrap", + html: productSections[4], }, { region: "cViz", @@ -128,12 +175,18 @@ function inferFieldGroup(path) { if (path === "content.legalHtml") return "Юридический блок"; if (path === "content.windowTitle" || path === "content.videoSrc") return "Видео-окно"; if (path.startsWith("content.features.")) return "Пункты"; + if (path.startsWith("content.sliderItems.")) return "Слайдер"; + if (path.startsWith("content.oneClick.")) return "Один клик"; + if (path.startsWith("content.mcp.")) return "MCP"; + if (path.startsWith("content.faq.")) return "FAQ"; + if (path.startsWith("content.cta.")) return "CTA"; + if (path.startsWith("content.plans.") || path.startsWith("content.pricing.")) return "Тарифы"; if (path.startsWith("content.heading.") || path === "content.introHtml") return "Заголовок"; return "Контент"; } -function field(path, label, kind = "text", renderAs = kind === "html" ? "html" : "text", group = null) { - return { path, label, kind, renderAs, group: group || inferFieldGroup(path) }; +function field(path, label, kind = "text", renderAs = kind === "html" ? "html" : "text", group = null, options = {}) { + return { path, label, kind, renderAs, group: group || inferFieldGroup(path), ...options }; } function tokenizeBlock(block, definition) { @@ -151,7 +204,7 @@ function tokenizeBlock(block, definition) { throw new Error(`Could not find "${value}" while tokenizing ${block.id}`); } - html = html.replace(value, token); + html = editableField.replaceAll ? html.split(value).join(token) : html.replace(value, token); } return { @@ -163,6 +216,24 @@ function tokenizeBlock(block, definition) { }; } +const demoSliderItems = [ + { videoSrc: "./assets/media/various-modes.mp4", title: "Переключение режимов ИИ" }, + { videoSrc: "./assets/media/project-flow.mp4", title: "Создание нового проекта" }, + { videoSrc: "./assets/media/ai-dock-mode.mp4", title: "ИИ-док" }, + { videoSrc: "./assets/media/account.mp4", title: "Аккаунт" }, + { videoSrc: "./assets/media/code-edits.mp4", title: "Редактирование кода с ИИ" }, + { videoSrc: "./assets/media/dev-server.mp4", title: "Dev-сервер с ИИ" }, + { videoSrc: "./assets/media/webflow-mcp.mp4", title: "Webflow MCP" }, + { videoSrc: "./assets/media/publish-flow.mp4", title: "Публикация" }, +]; + +function sliderEditableFields(prefix = "content.sliderItems", labelPrefix = "Слайд") { + return demoSliderItems.flatMap((_, index) => [ + field(`${prefix}.${index}.videoSrc`, `${labelPrefix} ${index + 1}: видео`, "media", "attr"), + field(`${prefix}.${index}.title`, `${labelPrefix} ${index + 1}: подпись`), + ]); +} + const typedBlockDefinitions = { "hero-waitlist": { type: "heroWaitlist", @@ -300,6 +371,279 @@ const typedBlockDefinitions = { field("content.features.3.bodyHtml", "Пункт 4: текст", "html"), ], }, + "component-library": { + type: "componentLibrary", + content: { + heading: { + muted: "Агентная", + middle: "Компонентная", + main: "библиотека.", + }, + introHtml: + 'Готовая к работе с агентами компонентная библиотека: добавление в один клик через приложение NODE.DC для Webflow и дальнейшая настройка под проект.', + sliderItems: demoSliderItems, + oneClick: { + heading: { + muted: "Один", + middle: "клик", + main: "добавления.", + }, + introHtml: 'С помощью расширения NODE.DC для Webflow. ', + items: [ + { + eyebrow: "Понимание компонентов", + bodyHtml: + 'Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность.', + }, + { + eyebrow: "Быстрый старт", + bodyHtml: + 'Используйте быстрые Bun сборки и автообновление для вашего кастомного кода.', + }, + ], + }, + mcp: { + heading: { + muted: "Получите", + middle: "более сильный", + main: "MCP.", + }, + introHtml: "Полностью переработанный и более быстрый MCP-сервер. ", + items: [ + { + eyebrow: "Понимание Webflow", + bodyHtml: + 'Используйте несколько агентов параллельно чтобы добавлять кастомный код, анимации и функциональность.', + }, + ], + }, + }, + editableFields: [ + field("content.heading.muted", "Заголовок: приглушённая строка"), + field("content.heading.middle", "Заголовок: средняя строка"), + field("content.heading.main", "Заголовок: основная строка"), + field("content.introHtml", "Вводный текст", "html"), + ...sliderEditableFields(), + field("content.oneClick.heading.muted", "Один клик: приглушённая строка"), + field("content.oneClick.heading.middle", "Один клик: средняя строка"), + field("content.oneClick.heading.main", "Один клик: основная строка"), + field("content.oneClick.introHtml", "Один клик: вводный текст", "html"), + field("content.oneClick.items.0.eyebrow", "Один клик: пункт 1, подпись"), + field("content.oneClick.items.0.bodyHtml", "Один клик: пункт 1, текст", "html"), + field("content.oneClick.items.1.eyebrow", "Один клик: пункт 2, подпись"), + field("content.oneClick.items.1.bodyHtml", "Один клик: пункт 2, текст", "html"), + field("content.mcp.heading.muted", "MCP: приглушённая строка"), + field("content.mcp.heading.middle", "MCP: средняя строка"), + field("content.mcp.heading.main", "MCP: основная строка"), + field("content.mcp.introHtml", "MCP: вводный текст", "html"), + field("content.mcp.items.0.eyebrow", "MCP: пункт 1, подпись"), + field("content.mcp.items.0.bodyHtml", "MCP: пункт 1, текст", "html"), + ], + }, + "ai-modes": { + type: "aiModes", + content: { + heading: { + muted: "Гибкие", + main: "режимы ИИ.", + }, + introHtml: 'Разные режимы и модели для разных задач.', + sliderItems: demoSliderItems, + }, + editableFields: [ + field("content.heading.muted", "Заголовок: приглушённая строка"), + field("content.heading.main", "Заголовок: основная строка"), + field("content.introHtml", "Вводный текст", "html"), + ...sliderEditableFields(), + ], + }, + faq: { + type: "faqSection", + content: { + heading: { + muted: "Частые", + middle: "вопросы", + main: "и ответы", + }, + introHtml: 'Подробный обзор возможностей, логики работы и внутреннего устройства.', + docsHref: "https://docs.ssscript.app/", + docsLabel: "Полная документация", + windowTitle: "FAQ", + faq: [ + { + question: "Это влияет на производительность?", + answerHtml: + "

Как и любой кастомный код, это добавляет только ту нагрузку, которую несёт сам код.

Все файлы собираются, минифицируются и сжимаются, чтобы минимально влиять на проект и не плодить внешние библиотеки и CDN-скрипты.

", + }, + { + question: "Где размещаются мои файлы?", + answerHtml: + "

После сборки файлы загружаются в Cloudflare R2 и отдаются через CDN-ссылку на выделенном домене проекта, чтобы получить быстрый и совместимый с Webflow результат.

", + }, + { + question: "Что делать, если я опубликовал не те файлы?", + answerHtml: + "

В панели деплоя есть мгновенный откат.

Нажмите откат, верните предыдущую рабочую версию, исправьте локально и опубликуйте заново.

", + }, + { + question: "Что такое ИИ-агент Webflow?", + answerHtml: + "

Помимо @plan, @build и @explore стандартных режимов агентов мы готовим @webflow режим, специально заточенный под Webflow: структуру проекта, взаимодействие с ним и эффективную разработку.

", + }, + { + question: "Что такое собственная база знаний?", + answerHtml: + "

Основано на многолетнем опыте написания кастомного кода для Webflow-анимаций.

WebGL, Three.js, GSAP и кастомная функциональность собраны в набор практик, пайплайнов и модульную систему, чтобы всё работало согласованно.

Также доступна библиотека компонентов: выберите компонент, добавьте в проект и попросите ИИ адаптировать его под задачу.

", + }, + { + question: "Как использовать это с Webflow?", + answerHtml: + "

При запуске NODE.DC доступна отдельная вкладка для встраивания.

В зависимости от задачи можно получить скрипты для конкретной страницы или единый app.js для всего проекта.

Сгенерированная ссылка содержит и продакшен-версию, следующую за URL деплоя, и локальную версию для предпросмотра без влияния на посетителей сайта.

", + }, + { + question: "Какие ИИ-модели доступны?", + answerHtml: + "

Мы используем основные доступные модели: OpenAI до Claude до Gemini.

Оркестратор выбирает модель под задачу автоматически, но вы можете вручную переключиться на нужную модель.

", + }, + { + question: "Как это работает?", + answerHtml: + "

Во время работы NODE.DC выполняет две задачи параллельно.

Поднимает локальную среду разработки на Bun, синхронизирует JavaScript и TypeScript, включает HMR и держит webhook для автоматического обновления сайта при изменениях.

Одновременно работает оркестратор ИИ-агентов: обрабатывает запросы, меняет код, проверяет состояние сборки и при необходимости обновляет проект Webflow.

", + }, + { + question: "Как работает публикация?", + answerHtml: + "

Процесс многоэтапный: сначала Bun собирает, сжимает, минифицирует и подготавливает проект вместе с библиотеками.

Затем файлы отправляются в CDN: cdn.node.dc/{USERNAME}/{PROJECT-NAME}. Ссылка уже содержит нужную структуру: вы видите локальную версию, а пользователи получают опубликованный скрипт.

", + }, + { + question: "Это работает с MCP?", + answerHtml: + "

Система изначально рассчитана на работу с Webflow MCP.

Подключите проект и авторизацию, чтобы ИИ-агенты получили доступ к Webflow-сборке. Подключение приложения в Webflow Designer даёт агентам доступ к контенту, элементам, стилям и CSS, а кастомный код получает полный контекст проекта.

", + }, + ], + }, + editableFields: [ + field("content.heading.muted", "Заголовок: приглушённая строка"), + field("content.heading.middle", "Заголовок: средняя строка"), + field("content.heading.main", "Заголовок: основная строка"), + field("content.introHtml", "Вводный текст", "html"), + field("content.docsHref", "Документация: ссылка", "url", "attr"), + field("content.docsLabel", "Документация: кнопка"), + field("content.windowTitle", "Окно: название"), + ...Array.from({ length: 10 }, (_, index) => [ + field(`content.faq.${index}.question`, `FAQ ${index + 1}: вопрос`, "text", "text", "FAQ", { + replaceAll: true, + }), + field(`content.faq.${index}.answerHtml`, `FAQ ${index + 1}: ответ`, "html", "html", "FAQ"), + ]).flat(), + ], + }, + "publish-cta": { + type: "publishCta", + content: { + cta: { + heading: { + muted: "Подключить.", + middle: "Поставить задачу.", + main: "Опубликовать.", + }, + intro: "Единый путь от разработки до продакшена.", + detailHtml: + 'Настройка примерно в 12 кликов: от скачивания приложения до запуска в проекте.', + href: "index.html#hero", + buttonLabel: "Встать в лист ожидания", + }, + }, + editableFields: [ + field("content.cta.heading.muted", "CTA: приглушённая строка"), + field("content.cta.heading.middle", "CTA: средняя строка"), + field("content.cta.heading.main", "CTA: основная строка"), + field("content.cta.intro", "CTA: вводный текст", "text", "text", "CTA"), + field("content.cta.detailHtml", "CTA: пояснение", "html", "html", "CTA"), + field("content.cta.href", "CTA: ссылка", "url", "attr", "CTA"), + field("content.cta.buttonLabel", "CTA: кнопка", "text", "text", "CTA"), + ], + }, + "pricing-table": { + type: "pricingTable", + content: { + pricing: { + eyebrow: "Тарифы", + heading: { + muted: "Код", + middle: "для No-Code,", + main: "усиленный ИИ.", + }, + introHtml: "Подписки на приложение с
включённым объёмом в каждом тарифе.
", + tokenBillingHtml: 'Токенная оплата сверх лимитов.', + founderLimitHtml: '200 Founder мест с фиксированной ценой на первый год.', + windowTitle: "Тарифы.app", + discountLabel: "Скидка 50%", + betaHref: "beta-apply.html", + founderHref: "founders.html", + betaButtonLabel: "Подать заявку в бету", + founderButtonLabel: "Оформить Founder-доступ", + basicButtonLabel: "Выбрать Basic", + advancedButtonLabel: "Выбрать Advanced", + noteHtml: "(*) Условия могут меняться по ходу тестирования, но мы постараемся сохранить заявленные обещания.", + enterpriseNoteHtml: + 'Enterprise BYOK-тарифы будут доступны с сентября 2026.', + }, + plans: [ + { + name: "Бета", + priceHtml: "Бесплатно", + period: "1 месяц", + }, + { + name: "Founder ", + priceHtml: '310', + period: "/ год, навсегда", + }, + { + name: "Basic", + priceHtml: '20', + period: "/ месяц", + }, + { + name: "Advanced", + priceHtml: '50', + period: "/ месяц", + }, + ], + }, + editableFields: [ + field("content.pricing.eyebrow", "Тарифы: надзаголовок"), + field("content.pricing.heading.muted", "Тарифы: приглушённая строка"), + field("content.pricing.heading.middle", "Тарифы: средняя строка"), + field("content.pricing.heading.main", "Тарифы: основная строка"), + field("content.pricing.introHtml", "Тарифы: вводный текст", "html"), + field("content.pricing.tokenBillingHtml", "Тарифы: оплата сверх лимитов", "html"), + field("content.pricing.founderLimitHtml", "Тарифы: Founder-лимит", "html"), + field("content.pricing.windowTitle", "Окно: название"), + field("content.pricing.discountLabel", "Founder: бейдж скидки"), + field("content.plans.0.name", "Бета: название"), + field("content.plans.0.priceHtml", "Бета: цена", "html"), + field("content.plans.0.period", "Бета: период"), + field("content.plans.1.name", "Founder: название"), + field("content.plans.1.priceHtml", "Founder: цена", "html"), + field("content.plans.1.period", "Founder: период"), + field("content.plans.2.name", "Basic: название"), + field("content.plans.2.priceHtml", "Basic: цена", "html"), + field("content.plans.2.period", "Basic: период"), + field("content.plans.3.name", "Advanced: название"), + field("content.plans.3.priceHtml", "Advanced: цена", "html"), + field("content.plans.3.period", "Advanced: период"), + field("content.pricing.betaHref", "Бета: ссылка", "url", "attr"), + field("content.pricing.founderHref", "Founder: ссылка", "url", "attr"), + field("content.pricing.betaButtonLabel", "Бета: кнопка"), + field("content.pricing.founderButtonLabel", "Founder: кнопка"), + field("content.pricing.basicButtonLabel", "Basic: кнопка"), + field("content.pricing.advancedButtonLabel", "Advanced: кнопка"), + field("content.pricing.noteHtml", "Тарифы: примечание", "html"), + field("content.pricing.enterpriseNoteHtml", "Тарифы: Enterprise-примечание", "html"), + ], + }, }; const staticElements = { @@ -479,7 +823,7 @@ function tokenizeStaticShell(source, definition) { tokenized = replaceShellLiteral( tokenized, "\n