Skip to content

App Calls Not Ready on Base Build and Farcaster Developer Mode #4

@LuminaEnvision

Description

@LuminaEnvision

Issue Description

The Farcaster Mini App shows "Ready not called" warning in:

  • Base Build preview tool
  • Farcaster Developer Mode preview tool

Preview Tool URL:

https://farcaster.xyz/~/developers/mini-apps/preview?url=https%3A%2F%2Fminiapp.decleanup.net

Warning Message:

"Your app hasn't called sdk.actions.ready() yet. This may cause the splash screen to persist."

Expected Behavior

The app should call sdk.actions.ready() as soon as possible after the page loads, which:

  1. Hides the splash screen
  2. Shows the app content
  3. Signals to Farcaster that the app is ready

Current Implementation

ready() Call Locations

The app implements ready() calls in two layers for maximum reliability:

1. Primary Handler: FarcasterProvider

File: components/farcaster/FarcasterProvider.tsx
Wraps: All pages via app/layout.tsx

Implementation:

  • ✅ Calls ready() immediately if SDK is available
  • ✅ Retries up to 3 seconds (15 attempts × 200ms) if SDK not immediately available
  • ✅ Checks multiple SDK locations:
    • sdk (imported from @farcaster/miniapp-sdk)
    • window.farcaster.sdk
    • window.farcaster
    • window.__farcasterSDK
  • ✅ Prevents duplicate calls via window.__farcasterReadyCalled flag
  • ✅ Comprehensive error handling and logging

2. Safety Handler: useFarcasterReady Hook

File: lib/hooks/useFarcasterReady.ts
Used In:

  • app/page.tsx (home page)
  • app/cleanup/page.tsx (cleanup page)
  • app/profile/page.tsx (profile page)

Purpose: Defense in depth - ensures ready() is called even if primary handler misses it

Code Pattern

// Immediate call if SDK available
const immediateSdk = sdk || window.farcaster?.sdk || window.farcaster
if (immediateSdk?.actions?.ready) {
  await immediateSdk.actions.ready({ disableNativeGestures: true })
}

// Main call with retry logic
async function callReady() {
  // Wait for SDK (up to 3 seconds)
  let sdkInstance = sdk || window.farcaster?.sdk || window.farcaster
  let attempts = 0
  while (!sdkInstance && attempts < 15) {
    await new Promise(resolve => setTimeout(resolve, 200))
    sdkInstance = sdk || window.farcaster?.sdk || window.farcaster
    attempts++
  }
  
  // Call ready()
  if (sdkInstance?.actions?.ready) {
    await sdkInstance.actions.ready({ disableNativeGestures: true })
  }
}

Debugging Information

Console Logs to Check

When the app loads, you should see these logs in the browser console:

Expected Logs:

🚀 FarcasterProvider: Starting SDK initialization
⚡ SDK available immediately, calling ready() right away...
📞 About to call sdk.actions.ready()...
✅ sdk.actions.ready() called successfully - splash screen hidden
✅ Page-level sdk.actions.ready() called successfully

If Logs Are Missing:

  • SDK not available (not in Farcaster context)
  • Error preventing ready() call
  • Timing issue

SDK Detection

The app checks for SDK in this order:

  1. sdk (imported from @farcaster/miniapp-sdk)
  2. window.farcaster.sdk
  3. window.farcaster
  4. window.__farcasterSDK

Possible Causes

  1. SDK Not Injected in Preview Environment

    • Preview tool may inject SDK differently than production
    • SDK might not be available when ready() is called
  2. Timing Issue

    • ready() called before SDK is injected
    • Current retry logic waits up to 3 seconds
  3. Preview Tool Detection Logic

    • Preview tool may use different detection method
    • May not recognize ready() call if SDK source is different
  4. Error Being Silently Caught

    • Error in ready() call might be caught and logged but not recognized by preview tool

Files Involved

Core Implementation

  • components/farcaster/FarcasterProvider.tsx - Primary ready() handler
  • lib/hooks/useFarcasterReady.ts - Safety ready() handler
  • app/layout.tsx - Wraps app with FarcasterProvider

Pages Using Hook

  • app/page.tsx - Home page
  • app/cleanup/page.tsx - Cleanup submission page
  • app/profile/page.tsx - Profile/claim page

SDK Configuration

  • package.json - SDK version: @farcaster/miniapp-sdk@^0.2.1

Testing Steps

  1. Open Preview Tool:

    https://farcaster.xyz/~/developers/mini-apps/preview?url=https%3A%2F%2Fminiapp.decleanup.net
    
  2. Check Browser Console:

    • Open DevTools
    • Look for ready() call logs
    • Check for any errors
  3. Verify SDK Availability:

    // In browser console
    console.log('SDK check:', {
      imported: typeof sdk !== 'undefined',
      windowFarcaster: typeof window.farcaster !== 'undefined',
      windowFarcasterSdk: typeof window.farcaster?.sdk !== 'undefined',
      readyCalled: window.__farcasterReadyCalled
    })
  4. Check Manifest:

    curl -s https://miniapp.decleanup.net/.well-known/farcaster.json | jq .

Next Steps

  1. Verify SDK Injection:

    • Check if SDK is available in preview environment
    • Verify SDK injection timing
  2. Test Ready() Call:

    • Manually call sdk.actions.ready() in console
    • Check if preview tool recognizes it
  3. Compare with Working Apps:

    • Check other Mini Apps that work in preview tool
    • Compare ready() implementation

Related Documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions