Cover photo

🟦 How to Build your first Base Mini App


Why?

By: Deca

Date: 9th September 2025

The past two weekends I built two Base Mini Apps at the Aleph Hack (Aug 29-31, 2025) and ETHWarsaw (Sep 5-7, 2025) respectively.

Upon Evan and Clemens’ request, I made this mini report, which distills the actual developer experience into a clear setup flow with caveats, tips, and dev tools.

Shoutout to 🍋Limone , Caso and Bianc8 who gave me advice along the way.

Follow these three steps in order to build and test your Mini App effectively.


📚 Step 1: Choose your SDKs wisely

You’ll only need two libraries:

  • One for Mini App logic

  • One for wallet connection

Use one of these combos:

  1. farcaster/miniapp-sdk + coinbase/wallet-sdk ← works best right now

  2. coinbase/onchainkit + coinbase/wallet-sdk

🚫 Avoid farcaster/frame-sdk - it’s deprecated and will cause issues.

🚫Don’t use BOTH farcaster/miniapp-sdk AND coinbase/onchainkit - pick one of the two.

Once you've picked, move on to Step 2: manifest setup.

Docs:


🧾 Step 2: Fill out the Farcaster Manifest

Use the official manifest builder:
https://farcaster.xyz/~/developers/mini-apps/manifest?domain=yourdomain.com

Hint 1: You’ll need to generate and include five images at exact dimensions:

  • icon.png: 512×512 px

  • splash.png: 400×400 px

  • hero.png: 1200×630 px

  • screenshot1.png: 1200×800 px

  • screenshot2.png: 1200×800 px

If using Next.js, place them in your /public folder.

You can use Canva to easily create documents of the correct size.

Hint 2: To generate your manifest, do not do it via the CLI!

npx create-onchain --manifest

Instead, to get your farcaster header, payload and signature, do it directly from the Farcaster app on your phone:

  1. Open settings

  2. Open advanced tab > enable developer mode

  3. On developer tools > domains, enter your domain and generate manifest

  4. Copy and paste the values of header, payload, and signature you have in the clipboard in the related env variables

Once all fields are green in the manifest tool, you're ready to build out your Mini App’s functionality.


🧪 Step 3: Testing and Debugging - What Works and What Doesn’t

By default, simply opening your app at localhost:3000 and using browser devtools is not sufficient to test Farcaster-specific behavior.

Here’s why:

  • The SDK provides a context object (sdk.context) populated only when the Mini App is rendered within a Farcaster client - like Base App, Farcaster App, or the Farcaster manifest preview tool.

  • You can test your own user context this way (e.g. sdk.context.user) via the preview site.

  • But if your logic depends on other context, like the author of the cast (sdk.context.location.cast.author), the preview tool won’t work - it doesn’t simulate the full cast environment.

This means that to test all context fields fully, you must push your app to production, post a cast linking to it, and open it from Base App.

But:

  • Pushing to prod takes time - typically 1-5 minutes per change (depends on host like Vercel, your git branches setup, whether you test the build locally, etc.)

  • You can’t access browser logs from Base App - debugging becomes hard.


🧰 Two Workable Debugging Solutions

Option 1: Use a tunneling service (e.g. ngrok)

  • Lets you test locally using a public URL

  • Works with the Farcaster manifest preview site

  • Preserves full access to browser logs (e.g. console.log)

    Setup:

    • Terminal 1: npm run dev

    • Terminal 2: npm run ngrok (set up a script for this in your package.json file)

    • Paste the generated URL (e.g. random-id.ngrok.io) into the manifest preview tool (without https://)

Pros:

  • Fast feedback loop

  • Easy access to logs

Cons:

  • Can't access full cast context (e.g. sdk.context.location.cast.author)

  • You might run into extra issues if your app’s logic changes based on domain (e.g. different auth providers per subdomain)

  • Tunnels may need to be reset often...

    • Clear cookies, browser cache, and app state

    • Restart both servers (npm run dev AND npm run ngrok)

🔎 This setup is useful when you're building more complex flows.


Option 2: Use an in-app DebugPanel component

This is what I used:

  1. Create a component that logs and displays relevant data visually inside the Mini App
    if (debugMode) {
      return <DebugPanel data={sdk.context} logs={clientLogs} />;
    }

  2. Serve the app at yourdomain.com/?debug=true

  3. Post a cast containing this URL

  4. Open the cast in Base App → DebugPanel is visible

  5. Copy-paste DebugPanel logs from your phone to your laptop (possibly feed them to an LLM)

Real example I built with DebugPanel:
🔗 https://base.app/post/0x23f1a925729e1f3a2ae58b2385b8e72764925121

Pros:

Cons:

  • Slow feedback loop (prod push every change)

  • You must manually transfer logs to your dev machine

If this was useful, please Recast this guide!
Deca