A deliberately small reference implementation for building a custom tattoo editor with the GTAX Tattoo API. It accepts artwork, lets a user choose separate male and female placement, then downloads a ready-to-install FiveM, single-player, RAGE:MP, or raw tattoo package.
The project uses a plain Node.js server and browser modules. Three.js is its only runtime dependency, and there is no build step.
- Load body zones and their defaults from the authenticated
GET /api/public/ped-tattoo/zonesendpoint through a server proxy. - Render the baked male and female GTA V freemode peds from GLB files.
- Request a render-only overlay GLB from
POST /api/public/ped-tattoo/preview. - Send camera rays to
POST /api/public/ped-tattoo/pickfor private server-side click placement. - Layer that overlay over public male and female freemode-ped GLBs with Three.js.
- Turn editor controls into the API's
maleandfemaleplacement JSON. - Send artwork and package settings as
multipart/form-data. - Keep
GTAX_API_KEYon the server; it is never included in browser JavaScript. - Stream the API's binary response and preserve its filename and rate-limit headers.
The private projection is performed by the Tattoo API. The public ped files do not contain GTAX's private placement data, and the browser receives a small render-only GLB with ordinary positions, normals, and texture coordinates. This keeps the example useful without publishing GTAX's placement implementation.
Requirements: Node.js 20 or newer and a GTAX API key.
cp .env.example .env
# Add your GTAX_API_KEY to .env
npm install
npm startOpen http://localhost:3000. For automatic server restarts while editing, use npm run dev.
The development server binds to 127.0.0.1 by default. Set HOST=0.0.0.0 in your deployment environment when the process must accept external connections.
Browser editor
├─ GET /api/zones ──────────┐
├─ POST /api/pick │ no API key in the browser
├─ POST /api/preview │ no API key in the browser
└─ POST /api/build │
│ │
▼ │
This Node server │
│ Authorization: Bearer $GTAX_API_KEY
▼ │
gtax.dev Tattoo API ◄────┘
│
▼
zip or dlc.rpf download
The browser creates FormData requests in public/app.js. public/tattoo-viewer.js only loads the public ped and the render-only overlay returned by the API. server.mjs forwards request bodies without parsing or rewriting the uploaded image. This keeps the projection logic and API key on the server side.
The server exposes only the required Three.js browser modules under /vendor/; the rest of node_modules is not publicly served.
Each enabled sex is sent as JSON alongside the image:
{
"enabled": true,
"zone": "ZONE_TORSO",
"uvPos": { "x": 0.75, "y": 0.55 },
"scale": { "x": 0.127, "y": 0.127 },
"rotation": 0,
"flipX": false,
"flipY": false
}The example intentionally exposes only the common controls. The API also accepts facing and updateGroup for advanced shop metadata behavior; both are available from the zones endpoint when your editor needs them.
The UI is optional. The reusable integration is the /api/preview and /api/build proxy pair:
- Receive
multipart/form-datafrom your own authenticated client. - Add
Authorization: Bearer ${GTAX_API_KEY}on your server. - Forward interactive placement requests to
https://gtax.dev/api/public/ped-tattoo/previewand load the returned overlay GLB over the matching public ped. - Forward the final package request to
https://gtax.dev/api/public/ped-tattoo/build. - Relay binary responses and their content headers.
In production, add your own authentication, request-size limit, abuse protection, and timeout before exposing the proxy to users. Your API key's quota is shared by everyone who can call that route.
npm testThe tests use a local fake GTAX server to verify static serving, zone proxying, multipart forwarding, secret handling, and response headers. No API key or network access is required.
GPL-3.0-or-later. See LICENSE.