Skip to main content
Mythic Framework resources follow a consistent structure that promotes organization, maintainability, and scalability. Understanding this structure is essential for both using and developing Mythic resources.

Standard Resource Structure

Every Mythic resource follows this pattern:
mythic-[name]/
├── fxmanifest.lua          # Resource manifest (required)
├── README.md               # Resource documentation
├── client/                 # Client-side Lua scripts
│   ├── component.lua       # Component registration
│   ├── events.lua          # Event handlers
│   ├── main.lua            # Main client logic
│   └── ...                 # Additional client files
├── server/                 # Server-side Lua scripts
│   ├── component.lua       # Component registration
│   ├── events.lua          # Event handlers
│   ├── callbacks.lua       # Server callbacks
│   ├── main.lua            # Main server logic
│   └── ...                 # Additional server files
├── shared/                 # Shared Lua scripts (optional)
│   ├── config.lua          # Shared configuration
│   └── utils.lua           # Shared utilities
├── config/                 # Configuration files
│   └── config.lua          # Resource-specific config
└── ui/                     # React UI (if applicable)
    ├── src/                # React source code
    │   ├── components/
    │   ├── reducers/
    │   ├── actions/
    │   └── App.jsx
    ├── dist/               # Built UI files
    │   ├── index.html
    │   └── main.js
    ├── package.json
    └── webpack.config.js
Not all resources have all folders. Simple resources may only have fxmanifest.lua and server/ or client/. Complex resources with UIs will have the full structure.

The fxmanifest.lua File

The manifest file is required for all FiveM resources. It defines metadata, dependencies, and files to load.

Basic Manifest

-- fxmanifest.lua
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'

author 'Your Name'
description 'Resource description'
version '1.0.0'

-- Client scripts
client_scripts {
    'client/main.lua'
}

-- Server scripts
server_scripts {
    'server/main.lua'
}

-- Shared scripts (loaded on both sides)
shared_scripts {
    'shared/config.lua'
}

Mythic Resource Manifest

Mythic resources typically include anti-cheat and organized file loading:
-- mythic-inventory/fxmanifest.lua
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'

-- Anti-cheat client check
client_script '@mythic-pwnzor/client/check.lua'

-- Shared scripts (loaded first on both sides)
shared_scripts {
    'shared/config.lua',
    'shared/items.lua'
}

-- Client scripts (wildcard pattern)
client_scripts {
    'client/*.lua'
}

-- Server scripts
server_scripts {
    'server/*.lua'
}

-- UI files
ui_page 'ui/dist/index.html'

files {
    'ui/dist/**/*'
}

Manifest Features

Declare resource dependencies:
dependencies {
    'mythic-base',     -- Required dependency
    'oxmysql'
}

-- Or specify optional dependencies
optional_dependencies {
    'mythic-phone'
}
Define exports other resources can use:
exports {
    'GetInventory',
    'AddItem',
    'RemoveItem'
}

server_exports {
    'GetPlayerInventory'
}

client_exports {
    'OpenInventoryUI'
}
For resources with NUI:
ui_page 'ui/dist/index.html'

files {
    'ui/dist/**/*',     -- All UI files
    'ui/assets/**/*'     -- Assets
}
For resources that add game data:
data_file 'HANDLING_FILE' 'handling.meta'
data_file 'VEHICLE_LAYOUTS_FILE' 'vehiclelayouts.meta'
data_file 'CARCOLS_FILE' 'carcols.meta'

files {
    'handling.meta',
    'vehiclelayouts.meta',
    'carcols.meta'
}

Directory Breakdown

client/ Directory

Contains all client-side Lua scripts. Common Files:
client/
├── component.lua       # Component registration
├── events.lua          # Event handlers
├── main.lua           # Main initialization
├── ui.lua             # NUI communication
├── commands.lua       # Client commands
├── threads.lua        # Client threads/loops
└── helpers.lua        # Helper functions
Example component.lua:
-- client/component.lua

-- Wait for framework ready
AddEventHandler('Core:Shared:Ready', function()
    -- Fetch required components
    local Logger = exports['mythic-base']:FetchComponent('Logger')

    -- Register client component
    exports['mythic-base']:RegisterComponent('InventoryClient', {
        Open = function(self)
            SetNuiFocus(true, true)
            SendNUIMessage({
                type = 'OPEN_INVENTORY'
            })
        end,

        Close = function(self)
            SetNuiFocus(false, false)
            SendNUIMessage({
                type = 'CLOSE_INVENTORY'
            })
        end
    })
end)
Example events.lua:
-- client/events.lua

