Most crypto apps lose the user before the first useful screen. Not because of the product — because of the paperwork.
Install a wallet. Write these twelve words on paper. Now go acquire the network's native token so you can pay fees. Oh, and to get that you'll need an exchange, which will ask for your ID.
That's four walls, and the person still hasn't done anything. By the time they reach the product they've spent all their patience on admin.
A few months ago I built Frontle, a daily geography game with real stablecoin prizes. It took third place at Celo's Colombia hackathon and is now under review for publication inside MiniPay. The interesting part wasn't the game — it was discovering that nearly all of those walls are optional.
Changing the question
The usual question is "how do I explain wallets to the user?"
The right question is "where are the people who already have one?"
There are hundreds of millions of people with a working crypto wallet who don't think of it that way: it's inside an app they already use for something else. MiniPay, Opera's wallet, has over 16 million users, many of them in markets where a stablecoin isn't speculation but the practical way to hold dollars.
Those people don't need anything explained. They already have a balance. What they need is for your app to work in there.
The steps
This is what I'd do again, in order.
1. Pick the chain for the audience, not the hype
The criterion isn't TPS or which chain is trending. It's: where are the people this is useful for? and what does a transaction cost?
If your product charges ten cents, a network where fees cost eighty cents isn't a poor technical choice — it's an impossible product. I picked Celo because fees are fractions of a cent and because MiniPay — my distribution — lives there.
2. Delete the wallet step
Inside MiniPay the wallet connects itself. You read the native window.ethereum and you're done:
// No connection library, no modal, no "Connect Wallet" button.
// Inside MiniPay's WebView the account is already available.
const [account] = await window.ethereum.request({
method: 'eth_requestAccounts',
})
No WalletConnect, no wallet picker, none of that modal with twelve logos that means nothing to anyone. For people arriving from outside I kept Privy as a fallback, but the main path has no connection step at all.
3. Abstract the gas
This is the trick that changes the experience most and that the fewest people use.
Normally, to spend your digital dollars you also need to hold the network's native token. It's as if paying by card required carrying separate coins for the terminal.
Celo solves this with CIP-64: the fee is paid in the same token you're transacting with. The user pays in USDT, gets charged in USDT, and never sees CELO or learns that it exists.
If your chain supports it, use it. If it doesn't, seriously consider switching: it's the difference between a product for people who already know and a product for anyone.
4. Put only the money on-chain
The beginner temptation is to put everything on-chain out of ideological purity. It's expensive, slow, and buys you nothing.
The line I drew:
| On-chain | Off-chain |
|---|---|
| Payments | Game logic |
| Pot accumulation | Daily ranking |
| Winner records | Profiles and stats |
| Prize withdrawal | Translations, UI |
Frontle's contract does four things: payAttempt, buyHint, rollDay, claim. Nothing else. Everything that changes often and isn't money lives in Postgres, where reading it costs microseconds instead of cents.
5. Bridge the two with an oracle, not with trust
Here's the real problem, and the one that decides whether your app is serious.
The ranking sits in a database I control. The prize can't depend on that: nobody should have to trust my Postgres to get paid.
The answer is to separate who computes from who holds the truth:
- A scheduled job reads the ranking when the day closes.
- That job writes the winners into the contract, through a function only the operator can call.
- From then on, the user withdraws straight from the contract. I'm no longer in the middle.
In Frontle that's an Edge Function calling rollDay(day, winners) at 00:10 UTC. Each winner then calls claim(day, level) themselves.
Postgres proposes, the chain disposes. If your database can change who gets paid, you don't have a protocol — you have a promise.
6. Make the first action free
The first attempt each day in Frontle costs nothing. You play, you understand the game, you see the accumulated pot, and only then do you decide whether you want a retry.
This isn't generosity, it's funnel design. Someone paying ten cents for a hint already understands what they're buying. Someone who has to pay before understanding simply leaves.
7. Charge in cents
Frontle's prices are 0.05 and 0.10 USDT. There's a concrete psychological reason: a first crypto transaction of ten cents isn't scary.
If your first interaction with a chain is moving fifty dollars, the cost of getting it wrong feels enormous and people freeze. At ten cents, you just try it. And once you've tried it, you know it works.
That's where people genuinely get familiar with the currency: not by reading an explainer thread, but by making one tiny transaction that goes fine.
8. Make the earnings visible
If you promise people can earn, show it with real, verifiable numbers. Frontle has a public /stats page that reads straight from the chain: what's in the pot, who won, how much was paid out.
The pot is built from 80% of revenue; 20% sustains the protocol. That ratio lives in the contract, not on the landing page. Anyone can check it.
What I learned about adoption
For years the industry has tried to get people to understand crypto. The order is backwards.
People don't want to understand a blockchain, the same way they don't want to understand SMTP to send an email. They want to play, to get paid, to send someone money. Familiarity comes after use, not before it.
The people playing Frontle didn't learn what a stablecoin is by reading. They learned it by winning forty cents on a Tuesday and seeing that they could spend it.
Where it stands
Frontle is in production at frontle.earth, with real users and real money, competing in Proof of Ship — Celo's monthly builder program — and under review to enter the MiniPay catalog.
The code is open: github.com/davidndeah/frontle. If you're building something similar, the part worth reading is supabase/functions/close-day — that's the oracle pattern, and it's the only genuinely hard thing in any of this.
