Wrong server was published before. This is the one that runs on the hosting account the video was made on: FiveRP - two-step registration (account, then an identity printed onto a passport), login that returns you to your resident, and a loading screen driven by the game's own streaming events. resources/[local]/fiverp-auth NUI + scrypt hashes + oxmysql resources/[local]/fiverp-characters identity, character load, spawn resources/[local]/fiverp-loadscreen loading screen sql/schema.sql accounts, characters docs/DESIGN.md the design system every screen follows docs/screens/ shot from the live server Only our own code is in here. cfx-server-data and oxmysql are fetched by install.sh instead of being vendored, which keeps the repo at 3.7 MB. install.sh does the whole box in one command: recommended FXServer build, cfx-server-data, oxmysql, MariaDB with the schema, resources, server.cfg (mode 600 - it carries the key and the database password), boot entry, then it waits for the Cfx registration. Tested end to end on a spare install root: 29 resources scanned, database and schema created, and it stopped exactly where a wrong licence key should stop it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
13 KiB
FiveRP — Server Design System
Единый стиль для всего сервера: loading screen, авторизация, будущие меню
(инвентарь, телефон, банк, HUD). Основан на белой «стеклянной» теме Filmorum
(fiveM_design.md), адаптирован под CEF/NUI FiveM.
Правило номер один: ни один компонент не хардкодит цвет, радиус или шрифт. Только
var(--…)из блока токенов ниже. Смена темы = одна строка.
0. Шрифт — Unbounded
Unbounded — основной шрифт всего сервера. Геометрический дисплейный гротеск, переменная ось веса 300–800. Никаких других сансов в интерфейсе.
Файлы лежат в каждом ресурсе локально (html/fonts/), а НЕ грузятся с
fonts.googleapis.com: у части игроков CEF стартует раньше сети, и веб-шрифт
успевает не приехать — интерфейс мигает системным шрифтом. Локальный woff2
рисуется с первого кадра.
@font-face {
font-family: 'Unbounded';
font-style: normal;
font-weight: 300 800; /* вариативный: один файл на все веса */
font-display: block; /* block, не swap — подмены шрифта быть не должно */
src: url('fonts/unbounded-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* + unbounded-latin-ext.woff2 и unbounded-cyrillic.woff2 теми же блоками */
--sans: 'Unbounded', -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, 'Helvetica Neue', Arial, sans-serif;
--mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas,
'Liberation Mono', 'DejaVu Sans Mono', monospace;
Как набирать Unbounded. Шрифт широкий и характерный — он требует другой типографики, чем SF Pro:
| Роль | Размер | Вес | Трекинг |
|---|---|---|---|
| Display (лого, экран загрузки) | 44–72px | 800 | -0.04em |
| H1 (заголовок панели) | 26–30px | 700 | -0.035em |
| H2 (секция) | 18–20px | 600 | -0.03em |
| Кнопка / линк | 14px | 600 | -0.01em |
| Body / инпут | 14–15px | 400 | -0.005em |
| Лейбл поля | 11px | 600 | +0.09em, uppercase |
| Eyebrow / надзаголовок | 10px | 600 | +0.20em, uppercase |
| Метаданные | 11–12px | 400 | 0 |
Правила:
- Крупный кегль = минусовой трекинг. У Unbounded широкие апроши; без
letter-spacing: -0.03emзаголовок расползается. - Мелкий кегль = плюсовой трекинг + uppercase. Ниже 12px строчные буквы Unbounded слипаются — все подписи только капслоком с разрядкой.
- Веса 300 и 800 — крайности, в интерфейсе живут 400/500/600/700.
- Не набирать Unbounded длинный текст. Абзац больше двух строк — читать тяжело. Для многострочных описаний кегль 13px/1.65 и вес 400, не больше.
- Цифры документов, ID, MRZ — только
--mono. Unbounded для них слишком «дизайнерский», а нужен вид машинного считывания.
1. Философия
- Air, light, frosted — полупрозрачные стеклянные панели поверх живой игры.
- Кислород — между карточками 12px, между секциями 40–48px.
- Один акцент — синий
#0071e3, дозированно: кнопка, ссылка, фокус. - Сдержанное движение — fade и подъём на 4px. Анимации ради анимации нет.
- Один герой на экран — крупный объект (паспорт, лого), остальное тихое.
2. Токены
:root {
--bg: #f5f5f7;
--bg-deep: #e8e8ed;
--surface: rgba(255, 255, 255, 0.72);
--surface-solid:#ffffff;
--panel: rgba(255, 255, 255, 0.80);
--header-bg: rgba(255, 255, 255, 0.70);
--field-bg: rgba(0, 0, 0, 0.04);
--field-bg-focus:#ffffff;
--fg: #1d1d1f;
--fg-secondary: #6e6e73;
--fg-tertiary: #a1a1a6;
--accent: #0071e3;
--accent-strong:#0077ed;
--accent-soft: rgba(0, 113, 227, 0.08);
--ring: rgba(0, 113, 227, 0.18);
--line: rgba(0, 0, 0, 0.06);
--line-strong: rgba(0, 0, 0, 0.10);
--hover: rgba(0, 0, 0, 0.04);
--success: #34c759;
--danger: #ff3b30;
--radius-lg: 1.5rem; /* 24px — крупные панели */
--radius-md: 1rem; /* 16px — карточки, инпуты */
--radius-sm: 0.7rem; /* 11px — мелочь */
--ease: cubic-bezier(0.25, 0.8, 0.25, 1);
color-scheme: light;
}
Тёмная и бежевая темы — через data-theme на html, переопределением тех же
токенов (--bg, --surface, --fg, --accent, --success, --danger).
3. КРИТИЧНО: особенности CEF во FiveM
Это не «хорошо бы», а условия, при нарушении которых интерфейс ломается в игре, оставаясь идеальным в браузере.
-
backdrop-filterиbox-shadowне живут на одном элементе. Композитор CEF рисует тень такого элемента непрозрачным прямоугольником — в игре под панелью появляется чёрный квадрат. Если нужны и блюр, и тень — тень вешать на элемент-обёртку, а блюр на внутренний. По умолчанию у стеклянных панелей тени нет вообще: их отделяет от игры блюр и светлая граница, этого достаточно. -
html, body { background: transparent }— иначе NUI закрашивает игру. -
Никаких затемняющих подложек. Экран за панелью — это игра, её видно и она красивая. Контраст добирается блюром и белой заливкой стекла, а не
rgba(0,0,0,…)поверх кадра. Допустим только осветляющий вуаль:radial-gradient(…, rgba(255,255,255,0.28), transparent). -
Шрифты — локальные woff2. См. раздел 0.
-
prefers-reduced-motion— обязательный блок с самого начала. -
Курсор и фокус —
SetNuiFocus(true, true)только когда панель открыта, и обязательноSetNuiFocus(false, false)при закрытии, иначе игрок остаётся без управления.
4. Стеклянная панель
.glass {
background: var(--surface);
backdrop-filter: saturate(180%) blur(24px);
-webkit-backdrop-filter: saturate(180%) blur(24px);
border: 1px solid rgba(255, 255, 255, 0.55);
border-radius: var(--radius-lg);
/* без box-shadow — см. раздел 3.1 */
}
Тень разрешена только элементам без backdrop-filter (карточки на
непрозрачном фоне, экран загрузки):
.shadow-soft { box-shadow: 0 1px 2px rgba(0,0,0,.03), 0 12px 40px -12px rgba(0,0,0,.12); }
.shadow-lift { box-shadow: 0 2px 4px rgba(0,0,0,.04), 0 24px 50px -16px rgba(0,0,0,.20); }
Ховер кликабельной карточки: transform: translateY(-4px), 0.4s --ease.
5. Кнопки
.btn-primary {
border-radius: 999px;
padding: 12px 24px;
font: 600 14px var(--sans);
letter-spacing: -0.01em;
color: #fff;
background-image: linear-gradient(180deg, var(--accent-strong), var(--accent));
box-shadow: 0 1px 1px rgba(0,0,0,.10), inset 0 1px 0 rgba(255,255,255,.20);
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-primary:active { transform: scale(0.97); }
.btn-primary:disabled { opacity: .5; pointer-events: none; }
.btn-ghost {
border-radius: 999px;
padding: 10px 20px;
font: 600 14px var(--sans);
color: var(--accent);
background: var(--accent-soft);
}
.btn-ghost:hover { background: rgba(0,113,227,.14); }
Ровно два стиля кнопок на весь сервер. Третий не заводить.
6. Поля ввода
.field {
width: 100%;
border-radius: var(--radius-md);
padding: 13px 14px;
font: 400 15px var(--sans);
letter-spacing: -0.005em;
color: var(--fg);
background: var(--field-bg);
border: 1px solid transparent;
outline: none;
transition: background-color .2s, border-color .2s, box-shadow .2s;
}
.field::placeholder { color: var(--fg-tertiary); }
.field:focus {
background: var(--field-bg-focus);
border-color: var(--accent);
box-shadow: 0 0 0 4px var(--ring); /* можно: у инпута нет backdrop-filter */
}
.field.is-bad { border-color: var(--danger); box-shadow: 0 0 0 4px rgba(255,59,48,.14); }
Лейбл над полем — 11px/600/+0.09em/uppercase/--fg-secondary.
7. Компоновка
- Панель по центру экрана, ширина
min(940px, 92vw), радиус--radius-lg. - Внутренние отступы панели 32–40px.
- Между полями формы 16px, между группами 24px.
- Двухколоночная схема «форма + герой»:
grid-template-columns: minmax(0,1fr) 420px. - Сворачивание в одну колонку — анимацией
grid-template-columnsиwidth, 620ms--ease.
8. Motion
.fade-up { animation: fadeUp .6s cubic-bezier(.22,1,.36,1) both; }
.delay-1 { animation-delay: .06s } .delay-2 { animation-delay: .12s }
.delay-3 { animation-delay: .18s } .delay-4 { animation-delay: .24s }
@keyframes fadeUp {
from { opacity: 0; transform: translateY(18px) scale(.995); filter: blur(6px); }
to { opacity: 1; transform: none; filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .001ms !important;
transition-duration: .001ms !important;
}
}
9. Фокус и доступность
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
::selection { background: var(--accent-soft); color: var(--accent-strong); }
Контраст текста к стеклу — не ниже 4.5:1. --fg-tertiary только для
плейсхолдеров и декоративных подписей, никогда для смысловых.
10. Существующие интерфейсы
| Ресурс | Что это | Файлы |
|---|---|---|
fiverp-loadscreen |
экран загрузки сервера | html/index.html, style.css, app.js |
fiverp-auth |
регистрация и вход, паспорт США | html/index.html, style.css, app.js |
fiverp-auth использует один «герой» — разворот паспорта США (страница с
данными: фото, поля, MRZ). Паспорт — единственный насыщенный цветом объект
на экране; форма рядом с ним остаётся полностью нейтральной.
11. Чек-лист нового интерфейса
- Скопировать
html/fonts/и блок:rootизfiverp-auth. html, body { background: transparent }.- Панель —
.glass, безbox-shadow. - Ни одного затемняющего слоя поверх игры.
- Шрифт Unbounded, трекинг по таблице из раздела 0.
- Акцент только
--accent; кнопки только.btn-primary/.btn-ghost. - Подключить
prefers-reduced-motion. SetNuiFocus(false, false)на закрытии — проверить руками.- Отрендерить в headless Chrome и посмотреть глазами до выката.