Why custom content needs a resource, not a drop folder
FiveM does not load loose files from your server root. Every custom asset, whether it is a uniform, a building interior, or a car, has to live inside a resource that the server registers and the client downloads. The runtime that makes this work is the asset streaming system. When a client connects, the server tells it which resources are active, the client downloads the streamed files, and the game's resource loader maps those raw assets into the game world.
That means the real skill is not finding content. It is packaging it so the game engine knows what each file is and when to load it. Two mechanisms do almost all the work: the stream folder, which holds raw game assets, and data_file entries in fxmanifest.lua, which register metadata so the engine treats those assets as vehicles, peds, interiors, or clothing rather than orphan files.
The stream folder
Inside any resource, a folder literally named stream is special. FiveM recursively scans it and registers every file it contains as a streamable game asset. You do not list files individually. The supported asset extensions include .ytd (texture dictionaries), .ydr and .yft (drawables and fragments, such as vehicle models), .ymap (map placements), .ytyp (archetype definitions), .ybn (collision bounds), and .ydd / .yld (ped components). Drop the raw files in, and they are available to stream.
A minimal fxmanifest.lua for a stream-only resource is short:
fx_version 'cerulean'
game 'gta5'
files {
'data/**/*.meta'
}
The stream folder itself needs no declaration. Metadata files outside it do.
EUP clothing: server distribution versus client install
EUP (Emergency Uniforms Pack) is the most common source of confusion because it has two completely different install paths.
The client-side path puts EUP files in the FiveM application data folder on each player's machine. This was the old approach and it does not scale. Every player must install the same pack, version drift causes texture mismatches, and you cannot control it. Avoid this for a public server.
The server-side path is the correct one. You stream the EUP component files from a resource so players download them automatically on connect. EUP ships ped component files: drawables (.ydd), texture dictionaries (.ytd), and the metadata that tells the game these are valid clothing slots. The metadata lives in shop apparel .meta files (the ..._shop.meta files that define which drawables exist for each ped), declared in your manifest:
data_file 'SHOP_PED_APPAREL_META_FILE' 'data/mp_m_freemode_01_shop.meta'
The component drawables go in stream, the .meta files go in a data folder declared under files, and you point the engine at each .meta with the matching data_file type. Note that SHOP_PED_APPAREL_META_FILE is the type for shop apparel metadata; general ped definitions in a peds.meta use a different type (PED_METADATA_FILE). Get the data_file type wrong and the clothing simply will not appear in the slot, even though the assets downloaded fine.
MLOs and ymaps: interiors versus placements
Custom buildings come in two shapes, and people conflate them.
A ymap is a placement file. It says "put these existing or streamed props at these coordinates." Shells and prop-based builds are usually ymaps. You stream the .ymap (and any .ytyp archetype it references) and the props appear.
An MLO (Map Loader Object) is a true interior with its own portals, rooms, and occlusion. It is heavier and almost always ships as a folder of .ytyp, .ymap, .ydr, .ytd, and collision .ybn files. The .ytyp defines the interior archetype, the .ymap places it and often disables the base game's interior, and the engine handles portal culling so you do not render the whole interior at once.
The practical install is the same for both: stream every asset file, and declare nothing extra in the manifest beyond the stream folder, because .ymap and .ytyp are auto-detected stream types. The trap is load order and shell removal. An MLO that replaces a default interior needs its accompanying ymap that strips the original, or you get the new interior fighting the old walls. Read the MLO's included notes; most ship a specific ymap for this.
Custom vehicles: the four-file pattern
Vehicles are the strictest content type because the engine needs four pieces of metadata to spawn a working car, and a missing one breaks the whole vehicle resource (sometimes silently, sometimes with a fatal load error).
- The model:
.yft(the vehicle and its_hiLOD) and.ytd(textures) go instream. vehicles.meta: registers the model name, handling id, and display strings. Without it the model name is not a spawnable vehicle.carcols.meta: defines mod kits, lights, and siren settings. Missing or malformedcarcols.metais a frequent cause of vehicles failing to load the entire resource.carvariations.meta: links color and kit variations to the model.handling.meta: defines the physics. A wronghandlingIdreference betweenvehicles.metaandhandling.metaproduces a car that spawns but drives like a default model or crashes the resource.
Declare each in the manifest:
files {
'data/vehicles.meta',
'data/carcols.meta',
'data/carvariations.meta',
'data/handling.meta'
}
data_file 'VEHICLE_METADATA_FILE' 'data/vehicles.meta'
data_file 'CARCOLS_FILE' 'data/carcols.meta'
data_file 'VEHICLE_VARIATION_FILE' 'data/carvariations.meta'
data_file 'HANDLING_FILE' 'data/handling.meta'
The files block makes the resource ship the file. The data_file line tells the engine what kind of file it is. You need both lines for each file. Listing it in files without a data_file is the single most common reason a freshly added car does nothing.
Replace versus addon
There are two ways to introduce a vehicle or interior, and choosing wrong causes conflicts.
An addon uses a brand new model name (for example mycar) that does not exist in the base game. Nothing else in the world changes. This is almost always the right choice for a server because two addon resources cannot collide unless they pick the same model name.
A replace overwrites a base game asset, reusing an existing name like adder. Every adder that spawns, including AI traffic, becomes your model. Two replace resources both targeting adder will conflict, and the load order decides which wins, producing the classic "my car changed after I added another mod" bug. Prefer addon for everything you can.
Texture sizes and the streaming budget
This is where servers quietly fall apart. FiveM streams assets into a fixed memory pool. Oversized textures do not just slow downloads; they exhaust the streaming budget and cause texture loss, where models render with missing or low-resolution skins, or the client crashes outright.
The practical rules: keep vehicle and clothing .ytd textures at sane power-of-two sizes. A 4096x4096 texture on a single shirt is wasteful when 1024 or 2048 looks identical in game. Compress textures (DXT/BC formats) inside the .ytd rather than shipping uncompressed. Watch your total stream memory; the more high-resolution MLOs and packs you stack, the closer you get to texture loss. When in doubt, downsize textures before adding more content. A server with fifty well-compressed cars runs better than one with ten 4K monsters.
Wiring it into server.cfg
No resource loads until you start it. After packaging, drop the resource folder into your resources directory and add it to server.cfg:
ensure my_custom_content
Use ensure rather than start; it starts the resource and restarts it cleanly if it was already running. Restart the server, watch the console for load errors, and test in game.