diff --git a/.gitignore b/.gitignore index 6b9d3d7..48436db 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ refs/public/placeholder-logo.png refs/public/placeholder.svg web/audit/cdp-audit*.txt css-lint.txt + +# Локальные планы с приватной информацией (выбранное имя домена) — не коммитить +docs/plan-domain.local.md diff --git a/docs/backlog.md b/docs/backlog.md index 3d078a7..76048f0 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -12,7 +12,9 @@ канал) - [ ] Пересмотреть поля - Plate, Position, Font Style - сейчас второй label - [ ] Font Style - обдумать выбор шрифта (google fonts???) как организовать - шрифты с кириллицей? сделать галочку "только с кириллицей"??? + шрифты с кириллицей? сделать галочку "только с кириллицей"??? (решение о + наборе и лицензиях: `docs/plan-platform.md` §4 — только OFL/Apache с + паспортом, семейства с кириллицей) - [ ] Посмотреть темную тему - слишком темная??? - [ ] на картинке результате при работе дергается высота надписи (высота иконки) - [ ] Глянуть что за ошибка (воспроизвелось на blur-png, в том числе и повторно) @@ -43,6 +45,34 @@ - [ ] составить план переноса preview -> корень, старый корень -> old - [ ] добавить i18n в preview +## SEO/GEO + +Общий план: `docs/plan-seo.md` (S0–S4). Старт — после C17. + +- [ ] переименование бренда + домен: чек-лист в локальном плане + `docs/plan-domain.local.md` (вне git, имя домена в репо не публикуется; + план-seo §6, R1/R2) +- [ ] download с селектором формата PNG/JPG/WebP/BMP для всех инструментов (райз + №7 → S1f) +- [ ] форматные страницы (`crop-jpeg`, …) — только по вордстату с уникальным + контентом; редиректы только для опечаток; клонов с canonical не делать + (план §5) +- [ ] sitemap.xml из реестра + `Sitemap:` в robots.txt (S1b/S1c) +- [ ] Seo.svelte: canonical + OG-теги, per-tool OG-картинки (S1d/S1e) +- [ ] контент страницы инструмента: seo-блок в словарях, H1/how-to/FAQ/related + (S2) +- [ ] JSON-LD (SoftwareApplication/FAQPage/Breadcrumb) + llms.txt (S3) +- [ ] GSC + приватная аналитика (Plausible/Umami/CF), дистрибуция (S4) + +## Платформа (API/PWA) + +Общий план: `docs/plan-platform.md`; WASM-ядро и CLI уже в `docs/roadmap.md` +(фазы 3–8) — здесь только новые треки. + +- [ ] PWA: manifest + service worker, оффлайн-режим, установка (после C19 и S1) +- [ ] API: спайк серверного ядра (нативный Rust vs edge-wasm), ключи, free tier + (после wasm-фаз 5–7) + ## Баги preview Зарегистрированы при написании e2e (`web/e2e/`, `pnpm --dir web test:e2e`) и diff --git a/docs/plan-platform.md b/docs/plan-platform.md new file mode 100644 index 0000000..dc72632 --- /dev/null +++ b/docs/plan-platform.md @@ -0,0 +1,132 @@ +# План: платформа — общее ядро, 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/C19 и 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 (не дублируются). +- PWA — после C17/C19 (один дизайн, реальные маршруты) и после S1 `plan-seo.md` + (не кешировать 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 + визуально идентичный результат; в дистрибутиве нет ни одного файла шрифта без + паспорта лицензии. diff --git a/docs/plan-redesign.md b/docs/plan-redesign.md index f2bcff6..6568a73 100644 --- a/docs/plan-redesign.md +++ b/docs/plan-redesign.md @@ -371,7 +371,10 @@ src/routes/preview/tools/[id]/+page.svelte shell. Убрать флаг/кнопку. **И обновить `newCode` в `web/eslint.config.js`:** заменить `src/routes/preview/**` на `src/routes/**` (после переезда все маршруты — новый дизайн), компонентный - glob `src/lib/components/kit/**` пока оставить. + glob `src/lib/components/kit/**` пока оставить. **И снять + `noindex, nofollow`** со страницы инструмента + (`preview/tools/[id]/+page.svelte`) — страницы становятся боевыми + лендингами ровно в момент переезда (SEO: `plan-seo.md`, S1a). - [ ] **[C18]** Правки импортов/редиректов после переноса, проверка билда. ### Шаг 6. Удаление старого diff --git a/docs/plan-seo.md b/docs/plan-seo.md new file mode 100644 index 0000000..986aaab --- /dev/null +++ b/docs/plan-seo.md @@ -0,0 +1,342 @@ +# План: SEO + GEO — индексация и конкуренция в image tools + +> **Статус (2026-09-09):** план к выполнению. Старт — после C17 +> (`plan-redesign.md`): до переезда `preview/*` на реальные маршруты страницы +> инструментов в `noindex`, применять техминимум некуда. +> +> **Цель:** каждая страница инструмента — индексируемый лендинг под конкретный +> интент («crop png», «make png transparent», «jpg to png»…), конкуренция с +> onlinepngtools.com за ядро запросов + попадание в ответы генеративных систем +> (ChatGPT, Perplexity, AI Overviews) — GEO. +> +> Задача: «для каждого инструмента — своя страница, и можно реально +> конкурировать с onlinepngtools». +> +> **Позиционирование (уточнено 2026-09-09):** сайт — не «PNG-инструменты», а +> **image tools с PNG-ядром**: любой инструмент работает с PNG/JPG/WebP/GIF/BMP +> на входе и отдаёт результат в PNG/JPG/WebP/BMP через селектор в кнопке +> Download. Дифференциатор — прозрачность/альфа/фон и no-upload-приватность. +> Референс-конкурент по ядру — onlinepngtools.com (см. §2). Долгосрочно ядро +> переезжает на wasm и обрастает API + PWA (оффлайн/установка) — +> `docs/roadmap.md` фазы 3–10, `docs/plan-platform.md`; для SEO это аргументы +> дистрибуции (S4c) и GEO-факты, схему сайта они не меняют. + +## 0. Решения + +- **Бренд: переименовать до индексации** (новое имя и домен сознательно не + записаны в этом репозитории — см. §6 и локальный план + `docs/plan-domain.local.md`, исключён из git: выбранное имя не должно утекать + в историю коммитов до покупки домена). Легенда честная: «started as PNG tools, + now all formats» — это контент-плюс, а не баг. Названия инструментов + (`crop-png`, …) и localStorage-ключи не переименовывать (см. решение про слаги + ниже). Точка истины по бренду: константа в i18n + README; хардкод в + компонентах недопустим. +- **Форматы: формат = выбор в UI, не отдельные страницы.** Download-кнопка + каждого инструмента — с селектором PNG/JPG/WebP/BMP (+quality для lossy). Райз + «выбор формата/качества в Download» вытащен из backlog №7 в S1f: механика уже + есть (`ToolEntry.output`), нужна как продуктовая основа «image + tools»-позиционирования. Отдельные страницы-конвертеры — только для + подтверждённых вордстатом интентов. +- **Слаги инструментов `-png` сохраняются.** Они держат низкоконкурентные + png-интенты; широкие интенты («crop image online») переносятся теми же + страницами контентом: H1 «Crop image», текст «works with PNG, JPG, WebP». + URL-алиасы без `-png` не создаются (канонический беспорядок). +- **Индексируемая локаль — EN** (базовая; конкурент англоязычный). RU-версия — + отдельно и позже: префикс `/ru/`, prerender обеих локалей, hreflang + (сознательно отложено в `archive/plan-i18n.md`). Пока язык переключается на + клиенте (localStorage) — для SEO не учитываем. +- **Прод-домен без `BASE_PATH`.** Сборка с базой (GitHub Pages `/repo/`) ломает + абсолютные URL, canonical и «корневость» страниц. Свой домен + корень. +- **URL-схема инструментов:** короткие плоские адреса. После C17 вынести + страницы инструментов в корень: `/crop-png` (как у конкурента), каталог — + `/tools`. Переезд `/preview/tools/[id]` → `/[id]` сделать **одновременно с + C17** (в одном атомарном коммите): после индексации переименование URL = 301 и + потеря позиций. +- **Без GA и рекламных скриптов:** аналитика — self-hosted Plausible/Umami или + Cloudflare Web Analytics. «No tracking» — часть позиционирования, её нельзя + подрывать собственными скриптами. +- **Честные методы.** Никакого клонированного текста, дорвеев, PBN. Контент — по + каждому инструменту, с ручной вычиткой. + +## 1. Аудит (2026-09-09) + +Фундамент уже есть: + +- SvelteKit + `adapter-static`, `prerender = true` на весь сайт + (`web/src/routes/+layout.ts`) — весь контент в статичном HTML, ботам не нужен + JS. Это главный технический козырь. +- 121 инструмент в `registry-new` с «SEO-шными» id (`crop-png`, + `add-border-png`, …) — URL уже повторяют паттерн конкурента. +- Уникальные `` + `<meta description>` на страницах инструментов старой + ветки; механика переносится на новую при C17. +- Каталог со ссылками на все инструменты (внутренняя перелинковка) и карта + инструментов против конкурента: `docs/tools-map.md` (у них 311, из них 107 — + нишевые клоны-серии Logo*/Icon*/Stamp* поверх обычных операций). +- EN-тексты в реестре + i18n-словари ru/en. + +Чего нет (пробелы закрываются этапами ниже): + +| Пробел | Где сейчас | Этап | +| ----------------------------------------------------- | ----------------------------------- | ------ | +| `sitemap.xml` | нет | S1 | +| `robots.txt` без `Sitemap:` | allow-all (`web/static/robots.txt`) | S1 | +| `rel=canonical` | нет | S1 | +| OG/Twitter-теги, OG-картинки | нет | S1 | +| `noindex, nofollow` на страницах инструментов preview | `preview/tools/[id]/+page.svelte` | S1/C17 | +| Контент страницы (H1-текст, how-to, FAQ, related) | только title/description | S2 | +| JSON-LD (SoftwareApplication, FAQPage, Breadcrumb) | нет | S3 | +| `llms.txt`, хабы категорий с текстом | нет | S3 | +| GSC + приватная аналитика | нет | S4 | + +## 2. Конкурент (onlinepngtools.com) + +Снято с живого сайта (2026-09-09): + +- ~311 URL в sitemap, все плоские (`/crop-png`, `/create-transparent-png`); + title вида «Crop a PNG – Online PNG Maker». +- Страница инструмента: h1 + 2–3 абзаца («World's simplest…», import/crop + примеры), примеры «before/after», how-to-блок, огромные футерные перелинковки + (серии Logo*/Icon*/Stamp*), страницы-хабы, price-wall. +- Сила: возраст домена, ссылочная масса, бренд, охват, серии-клоны под длинные + хвосты. +- Слабость (наш контраргумент): реклама, ежедневные лимиты free-плана, платное + коммерческое использование, апселл-модалки, страницы по ~450 КБ. +- Наш ответ в контенте каждой страницы: **no upload (всё локально в браузере), + no signup, no limits, бесплатно в т.ч. для коммерческого использования, open + source**. + +## 3. Стратегия + +1. **Не лобовая, а ядро интентов.** 80% объёма поиска приносят ~30–50 запросов. + Покрытие инструментов у нас почти полное (121); приоритет — контент и + качество страниц ядра, затем хвосты. +2. **Страница = лендинг, а не «пустая коробка».** Шаблон контента: H1 → 1–2 + абзаца «что делает» → как использовать (шаги) → параметры → FAQ (3–5 вопросов + уровня People-Also-Ask) → related tools по категории. +3. **CWV как измеримое преимущество.** Лёгкие быстрые страницы против ~450-КБ + страниц конкурента; после редизайна не потерять скорость. +4. **GEO.** LLM-системы цитируют страницы с прямыми определениями, списками, + таблицами и уникальными фактами. Всё это уже есть в данных реестра — отдавать + в HTML-структуре, без воды. +5. **Информационный контур — потом, не вместо.** Гайды по форматам (PNG/JPEG/ + WebP: история, модификации, lossy/lossless, прозрачность, «png vs jpeg») дают + E-E-A-T, перехватывают сравнительные запросы и служат хабами внутренних + ссылок на инструменты. Но это этап S3e и только после того, как написано ядро + S2: транзакционная страница приносит конверсию, информационная — только + трафик. Тонкие FAQ-страницы «про всё» не заводить — несколько сильных + материалов с ссылками на 3–5 инструментов каждый. +6. **Дистрибуция.** GitHub-репо (звёзды/форки = сигналы), alternative.to, + Product Hunt, Reddit по интенту — реальный путь набрать первые бэклинки без + бюджетов. + +## 4. Этапы + +### S1. Технический минимум (сразу после C17) + +- [ ] **[S1a]** Снять `noindex, nofollow` со страницы инструмента + (`preview/tools/[id]/+page.svelte`) — встроено в C17 как атомарный шаг + (см. `plan-redesign.md`). +- [ ] **[S1b]** Скрипт `web/scripts/gen-sitemap.mjs`: генерирует `sitemap.xml` в + `build/` из `TOOLS` реестра (`registry-new`) + статических страниц. Вызов + из `pnpm build` после `vite build` (adapter-static пишет в `build/`, + дописываем файл там же). Origin — из env (`PUBLIC_SITE_ORIGIN`), учёт + опционального `BASE_PATH`. +- [ ] **[S1c]** `robots.txt`: `Sitemap:` + закрыть служебные маршруты + (`/preview/kit` до C17; после — вернуть минимальный allow-all). +- [ ] **[S1d]** Компонент `Seo.svelte` (kit): canonical (абсолютный URL по + актуальному маршруту), OG-теги (title/description/type/url/image), + twitter:card. Подключить в root-layout. +- [ ] **[S1e]** OG-картинки per-tool: генерация PNG-карточек скриптом на + существующем ядре (мы сами умеем рисовать PNG) — имя инструмента + бренд, + файл `static/og/[id].png`, ссылка из `Seo.svelte`. +- [ ] **[S1f]** Download-кнопка с селектором формата PNG/JPG/WebP/BMP (+quality + для lossy) для всех инструментов — механика `ToolEntry.output` уже есть + (backlog №7, райз «выбор формата/качества»). Продуктовая основа «image + tools»-позиционирования: без неё сайт остаётся PNG-сайтом. Вести + параллельно с C18–C19. +- [ ] **[S1g]** Поведение конвертеров после S1f: не предлагать в меню форматов + формат исходника (disable) — чтобы «convert png to jpg» не мог сохранить в + png. Существующие страницы не трогать: `jpg-to-png`, `png-to-jpg`, + `png-to-webp`, `png-to-bmp` остаются самостоятельными лендингами со своим + контентом (§5). +- Гейты: build зелёный; в `build/` лежит корректный `sitemap.xml` со всеми + инструментами; canonical/OG присутствуют на всех страницах; e2e зелёные. + +### S2. Контентный слой (параллельно C18–C19, волнами по категориям) + +- [ ] **[S2a]** Схема данных: `seo`-блок per-tool (`longDescription`, + `howTo: string[]`, `faq: {q, a}[]`) — в i18n-словарях (ru/en), не в коде + реестра. Черновики — генерацией из схемы параметров инструмента, вычитка + вручную пачками по категориям (самый трудоёмкий этап: ~121 × 2 локали; RU + — отложить до решения о `/ru/`). +- [ ] **[S2b]** Компонент контента страницы инструмента (kit): H1, lead, how-to + (`ol`), описание параметров (из схемы), FAQ, related tools (перелинковка + внутри категории + 2–3 «соседних» интента). +- [ ] **[S2c]** Хлебные крошки (Каталог → Категория → Инструмент) в UI. +- [ ] **[S2d]** Первая волна контента — топ-30 инструментов ядра (приоритет по + вордстату: transparent png, jpg→png, compress, resize, crop, rotate, + circle crop, add text, pixelate, grayscale…). +- Гейты: на каждой странице инструмента — уникальный текст ≥ 300 слов, H1 + совпадает с интентом, FAQ ≥ 3, related ≥ 3; текст в статике (prerender), не в + рантайме. + +### S3. Структурированные данные + GEO + +- [ ] **[S3a]** JSON-LD: `SoftwareApplication` (+ `offers` price 0) и `FAQPage` + на страницах инструментов; `WebSite` + `Organization` на главной; + `BreadcrumbList` на всех внутренних. Учесть: Google ограничил rich results + по FAQ/HowTo для мелких сайтов — разметка нужна прежде всего для + LLM-парсинга, она безвредна. +- [ ] **[S3b]** `llms.txt` в статике: короткий манифест сайта + список + инструментов с одним предложением на каждый (генерится из реестра тем же + скриптом, что sitemap). +- [ ] **[S3c]** Хабы категорий с текстом: 2–3 абзаца на категорию (что за + группа, когда какие инструменты применять), не голые списки карточек. +- [ ] **[S3d]** GEO-редактура: каждое описание начинается прямым определением + («Crop PNG is a free tool that cuts a rectangular area from a PNG image + right in your browser»), списки/таблицы для фактов, без вводных «в + современном мире…». Проверка: страница отвечает на запрос одним абзацем + «без скролла». +- [ ] **[S3e]** _(опционально)_ Информационные гайды по форматам: 3–4 сильных + материала (`/guides/png-format`, `/guides/jpeg-vs-png`, …): история и + модификации формата, lossy/lossless, прозрачность, когда какой формат + выбирать. Каждый — с ссылками на 3–5 связанных инструментов (хабы + перелинковки), FAQ из гайдов продублирован как FAQPage-разметка. Приоритет + ниже S2/S3a–d: только когда ядро написано и есть ресурс. +- Гейты: валидация JSON-LD (Rich Results Test без ошибок); `llms.txt` актуален + при добавлении инструментов (генерация, а не ручное редактирование). + +### S4. Измерение и запуск + +- [ ] **[S4a]** Google Search Console: собственность на домен, отправка sitemap, + мониторинг индексации и запросов. Бесплатно и обязательно. +- [ ] **[S4b]** Аналитика без трекинга: self-hosted Plausible/Umami либо + Cloudflare Web Analytics. GA/ЯМ не ставим (позиционирование). +- [ ] **[S4c]** Дистрибуция: закрепить GitHub-репо (README со скриншотами), + подача на alternative.to (страница против конкурента), Product Hunt, + тематические Reddit/HN-треды. Бэклинки — главный дефицит для конкуренции. +- [ ] **[S4d]** _(опционально, позже)_ Сравнительные посадочные «vs …» (без + негатива: «no limits, no signup, no upload») — по мере роста доверия + домена. +- [ ] **[S4e]** Контроль CWV: Lighthouse на страницы ядра после каждого крупного + этапа редизайна; цель — зелёные метрики на мобильных. + +## 5. Приоритизация инструментов (первая волна контента) + +Источник — `docs/tools-map.md` (121 реализовано; у конкурента 311, из них 107 — +клоны-серии). Первая волна — топ-интенты, где конкуренты ранжируются, а у нас +уже есть инструмент и он не хуже: + +- прозрачность/фон: create-transparent-png, remove-background, change-opacity +- конвертация: jpg-to-png, png-to-jpg, webp-to-png, svg-to-png, png-to-base64 +- геометрия: crop, resize, rotate, circle-crop, round-corners, flip +- цвет/фильтры: grayscale, invert, pixelate, add-text, watermark +- генерация: gradient, empty-canvas + +Новая волна форматов (после S1f): jpg↔webp и другие конвертации «формат → +формат» — только по подтверждённому вордстату; базовые кейсы закрывает селектор +формата в Download (S1f), страницы заводим лишь там, где интент стабильно +ищется. + +- **crop-png: H1 «Crop image online — free, no upload»**, текст «works with PNG, + JPG, WebP» — широкий интент обслуживается контентом страницы с png-слагом, + слаг при этом остаётся якорем дешёвого png-интента. + +### Форматные варианты страниц (`crop-jpeg`, `crop-webp`, …) + +Три возможных механики — важно не перепутать: + +1. **301-редирект `/crop-jpeg` → `/crop-png`** — законно только для опечаток и + альтернативных написаний (`crop-jpg` → `crop-jpeg`) и переименований + существующих страниц. Для самостоятельного запроса редирект — это отказ от + страницы: Google перестаёт показывать редирект, ранжировать будет только + цель. Как посадочная под «crop jpeg» не работает вообще. +2. **Зеркало с canonical на `/crop-png`** — технически легально, но бесполезно: + canonical-дубль в индекс не попадает, видимости не добавляет, а массовое + производство таких зеркал выглядит как накрутка площади и при ошибке в + canonical превращается в дорвейный кластер. Не делаем. +3. **Самостоятельная страница = самостоятельный контент.** Заводить `/crop-jpeg` + можно только если: (а) интент подтверждён вордстатом, (б) на странице + собственный текст — H1 «Crop JPEG», FAQ про качество/артефакты/ когда + выбирать JPEG вместо PNG, отличия от png-кейса, (в) текст написан или выверен + человеком, а не получен подстановкой формата в шаблон. Реестром + автоматизировать **данные** (тот же tool, другой дефолтный output) — можно; + автоматизировать **текст** — нельзя: массовая подстановка {tool}×{format} в + шаблон — doorway-паттерн, риск deindex всего сайта. + +Как правильно получать видимость под «jpeg»/«webp» без клонов: широкие +формулировки закрывает контент существующей страницы (H1 «Crop image», «works +with PNG, JPG, WebP» в тексте + селектор формата в Download, S1f). Отдельные +форматные страницы — точечные исключения по вордстату, не серия. + +### Convert-инструменты: страницы и «универсальный конвертер» + +Разводить два разных интента: + +- **«convert png to jpg»** — интент «страница-конвертер»: пользователь ищет + конкретную пару форматов (лучшее качество конверсии, меньше ошибок), это + готовые лендинги. Существующие (`jpg-to-png`, `png-to-jpg`, `png-to-webp`, + `png-to-bmp`, `svg-to-png`, …) **оставить и наполнить контентом как все**: + свой H1 («Convert PNG to JPG — free, no upload»), FAQ про + качество/прозрачность/фон, related. Селектор формата (S1f) их **не заменяет** + — он про «уже открыл инструмент и хочу другой формат на выходе». +- **«convert image» / «image converter»** — интент «швейцарский нож». Под него — + **один будущий инструмент `/convert-image`**: сначала пустой **core-tool** в + `core/` — функция ре-энкода («копия с перекодированием»: декодирует любой + поддержанный исходник в ImageData и кодирует в выбранный формат; поверх неё + S1f строит селектор формата). `ToolEntry` и страницу добавлять **только вместе + с собственным текстом** («Convert any image to PNG, JPG or WebP in your + browser») — core в коде не обязывает к странице. Этот же шаблон потом + закрывает форматные волны (jpg→webp и т.п.) без новых страниц. + +Не делать: серию `convert-jpeg`/`convert-webp`-клонов с подстановкой формата +(doorway, см. выше) и «универсальный конвертер» как единственную страницу вместо +форматных лендингов — теряется ядро «convert png to jpg»-запросов. + +Правило добавления новых инструментов: брать из хвоста конкурента только те +интенты, которые подтверждены вордстатом, и сразу с контентом S2 (страница без +текста — потраченный URL). + +## 6. Переименование бренда и домен (сделать до S1, дёшево сейчас) + +Новое имя и конкретный домен **не записаны в этом репозитории** — детальный +чек-лист в `docs/plan-domain.local.md` (исключён из git через `.gitignore`), +чтобы выбранное имя не попало в историю коммитов до покупки домена. + +- [ ] **[R1]** Механический переезд бренда на новое имя по чек-листу из + локального плана: GitHub-репо + `git remote set-url`, README, + `package.json` (корень + `web/`), `TopBar.svelte` / `Footer.svelte`, + `favicon.svg` (title в SVG), i18n-строки (`en.ts`, `ru.ts`: defaultTitle, + pageTitle, metaDescription). НЕ трогать: слаги инструментов (`*-png`), + ключи localStorage (`easy-png-tools:*` — или мигрировать отдельной + мелочью), историю docs/archive. +- [ ] **[R2]** Купить выбранный домен (кандидаты и пробы — в локальном плане) и + настроить деплой без `BASE_PATH` (§0). Домен нужен до S1: canonical и + sitemap генерятся от `PUBLIC_SITE_ORIGIN`. +- Порядок: R1+R2 в любой момент до C17; после индексации переименование = + переезд с 301, потеря позиций и ссылок — не делать. + +## 7. Что осознанно НЕ делаем + +- Клонирование 311 URL конкурента (низкокачественные дубли + нет ресурсов на + контент) — вместо этого ядро + обоснованные хвосты. +- RU-локаль в индексе до решения о структуре `/ru/` + hreflang. +- GA/реклама/трекинг — противоречит позиционированию. +- Дорвеи, программные зеркала, покупные ссылки. +- Массово-сгенерированные форматные клоны (`crop-jpeg`/`crop-webp` как копии + `crop-png` с подстановкой формата в шаблонный текст) — doorway-паттерн, риск + deindex всего сайта. Форматная страница — только уникальный контент + вордстат + (§5); редиректы — только для опечаток/переименований. +- URL-алиасы без `-png` для существующих инструментов и зеркальные + страницы-конвертеры «на каждый формат» без вордстата. + +## 8. Связанные документы + +- `docs/plan-redesign.md` — C17 (снятие noindex + переезд маршрутов), C18–C21. +- `docs/tools-map.md` — карта «наш инструмент ↔ интент конкурента». +- `docs/backlog.md` — пункты SEO/GEO в общем бэклоге. +- `docs/roadmap.md` — фазы 2–8 (ядро TS→Rust/wasm, CLI); фазы 9–10 — API и PWA. +- `docs/plan-platform.md` — планы API и PWA (общее ядро, оффлайн-режим). +- `docs/archive/plan-i18n.md` — отложенная многоязычная схема (будущий `/ru/`). +- `docs/plan-domain.local.md` — план переименования/домена; **в git не входит** + (`.gitignore`), лежит только локально. diff --git a/docs/roadmap.md b/docs/roadmap.md index b1a960d..f1524e6 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -4,7 +4,8 @@ > сайт живёт, каталог переведён в типизированный `registry-new` (121/125), идёт > редизайн на `preview/*` по `plan-redesign.md` (параллельная ветка, старый UI > на `(old)/`). Фазы 2–8 (эталоны, Rust/wasm, CLI, harness) — будущие, разделам -> ниже не запущены. +> ниже не запущены. Фазы 9–10 (API, PWA) спланированы отдельно в +> `docs/plan-platform.md`. ## 0. Решения @@ -142,11 +143,25 @@ wasm. - Порт оставшихся EASY → MEDIUM (свёртки, морфология, квантование; кодеки через крейт `image`). - Canvas-зависимые операции (текст, градиенты, штампы, `ctx.filter`): остаются в - TS с perceptual-классом либо реимплементация в Rust. + TS с perceptual-классом либо реимплементация в Rust. Для текста выбран курс на + реимплементацию в Rust (рендер без DOM + шрифты OFL с лицензионными + паспортами) — `docs/plan-platform.md`, §4. - batch-страница: дроп папки → wasm по всем файлам → zip. localStorage-пресеты (тот же JSON, что у CLI). - HARD: compress/optimize через oxipng/zopfli (в Rust — нативно). +### Фаза 9 — API (монетизация) — см. `docs/plan-platform.md` + +Серверная обёртка над тем же ядром (нативный Rust или wasm на edge — решает +спайк), ключи и free tier, платные лимиты, индексируемая документация `/api`. +Чек-лист и решения — `docs/plan-platform.md`, §1. + +### Фаза 10 — PWA — см. `docs/plan-platform.md` + +Manifest + service worker, оффлайн-режим («работает без сети — файлы не покидают +устройство»), установка как приложение. Wasm-фаз не требует, идёт после C17/C19 +и S1 из `plan-seo.md`. Чек-лист — `docs/plan-platform.md`, §2. + ## 3. Правила сравнения (для фаз 4–7) | Класс операции | Критерий |