A modern FiveM resource boilerplate using TypeScript, Svelte 5, and Tailwind CSS. Features a clean Controllers/Services architecture with NUI communication utilities ready to go.
bun (recommended), pnpm, npm, or yarn# Install dependencies
bun install
# Build the resource
bun build
# Watch mode (auto-rebuild on changes)
bun watch
# Develop NUI in browser (hot reload on port 3000)
bun web:dev
| Command | Description |
|---|---|
bun build |
Build all project files for production |
bun watch |
Watch and rebuild files during development |
bun web:dev |
Start Vite dev server for NUI development |
bun format |
Format code with Biome |
bun lint |
Lint code with Biome |
├── dist/ # Compiled output (auto-generated)
│ ├── client.js
│ ├── server.js
│ └── web/
├── locales/ # Translation files (ox_lib locale system)
│ └── en.json
├── scripts/ # Build scripts
├── src/
│ ├── client/
│ │ ├── Controllers/ # Event handlers & command registration
│ │ ├── Services/ # Business logic & reusable functions
│ │ └── index.ts # Client entry point
│ ├── server/
│ │ ├── Controllers/ # Event handlers & command registration
│ │ ├── Services/ # Business logic & database operations
│ │ └── index.ts # Server entry point
│ ├── common/ # Shared code (client + server)
│ └── fxmanifest.lua # Template for manifest generation
├── static/
│ └── config.json # Runtime configuration
├── web/ # NUI web interface (Svelte + Vite)
│ └── src/
│ ├── lib/
│ │ ├── nui/ # NUI communication utilities
│ │ └── utils.ts # Utility functions
│ ├── App.svelte # Root component
│ └── app.css # Global styles
└── fxmanifest.lua # Auto-generated manifest (do not edit)
Controllers (src/[client|server]/Controllers/)
Services (src/[client|server]/Services/)
// Client
SendNUIMessage({
action: 'setVisible',
data: true
});
<!-- NUI (Svelte) -->
<script lang="ts">
import { useNuiEvent } from "$lib/nui";
let visible = $state(false);
useNuiEvent<boolean>("setVisible", (data) => {
visible = data;
});
</script>
<!-- NUI (Svelte) -->
<script lang="ts">
import { fetchNui } from "$lib/nui";
async function handleAction() {
const response = await fetchNui<{ success: boolean }>("doAction", { id: 1 });
}
</script>
// Client
RegisterNuiCallback('doAction', (data: { id: number }, cb) => {
// Handle the action
cb({ success: true });
});
This boilerplate comes without pre-built UI components. To add shadcn-svelte components:
bunx shadcn-svelte@latest initbunx shadcn-svelte@latest add buttonSee shadcn-svelte documentation for more details.
| Alias | Path |
|---|---|
@common/* |
src/common/* |
@client/* |
src/client/* |
@server/* |
src/server/* |
$lib/* |
web/src/lib/* |
static/config.json)import Config from '@common/config';
if (Config.debug) {
console.log('Debug mode enabled');
}
locales/en.json)import { Locale } from '@common/locale';
const message = Locale('welcome', playerName);
See CLAUDE.md for comprehensive development documentation including: