Mobile-first PWA для русскоязычных семей, выбирающих город для релокации. Связывает медицинский профиль, климат, визовые сценарии и финансовую модель в один сквозной флоу — от первого вопроса до плана переезда.
Демо: https://relocation-companion.vercel.app
Между справочниками типа Numbeo и форумами есть разрыв: данные есть, а решения под конкретную семью нет. Приложение закрывает этот разрыв — учитывает здоровье, бюджет, визы и доступность среды и ведёт пользователя по шагам.
- Атлас локаций — 11+ городов (Чёрное море / Средиземное / Адриатика / Континент / Кавказ), фильтры по влажности, AQI, гастро-доступности, ВНЖ-сценариям
- Сравнение городов (до 3) — взвешенные критерии, контр-аргументы, lazy-loaded deep-секции
- AI-чат — пошаговый сценарий подбора города, кликабельные источники с классификацией доверия, добавление выводов в план одним нажатием
- Финансовая модель — Monte Carlo на 12–60 месяцев, транзит капитала, ROI-калькулятор
- План на 12 месяцев — Kanban с 6 swimlanes, критический путь, шаблоны документов
- Психологическая опора — 6 фаз релокации, ежедневный трекер (6 метрик), дневник пары, дневник симптомов
- База знаний — 200+ Q&A по 13 категориям, версионирование ответов с
deprecatedSince - Privacy-first — данные хранятся только в localStorage клиента (
rc2027:*), никакой телеметрии без opt-in
- Frontend: React 18.3.1 (self-hosted,
vendor/), JSX компилируется в бандл через esbuild - Сборка: esbuild конкатенирует
app/**+src/data/**→dist/app.bundle.js(без in-browser компиляции, без внешних CDN) - Стили: vanilla CSS с custom properties, mobile-first
- Хранилище:
localStorageчерез хукuseLocalState(key, init) - PWA: Service Worker (network-first + stale-while-revalidate), Web App Manifest, install-prompt + update-flow
- Безопасность: CSP (без unsafe-eval), HSTS, X-Frame-Options DENY, sanitization-хелперы, source-tier badges
- Диагностика:
RC_LOG— глобальные логи в localStorage,?logs=1для просмотра,?reset=1для сброса - Тесты: Playwright smoke-тесты, CI на GitHub Actions (build + validate + smoke)
- Dev-инструменты (Node ≥18): esbuild, AJV-валидация схем, парсер JSX через
@babel/parser, sharp для иконок
npm install # один раз
npm run build # собрать dist/app.bundle.js
npm run serve # локальный статик-сервер на :8765
# для разработки — авто-пересборка:
npm run dev # esbuild watchОткрыть http://localhost:8765. Браузер сам зарегистрирует Service Worker.
Важно: для регистрации SW нужен
https://илиlocalhost—file://не сработает. Бандлdist/не коммитится — генерируется командойbuild(и Vercel при деплое).
npm run build # esbuild → dist/app.bundle.js
npm run dev # esbuild watch (авто-пересборка)
npm run serve # статик-сервер на :8765
npm run test:smoke # Playwright smoke-тесты
npm run validate:locations # AJV-валидация всех JSON-досье городов
npm run validate:jsx # парсинг JSX через @babel/parser (синтаксис)
npm run audit:freshness # аудит свежести данных (--threshold 365 --format json)
npm run audit:urls # HEAD-запросы по всем 256+ source URL
npm run generate:icons # SVG → 5 PNG-вариантов (192/512/maskable/apple/favicon)app/ ← текущий слой приложения
├── app.jsx ← root, регистрация SW, состояние PWA
├── primitives.jsx ← UI-примитивы, хуки (useServiceWorker, useInstallPrompt, ErrorBoundary)
├── shell.jsx ← роутинг + PageResolver
├── styles.css ← главные стили
└── screens/ ← Today, Atlas, Compare, Chat, Plan, Profile
src/data/ ← данные
├── locations/ ← JSON-досье по схеме v1/v2 (yerevan.json, pomorie.json, …)
├── user-profile/ ← дефолтные профили
├── location-loader.js ← lazy-загрузчик досье
├── conditions.js ← медицинские условия
├── extras.js ← UI-секции расширений
├── qna.js ← 200+ Q&A-записей
└── index.js ← LOCATIONS, CRITERIA, PHASES, LANES, TASKS, GLOSSARY
scripts/ ← dev-инструменты (build, валидаторы, аудит, иконки)
tests/ ← smoke-тесты (Playwright)
icons/ ← мастер-SVG + сгенерированные PNG
docs/ ← design brief, user stories, data map, схемы
dist/app.bundle.js ← собранный бандл (esbuild, генерируется при деплое)
manifest.json ← Web App Manifest (shortcuts, maskable icons)
service-worker.js ← Service Worker с 3 стратегиями кеширования
vercel.json ← заголовки (CSP, HSTS, immutable-ассеты, SW no-cache)
index.html ← entry point
Service Worker регистрируется автоматически при загрузке. Стратегии:
| Ресурс | Стратегия | Пояснение |
|---|---|---|
| HTML + бандл + ассеты | network-first | свежее всегда побеждает, кэш — offline-fallback |
| JSON-досье городов | stale-while-revalidate | мгновенный показ + фоновое обновление |
SW не трогает внешние ресурсы — все зависимости (React) хостятся на своём origin (vendor/), не зависим от внешних CDN (важно для RU-сетей).
Поток обновлений:
git push→ Vercel build → деплой- Клиент при
visibilitychange(или раз в 60 минут) проверяет SW - При обнаружении нового
service-worker.js— UI-карточка «Доступно обновление» - Пользователь жмёт «Обновить» →
postMessage({type:'SKIP_WAITING'})→controllerchange→location.reload()
CACHE_VERSION в service-worker.js бампается вручную при breaking-изменениях в стратегии кеширования.
50-шаговый план Phase 6 живёт в BACKLOG.md. Текущий прогресс: 14/50 (28%).
История версий — в VERSIONS.md. Полный реестр файлов и их назначения — в FILES.md.
Хостится на Vercel: push в main → автоматический build → продакшн.
Заголовки (CSP, HSTS, immutable-иконки, Service-Worker-Allowed) сконфигурированы в vercel.json.
Продукт, структура данных и дизайн-система спроектированы автором; код написан в связке с Claude Code. Личный проект (pet): esbuild-пайплайн, PWA, Playwright-тесты и CI собраны как в рабочем продукте, потому что проект используется для реальных решений.
Алексей Черненко — AI-интегратор, Product Engineer. Telegram: @alex_chnk, GitHub: LongWinterNight
Код опубликован для ознакомления. Использование без отдельного разрешения автора запрещено.
