Публичный GitHub API заблокирует ваше интерактивное 3D-портфолио всего через 60 просмотров в час, если вы заранее не настроите инкрементальную регенерацию страниц или собственный прокси-сервер на Vercel. Создание по-настоящему иммерсивного веб-интерфейса требует не просто красивых моделей Three.js, а бескомпромиссной оптимизации — от нормирования анимации через дельту времени до рендеринга модальных окон через порталы React. Это детальное руководство по превращению связки Next.js, Tailwind CSS и Framer Motion в отказоустойчивую и плавную цифровую витрину разработчика.
💻 Разработка адаптивного портфолио: обзор проекта и окружение 0:00
Создание современного портфолио — это отличный способ прокачать навыки фронтенд-разработки, объединив Next.js, библиотеку Three.js для 3D-графики и Tailwind CSS для стилизации. В данном проекте основное внимание уделяется созданию уникального пользовательского опыта, включающего интерактивные 3D-модели, фоновую музыку с системой согласия пользователя и адаптивную верстку.
При первом посещении сайта пользователь видит окно согласия на воспроизведение фоновой музыки, выбор которого сохраняется в localStorage. Интерфейс включает анимированные кнопки, которые срабатывают при загрузке страницы, и центральный 3D-элемент. Одной из визуальных «фишек» является динамический фон с эффектом летящих светлячков (ранее в разговоре они касались создания этого эффекта). Интерактивность обеспечивается тем, что при наведении на иконки навигации (Home, About, Projects, Contact, GitHub, Resume) анимация фона приостанавливается, а пользователь видит соответствующую подпись. Сайт полноценно адаптирован для мобильных устройств, где навигационные элементы перестраиваются для удобного отображения на узких экранах.
Настройка окружения и подготовка зависимостей 6:01
Для старта разработки необходимо клонировать репозиторий со стартовым кодом через терминал: git clone [URL]. После перехода в директорию проекта выполняется установка всех необходимых библиотек с помощью npm install.
Ключевой стек технологий включает:
- EmailJS: для отправки данных из контактной формы напрямую на почту.
- React Three Fiber: основной React-рендерер для работы с Three.js.
- React Three Drei: набор вспомогательных инструментов и абстракций для Three.js.
- Framer Motion: для реализации сложных анимаций.
- Lucide React: библиотека иконок.
- React Hook Form: для удобной работы с формами и валидацией данных.
- Sonner: для отображения уведомлений в стиле Toast.
- clsx: утилита для условной генерации имен классов Tailwind CSS.
Конфигурация Tailwind и системные стили 8:13
Для обеспечения визуального единства проекта важно правильно настроить шрифты и цвета в конфигурационных файлах. Переменные шрифтов, такие как Inter, задаются в layout.js и затем подключаются в tailwind.config.js через параметр fontFamily, что позволяет использовать их через классы вроде font-enter.
Цветовая палитра проекта управляется через переменные CSS в globals.css в слое @layer base, что дает возможность гибко менять тему оформления. Применение переменных в Tailwind происходит через использование RGB-формата, что обеспечивает плавную работу с прозрачностью и оттенками. Также на этом этапе настраивается базовый компонент page.js, где с помощью clsx объединяются стили для корректного отображения шрифтов, фона и текста.
🌐 Оживляем интерфейс: интеграция фонов и глубинная настройка 3D-сцены 25:25
Интеграция фонового слоя и управление трехмерным пространством 26:15
В процессе верстки современного интерактивного веб-приложения правильное распределение слоев графики играет решающую роль, обеспечивая корректное отображение элементов интерфейса. На данном этапе разработки автор сталкивается с классической проблемой трехмерной фронтенд-разработки: сразу после успешной загрузки новой трехмерной модели она оказывается полностью скрытой за фоновым изображением страницы. Для исправления этого визуального бага применяется каскад CSS-стилей Tailwind в связке с архитектурными решениями Next.js.
Фоновое изображение, сгенерированное ранее с помощью генеративного искусственного интеллекта на платформе Playground AI, переводится в режим абсолютного позиционирования с помощью свойства fill. Данный атрибут заставляет картинку автоматически растягиваться на всю ширину и высоту экрана, подстраиваясь под текущие габариты пользовательского вьюпорта. Чтобы вернуть трехмерную сцену на передний план, разработчик открывает файл рендеринга модели и принудительно выставляет фону отрицательный индекс наложения — min-z-10 или Z - 10. Такой подход утапливает фоновый слой глубоко по оси Z, формируя чистую подложку для интерактивных компонентов. Дополнительно в процессе отладки кода исправляется досадная опечатка в конфигурации стилей страницы (screen вместо ошибочного значения), что мгновенно восстанавливает корректное полноэкранное отображение всей структуры приложения.
Рендеринг моделей с React Three Fiber и световая глубина 25:25
Основой для интеграции и отображения трехмерной графики в проекте выступает библиотека React Three Fiber. Полноценная работа с холстом требует обязательного добавления директивы "use client" в самом начале файла компонента, так как обработка WebGL-контекста и рендеринг сложных шейдеров должны происходить исключительно на стороне веб-браузера клиента. Все файлы трехмерных ресурсов, включая оптимизированные модели, размещаются централизованно в публичном статическом каталоге проекта по пути public/models/.
Для импорта тяжелых объектов применяется специализированный хук useGLTF, который парсит файл модели wizard-transformed.glb и возвращает структурированный набор узлов (nodes) и готовых текстурных материалов (materials). Чтобы манипулировать трехмерным объектом как единым целым, все составные полигональные сетки объединяются внутри родительского контейнера <group>. Первичная настройка пространственного положения — это всегда результат кропотливых экспериментов. Автор делится выверенными значениями координат, полученными опытным путем: по оси X выставляется нулевое значение, по оси Y модель опускается на -1.5 для центрирования, а по оси Z остается на нулевой отметке. Параллельно применяется масштабный коэффициент 0.06, уменьшающий гигантские исходные габариты фигуры до приемлемых пропорций веб-интерфейса.
Однако изначально отрендеренная модель выглядит абсолютно темным, нечитаемым силуэтом из-за полного отсутствия источников света на сцене. Вместо ручного добавления множества точечных или направленных светильников, разработчик внедряет универсальный компонент <Environment>, который проецирует на объект реалистичную карту освещения окружающей среды.
Библиотека предоставляет обширный спектр готовых пресетов освещения:
- Стандартные городские и интерьерные карты, такие как "apartment", "city" или "forest".
- Контрастные атмосферные варианты, включая "night" (создающий глубокие ночные тени) и "dawn" (рассвет).
Для данного портфолио автор выбирает именно пресет "dawn", обеспечивающий мягкий, естественный и достаточно яркий рассеянный свет. Финальным штрихом настройки сцены становится корректировка угла обзора: модель поворачивают на 25 градусов относительно оси X, чтобы придать персонажу более выразительный ракурс.
Инструменты оптимизации: gltf-jsx и внешние редакторы 27:06
Высокая скорость загрузки сайта напрямую зависит от качества подготовки графических ассетов. Ранее для оптимизации геометрии использовалась консольная утилита gltf-jsx, сжимающая исходный файл. Чтобы полностью исключить визуальные рывки и задержки интерфейса при первом посещении страницы, в коде задействуется метод useGLTF.preload, который кэширует тяжелые ресурсы до того, как они понадобятся в основном дереве рендеринга.
Если подбор пространственных параметров через ручное редактирование кода кажется слишком рутинным, существует альтернативный визуальный путь. Автор подробно описывает алгоритм работы с официальным веб-редактором Three.js Editor. Разработчику достаточно перетащить файл формата .glb или .gltf прямо в окно браузера. В интерактивном режиме можно визуально настраивать масштаб по всем осям, тестировать различные схемы окружения и менять углы вращения. После завершения калибровки готовая сцена экспортируется обратно в файл для последующей бесшовной интеграции в проект.
Стоит отметить, что в рамках этого же временного отрезка автор закладывает важный фундамент для последующей интерактивности приложения. В коде появляется хук useFrame, считывающий дельту времени и системные часы state.clock.elapsedTime для создания плавного циклического движения модели по синусоидальной траектории. Данная механика анимации 3D-объектов подробно рассматривается в третьей главе. Кроме того, начинается проработка интерфейсной логики кнопок: запуск вычислений углового шага (360 / buttonList.length) и их перевод в радианную меру для последующего позиционирования через тригонометрические функции синуса и косинуса. Этот математический аппарат служит основой для создания полноценной круговой навигации, механика которой детально раскрывается в четвертой главе.
🌌 Магия движения: Анимация 3D-объектов в реальном времени 50:20
Жизненный цикл кадра и хук useFrame 50:32
В современных веб-интерфейсах анимация давно вышла за рамки простых двумерных переходов. В то время как обычные элементы интерфейса, такие как иконки Lucide (home, user, phone, github), рендерятся через условные конструкции switch и могут обходиться стандартными CSS-свойствами вроде прозрачности границ или размытия backdrop-filter, полноценное трехмерное пространство требует принципиально иного подхода к динамике. Центральным инструментом для оживления 3D-сцен в экосистеме React Three Fiber выступает хук useFrame. Этот хук позволяет встроиться напрямую в глобальный цикл рендеринга браузера (requestAnimationFrame), выполняя заданный код на каждом изменяющемся кадре.
Введя этот инструмент, разработчик уходит от декларативного описания шагов, свойственного CSS. При настройке стандартных Tailwind-интерфейсов, где для кнопок рассчитываются сложные внутренние тени boxShadow со смещениями, интерфейс жестко привязан к разметке. В противоположность этому, внутри коллбэка useFrame можно напрямую и плавно мутировать свойства меша: например, изменять положение по относительным координатам. Это обеспечивает непревзойденную плавность, недостижимую классическими методами манипуляции DOM. Ранее в разговоре авторы уже касались базового рендеринга и оптимизации моделей, но именно на этапе интеграции хука useFrame статические объекты превращаются в живые элементы портфолио.
Синхронизация и вычисление плавных траекторий в 3D 57:36
Одной из главных проблем при работе с трехмерной графикой является зависимость скорости выполнения анимации от частоты обновления экрана (Hz) пользователя. Если просто увеличивать угол поворота 3D-модели на фиксированную величину на каждом кадре, то на мониторе с частотой 60 Гц объект будет двигаться в два раза медленнее, чем на игровом дисплее с частотой 120 Гц. Для решения этой проблемы хук useFrame предоставляет два важнейших аргумента: объект состояния (state) и дельту времени (delta). Значение delta отражает точное время в секундах, прошедшее с момента рендеринга предыдущего кадра. Умножая шаг анимации на эту дельту, мы гарантируем, что скорость движения 3D-модели останется неизменной на абсолютно любом устройстве.
Это сильно контразирует с двумерной анимацией вращения круговой навигации spin-slow за 40 секунд, где для компенсации вращения текста приходится программно задавать реверс от 0% до -360 градусов. В трехмерном пространстве все вычисления происходят на лету. Использование встроенных тригонометрических функций, таких как Math.sin(state.clock.getElapsedTime()), внутри кадрового цикла позволяет создавать реалистичные эффекты покачивания или левитации объектов. Более того, если пользователь переключает вкладку браузера или взаимодействует с другими элементами, анимацию можно изящно приостановить с помощью изменения флага воспроизведения. Это концептуально похоже на то, как в CSS-стилях для интерфейса применяется класс .pause для свойства animation-play-state, помогая избежать рассинхронизации элементов и удерживать идеальное центрирование всей композиции на экране.
Процедурный подход и управление координатами сцены 1:08:01
Особую сложность представляет создание органических, нецикличных движений для множества независимых объектов на сцене. В то время как для плоского фона разработчики могут использовать периодические функции вроде setInterval с шагом в 1 секунду для генерации элементов со случайным временем жизни и анимацией от 5 до 10 секунд, в 3D-пространстве такой подход вызвал бы катастрофическое падение производительности из-за постоянных перерендеров React. Процедурная анимация внутри useFrame решает эту задачу гораздо изящнее.
Мы можем инициализировать массив трехмерных объектов, присвоив каждому уникальный идентификатор через Math.random(), а затем рассчитывать их новые координаты по осям X, Y и Z прямо внутри кадрового цикла. Например, смещение позиций в пределах 100 пикселей сцены рассчитывается налету без изменения стейта компонента, используя лишь прямые ссылки на объекты (refs) и обновляя стили отрисовки. Ранее в разговоре упоминалось создание фонов, но именно трехмерная процедурная динамика выводит глубину сцены на новый уровень. Таким образом, правильное распределение математической логики внутри useFrame позволяет добиться потрясающих визуальных эффектов:
-
Плавная интерактивная левитация ключевых 3D-моделей на главной странице портфолио.
-
Динамическое изменение масштаба и прозрачности объектов в зависимости от положения курсора мыши и триггеров наведения.
-
Создание глубоких пространственных эффектов, где каждый элемент движется по своей уникальной, математически просчитанной траектории.
В завершение этого этапа разработки становится очевидно, что комбинация кастомных параметров Tailwind и мощного математического аппарата Three.js закладывает прочный фундамент для создания по-настоящему иммерсивного веб-интерфейса, подготавливая проект к дальнейшей интеграции интерактивных систем.
🧭 Оптимизация круговой навигации и архитектура сквозного интерфейса 1:26:39
Разработка интерфейса современного веб-приложения требует не только креативного визуального подхода, но и строгой системности. Ранее созданная концепция круговой навигации, основанная на точном тригонометрическом распределении элементов управления, стала визитной карточкой главной страницы портфолио. Однако по мере масштабирования проекта перед разработчиком встает задача переиспользования и оптимизации этих наработок для обеспечения сквозного стилистического единства на всех уровнях сайта. В начале данного фрагмента транскрипта автор завершает кастомизацию фонового эффекта светлячков с помощью радиального градиента, детальный разбор которого вынесен в главу 5, после чего сразу переходит к развертыванию страницы проектов, составляющей основу главы 6.
Наследование визуального языка круговой навигации 1:26:39
В процессе создания интерфейсных карточек для демонстрации пользовательских работ возникла необходимость наделить новые блоки тем же премиальным визуальным стилем, который отличает интерактивное меню. Чтобы не изобретать колесо и гарантировать стопроцентную визуальную сочетаемость элементов, автор принимает стратегическое решение скопировать удачные стилистические наработки: «Для заднего фона и рамок этого проекта мы собираемся использовать те же классы, что использовали в кнопках навигации, так что давайте скопируем их».
Инлайновые стили Tailwind CSS, отвечающие за полупрозрачные границы, мягкое размытие заднего плана в стиле Glassmorphism и градиентные переливы, переносятся из разметки кругового меню в макет нового списка. Это мгновенно связывает стартовый экран и внутреннюю страницу единым дизайн-кодом. Тем не менее прямое копирование развесистых строк утилит ухудшает читаемость разметки и усложняет дальнейшую поддержку. Возникает потребность связать динамику кругового меню и статику карточек общим источником стилистических правил.
Глобальная оптимизация кода через директиву @apply в Tailwind CSS 1:27:08
Для борьбы с дублированием кода и реализации принципа DRY разработчик переносит фокус внимания на архитектуру таблиц стилей. Он открывает конфигурационный файл global.css и внедряет кастомный класс утилиты под названием custom-bg. Внутри этого класса с помощью встроенной директивы @apply изолируется весь массив свойств, определяющих внешний вид интерактивных кнопок.
Этот шаг кардинально упрощает структуру компонентов. Вместо дублирования огромных цепочек классов в каждом отдельном элементом кругового меню и в макетах проектов теперь достаточно вызвать одну-единственную утилиту. Автор последовательно очищает код кнопок навигации, переводя их на использование нового класса: «Давайте сохраним это и используем данный класс. Для кнопок вместо старого набора применим эту одиночную утилиту, и все выглядит отлично, стили успешно применились». Такая оптимизация защищает проект от рассинхронизации интерфейса при будущих дизайн-вызовах.
Адаптация навигационной логики: создание компонента HomeButton 1:32:40
Если центральный хаб приложения удерживает фокус пользователя за счет сложной динамики и распределения кнопок по окружности, то навигация внутри целевых разделов требует стабильности и предсказуемости. Для обеспечения комфортного возврата пользователя на главную страницу проектируется специализированный изолированный компонент HomeButton.jsx. Архитектурно он становится прямым наследником кнопок кругового меню: «Он должен быть точно таким же, как кнопка навигации, поэтому давайте скопируем ее».
Внутри компонента разворачивается стандартный навигационный инструмент Link из экосистемы next/link. Текстовый маркер, определявший разделы в круговом меню, заменяется на статичное имя "home", а целевой маршрут перенаправляется на корневой адрес приложения. Вместо специфических контекстных иконок интегрируется лаконичный символ дома из библиотеки lucide-react с фиксированной толщиной линий strokeWidth, равной 1.5.
Ключевое отличие от кнопок главного меню заключается в позиционировании: кнопка возврата освобождается от тригонометрических расчетов и жестко привязывается к интерфейсу с помощью свойств fixed top-4 left-4. Из нее полностью вычищаются микроанимации, чтобы элемент оставался стабильным утилитарным якорем. Стоит упомянуть, что параллельно на странице организуется вывод трехмерной модели посоха, принципы рендеринга и анимации которой детально рассматриваются во 2-й и 3-й главах руководства.
🎩 Оформление раздела «О себе» и визуализация достижений 1:40:47
В процессе разработки страницы «О себе» (About) основное внимание уделяется созданию уникальной визуальной среды, которая отражает профессиональный стиль автора. Начальный этап включает интеграцию 3D-модели головного убора — эффектного элемента, который заменяет стандартные компоненты и задает тон всей странице.
Интеграция 3D-модели и верстка контента 1:41:01
Для импорта 3D-объекта используется формат GLTF, который обрабатывается с помощью React-компонентов. Модель размещается по центру экрана с использованием абсолютного позиционирования (position: absolute) и трансформаций CSS для идеального центрирования (top: 50%, translate-y: -1/2). Чтобы добиться эстетически приятного отображения, была скорректирована ориентация модели: вместо изменения позиции был применен поворот (rotation), что позволило скрыть нижнюю часть объекта и сфокусировать внимание пользователя на деталях.
Сразу под 3D-моделью располагается текстовый блок с приветствием. Структура верстки строится на принципах Flexbox:
- Использование
flex-direction: columnдля вертикального выравнивания заголовка и параграфа. - Применение адаптивных классов Tailwind CSS для позиционирования блоков.
- Настройка типографики: заголовок увеличен до размера
9xlс использованием акцентного цвета, а описание оформлено в светлых тонах для создания визуального контраста.
Создание модульных блоков информации 1:47:24
Для отображения профессиональной статистики и достижений была разработана система переиспользуемых компонентов ItemLayout. Это позволяет избежать дублирования кода при создании карточек с информацией:
- Компонент-обертка: Универсальный шаблон, принимающий
childrenи кастомные CSS-классы, что упрощает масштабирование интерфейса. - Сетка (Grid): Основная страница использует 12-колоночную сетку, где отдельные блоки (например, «25+ клиентов» или «4 года опыта») динамически занимают необходимое пространство (
col-span). - Стилизация: Применяются кастомные фоновые цвета, скругление углов
rounded-xlи эффекты теней, гармонирующие с ранее созданной навигацией.
Динамическая интеграция GitHub-статистики 1:55:44
Одной из самых интересных частей проекта является использование внешних API для вывода «живых» данных. Вместо статической верстки автор интегрирует динамически генерируемые карточки GitHub Stats.
Ключевые аспекты настройки визуализации:
- Гибкая настройка через URL-параметры: Использование различных тем (например,
radicalилиdark) и манипуляция параметрами (скрытие границhide_border=true, настройка цвета текста под акцентный цвет проекта) позволяют идеально вписать сторонние виджеты в дизайн сайта. - Оптимизация: Поскольку данные генерируются динамически, используется
lazy loadingдля изображений, что предотвращает блокировку отрисовки страницы. - Специфические виджеты: В дополнение к общей статистике профиля, внедряются карточки «самых используемых языков программирования» и визуализация навыков (Skill Icons), что дает пользователю наглядное представление о технологическом стеке автора.
Для завершения раздела «О себе» автор переходит к добавлению виджета GitHub-стриков, используя расширенные настройки прозрачности фона и тонкую подстройку цветов для создания бесшовного визуального перехода. Ранее в разговоре они касались создания фонового эффекта «светлячков», который дополняет атмосферу страницы.
🛠️ Глава 6. Разработка страницы проектов: интерактивные карточки и интеграция репозиториев 2:05:54
Визуализация проектной сетки и верстка компонентов карточек 2:05:54
На данном этапе разработки фокус смещается на создание эффектного и функционального списка проектов, который служит визитной карточкой любого фронтенд-разработчика. Для этого используется интеграция динамических карточек репозиториев, которые извлекают актуальные данные напрямую из профиля разработчика. Автор начинает с тонкой настройки стилей интерфейса, корректируя HTML-структуру и Tailwind-классы для достижения идеального визуального баланса на экранах разного разрешения.
Одним из ключевых шагов становится точечное управление сеткой макета. Параметр colspan расширяется до шести колонок, что позволяет карточке проекта занимать оптимальное пространство на экране и гармонично сочетаться с другими блоками портфолио. Чтобы избавиться от нежелательных отступов и сдвигов, разработчик полностью удаляет лишний паддинг. Примечательным техническим нюансом здесь является использование восклицательного знака перед утилитарными классами Tailwind (например, !p-0). Этот синтаксис автоматически компилируется в CSS-свойство !important, гарантируя стопроцентное переопределение любых сторонних или дефолтных стилей фреймворка. Для улучшения доступности (accessibility) и UX изменяется атрибут alt для изображений на значение "loading", а также оптимизируется процесс загрузки элементов с помощью специализированных CSS-классов. Вместо статичных иконок навыков в разметку интегрируется полноценный компонент карточки репозитория (repo card), который связывается с реальным URL-адресом проекта на GitHub.
Управление контентом и кастомизация отображения данных 2:08:15
Интерактивность страницы проектов во многом зависит от того, насколько гибко настроено отображение метаданных каждого репозитория. Разработчик наглядно демонстрирует, как адаптировать стандартные карточки под индивидуальные нужды портфолио. В коде обновляется имя пользователя и указывается конкретное имя целевого репозитория, что позволяет точечно выводить нужные проекты на экран, формируя репрезентативную выборку лучших работ. Сетка элементов фиксируется с помощью свойства colspan: 6, обеспечивая симметрию макета.
Особое внимание уделяется предотвращению типичной проблемы лонгридов и карточных интерфейсов — разной длине описаний репозиториев, которая часто разрушает сетку и ломает вертикальное выравнивание. Для решения этой задачи в конфигурацию компонента вводится свойство description lines count со значением 2. Благодаря этому ограничению, приложение автоматически обрезает текст описания, выводя строго первые две строки. Это не только сохраняет аккуратный и унифицированный внешний вид всей страницы, но и улучшает читаемость данных, делая интерфейс более предсказуемым для пользователя.
Архитектурная оптимизация: обход лимитов GitHub API через Vercel 2:09:09
При работе с внешними данными критически важно учитывать архитектурные ограничения сторонних сервисов. Прямое обращение к GitHub API для получения метаданных проектов имеет существенный недостаток, зафиксированный в официальной документации: стандартный лимит составляет всего 5 000 запросов в час для одного IP-адреса. В условиях реального продакшена, когда портфолио могут одновременно просматривать сотни пользователей, существует огромный риск столкнуться с ошибкой превышения лимита (rate limiter), из-за чего страница проектов просто перестанет отображать контент.
Для решения этой проблемы автор предлагает надежное архитектурное решение — развертывание собственного прокси-сервера. Вместо прямого использования дефолтных эндпоинтов разработчикам рекомендуется воспользоваться опцией "Deploy on your own" и настроить собственное серверное окружение на платформе Vercel. Собственный сервер берет на себя кеширование и оптимизацию запросов, избавляя сайт портфолио от жестких лимитов GitHub. Это гарантирует стабильную работу веб-приложения и бесперебойную визуализацию данных о проектах в любых условиях.
Ранее в разговоре авторы также затрагивали вопросы общей навигации, поэтому для исправления кликабельности интерфейса кнопке Home присваивается максимальный уровень z-index: 50. В завершение данного временного диапазона происходит переход к разметке страницы контактов и созданию формы обратной связи, детальный разбор которой с использованием React Hook Form и EmailJS вынесен в последующие главы.
🛠️ Интеграция GitHub API для динамического портфолио 2:30:55
Настройка запросов к GitHub REST API 2:31:08
Современное портфолио разработчика должно быть не просто статической визиткой, а живым организмом, отражающим его актуальную активность. Интеграция GitHub API позволяет превратить страницу «Обо мне» в динамический дашборд. Вместо ручного обновления количества созданных репозиториев или встраивания статичных скриншотов, веб-приложение делает прямой запрос к серверам GitHub, получая самую свежую информацию о профиле пользователя в реальном времени.
Для реализации этого функционала в рамках архитектуры Next.js оптимально использовать серверные компоненты или Route Handlers. Это позволяет скрыть персональные токены доступа (Personal Access Tokens) на стороне сервера, предотвращая их утечку в клиентский код. Базовый эндпоинт api.github.com/users/{username} предоставляет исчерпывающий массив данных: от количества публичных репозиториев и фолловеров до даты создания аккаунта. Параллельно, для получения более глубокой аналитики — например, суммарного количества звезд или детальной статистики по языкам программирования — разработчики часто задействуют GraphQL API от GitHub, который позволяет оптимизировать размер ответа и запрашивать только строго необходимые узлы данных.
Стоит отметить, что в процессе работы над сопутствующими элементами интерфейса на данном этапе хронометража автор видео также отвлекается на внедрение кастомной валидации полей ввода, детальный разбор которой будет представлен в следующих главах, сфокусированных на интерактивных формах.
Отображение карточек статистики в разделе «Обо мне» 2:35:16
После успешного получения и парсинга данных от API, ключевой задачей становится их репрезентативная визуализация. На странице «Обо мне» данные структурируются в виде адаптивной сетки карточек (Grid Layout), стилизованных с помощью Tailwind CSS. Каждая карточка отвечает за конкретную метрику: общее число коммитов за текущий год, количество форков, пул-реквестов и открытых issue.
Использование динамических данных позволяет внедрить элементы геймификации в портфолио. Например, если пользователь активно контрибьютит в open-source, уровень его активности может визуально влиять на цветовую гамму или анимационные эффекты элементов интерфейса. Интеграция сторонних решений, таких как кастомизированные виджеты статистики, органично вписывается в общую космическую или минималистичную стилистику сайта, создавая ощущение целостного программного продукта.
Параллельно с выводом карточек, в этой части демонстрации автор кратко настраивает всплывающие уведомления для других разделов сайта, чтобы протестировать реакцию интерфейса на системные события, однако подробный разбор системы уведомлений вынесен в отдельную специализированную главу.
Оптимизация запросов и кэширование данных 2:41:16
Важнейшим аспектом работы с внешними API является соблюдение лимитов на количество запросов (Rate Limiting). Для неавторизованных запросов GitHub устанавливает жесткое ограничение — не более 60 запросов в час с одного IP-адреса. Использование персонального токена увеличивает этот лимит до 5000 запросов, однако при высокой посещаемости портфолио даже этого объема может не хватить.
Для решения этой проблемы применяется стратегия инкрементальной статической регенерации (ISR) в Next.js. Страница «Обо мне» компилируется на сервере, а данные из GitHub API кэшируются на определенный промежуток времени — например, на один час. Таким образом, тысячи посетителей сайта получают мгновенный доступ к закэшированной версии страницы, а приложение выполняет всего один запрос к GitHub в час, полностью нивелируя риск блокировки или замедления работы интерфейса.
В процессе финальной полировки этой логики в видеоролике также проскакивают упоминания адаптации навигационной панели под мобильные экраны, детальный разбор которой читатели найдут в материалах, посвященных адаптивной верстке. Внедрение кэширования завершает создание надежного, быстрого и по-настоящему динамического раздела портфолио.
📬 Работа с контактной формой и интеграция EmailJS 3:08:35
Валидация и структура формы через React Hook Form 3:08:35
При переходе к финальным штрихам сборки портфолио особое внимание уделяется интерактивности и удобству взаимодействия с пользователем. На отметке автор открывает для редактирования страницу контактов, которая служит ключевым каналом связи между потенциальным заказчиком и разработчиком. Вместо применения громоздких решений для ручного управления состоянием каждого инпута, в проекте используется популярная библиотека React Hook Form. Данный инструмент позволяет минимизировать количество избыточных ререндеров всего компонента при вводе данных, что крайне важно для поддержания высокой производительности веб-приложения на любых устройствах.
Разработчик настраивает базовую обертку формы, детально прописывая адаптивную ширину элементов: на самых маленьких экранах мобильных телефонов элемент занимает всю доступную область (width-full), а при увеличении разрешения до брейкпоинта SM плавно сужается до трех четвертей от общей ширины экрана (width 3x4). Валидация вводимых данных реализуется непосредственно на стороне клиента. Это гарантирует, что пользователь не сможет отправить пустое сообщение или случайно указать некорректный адрес электронной почты. Каждое текстовое поле — будь то имя отправителя, тема или текст обращения — связывается с методом регистрации register.
Благодаря такой интеграции, сообщения об ошибках и предупреждения выводятся на экран динамически, мгновенно реагируя на действия посетителя. Примечательно, что сама исходная разметка формы оказалась спроектирована настолько удачно, что при проверке мобильного отображения на таймкоде автор отмечает полное отсутствие необходимости вносить серьезные изменения в разметку самих полей ввода, так как они изначально корректно подстраиваются под размеры мобильного экрана. Стоит отметить, что в данном временном отрезке автор также проводит масштабную адаптацию других страниц под мобильные устройства, однако подробный разбор медиа-запросов и адаптивной верстки вынесен в следующую главу статьи.
Подключение EmailJS для обработки и отправки сообщений 3:09:45
Обеспечив надежный сбор и валидацию данных на стороне клиента, необходимо организовать их гарантированную доставку на почтовый ящик владельца сайта. Для реализации этой задачи интегрируется облачный сервис EmailJS, позволяющий отправлять электронные письма непосредственно из клиентской части React-приложения без необходимости развертывания собственного полноценного Node.js-сервера или иного кастомного бэкенда. Такой архитектурный подход существенно упрощает общую структуру кодовой базы проекта и сводит к минимуму затраты на его долгосрочную техническую поддержку.
Интеграция EmailJS в коде опирается на вызов специального метода отправки, куда в качестве аргументов передаются три ключевых параметра безопасности:
- Идентификатор почтового сервиса (Service ID);
- Идентификатор настроенного шаблона письма (Template ID);
- Публичный ключ учетной записи разработчика (Public Key).
Автор настраивает функцию обработки события отправки формы onSubmit таким образом, чтобы после успешного прохождения всех этапов клиентской валидации React Hook Form сформированный объект данных мгновенно транслировался на серверы EmailJS. Сервис берет на себя всю рутину по автоматическому формированию заголовков письма и взаимодействию с SMTP-протоколами. Если процесс отправки завершается успешно, форма автоматически сбрасывает свое состояние в исходное с помощью метода reset(), оперативно подготавливая пользовательский интерфейс к отправке нового сообщения.
Оптимизация интерфейса страницы контактов 3:08:53
Помимо сугубо программной логики и обработки событий, страница контактов требует тонкой визуальной калибровки для достижения идеального пользовательского опыта. На таймкоде автор точечно корректирует вертикальные отступы основного контейнера, увеличивая значения padding-top и padding-bottom с помощью служебной утилиты Tailwind CSS py-8 для компактных мобильных дисплеев, тогда как для более крупных экранов, превышающих брейкпоинт SM, устанавливается значение py-0. Это позволяет добиться гармоничного и сбалансированного распределения пространства на странице.
Текстовое сопровождение формы также подвергается аккуратному рефакторингу: для параграфов устанавливается базовый размер шрифта text-sm на мобильных экранах, масштабируемый до text-base на ультракоротких дисплеях класса XS, что сохраняет отличную читаемость интерфейса в любых условиях.
Параллельно с финальной доработкой контактной зоны в кодовой базе приложения разворачивается масштабное внедрение анимаций для элементов круговой навигации и списков проектов с использованием библиотеки Framer Motion, полноценный разбор базовых принципов работы которой детально описан в десятой главе. Оптимизация разметки страницы контактов успешно завершает важнейший этап создания функционального интерфейса портфолио, превращая статичные стили Tailwind в отзывчивый, полностью готовый к работе инструмент реальной бизнес-коммуникации.
📱 Адаптивный интерфейс и интерактивные уведомления 3:21:11
Адаптивность и медиа-запросы в дизайне элементов 3:23:47
Разработка современного пользовательского интерфейса требует глубокой проработки его поведения на экранах различных устройств. В рассматриваемом фрагменте авторы подчеркивают, что создаваемый сайт становится полностью адаптивным. Для достижения этого результата используется мобильно-ориентированный подход и гибкая система утилит Tailwind CSS. Это позволяет настраивать стили элементов в зависимости от ширины экрана без необходимости написания громоздких кастомных медиа-запросов в отдельных CSS-файлах.
Особое внимание уделяется элементам управления, которые должны оставаться одинаково удобными как для клика мышью на десктопе, так и для тапа на экране смартфона. Например, при позиционировании фиксированной кнопки на мобильных устройствах задается отступ справа в 2.5 единицы, тогда как для экранов с шириной более 480 пикселей этот параметр увеличивается до 4 единиц. Параллельно с этим в коде настраивается управление аудио-контентом, детально рассматриваемое в следующей главе статьи. Разработчик устанавливает высокий индекс слоя z-index: 50, чтобы гарантировать отображение поверх остальных компонентов.
Размеры самих интерактивных элементов также динамически масштабируются для оптимизации UX на разных устройствах. На компактных мобильных экранах ширина и высота кнопок составляют 10 единиц, а при переходе к более крупным дисплеям эти значения увеличиваются до 14 единиц. Внутренние отступы (padding) следуют той же логике: базовый мобильный отступ равен 2.5 единицам, в то время как для десктопных версий он расширяется до 4 единиц.
Примером сложной адаптивной разметки является всплывающее диалоговое окно, созданное с целью получения согласия пользователя, которое полностью адаптировано под мобильные устройства. Чтобы контент внутри окна выглядел сбалансированно, разработчик использует брейкпоинты для настройки горизонтальных полей padding-x. На самых маленьких экранах отступы составляют 6 единиц, для средних экранов этот показатель возрастает до 10 единиц, а при активации стандартного брейкпоинта sm увеличивается до 16 единиц. Такой подход предотвращает сжатие интерфейсных элементов на смартфонах. Компонент стилизуется с использованием полупрозрачного фона, эффекта размытия backdrop-blur и границы с низким уровнем непрозрачности, что придает интерфейсу современный стеклянный вид.
Уведомления, диалоговые окна и обратная связь 3:21:45
Важнейшей частью взаимодействия пользователя с портфолио является получение мгновенной обратной связи от интерфейса. На данном этапе авторы завершают работу над анимацией элементов контактной формы. Финальный этап работы с контактной формой, интеграцию которой с EmailJS авторы подробно разбирали в предыдущей главе, тесно связан с выводом уведомлений. Успешная отправка данных или возникновение ошибок обязательно должны сопровождаться интерактивными всплывающими уведомлениями (Toast-сообщениями), чтобы пользователь четко понимал статус своего запроса. Хотя анимации подробно разбираются в других разделах, здесь также применяется анимация появления элементов формы, однако детальный разбор Framer Motion вынесен в заключительную главу статьи.
Toast-уведомления работают в связке с логикой валидации. Как только форма проходит проверку и данные отправляются, на экране появляется компактное всплывающее сообщение. В текущем фрагменте аналогичный механизм интерактивного информирования и сбора данных реализуется через систему модальных предупреждений. Если в локальном хранилище браузера (Local Storage) отсутствует запись о выборе пользователя, система мгновенно активирует состояние вызова окна.
Для вывода интерактивных уведомлений используется функция createPortal из библиотеки react-dom. Это позволяет рендерить интерфейс уведомления за пределами текущего DOM-дерева, монтируя его непосредственно в контейнер с идентификатором my-modal на уровне корневого макета. Пользователю выводится четкий вопрос о том, согласен ли он включить звуковое сопровождение. В коде прописывается проверка: если значение musicConsent уже сохранено со строковым значением true, то повторный вывод окна блокируется, а система ожидает первого легитимного действия на странице.
Для обработки первого взаимодействия пользователя с уведомлением система настраивает глобальные слушатели. Разработчик добавляет обработчики на ключевые события:
-
Клик мышью (
click) -
Нажатие клавиш (
key down) -
Касание тачскрина (
touch start)
Эти слушатели позволяют отследить момент, когда пользователь взаимодействует со страницей. Интерактивные сценарии продуманы до мелочей: при нажатии кнопки «Да» вызывается функция переключения, а при нажатии «Нет» вызывается функция закрытия, предотвращая навязчивые повторные уведомления. Всплывающие уведомления и диалоговые окна выступают главным инструментом качественной коммуникации между веб-приложением и посетителем.
🎵 Финальные штрихи: управление аудио и магия Framer Motion 3:46:26
Завершающий этап разработки портфолио сосредоточен на тонкой настройке пользовательского опыта (UX). В современных веб-интерфейсах грань между «впечатляющим» и «раздражающим» очень тонка, особенно когда речь идет об автоматическом воспроизведении звука или навязчивых анимациях. В финале проекта основное внимание уделяется созданию интеллектуальной системы управления аудио-контентом и финальной полировке анимаций, которые делают сайт «живым».
Интеллектуальное управление аудио и сохранение предпочтений 3:46:26
Реализация фонового аудио в веб-приложениях требует соблюдения баланса. Просто включить музыку при загрузке — плохой тон, а спрашивать разрешение при каждом обновлении страницы — верный способ заставить пользователя уйти. Решение, предложенное в данном проекте, базируется на строгой логике согласия и использовании LocalStorage для сохранения выбора посетителя .
Техническая реализация включает в себя проверку двух ключевых параметров: факта согласия (musicConsent) и времени этого согласия (consentTime). Автор использует элегантную формулу для ограничения срока действия этого выбора. Чтобы не беспокоить пользователя постоянно, согласие сохраняется ровно на три дня. В коде это реализуется через вычисление временного интервала: текущая дата сравнивается с моментом получения согласия, к которому прибавляется сумма миллисекунд, эквивалентная 72 часам (3 дня
«Этот компонент можно использовать где угодно, — отмечает автор, — потому что он хранит в локальном хранилище всё необходимое: и факт согласия, и метку времени» . Такая архитектура универсальна. Ее можно адаптировать не только для управления звуком, но и для реализации любых других типов всплывающих окон, например, уведомлений о файлах cookie или рекламных баннеров . Если пользователь нажимает «Да», музыка начинает играть автоматически при последующих визитах в течение заданного периода, создавая бесшовный аудиовизуальный опыт.
Framer Motion: stagger-анимации и эстетика появления 3:51:37
Одним из главных инструментов, обеспечивающих премиальный вид портфолио, стал Framer Motion. В отличие от простых CSS-переходов, эта библиотека позволяет реализовывать сложные stagger-анимации (каскадное появление), которые критически важны для первого впечатления при загрузке страницы .
Stagger-эффект работает по принципу домино: элементы интерфейса (иконки навигации, текстовые блоки, карточки проектов) появляются не одновременно, а с небольшим, строго выверенным шагом задержки. Это создает ощущение осознанного движения и направляет взгляд пользователя от одного важного элемента к другому. В контексте данного проекта, где ранее в разговоре касались создания сложной круговой навигации, Framer Motion связывает все разрозненные компоненты в единую динамическую систему.
Применение Framer Motion в финальной стадии позволяет:
- Управлять сложными состояниями входа и выхода элементов (AnimatePresence).
- Создавать плавные переходы между страницами портфолио.
- Обеспечивать отзывчивость интерфейса на действия пользователя, дополняя 3D-сцены, созданные с помощью Three.js .
Использование этой библиотеки превращает статический набор данных в интерактивное повествование, где каждый элемент «знает», когда и как ему выйти на сцену.
Оптимизация доставки контента и завершение проекта 3:49:15
Финальный аккорд разработки — техническая оптимизация, без которой даже самые красивые анимации могут подтормаживать. Автор уделяет особое внимание производительности изображений и тяжелых 3D-моделей. Для ускорения отрисовки ключевых визуальных элементов в компонентах Image Next.js активируется свойство priority . Это заставляет браузер загружать изображения в первую очередь, предотвращая эффект «прыгающего» контента при появлении анимаций Framer Motion.
Для работы с тяжелыми 3D-моделями внедряется механизм динамического импорта (next/dynamic) . Установка параметра ssr: false гарантирует, что модели будут рендериться исключительно на стороне клиента . Это критически важно, так как серверный рендеринг (SSR) не может обрабатывать WebGL-контент, и попытка сделать это привела бы к ошибкам или существенной задержке первой отрисовки.
«Моя цель — показать вам множество вещей, которые можно реализовать в одном проекте», — резюмирует автор, перечисляя стек технологий: Three.js для 3D, Framer Motion для анимаций, React Hook Form для работы с формами и Sooner для уведомлений . Проект завершается призывом к творчеству: использовать полученную базу для создания собственных уникальных версий портфолио, экспериментируя со временем stagger-эффектов и логикой взаимодействия с пользователем .