-- Listen to server events
RegisterNetEvent('mythic-inventory:client:UpdateInventory', function(inventory)
    SendNUIMessage({
        type = 'SET_INVENTORY',
        inventory = inventory
    })
end)

RegisterNetEvent('mythic-inventory:client:ItemUsed', function(item)
    print('Used item:', item)
end)

-- Local events
AddEventHandler('mythic-inventory:client:Open', function()
    COMPONENTS.InventoryClient:Open()
end)

server/ Directory

Contains all server-side Lua scripts. Common Files:
server/
├── component.lua       # Component registration
├── events.lua          # Event handlers
├── callbacks.lua       # Server callbacks
├── main.lua           # Main initialization
├── commands.lua       # Server commands
├── database.lua       # Database operations
└── helpers.lua        # Helper functions
Example component.lua:
-- server/component.lua

-- Request dependencies
exports['mythic-base']:RequestDependencies('Inventory', {
    'Database',
    'Logger',
    'Characters'
}, function(errors)
    if #errors > 0 then
        print('Failed to load Inventory dependencies')
        return
    end

    -- Register server component
    exports['mythic-base']:RegisterComponent('Inventory', {
        _protected = true,
        _name = 'inventory',

        Get = function(self, characterId, callback)
            COMPONENTS.Database.Game:findOne({
                collection = 'inventory',
                query = {
                    owner = characterId
                }
            }, function(success, inventory)
                if callback then
                    callback(success, inventory)
                end
            end)
        end,

        AddItem = function(self, characterId, item, count, metadata)
            -- Implementation
            return true
        end,

        RemoveItem = function(self, characterId, slot, count)
            -- Implementation
            return true
        end
    })
end)
Example callbacks.lua:
-- server/callbacks.lua

-- Register callback for client requests
COMPONENTS.Callback:RegisterCallback('mythic-inventory:GetInventory', function(source, data, cb)
    local char = COMPONENTS.Characters:GetCharacter(source)
    local inventory = COMPONENTS.Inventory:Get(char.SID)

    cb(inventory)
end)

COMPONENTS.Callback:RegisterCallback('mythic-inventory:UseItem', function(source, data, cb)
    local char = COMPONENTS.Characters:GetCharacter(source)
    local success = COMPONENTS.Inventory:UseItem(char.SID, data.slot)

    cb({ success = success })
end)

shared/ Directory

Contains scripts loaded on both client and server. Use Cases:
  • Configuration that both sides need
  • Shared utility functions
  • Constants and enums
  • Data structures
Example config.lua:
-- shared/config.lua

Config = {}

Config.MaxSlots = 50
Config.MaxWeight = 100

Config.ItemTypes = {
    WEAPON = 1,
    CONSUMABLE = 2,
    TOOL = 3,
    RESOURCE = 4
}

Config.Rarities = {
    COMMON = { label = 'Common', color = '#FFFFFF' },
    RARE = { label = 'Rare', color = '#0070DD' },
    EPIC = { label = 'Epic', color = '#A335EE' },
    LEGENDARY = { label = 'Legendary', color = '#FF8000' }
}

config/ Directory

Resource-specific configuration files. Example:
-- config/config.lua

Config = Config or {}

-- Inventory configuration
Config.Inventory = {
    -- UI settings
    UI = {
        position = 'right',
        theme = 'dark'
    },

    -- Gameplay settings
    Gameplay = {
        dropOnDeath = true,
        losePercentage = 0.5,
        allowTrade = true
    },

    -- Shop locations
    Shops = {
        {
            name = '24/7 Supermarket',
            coords = vector3(25.7, -1347.3, 29.5),
            items = {
                { item = 'water', price = 10 },
                { item = 'sandwich', price = 15 }
            }
        }
    }
}

ui/ Directory

React-based user interfaces. Structure:
ui/
├── src/                    # Source code
│   ├── components/         # React components
│   │   ├── Inventory.jsx
│   │   ├── ItemSlot.jsx
│   │   └── Tooltip.jsx
│   ├── reducers/           # Redux reducers
│   │   └── inventoryReducer.js
│   ├── actions/            # Redux actions
│   │   └── inventoryActions.js
│   ├── hooks/              # Custom React hooks
│   │   └── useNuiEvent.js
│   ├── utils/              # Utilities
│   │   └── fetchNui.js
│   ├── App.jsx             # Main component
│   └── index.jsx           # Entry point
├── dist/                   # Built files (webpack output)
│   ├── index.html
│   └── main.js
├── package.json
├── webpack.config.js
└── README.md
Example App.jsx:
// ui/src/App.jsx
import React, { useState, useEffect } from 'react';
import { useNuiEvent } from './hooks/useNuiEvent';
import { fetchNui } from './utils/fetchNui';
import Inventory from './components/Inventory';

