PlayDeck
Home / Course / Capstone: Your 30-Day Pick-a-Path Plan
Track B · Lesson 7

Capstone: Your 30-Day Pick-a-Path Plan

You now know the pieces: framework, ox stack, server-side validation, and the rules that keep a creator on the right side of Cfx. The thing that stops most people from earning isn't skill — it's scatter. They start five resources and finish none. This lesson hands you one 30-day path so you finish exactly one thing and put it where people can pay for it.

Step 0: Pick exactly one path (and only one)

Thirty days is enough for one shippable resource. It is not enough for three. Choose the path that matches what you actually enjoy, then close the other tabs.

Write your choice down. The rest of the plan assumes you committed.

The 30-day map

Week 1 — Scope and pin. Define the smallest version of your resource that someone would pay for. Cut everything else to a "later" list. Pin one framework now — Qbox or QBCore — and do not mix in ESX snippets later because an AI suggested them. Stand up a clean test server. Write a one-paragraph spec: what it does, what it depends on (ox_lib, ox_inventory, ox_target), and what it explicitly does not do.

Week 2 — Build the core loop. Get the main interaction working end to end on your own machine. Use lib.callback for anything where the server decides the outcome. Lean on ox_target for interaction points instead of distance loops. Every time AI hands you a native or export, verify it against the official reference and the PlayDeck sandbox before you trust it — invented functions are the number-one reason a "finished" script throws on someone else's server.

Week 3 — Harden and validate. Assume every value from the client is a lie. Move all money, item grants, and state changes server-side. Test on a second account so you're not the owner of everything. Write the README: install steps, dependencies, config, and a changelog. This is the week your resource stops being a demo.

Week 4 — Package and list. Strip debug prints, set a sane fxmanifest.lua, tag a version. Set up your store on Tebex or the Cfx Marketplace, write an honest listing, record a 60-second clip. Run the compliance checklist below one last time, then publish. Spend the final two days answering your first buyers fast — early support reviews are worth more than any ad.

Bake compliance in from day one

Don't bolt compliance on at the end. Check it every week. As of January 2026 there are exactly two sanctioned ways to sell FiveM content: Tebex and the Cfx Marketplace. Anything else — a Discord with a PayPal link, a third-party "leak fix" store — risks your Cfx account.

Run this list before you list:

Treat that list as principles, not gospel — the Cfx Platform License Agreement (PLA) is the source of truth, and it changes. Read the current PLA yourself before each launch and link to it from your own notes. When in doubt, the safe move is the boring one.

Where AI helps, and where it burns you

AI is excellent for the parts that are tedious: scaffolding a config table, drafting your README, sketching a UI. It is dangerous for the parts that are load-bearing. It will confidently invent ox exports that don't exist, mix QBCore and ESX in the same file, reach for deprecated callbacks instead of lib.callback, and — worst for an earn product — trust the client. Use it to draft, then verify every native and export against the real reference and test in the sandbox. The code you sell is your reputation; don't ship a hallucination.

A compliance gate you can actually code

Here's the pattern that keeps a paid grant both safe and rule-compliant: an allowlist of cosmetic/convenience-only items, plus a server-side check that the buyer actually owns the purchase.

-- server/earn_grant.lua
-- Pinned stack: Qbox/QBCore + ox_lib + ox_inventory.
-- Verify every export below against the live ox docs in the PlayDeck
-- sandbox before shipping. AI invents ox functions that don't exist.

-- Compliance allowlist: ONLY cosmetic or convenience items may be granted.
-- If it changes who wins a fight, it is pay-to-win and does NOT belong here.
local SELLABLE = {
    tuxedo_white = true, -- cosmetic outfit
    plate_custom = true, -- vanity license plate
    garage_slot  = true, -- convenience: one extra parking slot
}

-- You implement this against YOUR Tebex / Cfx purchase records
-- (fed by webhook into your own DB). Never trust client-sent ownership.
local function playerOwnsPurchase(license, sku)
    return Purchases.hasUnclaimed(license, sku) -- your data layer
end

lib.callback.register('playdeck:redeemPurchase', function(source, sku)
    -- The client chose the sku; the server decides if it's allowed.
    if not SELLABLE[sku] then return false, 'not redeemable' end

    local license = GetPlayerIdentifierByType(source, 'license')
    if not license or not playerOwnsPurchase(license, sku) then
        return false, 'no matching purchase'
    end

    -- Grant once, then mark it claimed so it can't be redeemed twice.
    local ok = exports.ox_inventory:AddItem(source, sku, 1)
    if ok then Purchases.markClaimed(license, sku) end
    return ok and true or false
end)

The allowlist is your compliance gate; the server check is your security gate. Both live on the server, where the client can't reach them.

Practice

This week, complete Step 0 and Week 1 for real. Pick your single path, write the one-paragraph spec, pin your framework, and stand up a clean test server with ox_lib, ox_inventory, and ox_target installed. Then open the current Cfx PLA and read it top to bottom — before you write a line of sellable code.

Recap

Learn it by building it

PlayDeck is an original course on building GTA roleplay scripts with AI — Lua, frameworks, NUI, debugging, and a browser sandbox to test every lesson without booting the game.

Browse the course