П/ВИН

Редизайн pashavin.ru: от статики к Three.js и GSAP

·8 мин чтения
Редизайн pashavin.ru: от статики к Three.js и GSAP

Когда твой сайт — это витрина для клиентов, инвесторов и сообщества одновременно, планка качества сразу поднимается. Именно с этой мысли началась большая работа над pashavin.ru — персональным сайтом-портфолио, который из простой визитки должен был превратиться в полноценный маркетинговый инструмент. В этой статье расскажу, что именно мы сделали, какие проблемы решали и куда движемся дальше.

Контекст: что было в начале

Проект строится на стеке Next.js + React + TypeScript + Tailwind CSS. Никакой базы данных — все данные хранятся в TypeScript-файлах прямо в репозитории. Это осознанное решение: портфолио не требует динамики на сервере, зато требует скорости, надёжности и простоты деплоя.

Деплой идёт через Dokploy — self-hosted PaaS, который слушает GitHub webhook и автоматически собирает новую версию при каждом пуше в master. Workflow максимально прямолинейный: поправил код → закоммитил → запушил → через пару минут изменения на проде.

На старте у сайта было 10 секций на главной странице и базовая форма обратной связи. Но со временем накопился список улучшений, которые превратились в несколько волн разработки.

Проблема первая: форма обратной связи была слишком бедной

Исходная форма «Связаться» содержала минимум полей — имя, телефон и тема обращения. Этого явно не хватало: потенциальный клиент не мог ни написать развёрнутый запрос, ни оставить email или Telegram для удобного ответа.

Параллельно нужно было настроить доставку заявок. Решение очевидное — Telegram-бот. Токен бота и chat ID были добавлены как переменные окружения в Dokploy (в коде они нигде не фигурируют — только через process.env). API-роут на Next.js собирает данные из формы и отправляет отформатированное сообщение в личку.

Что добавили в форму

К обязательным полям (имя + телефон) добавились необязательные:

  • Emailtype=email, стандартная валидация браузера
  • Telegram — текстовое поле, плейсхолдер @username
  • Сообщение<Textarea> на 3-4 строки, чтобы человек мог описать задачу подробно

Для textarea использовали компонент из shadcn/ui — он хорошо вписывается в существующую дизайн-систему и не требует лишних зависимостей.

API-роут обновился так, что необязательные поля попадают в Telegram-сообщение только если они заполнены. Никакого мусора в уведомлениях — только релевантная информация.

// app/api/contact/route.ts (упрощённо)
export async function POST(req: Request) {
  const { name, phone, email, telegram, topic, message } = await req.json()
 
  const lines = [
    `👤 *${name}*`,
    `📞 ${phone}`,
    email ? `📧 ${email}` : null,
    telegram ? `✈️ ${telegram}` : null,
    `📌 Тема: ${topic}`,
    message ? `\n💬 ${message}` : null,
  ].filter(Boolean)
 
  await fetch(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      chat_id: process.env.TELEGRAM_CHAT_ID,
      text: lines.join('\n'),
      parse_mode: 'Markdown',
    }),
  })
 
  return Response.json({ ok: true })
}

Простая интеграция, но она работает надёжно — заявки прилетают мгновенно, ни одна не теряется.

Проблема вторая: блок «Обо мне» не передавал экспертизу

Раздел о себе был слишком лаконичным. Для человека, который занимается автоматизацией маркетинга, AI-контент-системами и строит стартапы — это упущенная возможность.

Добавили блок «Экспертные темы» с конкретными направлениями:

  • Автоматизация маркетинга и продаж
  • ИИ-контент-заводы
  • Стратегии роста прибыли через ИИ
  • Привлечение клиентов с помощью ИИ
  • Системное использование нейросетей в команде
  • Создание стартапа с помощью ИИ от идеи до выручки

Данные уже лежали в data/personal.ts — просто раньше не рендерились на странице. Параллельно скорректировали aspect-ratio фотографии с 3/4 на 9/16 для более вертикального и современного кадрирования.

Проблема третья: проекты вели на внешние ссылки

Секция «Разработки с помощью ИИ» отображала карточки проектов со ссылками на внешние сайты. Проблема в том, что пользователь уходил с сайта, не получив полной истории проекта.

Решение — внутренние страницы-кейсы по маршруту /projects/[slug]. Маршрут уже существовал в коде, но использовал данные из другого файла и выглядел как упрощённая карточка.

Планировался полноценный редизайн этих страниц в духе brutalist typography: крупный hero с названием проекта, marquee со стеком технологий, детальное описание с метриками, скриншоты.

Для хранения данных спроектировали расширенную TypeScript-структуру:

type ProjectCategory = 'startup' | 'product' | 'expertise' | 'bot' | 'infrastructure'
 
interface Project {
  slug: string
  name: string
  tagline: string
  description: string
  category: ProjectCategory
  stack: string[]
  metrics?: { label: string; value: string }[]
  screenshots?: string[]
  externalUrl?: string
  highlights: string[]
}

Отдельная идея — автоматическое обновление данных: Claude Code при работе над каждым проектом читает KNOWLEDGE.md и может обновлять данные в портфолио. Фактически, портфолио само себя поддерживает в актуальном состоянии.

Большой редизайн: от ТЗ к реализации

Параллельно с точечными улучшениями созревало понимание, что сайту нужен кардинальный редизайн. Уровень — Awwwards. Не просто красивый, а по-настоящему запоминающийся.

Было составлено ТЗ для дизайнера, проработана каждая секция. Первая волна реализации дала работающий сайт с анимациями на чистом CSS и IntersectionObserver — неплохо, но далеко от задуманного.

