# Сайт-генератор резюме без опыта работы
Сайт для тех, кто ищет первую работу (школьники, студенты, выпускники колледжей/вузов, гэп-год) и не знает, что писать в резюме без опыта. Помогает найти "скрытые" навыки в хобби/интересах и объясняет, где они пригодятся.
## Статус
Прототипная стадия. Все файлы ниже — рабочие черновики для оценки тона, механик и дизайна, не production-код.
**Куда смотреть в первую очередь:** `START_HERE.md` — краткий вход для новой сессии/устройства
(как запустить, карта проекта, текущая точка останова). Здесь — полный журнал решений и
роадмап; деплой — в `docs/DEPLOY.md`.
**Astro-версия собрана (пункт 2 плана «Дальнейшие шаги» → см. конец README).** Теперь в репозитории
две плоскости:
- Ветка/репо на GitHub: **github.com/Splendor1980/resume-site-v17** (пуб/приват — как создано). Это
git-ремот для синхронизации проекта между устройствами, а не хостинг сайта (см. «Дорожная карта»).
- `index.html` и `data/`, `prototypes/` **в корне** — прежний прототип (SPA на чистом JS), сохранён
как история решений и для сравнения;
- **Astro-приложение** в `src/` — статические SEO-страницы идей + конструктор как «остров» на
`/konstruktor/`. Именно его нужно развивать дальше и хостить (шаг 3 плана — домен и хостинг).
**Как запустить Astro-версию локально:**
```
npm install # первый раз
npm run dev # http://localhost:4321/ (только один раз потребуется npx playwright install chromium)
npm run build # статическая сборка в dist/
npm run preview # посмотреть собранное
npm run test:e2e # headless-проверка конструктора и SEO-страниц (Playwright)
```
Важно: `npm run build` сам копирует `data/ideas.json`, `prototypes/` и `README.md` в `public/`
(скрипт `scripts/sync-data.mjs`) — это runtime-файлы, на которые ссылается конструктор. Если меняешь
`data/ideas.json` — правь только корневой файл, копия в `public/` обновится при сборке.
Архивы для скачивания версионируются по папке (`resume-site-v4`, следующий будет `v5` и
так далее) — не переиспользуем номер версии повторно, чтобы не путать файлы в загрузках.
**Правило версионирования (договорённость с v17):** текущая папка проекта — `resume-site-v17`,
при загрузке на GitHub имя папки/репо НЕ меняем. Каждое следующее крупное изменение — это
переименование папки в `resume-site-v18`, `resume-site-v19` и т.д. (номер +1 от текущего,
не пропуская). Мелкие правки внутри одной версии папку не переименовывают.
## Структура
```
index.html — ГЛАВНАЯ СТРАНИЦА продукта (не список черновиков!):
три режима поиска идей (листай / по профессии / помощник-подсказчик)
+ резюме слева, само переключается между компактным и плотным
шаблоном в зависимости от объёма выбранного контента (< 2 выбранных
идей → компактный сайдбар-шаблон, 2+ → плотный многосекционный).
Шестерёнка (правый верхний угол) открывает служебную панель со
ссылками на черновики ниже — обычный посетитель туда не заходит.
data/
ideas.json — база связок "интерес → навыки → роли → комментарий", 103 записи
(schema v3: category — устойчивая, examples_now — обновляемые
конкретные примеры игр/сериалов, освежать раз в 6-12 мес)
about-snippets.json — примеры фрагментов "О себе/навыки" для вдохновения,
размечены по persona, tone и length (short/medium/long)
prototypes/ (черновики, оставлены для истории решений — доступны из index.html через шестерёнку)
01-cards-board.html — экран "листания идей" с фильтром по тегам
02-builder-split-screen.html — первая версия конструктора со статичным шаблоном резюме
03-template-compact-vs-dense.html — сравнение шаблонов резюме под разный объём текста
(дизайн отсюда перенесён в главный index.html)
04-mode-switcher.html — предыдущая версия главной страницы (три режима), но ещё
со статичным, не адаптивным шаблоном резюме слева
05-ai-assistant-system-prompt.md — черновик системного промта для платного ИИ-ассистента
(режим 3); провайдер — YandexGPT Lite, подключение
отложено до появления реального спроса (см. README)
src/ — Astro-приложение (SSG под SEO), мастер-копия конструктора
layouts/BaseLayout.astro — общий
SEO-страниц: title/description/canonical/OG/метрика,
JSON-LD (передаётся как structuredData)
components/
Constructor.astro — «ОСТРОВ» интерактивности, перенесён из index.html почти без изменений.
Отличия от прототипа: fetch('/data/ideas.json') по абсолютному пути,
ссылки черновиков и данных абсолютные (/prototypes/...), заголовок
карточки стал ссылкой на её SEO-страницу. CSS — изолированный (is:global),
JS собирается/минифицируется Astro. Логика отлажена Playwright-тестом —
сознательно не переписывалась на React/Vue.
Header.astro / Footer.astro / Metrika.astro
pages/
index.astro — лендинг: hero под длинный поисковый запрос, «как работает», подборка
популярных идей, все темы, FAQ (с JSON-LD FAQPage), CTA на конструктор
idei/index.astro — полный список 103 идей, сгруппированных по тегам (ItemList JSON-LD)
idei/[slug].astro — СТАТИЧЕСКИЕ SEO-СТРАНИЦЫ: 103 шт., по одной на запись ideas.json.
Route: /idei/strategy_games/ и т.д. Внутри: хлебные крошки, activity_title
(h1/заголовок), resume_bullet, comment как объяснение «почему интересно
работодателю», навыки, роли, примеры, employer_value, блок исследований,
CTA на конструктор, похожие идеи (связи по тегам). JSON-LD Article.
konstruktor.astro — страница-обёртка для Component.astro (полный экран приложения).
methodika.astro — страница «О методологии» (/methodika/): принцип «хобби → навыки →
роль», подходы Ramit Sethi / Laszlo Bock / инфостиль, честная пометка
«исследования есть у 3 из 103» + блок с реальными источниками
(динамически из data/ideas.json), AboutPage JSON-LD, CTA на конструктор
public/ — статика, попадающая в dist как есть
data/ideas.json — рабочая копия для runtime-fetch конструктора (автообновляется сборкой)
prototypes/, README.md, favicon.svg, og-cover.svg, robots.txt
astro.config.mjs — site (=https://resumegenerator.ru), trailingSlash, @astrojs/sitemap
(конструктор исключён)
scripts/
sync-data.mjs — копирует data/prototypes/README в public/ (вызывается prebuild)
run-e2e.mjs — обёртка теста: сама поднимает «astro preview» на :4321, ждёт готовности,
запускает test-constructor.mjs и гасит сервер (нужен только npm run build;
это то, что реально вызывает npm run test:e2e)
test-constructor.mjs — сами проверки: 103 карточки, фильтры, add/toggle, режимы, чат, дровер,
SEO-ссылка на статику, лендинг, список идей
upload-yandex.mjs — выгрузка dist/ в Yandex Cloud Object Storage (AWS SDK, без глобального CLI):
node scripts/upload-yandex.mjs {buckets|sync [--delete]|configure}
(ключи из deploy/.env, см. см. docs/DEPLOY.md)
data/ — источник истины (см. выше), из него генерируются и статика в /idei,
и (через public-копию) доска в конструкторе
```
## Ключевые решения по ходу разработки
- **Монетизация**: бесплатно — генерация идей и вдохновение; платно (~50₽ или пакетом) —
скачивание/редактирование. Рассматриваются варианты: пакет вместо разового платежа,
бесплатный экспорт с watermark, "поделись — получи бесплатно".
- **Экономика ИИ**: основной объём (подбор идей, сборка черновика резюме) работает БЕЗ
живого вызова ИИ — за счёт заранее подготовленной базы `ideas.json`. Живой ИИ подключается
только на платном этапе финальной редактуры текста.
- **SEO**: интерактивный конструктор (это, по сути, SPA на JS) поисковики не индексируют.
Реальный SEO-трафик должен идти через отдельные статические страницы, сгенерированные
из `ideas.json` (например `/idei/kvadrokopter-pomoshnik-blogera`). Нужен SSG-фреймворк —
чистый `index.html` для этого не подходит.
- **Переход на Astro сделан (шаг 2 плана).** Маршруты: `/` — SEO-лендинг, `/idei//` —
103 статические страницы идей (генерируются из `ideas.json` на сборке), `/konstruktor/` —
интерактивный конструктор как «остров» (перенесён из `index.html` почти без изменений).
Подробное дерево — в разделе «Структура». Осознанные решения, принятые при переносе:
- **Конструктор НЕ переписан на React/Vue** — логика в `Constructor.astro` осталась ванильной,
проверена Playwright-тестом (запуск `npm run test:e2e`). Нативный скрипт собирается и
минифицируется Astro-бандлером; это и есть «остров» в смысле Astro — вся остальная часть
сайта статический HTML.
- **Слаги — английские id из базы** (`/idei/strategy_games/`), а не транслитерация названий.
Причина: стабильность и уникальность без ручной разметки 103 записей; транслитерация
русских названий в слаги — отдельная контентная/техзадача, не сделано.
- **`ideas.json` живёт в двух местах**: источник истины `data/ideas.json` (из него генерируются
SEO-страницы на сборке) + рабочая копия `public/data/ideas.json` для runtime-fetch()
конструктора. Копию обновляет `scripts/sync-data.mjs` при каждом `npm run build` — руками
ничего не трогаем.
- **Домен вписан**: `site` в `astro.config.mjs` и `Sitemap:` в `public/robots.txt` =
**`https://resumegenerator.ru`** (куплен на reg.ru), на него указывают canonical/OG/sitemap.
Канонический адрес — без `www`; редирект `www` → без `www` делаем на DNS/хостинге (шаг 3).
- **HTTPS включён и работает** (18.08.2026): сертификат Let's Encrypt выпущен на домен
(`CN=resumegenerator.ru`, действителен до 16.11.2026), `http://` отдаёт 301 → `https://`,
каталоги `/`, `/idei/`, `/methodika/`, sitemap/robots проверены по https — 200, live E2E PASS.
Открывается из РФ (Yandex Cloud), переживает перевыпуск сертификата автоматически.
- **Стек**: выбран **Astro** — статическая генерация страниц под SEO + "острова" интерактивности
только там, где нужны (конструктор резюме). Astro не привязан к конкретному хостингу.
- **Хостинг — НЕ Vercel**: изначально рассматривался Vercel, но отклонён. Причины: (1) российские
карты не принимаются для платных тарифов, (2) отдельные сайты на `*.vercel.app` реально
попадают в реестр Роскомнадзора, (3) есть подтверждённые случаи, когда `.ru`-домен, привязанный
к Vercel, переставал открываться с мобильного интернета в РФ без VPN. Для сайта на российскую
аудиторию (и с `.ru`-доменом) это неприемлемый риск.
Решение: **Yandex Cloud** (Object Storage + Cloud Functions — аналог связки Vercel) либо для
старта проще — **обычный российский VPS** (Timeweb Cloud, Selectel, Beget) с Node.js,
отдающим и статику, и вебхук оплаты с одной машины. Оплата хостинга и оплата от пользователей
(через ЮKassa) в этом случае в одной валюте/юрисдикции — меньше точек отказа.
GitHub Pages по-прежнему годится только для просмотра статических прототипов (нет
серверных функций для вебхука оплаты), не для продакшена.
- **Не только лето**: изначально ниша задумывалась как "выпускники + летние подработки",
но верно расширена до "любой, кому нечего писать в резюме" — зимние каникулы, первая
работа после колледжа/вуза, гэп-год. Все тексты должны быть сезонно-нейтральными.
- **Актуальность примеров**: конкретные игры/сериалы/тренды быстро устаревают, поэтому в
схеме `ideas.json` они вынесены в отдельное поле `examples_now`, не смешанное с
устойчивой логикой (`category`, `skills`, `roles`).
- **Авторское право**: реальные резюме/тексты других людей брать нельзя ни для дизайна
(лицензии), ни для контента (авторское право + чужие персональные данные). Вместо этого —
собственная база примеров, сгенерированная с нуля.
- **Адаптивные шаблоны**: короткий текст ("О себе" в одну строку) не должен выглядеть как
пустой лист А4. Решение — шаблоны на два типа: "компактный" (сайдбар, крупная типографика,
визуальные элементы для малого объёма контента) и "плотный" (для тех, у кого есть что
рассказать развёрнуто). Система должна сама подбирать шаблон по объёму заполненного
контента, а не спрашивать пользователя.
- **AI-провайдер — выбор сделан (YandexGPT Lite), но подключение сознательно отложено**:
сравнивали GigaChat Business, YandexGPT Lite и агрегатор Ofox.ai — Ofox отклонён (не решает
вопрос доступа/данных из РФ, просто прокси поверх зарубежных моделей, неясный статус для
встраивания в клиентский продукт). YandexGPT Lite выигрывает у GigaChat Business по порогу
входа (не требует юрлица для базового доступа). НО: оба тарифицируются по токенам без
абонплаты — значит подключать их есть смысл только когда появится реальный трафик.
Режимы 1 и 2 (карточки, поиск по профессии) не требуют ИИ вообще — работают на чистом
`ideas.json`. Запускаем их первыми, без ИИ-зависимости и без затрат.
**Триггер для подключения живого ИИ**: когда появится измеримый сигнал, что люди реально
доходят до режима 3 и хотят большего, чем дают карточки — не раньше.
До этого момента режим 3 остаётся локальным помощником-подсказчиком (поиск по ключевым
словам + словарь синонимов, уже реализовано в `index.html`), без единого платного вызова.
- **Три режима конструктора** (переключаются одной кнопкой на экране):
1. *Листай и собирай* — базовый режим, карточки идей с фильтром по тегам (уже реализован).
2. *Навыки под профессию* — обратный режим: пользователь выбирает интересующую роль/профессию,
система показывает навыки, которые для неё может — но не факт что имеет — обладать; это
переиндексация того же `ideas.json` по полю `roles`, отдельных данных не требует.
3. *Помощник-подсказчик* — сейчас бесплатный и локальный: наводящими вопросами и
ветвлением по темам подбирает идеи из `ideas.json` (поиск по ключевым словам +
словарь синонимов, без внешнего ИИ). Живой платный ИИ (RAG поверх той же базы) —
в бэклоге, подключается по указанному выше триггеру.
- **Самозанятость**: подходит для приёма платежей от физлиц (ставка 4% НПД, лимит дохода
2.4 млн ₽/год). Для приёма оплаты + автофискализации чеков — агрегаторы вроде ЮKassa,
CloudPayments (сами формируют чек в "Мой налог").
- **`index.html` теперь загружает полную базу через `fetch('data/ideas.json')`**, а не
захардкоженный список ~20 карточек, как было раньше во всех трёх режимах. Все 103 записи
теперь видны и в "листай и собирай", и в "навыки под профессию", и в подсказчике.
Важно: `fetch()` не работает при открытии файла двойным кликом с диска (`file://`) —
нужен локальный сервер (`python -m http.server`) или реальный хостинг (GitHub Pages и
выше уже подходят). На этот случай на странице показывается понятное предупреждение
вместо молчаливой пустой страницы.
- **Резюме-панель увеличена (~в 1.6 раза, 300px → 480px макс.) и стала редактируемой**:
поля Имя, Целевая роль, Телефон, Email, Образование — обычные ``, значения
хранятся в отдельном JS-объекте `profile`, который переживает перерисовку шаблона при
добавлении/удалении идей (проверено headless-тестом в Playwright — значения не теряются).
Вопрос "платно или бесплатно" по самому редактированию — сознательно не решён, нужно
обкатать на реальных пользователях сначала.
- **Исправлена ошибка: нельзя было убрать добавленную идею.** Кнопка "Добавить в резюме"
раньше навсегда переходила в состояние "Добавлено" без возможности отмены — теперь это
полноценный toggle (`toggleAdded()`), работает одинаково в режиме "листай" и в
рекомендациях подсказчика. В режиме "навыки под профессию" тоже поправлено: снятие
галочки с навыка убирает карточку из резюме, только если ни один другой отмеченный
навык больше не ссылается на ту же карточку.
- **Резюме больше не показывает объясняющий `comment` дословно.** Раньше в "Что предлагаю"
(компактный шаблон) и "Проектный опыт" (плотный шаблон) подставлялся текст поля
`comment` — а он написан вторым лицом, объясняющим тоном ("Стратегии учат
распределять ресурсы...") и адресован пользователю сайта, а не читается как то, что сам
кандидат написал бы о себе рекрутеру. Заменено на `skills` — короткие профессиональные
формулировки, которые уже есть в базе и звучат уместно в резюме. `comment` остался только
в карточках при листании — там ему место. Полноценные авторские резюме-формулировки под
каждую из 103 записей — в бэклоге как отдельная контент-задача, не сделано.
- **Локальный подсказчик получил словарь синонимов/жаргона** (`SYNONYMS` в `index.html`) —
около 40 записей вида "катка"/"дота"/"кс" → тег "игры", "стрим"/"твич" → тег "видео" и т.д.
Это упрощённая версия изначально задуманного "этапа 2" (полноценный ручной список
ключевых слов на каждую из 103 записей не сделан — это большой объём контентной работы,
отложено до появления сигнала, что базового стемминга + словаря недостаточно).
- **Добавлен тёплый блок-синтез черт характера** (`TRAIT_RULES` + `renderTraitSynthesis()`),
показывается в режиме "Помощник-подсказчик" после выбора 2+ идей. НЕ психологический
разбор в духе "глубокого" ИИ-примера (пользователь показал скриншот диалога с Google AI —
там реально впечатляющая генеративная глубина, но: а) для резюме подобный текст всё
равно избыточен, б) для настоящей персонализации нужен живой ИИ, не шаблоны — попытка
подделать это статикой быстро начинает повторяться и терять доверие). Вместо этого —
~14 правил вида "теги → черта характера" (например `["дети","животные"] → "забота о
других"`), каждое с 3 вариациями фразы для разнообразия, показывается отдельно от самого
резюме (это не документ для рекрутера, это поддержка для пользователя). Проверено
headless-тестом (Playwright): комбинация тегов "дети"+"животные" корректно матчит
правило "забота о других".
- **"О себе" и "Проектный опыт"/"Что предлагаю" стали редактируемыми полями** (textarea),
а не статичным текстом. Показывают автосгенерированный черновик, пока пользователь не
начнёт печатать — после первой правки поле "становится его" и не перезатирается при
добавлении новых идей (проверено тестом: правка переживает даже переключение между
компактным и плотным шаблоном). Есть кнопка "↺ вернуть автотекст" для отката.
- **Исправлена грамматическая ошибка в "О себе"**: было "Активно интересуюсь: [название
категории в именительном падеже]" — требует творительного падежа, согласование ломалось
почти всегда. Вместо ручного склонения 103 категорий (риск новых ошибок, нужна морфология)
формулировка переписана на "Мои интересы: [список]" — падеж вообще не нужен.
- **Отклонена идея с вымышленным "научно-исследовательским институтом"** для обоснования
связок навыков — это фабрикация несуществующего источника, репутационный и юридически
небезопасный риск (как заявления "исследования показали" у сомнительных БАДов). Если для
конкретных связок будут найдены настоящие исследования — их можно процитировать по
существу, с реальным источником. Общий вывод: уверенный тон без выдуманного авторитета.
- **Убрана запутанная/дублирующая подсказка в "Навыки под профессию"**: подсказка снизу
ссылалась на "профессию выше", но при длинном списке ролей это легко пропустить.
Верхняя подсказка (перед списком) сделана заметнее (карточка с иконкой вместо мелкого
серого текста), а нижняя переформулирована без отсылки к "выше".
- **Режим "Навыки под профессию" — починена навигация.** Оказалось, что база даёт 271
уникальную роль на 103 записи (роли слишком раздроблены — "Технический ассистент",
"Технический ассистент в геймдев-студии" и т.д. как отдельные строки). Добавлено поле
поиска над списком (фильтрует на лету) + после выбора профессии плитка сворачивается в
один чип "Выбрано: Х [изменить]", результат сразу виден без скролла через десятки чипов.
Отдельная задача на будущее (не сделано) — нормализовать/объединить похожие роли в самих
данных, а не только чинить интерфейс сверху.
- **Добавлен блок "🔬 Что говорят исследования"** — необязательное поле `research` в
`ideas.json` (v3.1), пока заполнено только для 3 карточек (`reading_books`, `team_shooter`,
`team_sport`), где реально существуют метаанализы/систематические обзоры. Каждая запись
содержит: вывод, честную оговорку (воспроизводимость, ограничения) и реальный источник со
ссылкой. Раскрывается по клику в карточке при листании, в резюме не попадает (как и
`comment`). Осознанно НЕ добавлено на все 103 записи — для большинства узких связок
("квадрокоптер → пространственное мышление") просто не существует профильных исследований;
добавлять туда наукообразный текст значило бы либо упрощать до неправды, либо фабриковать
источник (что мы уже отклонили как отдельную идею с вымышленным институтом).
- **Резюме-панель теперь масштабируется под размер экрана**, а не упирается в жёсткий
потолок в пикселях. Было `minmax(320px, 480px)` — на больших мониторах колонка визуально
"терялась" на фоне выросшего правого блока. Стало `minmax(320px, min(34vw, 560px))` —
растёт вместе с окном, но не бесконечно (проверено тестом: 435px на экране 1280px,
560px на экране 1920px).
- **Поле "Образование" было однострочным ``** — длинный текст обрезался по ширине
вместо переноса. Заменено на `