function App() {
    const [visible, setVisible] = useState(false);
    const [inventory, setInventory] = useState([]);

    // Listen to NUI messages from client
    useNuiEvent('SET_INVENTORY', (data) => {
        setInventory(data.inventory);
    });

    useNuiEvent('OPEN_INVENTORY', () => {
        setVisible(true);
    });

    useNuiEvent('CLOSE_INVENTORY', () => {
        setVisible(false);
    });

    // Handle ESC key
    useEffect(() => {
        const handleEscape = (e) => {
            if (e.key === 'Escape' && visible) {
                fetchNui('closeInventory');
                setVisible(false);
            }
        };

        window.addEventListener('keydown', handleEscape);
        return () => window.removeEventListener('keydown', handleEscape);
    }, [visible]);

    if (!visible) return null;

    return <Inventory items={inventory} />;
}

export default App;

File Naming Conventions

Naming Pattern:
  • Lowercase with underscores: item_manager.lua
  • Or descriptive names: component.lua, events.lua, main.lua
Prefixes (mythic-base pattern):
  • sh_ = Shared (both sides)
  • sv_ = Server only
  • cl_ = Client only
sh_config.lua
sv_database.lua
cl_ui.lua
Components: PascalCase
Inventory.jsx
ItemSlot.jsx
ContextMenu.jsx
Utilities: camelCase
fetchNui.js
formatMoney.js
Reducers: Descriptive with suffix
inventoryReducer.js
hudReducer.js
Always named config.lua or descriptive of what they configure:
config.lua
items.lua
shops.lua
jobs.lua

Resource Load Order

Order matters! Resources must load in the correct sequence. Example from configs/resources.cfg:
# 1. Database (required by everything)
ensure oxmysql

# 2. Core framework (MUST load first)
ensure mythic-base

# 3. Anti-cheat (early for protection)
ensure mythic-pwnzor

# 4. Core systems
ensure mythic-queue
ensure mythic-loadscreen

# 5. Character system (required by most features)
ensure mythic-characters

# 6. Feature resources (order matters for dependencies)
ensure mythic-inventory      # Required by shops
ensure mythic-jobs           # Required by job-specific resources
ensure mythic-economy        # Required by shops, properties

# 7. Dependent features
ensure mythic-shops          # Depends on inventory, economy
ensure mythic-properties     # Depends on economy, characters

# 8. UI resources (depend on features)
ensure mythic-hud
ensure mythic-phone
ensure mythic-menu

Best Practices

Consistent Structure

Follow the standard structure for all resources. Makes navigation and maintenance easier.

Separate Concerns

Keep client, server, and UI code separate. Don’t mix them in the same file.

Use Wildcards

Use client/*.lua and server/*.lua in fxmanifest for easier file management.

Document Everything

Include README.md explaining what the resource does and how to configure it.

Config Files

Externalize configuration. Never hardcode values that might change.

Modular Code

Break large files into smaller, focused modules. Don’t put everything in main.lua.

Example: Complete Resource

Here’s a simple but complete example resource following Mythic structure:
mythic-example/
├── fxmanifest.lua
├── README.md
├── client/
│   ├── component.lua
│   ├── events.lua
│   └── main.lua
├── server/
│   ├── component.lua
│   ├── events.lua
│   ├── callbacks.lua
│   └── main.lua
├── shared/
│   └── config.lua
└── config/
    └── config.lua
fxmanifest.lua:
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'

client_script '@mythic-pwnzor/client/check.lua'

shared_scripts {
    'shared/config.lua'
}

client_scripts {
    'client/*.lua'
}

server_scripts {
    'server/*.lua'
}
shared/config.lua:
Config = {}
Config.Debug = false
Config.Feature = {
    enabled = true,
    cooldown = 60000
}
server/component.lua:
exports['mythic-base']:RequestDependencies('Example', {
    'Logger',
    'Database'
}, function(errors)
    if #errors > 0 then return end

    exports['mythic-base']:RegisterComponent('Example', {
        DoSomething = function(self, player)
            COMPONENTS.Logger:Info('Example', 'Doing something')
            return true
        end
    })
end)
server/events.lua:
RegisterNetEvent('mythic-example:server:DoAction', function()
    local src = source
    COMPONENTS.Example:DoSomething(src)
end)
client/events.lua:
AddEventHandler('mythic-example:client:Notify', function(message)
    print('Notification:', message)
end)

Next Steps

Start simple: When creating a new resource, start with the minimal structure (fxmanifest.lua + one server or client file) and expand as needed. Don’t create empty folders.