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:
- Hides the splash screen
- Shows the app content
- 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:
sdk (imported from @farcaster/miniapp-sdk)
window.farcaster.sdk
window.farcaster
window.__farcasterSDK
Possible Causes
-
SDK Not Injected in Preview Environment
- Preview tool may inject SDK differently than production
- SDK might not be available when ready() is called
-
Timing Issue
- ready() called before SDK is injected
- Current retry logic waits up to 3 seconds
-
Preview Tool Detection Logic
- Preview tool may use different detection method
- May not recognize ready() call if SDK source is different
-
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
-
Open Preview Tool:
https://farcaster.xyz/~/developers/mini-apps/preview?url=https%3A%2F%2Fminiapp.decleanup.net
-
Check Browser Console:
- Open DevTools
- Look for ready() call logs
- Check for any errors
-
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
})
-
Check Manifest:
curl -s https://miniapp.decleanup.net/.well-known/farcaster.json | jq .
Next Steps
-
Verify SDK Injection:
- Check if SDK is available in preview environment
- Verify SDK injection timing
-
Test Ready() Call:
- Manually call
sdk.actions.ready() in console
- Check if preview tool recognizes it
-
Compare with Working Apps:
- Check other Mini Apps that work in preview tool
- Compare ready() implementation
Related Documentation
Issue Description
The Farcaster Mini App shows "Ready not called" warning in:
Preview Tool URL:
Warning Message:
Expected Behavior
The app should call
sdk.actions.ready()as soon as possible after the page loads, which:Current Implementation
ready() Call Locations
The app implements
ready()calls in two layers for maximum reliability:1. Primary Handler:
FarcasterProviderFile:
components/farcaster/FarcasterProvider.tsxWraps: All pages via
app/layout.tsxImplementation:
ready()immediately if SDK is availablesdk(imported from@farcaster/miniapp-sdk)window.farcaster.sdkwindow.farcasterwindow.__farcasterSDKwindow.__farcasterReadyCalledflag2. Safety Handler:
useFarcasterReadyHookFile:
lib/hooks/useFarcasterReady.tsUsed 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 itCode Pattern
Debugging Information
Console Logs to Check
When the app loads, you should see these logs in the browser console:
Expected Logs:
If Logs Are Missing:
SDK Detection
The app checks for SDK in this order:
sdk(imported from@farcaster/miniapp-sdk)window.farcaster.sdkwindow.farcasterwindow.__farcasterSDKPossible Causes
SDK Not Injected in Preview Environment
Timing Issue
Preview Tool Detection Logic
Error Being Silently Caught
Files Involved
Core Implementation
components/farcaster/FarcasterProvider.tsx- Primary ready() handlerlib/hooks/useFarcasterReady.ts- Safety ready() handlerapp/layout.tsx- Wraps app with FarcasterProviderPages Using Hook
app/page.tsx- Home pageapp/cleanup/page.tsx- Cleanup submission pageapp/profile/page.tsx- Profile/claim pageSDK Configuration
package.json- SDK version:@farcaster/miniapp-sdk@^0.2.1Testing Steps
Open Preview Tool:
Check Browser Console:
Verify SDK Availability:
Check Manifest:
Next Steps
Verify SDK Injection:
Test Ready() Call:
sdk.actions.ready()in consoleCompare with Working Apps:
Related Documentation