Serve ox_inventory item images from a CDN
Move ox_inventory’s web/images to a CDN with one zip and one convar: a lighter resource, faster joins, and item images you can replace without a restart.
By Termi
- ox_inventory
- CDN
- Performance
On this page
- Why move the images out of the resource
- How ox_inventory finds an image
- Upload the images
- From the panel
- Over the API
- With rclone (S3)
- Point ox_inventory at the CDN
- Take the images out of the resource
- Adding and replacing images later
- If an image does not show
- Common questions
- Where does ox_inventory load item images from?
- How do I change the image path in ox_inventory?
- Why are my ox_inventory item images not showing?
- Can ox_inventory use WebP or JPG item images?
- Do I have to restart ox_inventory to change an item image?
Every item in ox_inventory has a PNG in ox_inventory/web/images. On a server with a few hundred custom items that folder easily grows to tens of megabytes, and all of it is part of a resource that every player downloads before they can play. This guide moves the images to a CDN: one zip upload, one line in server.cfg, and the inventory loads its images from cdn.fivedock.dev instead.
Why move the images out of the resource
ox_inventory’s fxmanifest.lua lists web/images/*.png under files, which makes every image a resource file: the server sends it to each client, and the client keeps it in its FiveM cache. That has a few costs:
With a CDN the images are not part of the resource at all. The inventory’s browser page asks for an image only when it has to show that item, and keeps it in its HTTP cache for next time. A player who never opens the gun shop never downloads the gun images.
How ox_inventory finds an image
ox_inventory reads the replicated convar inventory:imagepath and builds each image link as <imagepath>/<item name>.png. The default points into the resource itself:
default nui://ox_inventory/web/images/burger.png
CDN https://cdn.fivedock.dev/o/<your-workspace>/items/burger.pngSo all it needs is a folder on the web where every image is named exactly like its item. Two details from the ox_inventory source:
Upload the images
On FiveDock, a file uploaded with a key gets a link that never changes: https://cdn.fivedock.dev/o/<your-workspace>/<key>. Upload the images so that burger.png gets the key items/burger.png, and the imagepath is …/items. Your workspace slug is the short name shown in the panel, and it is also your S3 bucket name.
From the panel
FiveDock unpacks the archive and stores each image as its own file. Folders inside the archive are kept, which is why you zip the images and not the images folder: burger.png becomes items/burger.png, not items/images/burger.png. Anything that is not an accepted image, like a stray readme.txt, is skipped and listed in the result.
Over the API
The same in one request, with an API token (fd_live_…, made on the Tokens page) that has the files:write scope:
cd ox_inventory/web/images
zip -r ../images.zip .
curl -X POST https://api.fivedock.dev/api/v3/file/archive \
-H "Authorization: Bearer fd_live_…" \
-F "file=@../images.zip" \
-F "path=items"{
"status": "ok",
"data": {
"uploaded": [
{
"key": "items/burger.png",
"url": "https://cdn.fivedock.dev/o/my-city/items/burger.png",
"fileUrl": "https://cdn.fivedock.dev/f/…png",
"filename": "burger.png",
"path": "/items",
"size": 18233,
"mime_type": "image/png",
"deduplicated": false
}
],
"skipped": [{ "name": "readme.txt", "reason": "unsupported_type" }]
}
}url is the stable keyed link; fileUrl is the per-upload link that every file also gets. One archive can hold up to 5,000 files, which covers nearly any item list. If yours is bigger, upload it in two archives or use rclone.
With rclone (S3)
If you keep your server in Git or deploy with scripts, the S3 endpoint is the most comfortable route. Set up an rclone remote called fivedock as shown in the upload docs, then:
# my-city = your workspace slug (it is also your S3 bucket name)
rclone sync ./ox_inventory/web/images fivedock:my-city/items --dry-run
rclone sync ./ox_inventory/web/images fivedock:my-city/itemsrclone sync makes the destination match the source, and that includes deleting files in items that are not in your local folder. Run it with --dry-run first, or use rclone copy if you only ever add and update.
Objects you put over S3 are keyed files too, so they get the same stable links.
Point ox_inventory at the CDN
Add the convar to server.cfg, above the line that starts ox_inventory:
setr inventory:imagepath "https://cdn.fivedock.dev/o/<your-workspace>/items"
ensure ox_inventoryBefore you restart, open one image in your browser to check the link, for example https://cdn.fivedock.dev/o/<your-workspace>/items/burger.png.
Take the images out of the resource
Join the server, open your inventory and a shop or two, and check that the images load. Once they do, move the PNG files out of ox_inventory/web/images and keep them somewhere else: that folder is now the source for your uploads, not part of the server.
When you update ox_inventory later, leave web/images out of the copy, or empty it again afterwards.
Adding and replacing images later
To add an image for a new item, or fix an old one, upload the PNG with the key it should have: Upload in the items folder of the panel with Keep file names on, or the API:
curl -X POST https://api.fivedock.dev/api/v3/file \
-H "Authorization: Bearer fd_live_…" \
-F "[email protected]" \
-F "key=items/burger.png"If items/burger.png already exists, the upload replaces it behind the same link; the old version is kept for 7 days before it is purged. Keyed links are cached for 5 minutes and then revalidated, so players see the new image within about five minutes, with no restart and nothing new to download when they join.
If an image does not show
The same keyed links work for any other image your UI loads, such as vehicle thumbnails or mugshots: upload once and use the link wherever you need it.
Common questions
Where does ox_inventory load item images from?
From the replicated convar inventory:imagepath, which defaults to nui://ox_inventory/web/images, the web/images folder inside the resource. For each item, ox_inventory builds the link <imagepath>/<item name>.png. An item’s own client.image overrides that: a full URL is used as it is, and a bare file name is looked up under the imagepath.
How do I change the image path in ox_inventory?
Add setr inventory:imagepath "https://cdn.fivedock.dev/o/<your-workspace>/items" to server.cfg above ensure ox_inventory, with no slash at the end, and restart ox_inventory once. It has to be setr, because the inventory UI runs on the client and only setr convars reach clients. Every image must then sit at that address, named exactly like its item, with a .png extension.
Why are my ox_inventory item images not showing?
Usually the file name does not match the item name exactly, including upper and lower case, or the file is not a .png. If every image is missing, open the imagepath plus /burger.png in a browser: a 404 means the folder or the workspace slug in the path is wrong. Also check that the convar was set with setr, not set.
Can ox_inventory use WebP or JPG item images?
Only item by item. The imagepath lookup always adds .png to the item name, so a burger.webp next to it is never requested. Set the item’s client.image to burger.webp, which is looked up under the imagepath, or to a full URL, and the inventory’s NUI page loads it like any browser would.
Do I have to restart ox_inventory to change an item image?
Not when the images are on a CDN. Upload the new PNG to the same key, such as items/burger.png, and players see it within about five minutes, once their cached copy expires. Images inside web/images only reach players after ox_inventory restarts.