@belibathan/nuikit
v0.9.0
Published
The nuikit command line: `nuikit check` audits a FiveM resource against the nuikit protocol's conformance levels (themed, well-behaved, native), `nuikit tokens` lists the theme tokens.
Maintainers
Readme
nuikit
The command line for the nuikit protocol, the UI platform layer for FiveM.
npx @belibathan/nuikit check ./my_resource # grade one resource
npx @belibathan/nuikit check ./resources --level 2 # every resource under a folder; exit 1 if any is below level 2
npx @belibathan/nuikit tokens # the theme tokens a UI should read
npx @belibathan/nuikit theme new my-server # a theme file to start from (graphite by default)nuikit check [path…]
Audits a FiveM resource folder (fxmanifest.lua or __resource.lua, client Lua, web sources and/or built files)
and reports the conformance level it reaches, with file:line:column for everything that keeps it from the next.
A folder that isn't a resource is searched for resources (four levels deep). It reads files with a tokenizer, not
a compiler, so it takes milliseconds and needs nothing installed.
| Level | Name | Means |
|---|---|---|
| 1 | themed | Reads the server's theme tokens and hard-codes no colour a token covers |
| 2 | well-behaved | Declares nuikit_protocol, registers surfaces, never calls SetNuiFocus itself, releases focus on stop, handles Escape through surfaces |
| 3 | native | Runs on the nuikit runtime (nuikit.lua + nuikit-core) and builds on shadcn/ui components |
| Rule | Level | Finds |
|---|---|---|
| color/hardcoded | 1 | Hex, rgb(), hsl(), oklch(), lab()… literals and named colours in CSS, markup and script strings. Token definitions in :root/.dark/@theme, var(--token, fallback) fallbacks, black/white shadows and masks are allowed. |
| color/palette-class | 1 | Tailwind palette classes (bg-emerald-500, hover:text-red-400/80), in class strings and @apply |
| tokens/none | 1 | A UI that never reads a token (var(--primary), bg-primary, nk-*) |
| manifest/protocol | 2 | ui_page without nuikit_protocol '1' |
| surfaces/none | 2 | A ui_page with no NUI.surface / NUI.open |
| focus/direct | 2 | SetNuiFocus / SetNuiFocusKeepInput outside nuikit.lua |
| focus/no-release | 2 | Direct focus with no onClientResourceStop handler that releases it |
| escape/adhoc | 2 | A keydown/keyup Escape check that posts a close callback itself (advisory for overrides, whose protocol dictates it) |
| native/runtime | 3 | nuikit.lua not loaded, or the page doesn't import nuikit-core |
| native/components | 3 | No components/ui/* (shadcn / nuikit registry) |
| perf/remote-asset | advisory | Fonts, styles and media fetched from the network (@import url(https://…), <link href>, src) |
| perf/frame-send | advisory | SendNUIMessage / NUI.send inside a loop that waits Wait(0) |
| attention/glow | advisory | More than one part marked data-nk-glow |
| cef/backdrop-filter | advisory | A raw backdrop-filter in CSS or inline styles. Set --nk-backdrop-filter instead: kit.css applies it behind --nk-backdrop, which a server whose clients draw backdrop filters as black boxes turns off |
| cef/has | advisory | :has() in a stylesheet selector (unsupported in Chromium 103) |
| cef/container | advisory | @container queries and container-type (unsupported in Chromium 103) |
| cef/individual-transform | advisory | scale: / translate: / rotate: properties in source CSS (Chromium 104+) |
| cef/color-mix-inline | advisory | color-mix() / oklch() in a style="" attribute or a JS style value (the plugin only lowers stylesheets) |
Comments are never scanned. Silence a deliberate exception (GTA's own palettes, item art) with a reason:
/* nuikit-ignore color/hardcoded: GTA hair palette, the theme can't know it */
background: #1c1f21;nuikit-ignore [rules] works on the same line or alone on the line above; nuikit-ignore-next-line [rules] on the
line above. Without rule ids it silences every rule on that line. For a block (a table of colours an upstream protocol sends), wrap it in nuikit-ignore-start [rules] … nuikit-ignore-end.
Options: --level <1|2|3> (exit 1 below it), --json, --verbose (every finding, not five per rule),
--include-built (also grade dist/ and build/ when sources exist; with no sources, built HTML and CSS are graded
automatically). Exit codes: 0 pass, 1 below --level, 2 bad arguments or no resource found.
Findings in a src/index.css synced from the kit's template are marked as inherited and collapsed into one line,
because they're fixed once in packages/create-nuikit/index.css.tpl.
nuikit tokens
Prints tokens v1 (docs/tokens.md): the shadcn base tokens plus success, warning, info, hud,
vital-*, nk-scale and nk-motion. --json for tooling, --css for a plain list of custom properties.
nuikit theme new <name>
Writes a theme file that starts from a shipped theme (--from, default graphite; nuikit theme --list names them).
The file sets the chosen theme's values in @layer nk.theme { .dark { … } }, then lists every other lever the
kit has, commented out with its default and range, grouped by the concepts of levers.md:
/* Geometry: slant, keycap wall, radii, chamfer and hairlines */
/* --nk-tile-skew: nk-skew (-20deg..20deg) */The levers come from nuikit-core's token tables, so a new lever shows up here when it lands in the tokens. The file is
values only (theme/values-only passes) and compiles to the same tokens as the theme it starts from, with no warnings.
Options: --out <file> (default theme.css), --force to overwrite. Copy the file over nuikit/theme.css, then nuikit theme reload.
API
import { check, checkResource } from "nuikit";
const [result] = check("./my_resource"); // { level, findings: [{ rule, level, severity, file, line, column, message }], … }MIT · @belibathan
