Creating a New NUI App
Step-by-step guide to creating a new FiveM NUI application in the monorepo.
This guide walks you through creating a new NUI app from scratch using the shared Monospace packages.
Create package.json
Add a package.json referencing the shared packages:
{
"name": "my-nui-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"lint": "biome check --write"
},
"dependencies": {
"@repo/ui": "workspace:*",
"preact": "^10.28.3",
"zod": "^4.3.6"
},
"devDependencies": {
"@repo/vite-config": "workspace:*",
"@repo/biome-config": "workspace:*",
"@repo/tailwind-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@preact/preset-vite": "^2.10.3",
"autoprefixer": "^10.4.24",
"postcss": "^8.5.6",
"tailwindcss": "3",
"typescript": "~5.9.3",
"vite": "^7.3.1"
}
}Create Vite config
Import the shared Vite configuration:
import { preactConfig } from '@repo/vite-config'
import { defineConfig, type UserConfig } from 'vite'
export default defineConfig({
...(preactConfig as UserConfig),
})This gives you the Preact preset and a relative base path (./) which is required for NUI embedding in FiveM.
Create Tailwind & PostCSS configs
Re-export the shared configurations:
import tailwindcss from '@repo/tailwind-config/tailwind'
export default tailwindcssimport postcss from '@repo/tailwind-config/postcss'
export default postcssCreate TypeScript configs
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}{
"extends": "@repo/typescript-config/preact-library.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"react": ["./node_modules/preact/compat/"],
"react-dom": ["./node_modules/preact/compat/"]
}
},
"include": ["src"]
}Create Biome config
{
"extends": ["@repo/biome-config/biome"]
}Create the entry point
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My NUI App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>@import '@repo/tailwind-config/style';import { render } from 'preact'
import './index.css'
import { App } from './app.tsx'
const element = document.getElementById('app')!
render(<App />, element)import { Button } from '@repo/ui/components/button'
export function App() {
return (
<>
<Button>Hello World</Button>
</>
)
}The @repo/vite-config sets base: './' to produce relative asset paths. This ensures the built NUI works correctly when embedded in FiveM, where assets are served from a local file path.