Integration Examples
Real-world code examples showing how to integrate uz_AutoShot thumbnails into clothing scripts, shops, and NUI panels.
Integration Examples
These examples show how to use uz_AutoShot's HTTP API and exports in real-world scenarios. All examples fetch photos directly from the local HTTP server — no file copying or Lua proxy needed.
NUI Callback (Lua → JS)
The simplest way to pass the API URL from Lua to your NUI:
-- client.lua (your clothing script)
RegisterNUICallback('getClothingPhotos', function(data, cb)
local url = exports['uz_AutoShot']:getManifestURL(data.gender, data.type, data.id)
PerformHttpRequest(url, function(status, body)
if status ~= 200 then
cb({ items = {} })
return
end
local decoded = json.decode(body)
cb({ items = decoded and decoded.items or {} })
end, 'GET')
end)// nui/script.js
const response = await fetch(
`https://cfx-nui-YOUR_SCRIPT/getClothingPhotos`,
{
method: 'POST',
body: JSON.stringify({ gender: 'male', type: 'component', id: 11 })
}
)
const { items } = await response.json()This approach routes through Lua. For better performance, fetch directly from JS — see the next example.
Direct Fetch (JS only)
Since the HTTP server has CORS enabled, you can skip Lua entirely:
// Fetch all male tops
async function getClothingItems(gender, type, id) {
const res = await fetch(
`http://127.0.0.1:3959/api/manifest/${gender}/${type}/${id}`
)
if (!res.ok) return []
const data = await res.json()
return data.items
}
// Usage
const tops = await getClothingItems('male', 'component', 11)
const hats = await getClothingItems('male', 'prop', 0)React — Thumbnail Grid
A complete React component that fetches and displays clothing thumbnails:
import { useState, useEffect } from 'react'
const API_BASE = 'http://127.0.0.1:3959'
function ClothingGrid({ gender, type, categoryId }) {
const [items, setItems] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
setLoading(true)
fetch(`${API_BASE}/api/manifest/${gender}/${type}/${categoryId}`)
.then(res => res.json())
.then(data => {
setItems(data.items || [])
setLoading(false)
})
.catch(() => setLoading(false))
}, [gender, type, categoryId])
if (loading) return <div className="loading">Loading...</div>
if (!items.length) return <div className="empty">No photos captured yet</div>
return (
<div className="clothing-grid">
{items.map((item) => (
<button
key={`${item.drawable}_${item.texture}`}
className="clothing-item"
onClick={() => applyClothing(item)}
>
<img
src={item.url}
alt={`Drawable ${item.drawable}`}
loading="lazy"
/>
<span>{item.drawable}</span>
</button>
))}
</div>
)
}
function applyClothing(item) {
fetch(`https://cfx-nui-YOUR_SCRIPT/applyClothing`, {
method: 'POST',
body: JSON.stringify({
itemType: item.type,
id: item.id,
drawable: item.drawable,
texture: item.texture,
}),
})
}.clothing-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
gap: 8px;
padding: 12px;
}
.clothing-item {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 4px;
cursor: pointer;
transition: border-color 0.15s;
}
.clothing-item:hover {
border-color: rgba(255, 255, 255, 0.3);
}
.clothing-item img {
width: 100%;
aspect-ratio: 1;
object-fit: contain;
}React — Category Selector with Thumbnails
A full clothing browser with category tabs and thumbnail grid:
import { useState, useEffect, useCallback } from 'react'
const API_BASE = 'http://127.0.0.1:3959'
const CATEGORIES = [
{ type: 'component', id: 11, label: 'Tops' },
{ type: 'component', id: 4, label: 'Pants' },
{ type: 'component', id: 6, label: 'Shoes' },
{ type: 'component', id: 1, label: 'Masks' },
{ type: 'component', id: 8, label: 'Undershirt' },
{ type: 'prop', id: 0, label: 'Hats' },
{ type: 'prop', id: 1, label: 'Glasses' },
]
function ClothingBrowser({ gender = 'male' }) {
const [activeCategory, setActiveCategory] = useState(CATEGORIES[0])
const [items, setItems] = useState([])
const [selected, setSelected] = useState(null)
useEffect(() => {
const { type, id } = activeCategory
fetch(`${API_BASE}/api/manifest/${gender}/${type}/${id}`)
.then(res => res.json())
.then(data => setItems(data.items || []))
.catch(() => setItems([]))
}, [gender, activeCategory])
const handleApply = useCallback((item) => {
setSelected(item.drawable)
fetch(`https://cfx-nui-YOUR_SCRIPT/applyClothing`, {
method: 'POST',
body: JSON.stringify({
itemType: item.type,
id: item.id,
drawable: item.drawable,
texture: item.texture,
}),
})
}, [])
return (
<div className="clothing-browser">
<div className="categories">
{CATEGORIES.map((cat) => (
<button
key={`${cat.type}_${cat.id}`}
className={activeCategory === cat ? 'active' : ''}
onClick={() => setActiveCategory(cat)}
>
{cat.label}
</button>
))}
</div>
<div className="items-grid">
{items.map((item) => (
<button
key={`${item.drawable}_${item.texture}`}
className={`item ${selected === item.drawable ? 'selected' : ''}`}
onClick={() => handleApply(item)}
>
<img src={item.url} alt={`#${item.drawable}`} loading="lazy" />
</button>
))}
</div>
</div>
)
}React — Custom Hook
A reusable hook for fetching clothing data:
import { useState, useEffect } from 'react'
const API_BASE = 'http://127.0.0.1:3959'
export function useClothingItems(gender, type, categoryId) {
const [items, setItems] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
if (!gender || !type || categoryId === undefined) return
setLoading(true)
setError(null)
fetch(`${API_BASE}/api/manifest/${gender}/${type}/${categoryId}`)
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json()
})
.then(data => {
setItems(data.items || [])
setLoading(false)
})
.catch(err => {
setError(err.message)
setItems([])
setLoading(false)
})
}, [gender, type, categoryId])
return { items, loading, error }
}
// Usage in any component:
function TopsGrid() {
const { items, loading, error } = useClothingItems('male', 'component', 11)
if (loading) return <Spinner />
if (error) return <p>Error: {error}</p>
return (
<div className="grid">
{items.map(item => (
<img key={item.drawable} src={item.url} alt={`#${item.drawable}`} />
))}
</div>
)
}Check if Photo Exists
Before displaying a thumbnail, check if it was captured:
async function hasPhoto(gender, type, id, drawable, texture = 0) {
const params = new URLSearchParams({ gender, type, id, drawable, texture })
const res = await fetch(`${API_BASE}/api/exists?${params}`)
const data = await res.json()
return data.exists
}
// Usage
const exists = await hasPhoto('male', 'component', 11, 5)
if (exists) {
img.src = `http://127.0.0.1:3959/shots/male/11/5_0.png`
} else {
img.src = '/placeholder.png'
}Lua — Clothing Shop Integration
Example for a clothing shop script that uses uz_AutoShot photos:
-- Open shop with thumbnails from uz_AutoShot
RegisterCommand('clothingshop', function()
local ped = PlayerPedId()
local gender = (GetEntityModel(ped) == GetHashKey('mp_m_freemode_01')) and 'male' or 'female'
-- Build photo URLs for all tops
local items = {}
local numDrawables = GetNumberOfPedDrawableVariations(ped, 11)
for i = 0, numDrawables - 1 do
items[#items + 1] = {
drawable = i,
price = math.random(100, 5000),
photo = exports['uz_AutoShot']:getPhotoURL(gender, 'component', 11, i, 0)
}
end
-- Send to NUI
SendNUIMessage({
type = 'openShop',
category = 'Tops',
items = items,
})
SetNuiFocus(true, true)
end)