Cover photo

My First On-Chain Experience on Base

The Wall Base: Technical Architecture of a Social Mini App on Base App

On December 18, 2025, Base officially launched its Mini App SDK, but I got access a bit earlier during the beta phase.
That immediately raised a question for me:

Can I build a mini app where every user action leaves an on-chain footprint, while still keeping a fast, Web2-like UX?

That’s how The Wall Base was born — a social mini app running inside Farcaster / Base App.

What is The Wall Base?

The Wall Base consists of:

  • a social feed of posts;

  • NFT minting for each post;

  • a marketplace tovery action;

  • an off-chain raffle that pays the pool to a random NFT owner.

This is my first experience with Base SDK and on-chain development, and in this article I share what I learned and what I struggled with.

If you have suggestions on how something could be done better or simpler — feel free to leave a comment. I’d really appreciate feedback.

Architecture Overview

Tech Stack

  • Next.js 14 (App Router) — server components, layouts

  • TypeScript

  • Tailwind CSS

  • Zustand for local state

  • viem and wagmi for on-chain interactions

App Router inside Base App: Important Constraints

Inside Base App, you cannot rely on standard web assumptions:

  • full SSR is not available (part of the environment is restricted);

  • unstable fetch calls (some origins are blocked);

  • system navigation (window.location) is not allowed — everything must stay inside the mini-app sandbox.

Base App is very friendly to Vercel, so deployment was straightforward.

Critical rules:

  • use

