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>
  );
};
Provide your users with direct access to Mini Apps, group messages, and DMs using our deeplinking schema.

Mini Apps

Launch your mini app directly from external sources like websites, QR codes, or other applications.
index.html
<a href="cbwallet://miniapp?url=${MINI_APP_URL}">
  Launch Mini App
</a>

Group Messages

Navigate users directly to a specific group chat conversation.
DeeplinkButton.tsx
<button 
  onClick={() => openUrl(`cbwallet://messaging/${conversationID}`)} 
>
  Join Members Only Chat
</button>

Direct Messages (Users or Agents)

Start a private conversation with a specific user or agent.
DeeplinkDM.tsx
<button 
  onClick={() => openUrl(`cbwallet://messaging/${address}`)} 
>
  Send Direct Message
</button>

Schema

Group Message Parameters

conversationID
string
required
The unique identifier for an XMTP group conversation.

Direct Message Parameters

address
string
required
The 0x address of the user or agent you want to chat with (in hex format, e.g., 0xabc...1234).