<!-- fivemad.com, Markdown source of https://fivemad.com/docs/development/first-resource -->
> Source: https://fivemad.com/docs/development/first-resource
> Section: Development
> Tags: first resource, tutorial, fxmanifest, lua, RegisterCommand, ensure, f8 console, beginner
> Last updated: 2026-09-22
> Site map for assistants: https://fivemad.com/llms.txt

# Your first FiveM resource

Build a FiveM resource from scratch: folder, fxmanifest.lua, client and server scripts, a /hello command, a car spawner, ensure and restart, and reading the F8 console.

In this tutorial you build a resource with a client script and a server script, add chat commands, spawn a car, and learn the edit, `ensure`, test loop you'll use every day. You need a local server (see [Windows setup](/docs/server-setup/windows)) and VS Code (see [Start developing](/docs/development)).

[FiveM Scripting: Creating Your First Script (Twisle)](https://www.youtube.com/watch?v=dkqbgV2KUKw) (YouTube video)

## 1. Create the folder

Inside your server data folder, go to `resources`. Create a category folder `[local]` for your own work if it doesn't exist, and inside it a folder for the resource:

```text
resources/
└─ [local]/
   └─ hello_world/
      ├─ fxmanifest.lua
      ├─ client.lua
      └─ server.lua
```

The folder name **is** the resource name. Use lowercase, no spaces: `hello_world`, not `Hello World`.

## 2. Write the manifest

`fxmanifest.lua` tells FXServer what the resource is and which files run where:

```lua title="resources/[local]/hello_world/fxmanifest.lua"
fx_version 'cerulean'
game 'gta5'

name 'hello_world'
author 'You'
description 'My first FiveM resource'
version '1.0.0'

client_script 'client.lua'
server_script 'server.lua'
```

- `fx_version 'cerulean'` is the current manifest version. Always use it for new resources.
- `game 'gta5'` says this is for FiveM (RedM uses `rdr3`).
- `client_script` and `server_script` list the files for each side. Use the plural forms with `{ }` for several files, and globs like `'client/*.lua'` work.

You can generate manifests with the [fxmanifest Generator](/tools/fxmanifest-generator), which also warns about common mistakes.

## 3. A client command

```lua title="resources/[local]/hello_world/client.lua"
RegisterCommand('hello', function(source, args, rawCommand)
    local name = args[1] or 'world'
    TriggerEvent('chat:addMessage', {
        color = { 0, 200, 255 },
        args = { 'Hello', ('Hello, %s!'):format(name) },
    })
end, false)
```

- `RegisterCommand(name, handler, restricted)` creates `/hello`. On the client, `source` is always 0. `args` is a table of the words after the command.
- `TriggerEvent('chat:addMessage', ...)` sends a local event to the chat resource, which shows the message.
- `false` means anyone can use it. `true` would require the `command.hello` ACE permission.

## 4. A server command

```lua title="resources/[local]/hello_world/server.lua"
RegisterCommand('whoami', function(source, args)
    if source == 0 then
        print('This command was run from the server console.')
        return
    end

    local name = GetPlayerName(source)
    local license = GetPlayerIdentifierByType(source, 'license')

    print(('[hello_world] %s (id %d) asked who they are'):format(name, source))

    TriggerClientEvent('chat:addMessage', source, {
        args = { 'Server', ('You are %s, player id %d, %s'):format(name, source, license or 'no license') },
    })
end, false)
```

On the server, `source` is the **server ID** of the player who typed the command, or `0` for the console. `print` goes to the server console (txAdmin Live Console), and `TriggerClientEvent(name, target, ...)` sends an event to one player (`-1` sends to everyone).

## 5. Start it

In the txAdmin **Live Console** (or the server window), type:

```text
refresh
ensure hello_world
```

- `refresh` rescans the resources folder, so FXServer notices your new folder.
- `ensure` starts it (or restarts it if it's running).

You should see `Started resource hello_world`. To start it on every boot, add it to `server.cfg`:

```cfg title="server.cfg"
ensure hello_world
# or, to start everything in [local]:
ensure [local]
```

## 6. Test in game

Connect to your server, press <kbd>T</kbd> to open chat, and type `/hello` or `/hello Bob`. Then `/whoami`. You should see both messages, and the server console shows the `print` line.

## 7. The edit loop

Change the message in `client.lua`, save, then in the server console:

```text
ensure hello_world
```

The resource restarts and every connected client reloads it. Test again. This loop (edit, save, `ensure`, test) is how you'll work. You only need `refresh` again when you **add** a resource or change `fxmanifest.lua`.

> [!TIP]
> You can also type `ensure hello_world` in the **F8 console** in game if your account has permission to run server commands (the txAdmin master admin does, through `add_ace group.admin command allow`).

## 8. Read the F8 console

Press <kbd>F8</kbd> in game. This is the **client console**. Client `print` output and client errors show here. Add a print to `client.lua`:

```lua
print('hello_world client loaded')
```

`ensure` again and look for the line in F8. Now break something on purpose:

```lua
RegisterCommand('broken', function()
    local ped = nil
    print(ped.health) -- indexing nil
end, false)
```

Run `/broken` and F8 shows something like:

```text
SCRIPT ERROR: @hello_world/client.lua:14: attempt to index a nil value (local 'ped')
```

It tells you the resource, the file, the **line**, and what went wrong. Server errors look the same in the server console. More in [Debugging](/docs/development/debugging).

## 9. Spawn a car

Now use some game natives. This is the example from the official "creating your first script" guide:

```lua title="client.lua"
RegisterCommand('car', function(source, args)
    local vehicleName = args[1] or 'adder'

    if not IsModelInCdimage(vehicleName) or not IsModelAVehicle(vehicleName) then
        TriggerEvent('chat:addMessage', { args = { 'Invalid vehicle model: ' .. vehicleName } })
        return
    end

    RequestModel(vehicleName)
    while not HasModelLoaded(vehicleName) do
        Wait(500)
    end

    local playerPed = PlayerPedId()
    local pos = GetEntityCoords(playerPed)

    local vehicle = CreateVehicle(vehicleName, pos.x, pos.y, pos.z, GetEntityHeading(playerPed), true, false)
    SetPedIntoVehicle(playerPed, vehicle, -1)

    SetEntityAsNoLongerNeeded(vehicle)
    SetModelAsNoLongerNeeded(vehicleName)

    TriggerEvent('chat:addMessage', { args = { 'Enjoy your new ' .. vehicleName .. '!' } })
end, false)
```

What's going on:

- `IsModelInCdimage` / `IsModelAVehicle` check the model exists and is a vehicle. Natives accept a model name string and hash it for you.
- `RequestModel` + `HasModelLoaded` loads the model. `Wait(500)` gives the game time, without it the loop would freeze the game.
- `PlayerPedId()` is your character, `GetEntityCoords` its position (a `vector3`).
- `CreateVehicle(model, x, y, z, heading, isNetwork, netMissionEntity)` spawns it, networked so others see it.
- `SetPedIntoVehicle(ped, vehicle, -1)` seats you as the driver (`-1`).
- `SetModelAsNoLongerNeeded` frees the model from memory.

Try `/car sultan` or `/car zentorno`. Find spawn names in the [Model & Hash Browser](/tools/model-hash-browser).

> [!WARNING]
> Spawning vehicles from the client is fine for a learning server, but on a real server anyone could trigger it. Real resources spawn vehicles on the server, after checking permissions and money. See [Client, server and events](/docs/development/client-server-events).

## 10. Organise as it grows

When the resource gets bigger, split it:

```text
hello_world/
├─ fxmanifest.lua
├─ config.lua          shared settings
├─ client/
│  └─ main.lua
└─ server/
   └─ main.lua
```

```lua title="fxmanifest.lua"
fx_version 'cerulean'
game 'gta5'

shared_script 'config.lua'
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }
```

```lua title="config.lua"
Config = {}
Config.DefaultCar = 'adder'
Config.Greeting = 'Hello'
```

Shared scripts load first, on both sides, so `Config` is available in client and server files.

## What you learned

- A resource is a folder with `fxmanifest.lua`.
- `refresh` finds new resources, `ensure` starts or restarts them.
- Client scripts run in the game, server scripts in FXServer, and `print` goes to F8 or the server console.
- Errors show file and line.
- Natives do the game work, and loading models needs a wait loop.

Next: [Client, server and events](/docs/development/client-server-events).
