Skip to main content

Overview

Use the functions provided by the @farcaster/miniapp-sdk to navigate users from your mini app throughout the Base app and to external links with a native user experience.
# Mini App Navigation Pattern Migration

## Context
I'm building a Farcaster Mini App on Base. Mini Apps must use official SDK functions for all navigation and external interactions to ensure cross-client compatibility.

## Your Task
Review this file and refactor any incorrect navigation patterns to use the correct SDK actions.

## Incorrect Patterns to Fix

### Don't Use:
- Direct HTML links: `<a href="">`, `<Link href="">`
- Window navigation: `window.open()`
- Static URLs or deeplinks to Farcaster
- Client-specific URLs (like Warpcast URLs)
- Composer intent URLs: `https://farcaster.com/~/compose?text=...`
- Direct cast URLs for viewing

## Correct SDK Actions

### For Farcaster SDK (`@farcaster/miniapp-sdk`)
1. **External Links:** Use `sdk.actions.openUrl(url)`
2. **Create Posts:** Use `sdk.actions.composeCast({ text, embeds })`
3. **View Casts:** Use `sdk.actions.viewCast(castUrl)`

### For MiniKit (`@coinbase/onchainkit/minikit`)
1. **External Links:** Use `useOpenUrl()` hook
2. **Create Posts:** Use `useComposeCast()` hook
3. **View Casts:** Use `useViewCast()` hook

## Migration Examples

// BEFORE (Incorrect)
<a href="https://example.com">Visit Site</a>
<button onClick={() => window.open('https://example.com')}>Open</button>

// AFTER (Correct - Farcaster SDK)
import { sdk } from '@farcaster/miniapp-sdk';
<button onClick={() => sdk.actions.openUrl('https://example.com')}>Visit Site</button>

// AFTER (Correct - MiniKit)
import { useOpenUrl } from '@coinbase/onchainkit/minikit';
const openUrl = useOpenUrl();
<button onClick={() => openUrl('https://example.com')}>Visit Site</button>

// BEFORE (Incorrect)
window.open('https://farcaster.com/~/compose?text=Check this out!')

// AFTER (Correct - Farcaster SDK)
sdk.actions.composeCast({
  text: 'Check this out!',
  embeds: [window.location.href]
})

// AFTER (Correct - MiniKit)
const { composeCast } = useComposeCast();
composeCast({
  text: 'Check this out!',
  embeds: [window.location.href]
})

External Navigation

Opening External URLs

  • Farcaster SDK
  • MiniKit
Use sdk.actions.openUrl() to safely open external websites in the client’s in-app browser:
App.tsx
import { sdk } from '@farcaster/miniapp-sdk';

// Correct: Use SDK action
const openExternalSite = () => {
  sdk.actions.openUrl('https://example.com');
};

// Incorrect: Direct HTML link
// <a href="https://example.com">Visit Site</a>

Composing Casts

  • Farcaster SDK
  • MiniKit
Use sdk.actions.composeCast() instead of composer intent URLs:
App.tsx
import { sdk } from '@farcaster/miniapp-sdk';

// Correct: Use SDK action
const shareContent = () => {
  sdk.actions.composeCast({
    text: 'Check out this Mini App!',
    embeds: ['https://yourminiapp.com']
  });
};

// Incorrect: Composer intent URLs
// window.open('https://farcaster.com/~/compose?text=...')

Viewing Casts

  • Farcaster SDK
  • MiniKit
Use sdk.actions.viewCast() instead of cast intent URLs:
App.tsx
import { sdk } from '@farcaster/miniapp-sdk';

// Correct: Use SDK action
const viewCast = () => {
  sdk.actions.viewCast('https://base.app/post/0xffdec7c879aad726b5400d22ec8a89aaff6e0737');
};

Conditional Navigation

If your mini app can be opened in the browser, implement conditional navigation to handle cases where mini app-specific functions (e.g., Compose Cast) are unavailable.
ConditionalNavigation.tsx
import { sdk } from 'farcaster/miniapp-sdk';

const ConditionalNavigation = () => {
  const context = sdk.context;
  
  const handleNavigation = () => {
    // Adapt behavior based on client capabilities
    if (context.client.clientFid) {
      sdk.actions.openUrl('https://app-specific-url.com');
    } else {
      // Fallback for other clients
      window.open('https://fallback-url.com', '_blank');
    }
  };

  return (
    <button onClick={handleNavigation}>
      Open External Resource
    </button>
  );
};
I