mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
145 lines
13 KiB
Markdown
145 lines
13 KiB
Markdown
# План: платформа — общее ядро, API и PWA
|
||
|
||
> **Статус: active.** Этот план добавляет к `docs/roadmap.md` то, чего там нет:
|
||
> **API** (фаза 9, возможная монетизация) и **PWA** (фаза 10, оффлайн +
|
||
> установка), плюс шрифты (раздел 4 — частично относится к фазе 8, поэтому
|
||
> решения фазы 8 здесь дублируются). WASM-ядро, эталоны и CLI — фазы 2–8
|
||
> `docs/roadmap.md`, они здесь не пересказываются. Оба трека стартуют после
|
||
> wasm-фаз; PWA не ждёт API и может идти раньше.
|
||
|
||
## 0. Решения
|
||
|
||
- **Одно ядро — три потребителя.** Rust-крейт `core/` (roadmap фаза 4) даёт:
|
||
wasm-пакет для сайта (фаза 5), нативный CLI (фаза 6), серверный слой API (фаза
|
||
9). Единый контракт — JSON-пайплайн `{id, params}` (заложен в roadmap §0 и
|
||
совпадает с `Page.steps`, реализуется в фазе 11); эталонные файлы и harness
|
||
(фазы 2, 3, 7) гарантируют одинаковый результат во всех рантаймах.
|
||
- **API — нативный Rust на сервере, не wasm.** В браузере wasm нужен ради
|
||
доставки и песочницы; на сервере крейт линкуется напрямую — быстрее и проще.
|
||
Исключение — edge-воркеры (см. спайк ниже): там исполняется тот же
|
||
wasm-артефакт фазы 5.
|
||
- **PWA не трогает SEO-схему.** Сайт остаётся полностью prerendered-статикой;
|
||
service worker добавляет оффлайн-слой поверх и не отвечает за HTML ботовам.
|
||
- **Монетизация не ломает позиционирование.** Браузерные инструменты —
|
||
бесплатные, картинка обрабатывается в браузере и никуда не отправляется.
|
||
Счётчик посещений GA4 этому не противоречит (границы — `docs/plan-seo.md` §0).
|
||
API — отдельный продукт для автоматизации/бизнеса. Файлы в API обрабатываются
|
||
в памяти: без хранения и логирования содержимого.
|
||
|
||
## 1. Фаза 9 — API (после фаз 5–7)
|
||
|
||
- [ ] **[A1]** Спайк сервера: (а) axum/actix + нативный `core/` на VPS против
|
||
(б) wasm-артефакт фазы 5 на edge (CF Workers). Сравнить: стоимость, лимиты
|
||
памяти/времени на больших картинках, сложность деплоя и rate-limiting.
|
||
Решение записать в §0 этого файла.
|
||
- [ ] **[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-аудитория
|
||
— источник бэклинков (`docs/plan-seo.md`, S4c).
|
||
- Гейт: один и тот же пайплайн даёт пиксельно идентичный результат в браузере,
|
||
CLI и API (harness фазы 7 расширяется третьим рантаймом).
|
||
|
||
## 2. Фаза 10 — PWA (после S1)
|
||
|
||
- [ ] **[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; пайплайн как продуктовая
|
||
фича — фаза 11 того же документа.
|
||
- PWA — после S1 `plan-seo.md`; API — после фаз 5–7.
|
||
- Синергия с дистрибуцией: «works offline, installable» и публичный API —
|
||
аргументы для Product Hunt / alternative.to / GitHub (`docs/plan-seo.md`, S4c)
|
||
и для GEO-текстов (`llms.txt`, описания категорий).
|
||
|
||
## 4. Шрифты: лицензирование и DOM-free рендер текста
|
||
|
||
Текст — один из canvas-зависимых классов, которые roadmap (фаза 8) держит в TS
|
||
(перечень — там же); для текста выбран курс на реимплементацию, остальные классы
|
||
не переносятся. Для CLI/API текст всё равно придётся рендерить в Rust, поэтому
|
||
решение: **перевести text-инструменты в ядро** (в браузере canvas-рендер
|
||
остаётся TS-фолбэком для A/B). Два вопроса — легальность шрифтов в дистрибутиве
|
||
и рендер без DOM.
|
||
|
||
**Когда начинать:** блока F1–F4 нет — они не привязаны к фазе roadmap, но F5/F6
|
||
без них бессмысленны (нечего рендерить). Реализуется всё это в фазе 8, поэтому
|
||
лицензирование стоит закрыть до неё, а не после.
|
||
|
||
### Лицензирование (решить до выбора шрифтов, 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/<name>/` (или эквивалент): файл(ы),
|
||
LICENSE, источник, версия, хеш; **новый гейт** «у каждого файла шрифта
|
||
есть паспорт» — его ещё нет, проектируется здесь и добавляется в
|
||
`pnpm verify` по правилам `docs/quality-gates.md` (решение о fail-режиме —
|
||
`docs/decisions.md`). Браузер грузит шрифты из бандла, не из ОС и не с
|
||
`fonts.googleapis.com`-CDN (сторонний запрос = утечка IP пользователя,
|
||
лишняя зависимость от чужой инфраструктуры), — одинаковый результат у всех
|
||
пользователей и во всех рантаймах.
|
||
- [ ] **[F4]** Кириллица: приоритет семействам с полным покрытием — Liberation
|
||
Sans, PT Sans/PT Serif, Noto Sans, Inter, Roboto (OFL/Apache), DejaVu Sans
|
||
(пермиссивная лицензия Bitstream Vera: редистрибуция и коммерческое
|
||
использование разрешены) — закрывает и backlog-вопрос про «только с
|
||
кириллицей».
|
||
- **Стартовый набор** (все OFL/Apache, с кириллицей; состав не догма —
|
||
расширяется по запросам, каждый проходит паспорт F3). Сейчас в бандле сайта
|
||
лежат `@fontsource/ibm-plex-sans` и `@fontsource/ibm-plex-mono` (тоже OFL) — в
|
||
наборе ниже их нет, и при введении паспорта 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
|
||
визуально идентичный результат; в дистрибутиве нет ни одного файла шрифта без
|
||
паспорта лицензии.
|