Что планируется в следующей волне

Полная переделка анимационного слоя. Стек:

  • React Three Fiber — 3D hero с ~2000 частицами (InstancedMesh для производительности), noise-based movement, bloom через postprocessing
  • GSAP + ScrollTrigger — все scroll-анимации: clip-path wipe при входе в секцию, line-by-line text reveal, parallax
  • Lenis — smooth scroll по всему сайту, синхронизированный с GSAP ticker

Архитектура:

// lib/gsap.ts — регистрация плагинов
import gsap from 'gsap'
import ScrollTrigger from 'gsap/ScrollTrigger'
import SplitText from 'gsap/SplitText'
 
gsap.registerPlugin(ScrollTrigger, SplitText)
export { gsap, ScrollTrigger, SplitText }
 
// lib/lenis.ts — инициализация
import Lenis from 'lenis'
import { gsap } from './gsap'
 
export function initLenis() {
  const lenis = new Lenis()
  gsap.ticker.add((time) => lenis.raf(time * 1000))
  gsap.ticker.lagSmoothing(0)
  return lenis
}

Hero секция на Three.js — это не просто красота. Частицы создают ощущение технологичности и движения, которое невозможно передать через CSS. Bloom-эффект на частицах, camera parallax при движении мыши, lazy load чтобы не тормозить LCP — всё продумано.

Для каждой секции — своя механика:

  • About: clip-path wipe при входе, sticky фото с parallax, line reveal для текста
  • Expertise: conic-gradient border rotating по периметру карточек при hover
  • Projects: staggered card entrance через GSAP timeline
  • Stats: counter animation от 0 до целевого значения при попадании в viewport

Структура данных и масштабируемость

Одно из ключевых архитектурных решений — держать все данные в TypeScript. Это даёт:

  1. Типобезопасность — компилятор поймает опечатку в названии поля
  2. Простой деплой — нет баз данных, нет миграций, нет downtime
  3. Git как CMS — история изменений контента в коммитах
  4. Статическая генерация — Next.js генерирует все страницы при билде, скорость максимальная

Для страниц проектов Next.js генерирует статические пути через generateStaticParams:

// app/projects/[slug]/page.tsx
export async function generateStaticParams() {
  return projects.map((p) => ({ slug: p.slug }))
}
 
export async function generateMetadata({ params }: Props) {
  const project = projects.find((p) => p.slug === params.slug)
  return {
    title: `${project?.name} | Паша Вин`,
    description: project?.tagline,
  }
}

Каждая страница проекта получает правильные мета-теги автоматически — хорошо и для SEO, и для шаринга в соцсетях.

Деплой и DevOps

Докплой обрабатывает деплой через GitHub webhook. Схема:

  1. Пуш в master
  2. GitHub отправляет webhook в Dokploy
  3. Dokploy клонирует репозиторий, запускает next build
  4. При успешном билде — переключает трафик на новый контейнер

Rate limiting для API-роута добавили заранее — стандартная защита от спама на форме обратной связи. Без неё форма становится лёгкой мишенью для ботов.

Auto-sync скрипт следит за изменениями в рабочей директории и автоматически коммитит и пушит — это ускоряет итерации при активной разработке, хотя для продакшена такой подход требует осторожности.

Результат и метрики

Что получили к текущему моменту:

  • Рабочий сайт с 10 секциями, адаптивным дизайном, работающей формой
  • Telegram-интеграция — заявки приходят мгновенно в личку
  • Блок экспертизы — теперь сразу понятно, с какими задачами можно обращаться
  • Основа для страниц проектов — маршрут /projects/[slug] готов, нужна только финальная стилизация
  • Автоматический деплой — любой пуш в master уходит на прод за ~2 минуты

Следующий шаг — полная анимационная переработка с Three.js hero и GSAP scroll-анимациями. Основа готова, архитектура спроектирована.

Выводы и уроки

Работа над персональным сайтом — это особый тип проекта. С одной стороны, нет жёстких дедлайнов и нет клиента, которому нужно отчитываться. С другой — именно это делает его ловушкой: легко застрять в перфекционизме или, наоборот, откладывать улучшения бесконечно.

Главный урок — итеративный подход работает лучше всего. Сначала запустить рабочую версию, потом точечно улучшать. Форма с тремя полями лучше, чем идеальная форма, которой нет. Простые CSS-анимации лучше, чем не запущенный Three.js. Мы сначала получили работающий продукт, а потом начали его улучшать — и это правильная последовательность.

Разделение данных и представления — ещё один важный принцип. Когда весь контент лежит в TypeScript-файлах с чёткими интерфейсами, добавление нового проекта занимает пять минут. Никаких CMS, никаких интерфейсов для редактирования — просто добавил объект в массив и задеплоил. Для разработчика это максимально удобно.

Инфраструктура должна исчезать — деплой через Dokploy полностью убирает операционную нагрузку. Не нужно думать про nginx, SSL-сертификаты, рестарты процессов. Фокус остаётся на продукте. Именно так и должно работать современное портфолио разработчика.

Наконец, анимации — это не украшение, это коммуникация. Правильно сделанный Three.js hero передаёт технологичность лучше, чем любой текст. Scroll-анимации направляют внимание, создают ритм. Когда для потенциального клиента или работодателя сайт говорит: «его автор разбирается в современных технологиях» — это ценнее любого резюме. Именно поэтому редизайн с GSAP и Three.js в приоритете следующей сессии.


Ссылки по теме:

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.