Play it
Open the example game (development servers: platform-dev, platform-web-dev, pay-dev).
Download the project (.zip): plain Node.js and browser JavaScript, no dependencies, no build step.
What it shows
A best-of-five rock-paper-scissors match against a bot: first to 3 points wins, and draws don't count. Each match costs 1 ticket, and winning pays 50 Gita coins. Every platform feature is in it:
| Feature | Where in the game | Wiki page | Code |
|---|---|---|---|
| Sign in with Baziness (splash choice), account switch, logout | first launch; Settings → «اتصال حساب» | Login | public/js/platform.js, server/services.js (platformToken, platformLogin) |
Currencies: tickets (local) and Gita coins (get-coin) |
the top bar chips, the reward banner | Gita coins | public/js/platform.js (getCoin), public/js/app.js (renderTopbar) |
Winner gets 50 Gita coins (add-coin, idempotent), sign-in required to claim |
the result popup, the "reward waiting" strip | Gita coins | server/services.js (claimMatchReward), public/js/app.js (claim) |
| «انتخاب جایزه» reward page | the purple banner | Reward page | public/js/platform.js (openRewardSelection) |
| Tutorial: rules → coach mark → game-offer page → «خرید موفق» starter pack (5 tickets) | first launch | Tutorial offer page | public/js/app.js (tutorial section), server/services.js (claimStarterPack) |
| Swipe-down sheet | every Baziness page | Bottom sheet | public/js/sheet.js, public/styles.css |
Baziness Pay: «بستهی بلیت», 10 tickets for 4,900 Toman (SKU example_pack) |
the shop card | Baziness Pay | server/pay.js, server/services.js (startPurchase, verifyPurchase), public/js/purchase.js |
UTM / ?tag= first-touch capture |
any link, e.g. …/example/?utm_source=wiki&utm_medium=docs |
Links & UTM | public/js/api.js (FIRST_TOUCH), server/services.js (ensureUser) |
Run it locally
unzip baziness-example-rps.zip && cd baziness-example-rps
cp .env.example .env # fill in BAZINESS_CLIENT_ID / BAZINESS_CLIENT_SECRET
npm start # → http://127.0.0.1:4380/Requirements: Node.js 20+. Data lives in data/db.json, a tiny JSON store standing in for your database.
.env |
Development value |
|---|---|
BAZINESS_CLIENT_ID / BAZINESS_CLIENT_SECRET |
the example's dev client (ask the platform team, or use your own game's) |
BAZINESS_PLATFORM_PACKAGE_NAME |
com.karizmastudio.example |
BAZINESS_PAY_BASE_URL |
https://pay-dev.karizmastudios.org |
BAZINESS_PAY_PACKAGE_NAME |
com.karizmastudio.example |
PACK_SKU / PACK_PRICE |
example_pack / 4900 |
Tip
No credentials? It still runs. With
BAZINESS_PLATFORM_ENABLED=falsethe Baziness UI disappears and winnings are kept locally. WithDEV_FAKE_BAZINESS_PAY=trueandBAZINESS_PAY_BASE_URL=http://localhost:4380/dev/baziness, purchases go through a built-in fake gateway with a «پرداخت موفق» button.
Testing tips
- Signing in: on this dev deployment, «ورود با حساب بازینس» accepts any phone number with the code
111111. No SMS is sent. - Replay the tutorial: use «بازنشانی این دستگاه» in the lobby footer. It clears local storage, so the next boot is a brand-new player.
- A second player in the same browser: add
?device=someone-elseto the URL. - Claiming as a guest: win a match without signing in. The claim answers
PLATFORM_NOT_LINKEDand the login sheet opens. After you sign in, the claim retries by itself. - A purchase you finish later: start a purchase, pay, close the game, and open it again. The lobby reconciles pending payments.
- Campaign links: open
…/example/?utm_source=wiki&utm_campaign=test. The address is clean after load, and the tags are stored on the account when it is created.
Project layout
baziness-example-rps/
├── .env.example every setting, documented
├── package.json "npm start" — no dependencies
├── server/
│ ├── index.js HTTP routes + static files (relative paths: works at / or /example/)
│ ├── env.js configuration (.env loader)
│ ├── platform.js platform client: auth, create-user, tokens, add-coin ← secret stays here
│ ├── pay.js Baziness Pay: buy URL, get_payment, verify_payment (form), consume
│ ├── services.js accounts & linking, match rules, rewards, starter pack, purchases
│ ├── store.js JSON-file store (swap for your database)
│ └── fake-pay.js local fake gateway (never in production)
└── public/
├── index.html, styles.css
├── assets/ art (hands, bot, pack, prize, Gita coin, ticket, Baziness logo)
└── js/
├── api.js first module: UTM capture, device id, fetch wrapper
├── platform.js BazinessPlatform: page URLs, messages, login, get-coin
├── sheet.js the swipe-down sheet
├── purchase.js Pay popup: tab opened in the click, verify on focus
├── ui.js DOM helpers, Persian numbers, toasts, modals
└── app.js splash, lobby, match, tutorialHosting it under a path
The client only uses relative URLs (api/…, assets/…), so the same files work at / or under a prefix. On the wiki's dev server, nginx strips /example/ and proxies to the Node process:
location = /example { return 301 /example/; }
location /example/ {
proxy_pass http://127.0.0.1:4380/; # trailing slash: /example/api/me → /api/me
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}