# План: платформа — общее ядро, API и PWA > **Статус (2026-09-09):** план-набросок. WASM-ядро и CLI уже описаны в > `docs/roadmap.md` (фазы 3–8) и здесь не дублируются — этот план добавляет то, > чего в roadmap нет: **API** (фаза 9, возможная монетизация) и **PWA** (фаза > 10, оффлайн + установка). Оба стартуют после wasm-фаз; PWA не ждёт API и может > идти раньше. ## 0. Решения - **Одно ядро — три потребителя.** Rust-крейт `core/` (roadmap фаза 3) даёт: wasm-пакет для сайта (фаза 5), нативный CLI (фаза 6), серверный слой API (фаза 9). Единый контракт — JSON-пайплайн `{tool, params}` (заложен в roadmap §0); эталонные файлы и harness (фазы 2, 4, 7) гарантируют одинаковый результат во всех рантаймах. - **API — нативный Rust на сервере, не wasm.** В браузере wasm нужен ради доставки и песочницы; на сервере крейт линкуется напрямую — быстрее и проще. Исключение — edge-воркеры (см. спайк ниже): там исполняется тот же wasm-артефакт фазы 5. - **PWA не трогает SEO-схему.** Сайт остаётся полностью prerendered-статикой; service worker добавляет оффлайн-слой поверх и не отвечает за HTML ботовам. - **Монетизация не ломает позиционирование.** Браузерные инструменты — бесплатны и без трекинга; API — отдельный продукт для автоматизации/бизнеса. Файлы в API обрабатываются в памяти: без хранения и логирования содержимого — продолжение «privacy»-истории. ## 1. Фаза 9 — API (после фаз 5–7) - [ ] **[A1]** Спайк сервера: (а) axum/actix + нативный `core/` на VPS против (б) wasm-артефакт фазы 5 на edge (CF Workers). Сравнить: стоимость, лимиты памяти/времени на больших картинках, сложность деплоя и rate-limiting. Решение зафиксировать здесь. - [ ] **[A2]** Контракт: `POST /v1/process` — multipart (image) + JSON-пайплайн → изображение/архив; лимиты размера, коды ошибок; OpenAPI-спека. - [ ] **[A3]** Ключи и лимиты: Bearer-ключи, free tier (N запросов/мес), rate limiting по ключу; самостоятельная выдача/ротация ключей в кабинете — позже. - [ ] **[A4]** Биллинг: Stripe/LemonSqueezy (merchant of record), 2–3 тира по запросам/размеру файла. Только после стабильного free tier. - [ ] **[A5]** Документация как лендинг: `/api` — индексируемая страница (туториал, примеры curl/JS), OpenAPI, ссылка из `llms.txt`. Dev-аудитория — источник бэклинков (план-seo S4c). - Гейт: один и тот же пайплайн даёт пиксельно идентичный результат в браузере, CLI и API (harness фазы 7 расширяется третьим рантаймом). ## 2. Фаза 10 — PWA (после C17 и S1; C19 не блокер) - [ ] **[P1]** Манифест: имя (бренд после R1 из plan-seo §6), иконки 192/512 + maskable, theme-color из дизайн-токенов, `display: standalone`. - [ ] **[P2]** Service worker (SvelteKit `src/service-worker.ts`): precache app-shell; immutable-ассеты (build-hash) — cache-first; навигация по инструментам — stale-while-revalidate; offline-fallback страница. Спайком оценить вес полного precache: страницы маленькие, тяжёлое тащить по требованию. - [ ] **[P3]** Оффлайн-UX: индикатор «offline — работаете локально», своя кнопка установки (на `beforeinstallprompt`), стратегия обновления версии (prompt vs skipWaiting — решить на спайке). - [ ] **[P4]** SEO-безопасность: SW не перехватывает запросы ботов и не меняет HTML-ответы; canonical/prerendered-страницы не затрагиваются. Проверка: Lighthouse PWA + SEO зелёные после внедрения. - Гейт: каталог и топ-инструменты полностью работают в airplane-mode; повторный визит без сети открывается мгновенно. ## 3. Порядок и связи - WASM-ядро, эталоны, CLI — `docs/roadmap.md` фазы 2–8 (не дублируются). - PWA — после C17 (один дизайн, реальные маршруты) и после S1 `plan-seo.md`; C19 отложен и PWA не ждёт (не кешировать noindex-версии); API — после фаз 5–7. - Синергия с дистрибуцией: «works offline, installable» и публичный API — аргументы для Product Hunt / alternative.to / GitHub (plan-seo S4c) и для GEO-текстов (`llms.txt`, описания категорий). ## 4. Шрифты: лицензирование и DOM-free рендер текста Текст — единственный класс операций, который roadmap (фаза 8) держит в TS из-за canvas. Для CLI/API его всё равно придётся рендерить в Rust, поэтому решение: **перевести text-инструменты в ядро** (в браузере canvas-рендер остаётся TS-фолбэком для A/B). Два вопроса — легальность шрифтов в дистрибутиве и рендер без DOM. ### Лицензирование (решить до выбора шрифтов, backlog «Font Style») - [ ] **[F1]** В набор — только лицензии, допускающие **коммерческое использование и встраивание в продукт** (сайт + PWA + CLI + API): база — SIL OFL 1.1 (можно редистрибутировать и использовать коммерчески; нельзя продавать сами шрифты; требование — сохранять лицензию и имена при редистрибуции) и Apache 2.0 (Roboto, Open Sans, часть Noto). - [ ] **[F2]** Запрещённые категории: «free for personal use», shareware, шрифты без явной лицензии, MS core fonts (лицензия привязана к поставке с Windows-ПО). Отдельно проверять: бесплатность «для веба на одном домене» ≠ право класть TTF в дистрибутив CLI/API — у OFL/Apache таких ограничений нет, у прочих «free»-лицензий бывают. - [ ] **[F3]** Паспорт шрифта в `core/fonts//` (или эквивалент): файл(ы), LICENSE, источник, версия, хеш; CI-проверка «у каждого файла шрифта есть паспорт». Браузер грузит шрифты из бандла, не из ОС и не с `fonts.googleapis.com`-CDN (сторонний запрос = утечка IP пользователя, противоречит «no tracking»), — одинаковый результат у всех пользователей и во всех рантаймах. - [ ] **[F4]** Кириллица: приоритет семействам с полным покрытием — Liberation Sans, PT Sans/PT Serif, Noto Sans, Inter, Roboto (OFL/Apache), DejaVu Sans (пермиссивная лицензия Bitstream Vera: редистрибуция и коммерческое использование разрешены) — закрывает и backlog-вопрос про «только с кириллицей». - **Стартовый набор** (все OFL/Apache, с кириллицей; состав не догма — расширяется по запросам, каждый проходит паспорт F3): - базовый sans: **Inter** (дефолт add-text), **PT Sans** / **Golos Text** (профессиональная русская типографика), **Noto Sans** (фолбэк покрытия); - serif: **PT Serif**, **Lora**, **Playfair Display** (display); - mono: **JetBrains Mono** (дефолт), **Roboto Mono**; - display/акцент: **Oswald** (узкий), **Rubik** (округлый), **Comfortaa**, **Caveat** (рукописный), **Amatic SC** (маркерный); - кириллицу проверить по файлу при добавлении: Bebas Neue, Pacifico (добавлялась поздними версиями). Источник файлов — только Google Fonts / Fontsource (версионированные пакеты под паспорт F3); случайные «free font»-сайты — нет. Вес: woff2-сабсеты latin+cyr лениво в браузере, TTF в CLI (~2–4 МБ суммарно), в wasm не зашивать — грузить из статики по требованию. ### Рендер без DOM (спайк — фаза 5–6, реализация — фаза 8) - [ ] **[F5]** Спайк стека: растеризация глифов (`ab_glyph`/`rusttype`) + шейпинг (`swash`/`harfrust`; для латиницы/кириллицы сложный шейпинг не критичен, сложные письменности — осознанно не в первой версии) → отрисовка в наш `Image`. Эталон — canvas-рендер TS (perceptual-класс по roadmap §3): совпадать обязаны позиция/выравнивание/переносы, пиксели будут отличаться хинтингом/антиалиасингом. - [ ] **[F6]** Единый текстовый API для TS-core и Rust-core: параметры текста — из JSON-схемы инструмента, шрифт — **id из реестра шрифтов** (не системное имя), метрики базовой линии считать в ядре, а не через canvas `measureText` (иначе TS и Rust разъедутся). - Гейт: один и тот же текстовый шаг пайплайна даёт в браузере (wasm), CLI и API визуально идентичный результат; в дистрибутиве нет ни одного файла шрифта без паспорта лицензии.