# mri-fivem-liquid-glass (full docs)
# For AI agents
This project is built to be used and improved by AI coding agents as much as by people. Three
steps and your agent knows the whole library:
`setup-ai` writes the library skill where each agent looks for it (`.claude/skills/`, `AGENTS.md`,
`.cursor/rules/`, `.github/copilot-instructions.md`). Running it again updates the same block
instead of duplicating it. Without `--agent` it detects the agents already used in the project.
## Using the library from an agent
- **Agent skill**: the npm package ships `skills/mri-fivem-liquid-glass/SKILL.md`, a ready skill in
the Claude Code / Agent Skills format. Copy it into your agent's skills folder, or point the
agent at `node_modules/mri-fivem-liquid-glass/skills/mri-fivem-liquid-glass/SKILL.md`.
- **[`/llms.txt`](/llms.txt)**: a short map of the docs and the API for language models;
[`/llms-full.txt`](/llms-full.txt) has every guide page in one file.
- **[JSON API](/api)**: options, attributes and presets as data, always generated from the source.
## Improved it? Send it back
If your agent fixed a bug, tuned a shader or added a feature while using this library in a
project, **open a pull request upstream** instead of keeping a private patch. Everyone gets the
improvement and your project keeps getting updates without conflicts.
1. Read [`AGENTS.md`](https://github.com/mur4i/mri-fivem-liquid-glass/blob/main/AGENTS.md) in the
repository: how to build, test and what reviewers expect.
2. Keep the change focused and explain what was seen in game versus in the browser.
3. Open the pull request at
[github.com/mur4i/mri-fivem-liquid-glass](https://github.com/mur4i/mri-fivem-liquid-glass/pulls).
Changes to docs, examples and the community registry merge automatically when the checks pass.
Changes to the library code get a quick review from a maintainer.
## Ground rules for agents
- Target the FiveM browser: Chromium 103 and WebGL2. No newer browser APIs.
- Never copy code from closed or paid resources.
- Do not claim it was tested in game unless it was.
---
# Contributing
Thanks for helping. Issues and pull requests in English or Portuguese are both welcome.
## Fastest ways to help
- **Share your project** in the [Showcase](/showcase): add one JSON file, it merges by itself.
- **Share a preset** in [Presets](/presets): same thing.
- **Report numbers**: FPS and `resmon` on your hardware, as an issue.
- **Improve the docs**: every page has an "Edit this page" link at the bottom.
## Registry pull requests
Add one file per entry. The CI validates it against the schema and merges it when green.
::: code-group
```json [registry/showcase/my-server.json]
{
"id": "my-server",
"name": "My Server HUD",
"author": "your-github-user",
"description": "Inventory and phone with liquid glass.",
"url": "https://example.com",
"repo": "https://github.com/you/your-resource",
"image": "my-server.webp",
"tags": ["hud", "inventory"]
}
```
```json [registry/presets/my-preset.json]
{
"id": "my-preset",
"name": "My preset",
"author": "your-github-user",
"description": "What it looks like and where it fits.",
"options": { "blur": 16 },
"attributes": { "data-glass": "liquid", "data-glass-bezel": "20" }
}
```
:::
Showcase images go in `registry/showcase/images/`, WebP, at most 300 KB.
Not comfortable with pull requests? Use the issue forms
["Add my project to the showcase"](https://github.com/mur4i/mri-fivem-liquid-glass/issues/new?template=showcase.yml)
and ["Share a preset"](https://github.com/mur4i/mri-fivem-liquid-glass/issues/new?template=preset.yml).
## Code
Read [CONTRIBUTING.md](https://github.com/mur4i/mri-fivem-liquid-glass/blob/main/CONTRIBUTING.md)
for the development setup, code rules and commit format.
---
# FiveM resource
Patterns that matter once the glass lives in a real resource. The full working version is
[`examples/showcase-resource`](https://github.com/mur4i/mri-fivem-liquid-glass/tree/main/examples/showcase-resource)
(`/liquidglass` in game).
## Manifest
```lua
fx_version 'cerulean'
game 'gta5'
ui_page 'html/index.html'
files {
'html/index.html',
'html/mri-liquid-glass.iife.min.js', -- only if you ship the file instead of the CDN
}
```
## Start once, render on demand
Start the glass when the page loads. Open and close screens by adding and removing their markup:
with no `[data-glass]` left in the DOM, the render loop stops by itself. Hiding with
`display: none` also stops drawing, but keeps a cheap check running every frame.
```js
MriLiquidGlass.startGameGlass()
window.addEventListener('message', (e) => {
if (e.data.action === 'open') root.innerHTML = template()
if (e.data.action === 'close') root.innerHTML = ''
})
```
## Focus
```lua
SetNuiFocus(true, true) -- cursor and keyboard go to the page
SetNuiFocus(false, false) -- back to the game
```
## Looking around while a screen is open
A nice touch: drag on empty space to turn the camera, release to get the cursor back. Do not drop
the focus on mouse down: the game never sees that press and the drag ends immediately. Keep the
focus and pass the input through instead, so the page still receives the release:
```lua
local blocked = { 24, 25, 140, 141, 142, 257, 263 } -- attack and melee while dragging
RegisterNUICallback('lookStart', function(_, cb)
cb('ok')
looking = true
SetNuiFocusKeepInput(true)
CreateThread(function()
while looking do
for i = 1, #blocked do DisableControlAction(0, blocked[i], true) end
Wait(0)
end
end)
end)
RegisterNUICallback('lookEnd', function(_, cb)
looking = false
SetNuiFocusKeepInput(false)
cb('ok')
end)
```
```js
root.addEventListener('pointerdown', (e) => {
if (e.target.closest('[data-glass]')) return // buttons and panels keep working
post('lookStart')
})
window.addEventListener('pointerup', () => post('lookEnd'))
window.addEventListener('blur', () => post('lookEnd'))
```
## Several resources with glass
Each NUI page runs its own glass. Two pages open at the same time cost twice; keep glass on the
screens the player looks at, not on always-on HUD pieces.
## DUI and iframes
DUI pages (`?mode=dui`) are skipped on purpose. Pages inside iframes are not tested yet: if you
try, tell us in an issue.
---
# React, Vue, Svelte
The library is framework free: start it once, mark elements with attributes. These snippets show
where "once" lives in each framework.
::: code-group
```tsx [React]
import { useEffect } from 'react'
import { startGameGlass } from 'mri-fivem-liquid-glass'
export function App() {
useEffect(() => {
const glass = startGameGlass({ fallbackImage: import.meta.env.DEV ? '/dev-bg.jpg' : null })
return () => glass.stop()
}, [])
return
Hello
}
```
```vue [Vue]
Hello
```
```svelte [Svelte]
Hello
```
```html [Plain HTML]
Hello
```
:::
## TypeScript and `data-*` in JSX
`data-glass` and friends are plain attributes, so no typing is needed. The option types ship
with the package: `GameGlassOptions`, `GameGlassHandle`.
## MRI ui-kit
Projects on [`@mriqbox/ui-kit`](https://github.com/mri-Qbox-Brasil/mri-ui-kit) 4.34+ already get
this library through the kit: `startGameGlass` is re-exported, and `startSuiteGlass` turns the
suite's "liquid" theme into glass on every surface.
---
# Quick start
## 1. Install
::: code-group
```bash [npm]
npm i mri-fivem-liquid-glass
```
```bash [pnpm]
pnpm add mri-fivem-liquid-glass
```
```html [No bundler]
```
:::
Offline or pinned: copy `node_modules/mri-fivem-liquid-glass/dist/mri-liquid-glass.iife.min.js`
next to your `index.html` and list it in the `files` of your `fxmanifest.lua`.
## 2. Start it once
```ts
import { startGameGlass } from 'mri-fivem-liquid-glass'
startGameGlass()
```
With the script tag: `MriLiquidGlass.startGameGlass()`.
It returns `{ refresh, stop }`. Call it once when the NUI boots, not every time a screen opens.
## 3. Mark your surfaces
```html
Frosted panel
```
## 4. Three CSS rules
```css
/* The page must stay transparent so the game shows through. */
html, body, #root { background: transparent; }
/* The library draws on a canvas at z-index 0; your UI goes above it. */
#root { position: relative; z-index: 1; }
[data-glass] {
background: rgba(255, 255, 255, 0.06); /* tint over the blur: keep it low */
border: 1px solid rgba(255, 255, 255, 0.22);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 16px 36px rgba(0, 0, 0, 0.3);
}
/* Flip the text over bright scenes. */
[data-glass-backdrop='bright'] { color: #111; }
```
::: danger Do not use backdrop-filter
Remove every `backdrop-filter` from glass elements. In CEF it composites against the page, not
the game, and paints a solid layer over the real glass.
:::
## 5. Develop outside the game
In a normal browser there is no game frame, so the library stays off. Pass a screenshot to see
the real look while you design:
```ts
startGameGlass({ fallbackImage: import.meta.env.DEV ? '/dev-bg.jpg' : null })
```
`fallbackImage` takes a URL, an `` or a `