export const dynamic = "force-dynamic";
  • when UI must update on every request;

  • avoid window-dependent logic in server components;

  • keep heavy API logic inside /api/* routes.

Backend Layer: API, KV, and Off-Chain Data

Posts live off-chain — otherwise the mini app would be painfully slow when loading the feed.

Storage

  • Vercel KV — main production storage

  • local JSON file — development mode

Data Placement

DataWhereWhyPostsKVFast, almost freeReactionsKVLow trafficWinners historyKVNo need to be on-chainPost ↔️ NFT mappingForumNFT contractMost valuable data

Smart Contracts: ForumNFT and Marketplace on Base Mainnet

All production contracts of The Wall Base are deployed on Base mainnet.

What is Base?

Base is an Ethereum Layer 2 rollup developed by Coinbase, built on the OP Stack.

This gives us:

  • full EVM compatibility (Solidity, Hardhat, Foundry);

  • significantly lower fees than Ethereum mainnet;

  • fast transaction finality;

  • native integration with Coinbase and Base App.

For mini apps, Base is almost ideal: cheap gas, fast UX, Ethereum-level security.

Why Development Was Done on Base Sepolia

Even though production runs on Base mainnet, all development and testing happened on Base Sepolia, the Base testnet.

Reasons are straightforward:

  • contract deployment costs real ETH;

  • every logic mistake costs money;

  • testnet behavior mirrors mainnet almost exactly.

Deploying a simple ERC-721 contract on Base mainnet typically costs $5–10, depending on complexity and network load.

So all logic — from minting to prize pool — was fully tested on testnet first.

How Contract Deployment Actually Works

This is something beginners often misunderstand.

A smart contract is not deployed from an IDE.

Deployment flow:

  • written locally (Solidity);

  • compiled locally (Hardhat);

  • sent to the network via an EVM wallet.

You need:

  • a wallet private key;

  • a network RPC endpoint;

  • ETH balance (testnet or mainnet).

Deployment is just a regular transaction that sends contract bytecode to the network.

npx hardhat run scripts/deploy.js --network base

Test ETH for Base Sepolia

To use Base Sepolia, you need test ETH.

I used the Alchemy faucet:
https://www.alchemy.com/faucets/base-sepolia

Important caveat: it usually works only for wallets with mainnet activity.

I couldn’t find a faucet that reliably sends ETH to brand-new wallets.
An alternative is bridging ETH from Ethereum testnet to Base Sepolia using testnet bridges — these exist, but for beginners it’s another quest.

If you’re stuck — ask in the comments, I’ll try to point to currently working bridges.

On-Chain vs Off-Chain Separation

The project clearly separates two layers.

On-chain

  • smart contracts (ForumNFT, Marketplace);

  • funds custody;

  • NFT ownership;

  • prize pool.

Off-chain

  • frontend (Next.js);

  • post storage;

  • winner selection;

  • UI/UX;

  • RPC interaction.

Contracts are deployed independently from the frontend and communicate via RPC.

Moving from Base Sepolia to Base Mainnet

Once contracts were fully tested on Base Sepolia, moving to mainnet was simple:

  1. Deploy contracts to Base mainnet

  2. Get new contract addresses

  3. Update frontend configuration

# beforeNEXT_PUBLIC_BASE_RPC_URL=https://sepolia.base.orgNEXT_PUBLIC_NFT_CONTRACT_ADDRESS=0xTestAddress
# afterNEXT_PUBLIC_BASE_RPC_URL=https://mainnet.base.orgNEXT_PUBLIC_NFT_CONTRACT_ADDRESS=0xMainnetAddress

Thanks to EVM compatibility, contract behavior is identical — although the migration still had pitfalls, which I’ll describe below.

ForumNFT: Custom ERC-721

Key features:

  • minting at a fixed price;

  • 50% → rewardPool, 50% → ownerBalance;

  • mappings between posts and tokens;

  • service values:

  • nextTokenId

  • MIN_REWARD_RESERVE = 0.0001 ether

adminSetNextTokenId

function adminSetNextTokenId(uint256 value)    external    onlyOwner

Why it exists:

During beta testing, mini apps generate many temporary posts.
I periodically burned the entire collection and reset state — which required resetting nextTokenId.

⚠️ If called without a full burn → token ID collisions are possible.

Marketplace

  • NFT listings with price

  • purchases with commission

  • part of the fee goes to rewardPool

  • all trades are standard ETH transactions (cheap on Base)

Prize Pool Logic

The pool is funded by:

minting (50%)+ marketplace fees+ ownerBalance (manual top-ups)

A 0.0001 ETH reserve is always preserved — otherwise the pool could hit zero and break ETH/USD price queries.

Why the Raffle Is Off-Chain

Base Mini Apps:

  • don’t support on-chain randomness;

  • have no built-in VRF;

  • can’t force users to wait for Chainlink callbacks.

Implementation:

  • /api/reward/draw selects a random post (PRNG + filters);

  • sends payPrize(winner, tokenId, amount) transaction;

  • stores winner history in KV.

Farcaster Mini App SDK Integration

Used methods:

  • sdk.actions.openUrl() — open user profil

  • sdk.actions.openPage() — internal navigation

  • sdk.ready() — required before rendering UI

Constraints:

  • no window.location navigation;

  • links must be whitelisted in the manifest;

  • only base.app and farcaster.xyz links are clickable.

RPC: Why Nothing Worked on Mainnet at First

This was one of the most painful issues.

Marketplace NFTs wouldn’t load, prize pool wouldn’t update.
The root cause was public RPC throughput limits.

What I tried initially

  • https://mainnet.base.org

  • https://developer-access-mainnet.base.org

  • shared Infura / Alchemy endpoints

Problems:

  • 4–7s timeouts on reads;

  • unstable viem/wagmi responses;

  • random execution reverted;

  • eth_call worked while eth_sendTransaction failed;

  • additional rate limits inside Base App WebView.

For mini apps, this is fatal.

Solution: Private RPC from Coinbase Developer Platform

Normally private RPCs are paid, but Coinbase Developer Platform provided them for free, plus:

  • $500 in USDC credits

  • gas fee rebates for app users

Private endpoint:

https://base-mainnet.g.alchemy.com/v2/<private_key>

Used as:

NEXT_PUBLIC_BASE_RPC_URL=<private_rpc>

Results:

  • response time dropped to 90–120 ms;

  • no missed eth_call;

  • stable mobile behavior;

  • marketplace loaded consistently;

  • prize pool updates became reliable.

Mini apps are extremely latency-sensitive — the difference was dramatic.

Admin Panel: Technical Details

Admin features:

  • view ownerBalance;

  • manage fees;

  • manual prize draw;

  • reset token counter;

  • hide posts (moderation);

  • mark featured posts (highlight key ecosystem users).

Security:

  • frontend checks ADMIN_ADDRESS;

  • real protection is on-chain via onlyOwner.

Mini App Manifest and Assets

File: public/.well-known/farcaster.json

{  "name": "The Wall Base",  "description": "Farcaster mini-app: NFT posts, marketplace, prize pool",  "iconUrl": "/200_00000.png",  "splashUrl": "/1024_00000.png",  "developer": "base.app/<username>"}

For development, noindex=true is required — otherwise the manifest gets cached.

Common Issues and Fixes

1. wagmi + mini app environment

You cannot rely on window.ethereum. Use the Base App connector.

2. BigInt in React state

BigInt inside JSON can crash WebView. Serialize to string.

3. ETH → USD rate

CoinMarketCap rate-limits aggressively. Cache for ~30 minutes.

Deployment

Contracts (Hardhat)

npx hardhat run scripts/deploy.js --network basenpx hardhat verify --network base <ForumNFT>

Frontend (Vercel)

  • root: /miniapp

  • build: npm run build

  • env: private RPC + contract addresses

Conclusion

What started as an experiment became a real product:

  • a social network — where every post is an NFT;

  • a marketplace — embedded directly into a mini app;

  • a prize pool — fully on-chain;

  • Base App integration — feels like a native mobile app.

Base Mini Apps open a huge opportunity for hybrid dApps.

If you’re interested in building on Base App, check the links below.

My baseapp account — a fundamental analysis of coins and earnings on AirDrops. I buy cryptocurrency on Bybit