Tap to earn money. Every tap adds $0.01 to your balance (spendable cash) and your net worth (total ever earned). Spend the balance on upgrades, boosters, and new payment methods (Piggy Bank, Wallet, QR DuitSekarang, Debit Card, Bank, Vault). Auto-investment keeps earning while you're away. Net worth goes on a global leaderboard.
The important part: the client has no authority. Balance, net worth, upgrades, and level all live in Supabase and are only ever changed by server-side functions that validate and rate-limit every action. Editing anything in devtools changes what you see, never what you have. (See Security.)
index.html the page shell
styles/main.css all styling
src/ front-end ES modules (no bundler needed)
config.js <-- YOU EDIT THIS: Supabase URL + anon key
supabase.js shared client
auth.js sign up / sign in / session
api.js the only file that calls the server functions
store.js tiny reactive state store
engine.js WASM bridge, canvas render loop, click batching
sky.js falling cash drops
hud.js shop.js leaderboard.js idle.js UI modules
main.js entry point
wasm/
engine.cpp the C++ visual engine (compile this)
game.js game.wasm GENERATED by the build — do not edit
db/ SQL, run in order in the Supabase SQL editor
01_schema.sql 02_config_data.sql 03_rls.sql 04_functions.sql
05_leaderboard.sql 06_feedback.sql
reset_players.sql admin: wipe all player PROGRESS (keeps accounts)
wipe_all_users.sql admin: delete all accounts and their data
assets/ images (method-*.png objects, coin, background, icons, logo)
design/ optional sprite-generation prompts
The emsdk/ toolchain is already in this repo. If you ever need a fresh copy:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latestYou must activate emsdk in every new terminal — that's what puts emcc on
your PATH. If emcc says "command not found", you skipped this step.
Windows (PowerShell) — activate, then run the build as a single line
(the \ line-continuations further down are Bash-only and break in PowerShell):
.\emsdk\emsdk_env.ps1
emcc wasm/engine.cpp -O2 -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME=createGame -s "EXPORTED_FUNCTIONS=['_engine_init','_engine_reconcile','_engine_tap','_engine_tick','_engine_display_cash','_engine_pulse','_engine_method_index','_engine_coin_count','_engine_coin_x','_engine_coin_y','_engine_coin_life']" -s "EXPORTED_RUNTIME_METHODS=['cwrap']" -o wasm/game.js(Old Command Prompt: use emsdk\emsdk_env.bat instead of the .ps1.)
macOS / Linux (Bash):
source ./emsdk/emsdk_env.sh
emcc wasm/engine.cpp -O2 \
-s WASM=1 \
-s MODULARIZE=1 \
-s EXPORT_NAME=createGame \
-s "EXPORTED_FUNCTIONS=['_engine_init','_engine_reconcile','_engine_tap','_engine_tick','_engine_display_cash','_engine_pulse','_engine_method_index','_engine_coin_count','_engine_coin_x','_engine_coin_y','_engine_coin_life']" \
-s "EXPORTED_RUNTIME_METHODS=['cwrap']" \
-o wasm/game.jsThis produces wasm/game.js and wasm/game.wasm. Re-run the emcc line any
time you change wasm/engine.cpp. The first build is slow (Emscripten compiles
and caches its system libraries once); later builds are quick.
- Create a project (free tier is fine).
- SQL Editor → run these files in order, each as a new query:
db/01_schema.sql→02_config_data.sql→03_rls.sql→04_functions.sql→05_leaderboard.sql→06_feedback.sql. - Authentication → Providers → Email: make sure Email is enabled. For a quick start you can turn off "Confirm email" so sign-ups log in instantly; leave it on for a real deploy (users then confirm via email before signing in).
- Project Settings → API: copy the Project URL and the anon public
key into
src/config.js.
The signup trigger creates each player's profile and starting state automatically (everyone starts at the Piggy Bank).
Admin scripts (db/reset_players.sql, db/wipe_all_users.sql) are optional
maintenance tools — run them by hand only when you want to reset progress or
clear accounts. They are destructive and have no undo.
WASM won't load from a file:// path, so serve the folder:
python3 -m http.server 8000
# open http://localhost:8000Create an account, and start tapping.
These are static files (index.html, styles/, src/, wasm/, assets/)
plus your Supabase project. Drop the folder on any static host:
- Vercel / Netlify / Cloudflare Pages: drag the folder in, or connect the repo.
- Point your subdomain at it via the CNAME the host gives you.
One requirement: wasm/game.wasm must be served as application/wasm. Vercel,
Netlify, and Cloudflare Pages all do this automatically.
The design in one line: the client sends actions, never values.
- No direct writes. RLS (
db/03_rls.sql) lets a user read only their own row and gives no insert/update/delete on balance/net worth. The only way those change is through theSECURITY DEFINERfunctions indb/04_functions.sql. - Server-authoritative economy.
do_click(n)credits at mostelapsed_seconds × 20clicks using the server clock, so autoclickers and "claim a huge number" attempts are both capped to human speed. Purchases recompute their price server-side and run in one atomic, row-locked transaction, so parallel requests can't double-spend. - Money model. Earning adds the same amount to both
net_worth(total earned, never drops, the leaderboard score) andbalance(spendable). Buying deducts frombalanceonly, so spending never hurts your rank. - Idle income uses the server clock only (
now() - last_idle_at, capped at 8h), so lying about time away earns nothing extra. Cash drops pay a fixed, cooldown-limited reward server-side. - The anon key is public on purpose. It only grants what RLS allows. The
secret
service_rolekey is never in the frontend. - The C++/WASM code has no authority. It runs in the browser and only drives visuals and an optimistic on-screen number; the server value always wins.
Honest limit: a human-speed autoclicker or a dedicated bot can still farm at a human rate, and someone can make multiple accounts. What's fully closed is the "edit a variable to set balance = 999999" class of cheat.
- Balance / prices: edit the numbers in
db/02_config_data.sql(method costs, multipliers, upgrade base costs, booster durations) and re-run that one file. Server constants (click cap, base tap, idle cap, cash-drop reward) are commented at the top ofdb/04_functions.sql. - Look: colors are CSS variables at the top of
styles/main.css; per-method glow colors are insrc/config.js; the wood texture is the--woodvariable. - Sprites: optional — see
design/for ready-to-use generation prompts. - Donations: a Buy Me a Coffee button is in
index.html(search "Buy Me a Coffee"). ReplaceYOUR_USERNAMEin the link with your handle.