Назад в блог

авг. 2026 г. · 9 мин. чтения

Из чего собран этот сайт

В августе 2026 года я пересобрал портфолио с нуля. Этот каталог показывает каждый элемент интерфейса вживую и объясняет, почему он выглядит именно так.

В августе 2026 года я пересобрал это портфолио с нуля. До этого в нём было два источника одних и тех же цветов, светлая тема, которая на главной странице попросту не работала, и 654 строки canvas-кода ради фона. Перестройка свела всё к одному набору токенов и горстке строительных блоков.

Этот материал — каталог к ним. В каждом разделе слева стоит настоящий элемент: не картинка, а тот же компонент, который использует остальной сайт. Переключите тему в шапке — примеры переключатся вместе с ней. Справа — почему элемент устроен именно так.

  • --bg
  • --surface
  • --elevated
  • --border
  • --text
  • --muted
  • --accent

src/app/globals.css

01

Токены вместо значений цвета

Цвета живут ровно в одном месте: как CSS-переменные в корневом селекторе и ещё раз — переопределённые для тёмной темы. Tailwind читает их через rgb(var(--surface) / <alpha-value>), поэтому модификаторы прозрачности вроде bg-surface/80 продолжают работать.

Выигрыш виден в коде компонентов: там написано bg-surface text-text — и ни одного dark:. Раньше таких префиксов было 54, и каждый был местом, где элемент мог оказаться правильным только в одной теме.

Значения выбраны не на глаз. Худший контраст основного текста поверх цветных пятен фона — 6,7:1 в тёмной теме и 7,5:1 в светлой, причём измерен в самой яркой точке пятна, а не в среднем.

Eyebrow

Überschrift

Fließtext in 16 px, so gesetzt, dass eine Zeile bequem gelesen wird.

Nebentext für Datum, Ort und Quellen.

src/design-system/index.ts

02

Шкала шрифта, растущая вместе с экраном

В прежней версии шкала Tailwind была увеличена глобально: text-base равнялся 19px вместо 16px. На десктопе это почти не замечалось, а на телефоне каждая страница выглядела раздутой, и заголовки переносились в неудачных местах.

Теперь вернулась стандартная шкала, а плавными остались только три «дисплейных» размера: clamp(2.25rem, 6vw, 4rem) для заголовка страницы. Между телефоном и большим монитором она масштабируется непрерывно, без отдельного правила на каждую ширину.

Моноширинный шрифт несёт даты, категории и мелкие подписи. Он помечает техническое и одновременно отделяет его от основного текста.

Projekte ansehenKontakt aufnehmenBlogmin-height 44 px

src/design-system/index.ts

03

Три кнопки, один стиль фокуса

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

У всех трёх задан min-height: 44px. Это размер, в который уверенно попадает подушечка пальца: обычная причина промахов на мобильных — слишком мелкие цели, а не слишком мелкий шрифт.

Рамку фокуса задаёт одно правило для всего интерактивного, питаемое переменной --ring. Тот, кто ходит по сайту с клавиатуры, везде видит одну и ту же рамку, и ни один новый компонент не сможет её забыть.

Redis mit Hochverfügbarkeit

Automatisiertes Deployment auf Kubernetes, Failover über Sentinel.

  • Redis
  • K8s
  • Helm
GitHub

src/components/sections/projects.tsx

04

Карточка проекта

Карточка несёт заголовок, два-три предложения о результате, стек в виде чипов и ссылки. Больше ничего: тот, кто просматривает проекты, читает заголовок и стек, остальное — подробности.

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

При наведении меняется лишь цвет рамки. Карточки, которые приподнимаются или увеличиваются, заставляют текст прыгать — при шести плитках рядом это быстро становится суетливым.

DevOps

  • Linux
  • Docker
  • K8s
  • Ansible

src/components/sections/skills.tsx

05

Технологии по задачам

Сначала технологии стояли рядом с проектами в одном ряду. Читалось так, будто они об одном и том же, хотя они отвечают на другой вопрос: не что я построил, а с чем я работаю.

Теперь у них собственный раздел, по карточке на категорию: DevOps, базы данных, backend, frontend, инструменты. Группировка говорит больше алфавитного списка, потому что показывает центр тяжести.

Намеренно без звёзд и процентных шкал. Такие оценки заявляют точность, которую невозможно проверить; контекст дают опыт работы и проекты.

  1. Juli 2025 — heute

    DevOps Engineer

  2. Sept. 2022 — Juli 2025

    Ausbildung Systemintegration

src/components/sections/experience-timeline.tsx

06

Опыт работы как лента времени

Опыт работы — единственное место, где порядок действительно несёт смысл, поэтому ему досталась единственная линия на странице.

Периоды набраны моноширинным шрифтом над должностью. Они достаточно коротки, чтобы поместиться в строку на любой ширине, а фиксированная ширина знака выравнивает их по столбцу.

Точки сидят на линии и скрыты от программ чтения с экрана: они не несут информации, которой нет в тексте.

JH
  • Start
  • Projekte
  • Kontakt

src/components/header.tsx

07

Три пути по одной странице

Поскольку всё лежит на одной странице, входов три. Шапка ведёт к разделам и к резюме. Ниже 768px ссылки уезжают в меню, а на виду остаются марка, тема, язык и кнопка резюме.

Справа столбик точек отмечает текущий раздел. IntersectionObserver следит за узкой полосой вокруг середины экрана — без неё отметка скачет между длинными разделами. Появляется от 1024px, ниже она только мешала бы.

У всех целей-якорей задан scroll-margin-top. Без него липкая шапка встаёт ровно над тем заголовком, к которому вы только что перешли.

Raster + Farbflächen

src/components/backgrounds/dot-grid.tsx

08

Фон, который не мешает

Предшественником было звёздное поле: 654 строки canvas, цикл отрисовки на каждой странице, заметный расход батареи. Его заменил узор из radial-gradient в виде точечной сетки — чистый CSS, без цикла отрисовки.

Поверх медленно плывут три цветных пятна. Анимируется только transform, поэтому работу берёт на себя компоновщик, а раскладка и отрисовка остаются нетронутыми. В тёмной теме взяты глубокие, а не светлые оттенки: они подкрашивают фон, не осветляя его, и текст поверх остаётся читаемым.

Сетка слегка смещается при прокрутке, а мягкое свечение следует за курсором — последнее только при pointer: fine; на сенсорных устройствах слушатель вообще не регистрируется. При prefers-reduced-motion: reduce всё замирает.

Что я вынес из этой работы

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

Второй по величине эффект — удаление. Неиспользуемый пакет на 600 КБ, второй hero-блок, целый стек аналитики: кода стало на 40 % меньше, а сайт умеет больше, чем раньше.

Код открыт: github.com/JahongirHabibov