авг. 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) для заголовка страницы. Между телефоном и большим монитором она масштабируется непрерывно, без отдельного правила на каждую ширину.
Моноширинный шрифт несёт даты, категории и мелкие подписи. Он помечает техническое и одновременно отделяет его от основного текста.
src/design-system/index.ts
03
Три кнопки, один стиль фокуса
Портфолио не нужно больше трёх вариантов кнопок: один для главного действия, один для равнозначных и один для навигации в шапке.
У всех трёх задан min-height: 44px. Это размер, в который уверенно попадает подушечка пальца: обычная причина промахов на мобильных — слишком мелкие цели, а не слишком мелкий шрифт.
Рамку фокуса задаёт одно правило для всего интерактивного, питаемое переменной --ring. Тот, кто ходит по сайту с клавиатуры, везде видит одну и ту же рамку, и ни один новый компонент не сможет её забыть.
Redis mit Hochverfügbarkeit
Automatisiertes Deployment auf Kubernetes, Failover über Sentinel.
- Redis
- K8s
- Helm
src/components/sections/projects.tsx
04
Карточка проекта
Карточка несёт заголовок, два-три предложения о результате, стек в виде чипов и ссылки. Больше ничего: тот, кто просматривает проекты, читает заголовок и стек, остальное — подробности.
Сначала первая плитка была вдвое больше остальных. Это выглядело динамичнее, но утверждало иерархию, которой нет: все проекты здесь одинаково настоящие. Теперь плитки одного размера, сетка спокойная, а акцент задаёт только порядок.
При наведении меняется лишь цвет рамки. Карточки, которые приподнимаются или увеличиваются, заставляют текст прыгать — при шести плитках рядом это быстро становится суетливым.
DevOps
Linux
Docker
K8s
Ansible
src/components/sections/skills.tsx
05
Технологии по задачам
Сначала технологии стояли рядом с проектами в одном ряду. Читалось так, будто они об одном и том же, хотя они отвечают на другой вопрос: не что я построил, а с чем я работаю.
Теперь у них собственный раздел, по карточке на категорию: DevOps, базы данных, backend, frontend, инструменты. Группировка говорит больше алфавитного списка, потому что показывает центр тяжести.
Намеренно без звёзд и процентных шкал. Такие оценки заявляют точность, которую невозможно проверить; контекст дают опыт работы и проекты.
Juli 2025 — heute
DevOps Engineer
Sept. 2022 — Juli 2025
Ausbildung Systemintegration
src/components/sections/experience-timeline.tsx
06
Опыт работы как лента времени
Опыт работы — единственное место, где порядок действительно несёт смысл, поэтому ему досталась единственная линия на странице.
Периоды набраны моноширинным шрифтом над должностью. Они достаточно коротки, чтобы поместиться в строку на любой ширине, а фиксированная ширина знака выравнивает их по столбцу.
Точки сидят на линии и скрыты от программ чтения с экрана: они не несут информации, которой нет в тексте.
- 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