Monospace

fetchNui

Send NUI callbacks from the browser to the FiveM Lua client.

fetchNui is a utility function for sending NUI callbacks from the browser (JavaScript) to the FiveM Lua client. It wraps the native fetch API and targets the FiveM NUI callback endpoint.

Import

import { fetchNui } from '@repo/ui/utils/fetch'

Signature

async function fetchNui<T = unknown>(
  eventName: string,
  data?: unknown,
  mockData?: T
): Promise<T>

Parameters

ParameterTypeDescription
eventNamestringThe NUI callback name registered in Lua via RegisterNUICallback
dataunknownOptional data payload to send
mockDataTOptional mock data returned in development mode

Returns

Promise<T> — The response from the Lua callback.

Usage

Basic Usage

import { fetchNui } from '@repo/ui/utils/fetch'

// Send a callback to Lua
const result = await fetchNui('getPlayerData')

// With payload
await fetchNui('updateSettings', { volume: 0.8, language: 'en' })

With Mock Data (Development)

When running in development mode (import.meta.env.DEV), you can pass mock data that is returned immediately without making a network request. This allows you to develop NUI interfaces outside of FiveM.

const playerData = await fetchNui('getPlayerData', undefined, {
  name: 'John Doe',
  id: 1,
  job: 'police',
})
// In dev mode: returns the mock data immediately
// In production: sends a real NUI callback to the Lua client

Mock data is only used when import.meta.env.DEV is true (during vite dev). In production builds, the mock data parameter is ignored and real NUI callbacks are sent.

How It Works

Under the hood, fetchNui sends a POST request to the FiveM NUI callback URL:

https://{resourceName}/{eventName}

The resourceName is obtained from window.GetParentResourceName(), which is provided by the FiveM NUI environment. When running outside FiveM (e.g., in a browser during development), it falls back to 'nui-frame-app'.

Corresponding Lua Code

On the Lua side, register a callback to handle the event:

RegisterNUICallback('getPlayerData', function(data, cb)
  local playerData = {
    name = GetPlayerName(PlayerId()),
    id = GetPlayerServerId(PlayerId()),
  }
  cb(playerData)
end)

Source

packages/ui/src/utils/fetch.ts
declare global {
  interface Window {
    GetParentResourceName: () => string
  }
}

export async function fetchNui<T = unknown>(
  eventName: string,
  data?: unknown,
  mockData?: T
): Promise<T> {
  const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: JSON.stringify(data),
  }

  if (import.meta.env.DEV && mockData) return mockData
  const resourceName = window.GetParentResourceName
    ? window.GetParentResourceName()
    : 'nui-frame-app'
  const resp = await fetch(`https://${resourceName}/${eventName}`, options)
  const respFormatted = await resp.json()

  return respFormatted
}

On this page