Портфолио-проект: одностраничный сайт вымышленной студии коррекции ЛКП. React + TypeScript + Vite, чистый CSS, без UI-китов и без бэкенда. Внешних зависимостей две: Lenis (инерционный скролл) и OGL (WebGL-поверхность лака).
LAMINAR — вымышленный цех коррекции лакокрасочного покрытия. Клиент такой студии уже знает, что такое голограммы и толщиномер: ему продают не «блеск», а метод. Отсюда решение — страница как чертёж дефектовки: маркировка листов, размерные линии, штамп в подвале, данные в микронах и единицах блеска, единственный акцент цвета пометки на чертеже.
Фотографий автомобилей нет намеренно: студия показывает не чужую машину, а качество поверхности, а иллюстрировать выдуманные кейсы «доказательствами» было бы подлогом.
Дизайн-система, если коротко: 5 нейтралей + 1 акцент #B02F14, шкала кеглей из 9 ступеней
с шагом 1.25, один радиус (0), ноль теней, одно дисплейное семейство (вариативный Archivo,
контраст берётся с оси ширины) плюс IBM Plex Mono для данных, четыре разные ширины контейнеров
на шесть секций.
npm install
npm run dev # http://localhost:5173
npm run build # прод-сборка в dist/
npm run previewИдея. Сайт устроен как протокол измерений: главный материал — числа (µm, GU, часы), а единственное «изображение» — не фотография, а живая поверхность лака.
SIGNATURE — курсор это инспекционная лампа. Три motion-паттерна, не двадцать эффектов:
components/GlossPanel.tsx— образец ЛКП. Слои: краска и кривизна панели, отражение цеха с линией горизонта, линейный источник света, точечный блик, маррирование (голограммы), микрорельеф. Свет ведётся курсором через CSS-переменные--lx/--ly(registered properties, rAF-троттлинг, лёгкая инерция). Без точного курсора — медленный автоматический проход света. Вcomponents/BeforeAfter.tsxту же лампу двигает ручка слайдера — механика одна на весь сайт (pointer-drag, тач, клавиатура:role="slider", стрелки, Home/End,aria-valuenow).hooks/useReveal.ts— единый паттерн появления по скроллу (10px + fade, expo-out, stagger 60 мс, один раз).hooks/useSmoothScroll.ts— Lenis: инерционный скролл, якоря через тот же движок, rAF останавливается на скрытой вкладке. Плюс горизонтальная лента архива с прогрессом иhooks/useScrollKinetics.ts— ось ширины вариативного шрифта от скорости скролла.
Шейдер. gl/clearcoat.ts — поверхность лака на OGL: шагрень, кривизна панели, отражение
цеха, линейный источник 7000K, маррирование, дизеринг. Рисует по требованию (нет движения —
нет кадра), ленивая инициализация через IntersectionObserver, dpr ≤ 2 (1.5 на тач),
fallback на CSS-поверхность при отсутствии WebGL, потере контекста и reduce-motion.
Загрузка. components/Preloader.tsx + loading.ts — прогресс от реальных событий
(шрифты / компиляция шейдера / первый кадр), минимум 520 мс, аварийный выход на 2 с.
Контент до готовности скрыт visibility, поэтому подмена шрифтов не даёт CLS.
Фон. components/SheetBackground.tsx — подложка чертёжного листа: миллиметровка, линейка
с иглой на глубину прокрутки, приводочные метки. Анимация — animation-timeline: scroll(root),
ни одного rAF; без поддержки scroll-driven animations фон просто статичен.
Один тикер. ticker.ts — единственный rAF на странице: Lenis, кинетика, шейдер и троттлинг
указателя подписываются на него. Свои циклы заводить нельзя.
Изображения. public/archive/ — три кадра FSA/OWI 1942 (Library of Congress,
no known restrictions), единая обработка: SVG-дуотон в палитре проекта + печатный растр,
кроп 4:3, loading="lazy". Источник и права указаны прямо на странице.
Измерено в DevTools на этой сборке: LCP 237 мс, CLS 0.00 (на 4× CPU + Fast 4G — LCP 2.2 с), JS 95 КБ gzip, CSS 7.6 КБ gzip.
prefers-reduced-motion отключает всё перечисленное.
Ещё внутри: интерактивная карта кузова (SVG, замеры по зонам, штриховка перекрасов), горизонтальная лента кейсов с прогрессом, прайс-спецификация, форма записи с валидацией и состояниями idle → sending → success/error.
src/
components/ секции и два интерактивных примитива, у каждого свой CSS
gl/ clearcoat.ts — шейдер поверхности
ticker.ts единственный rAF на весь сайт
hooks/ useReveal, useSmoothScroll, useScrollKinetics
loading.ts прогресс загрузки от реальных событий
data/content.ts весь контент одним файлом
index.css токены (5 нейтралей + 1 акцент, радиус 0, expo-out), типографика, ширины, reveal
- Код — портфолио-проект, свободно для изучения.
- Фотографии в
public/archive/— Farm Security Administration / Office of War Information, съёмка Alfred T. Palmer, 1942. Library of Congress, no known restrictions on publication. Источник и права продублированы на самой странице. - Шрифты — Archivo и IBM Plex Mono (SIL Open Font License), подключены через Google Fonts.
- Студия LAMINAR вымышленная: название, контент, цены, реквизиты и кейсы — постановочные.