Loading...
Loading...
Converts Farcaster miniapp SDK projects into regular Base/web apps. Starts with an interactive quiz to choose between the default regular-app conversion and a narrowly isolated Farcaster surface when something truly needs to remain separate. Handles wagmi connectors, providers, auth, SDK actions, manifest routes, meta tags, dependencies, and read-only preservation.
npx skill4agent add base/skills convert-farcaster-miniapp-to-app| Path | Name | Who it's for | What happens |
|---|---|---|---|
| A | Regular App Default | Most projects | Strip Farcaster Mini App coupling and become a normal Base/web app |
| B | Isolated Farcaster Surface | The app still needs a small Farcaster-specific area | Convert the main app into a normal app, then keep only a separate Farcaster route/page for the remaining functionality |
Path Bpackage.jsonnextvitereact-scripts@remix-run/*dependenciesdevDependencies.ts.tsx.js.jsxsdk.actions.*sdk.quickAuthsdk.context.well-known/farcaster.jsonfarcasterMiniAppminiAppConnector@farcaster/@neynar/api.neynar.comapp/farcaster/pages/farcaster/openMiniAppsdk.context.clientBased on my scan, your project has [X] files using the Farcaster SDK with [summary of what is used].Which outcome do you want?
- (a) Regular app everywhere — remove Farcaster-specific behavior and just keep a normal Base/web app
- (b) Regular app first, plus a separate Farcaster area — keep the main app clean, but preserve a small isolated route/page if really needed
How deeply is the Mini App SDK used today?
- (a) Minimal — mostly
and a few helperssdk.actions.ready()- (b) Moderate — some
,context, profile links, or conditionalopenUrllogicisInMiniApp- (c) Heavy — auth, wallet connector, notifications, compose flows, or host-specific behavior
What is the smallest Farcaster feature set you actually need to preserve?
- (a) Read-only only — profile or cast display, links out to Farcaster profiles, maybe a small social page
- (b) Some Farcaster-specific interactions — there is a separate page/path that still needs more than read-only behavior
- (c) Not sure — analyze what is isolated already and recommend the smallest keep-surface possible
Does the project already have an isolated Farcaster-only route/page or integration that you want to keep as-is if possible?
- (a) Yes — preserve only that isolated surface
- (b) No — prefer removing it unless there is a very strong reason to keep it
After conversion, what should the main app use for authentication?
- (a) SIWE — wallet-based auth for the regular app
- (b) Existing non-Farcaster auth — keep whatever normal web auth already exists
- (c) No auth — remove auth entirely
| Desired outcome | Typical result |
|---|---|
| Path A — Regular App Default |
| Path B — Isolated Farcaster Surface |
Path BPath ABased on your answers, I'll use Path [X]: [Name]. This will [one-sentence description]. I'll now do a detailed analysis of your project.
package.jsonnextvitereact-scripts@remix-run/*@farcaster/miniapp-sdk@farcaster/miniapp-core@farcaster/miniapp-wagmi-connector@farcaster/frame-sdk@farcaster/frame-wagmi-connector@farcaster/quick-auth@farcaster/auth-kit@neynar/*.ts.tsx.js.jsx@farcaster/miniapp-sdk
@farcaster/miniapp-core
@farcaster/miniapp-wagmi-connector
@farcaster/frame-sdk
@farcaster/frame-wagmi-connector
@farcaster/quick-auth
@farcaster/auth-kit
@neynar/sdk.actions.ready
sdk.actions.openUrl
sdk.actions.close
sdk.actions.composeCast
sdk.actions.addMiniApp
sdk.actions.requestWalletAddress
sdk.actions.viewProfile
sdk.actions.viewToken
sdk.actions.sendToken
sdk.actions.swapToken
sdk.actions.signIn
sdk.actions.setPrimaryButton
sdk.actions.openMiniApp
sdk.quickAuth
sdk.context
sdk.isInMiniApp
sdk.getCapabilities
sdk.haptics
sdk.back
sdk.walletfarcasterMiniApp()
miniAppConnector()
farcasterFrame()
MiniAppProvider
MiniAppContext
useMiniApp
useMiniAppContext.well-known/farcaster.json
fc:miniapp
fc:frameNEYNAR_API_KEY
NEXT_PUBLIC_NEYNAR_CLIENT_ID
FARCASTER_
FC_coinbaseWalletsiweconnectkitrainbowkit@coinbase/onchainkitapp/farcaster/*## Conversion Analysis — Path [X]: [Name]
**Framework:** [detected]
**Farcaster packages:** [list]
**Files with Farcaster code:** [count]
### Wagmi Connector
- File: [path]
- Current connector: [farcasterMiniApp / miniAppConnector / farcasterFrame / none]
- Other connectors: [list]
- Action: [replace with coinbaseWallet / leave existing wallet setup / remove only]
### MiniApp Provider
- File: [path]
- Pattern: [simple / complex]
- Consumers: [files importing from this]
- Action: [stub / remove / isolate]
### SDK Action Calls
[list each: file, what it does, action]
### Manifest & Meta
- Manifest route: [path or N/A]
- Meta tags: [file or N/A]### Main App Outcome
- Action: remove Farcaster-specific UI and flows from the main app entirely
### Authentication
- Quick Auth used: [yes/no, file]
- Action: replace with SIWE / keep existing non-Farcaster auth / remove
### Existing Neynar Usage
- Package or files: [list or N/A]
- Action: remove entirely unless the user later re-scopes to Path B
### Environment Variables
[list all FC/Neynar vars that will be removed]### Main App Outcome
- Action: convert the main app into a normal web app first
### Isolated Farcaster Surface
- Route/page to keep: [path or proposed path]
- Scope: [read-only / mixed / host-specific]
- Recommended target scope: [prefer read-only / quarantine existing behavior / remove]
### Authentication
- Quick Auth used: [yes/no, file]
- Main app action: replace with SIWE / keep existing non-Farcaster auth / remove
- Isolated Farcaster surface action: [remove auth coupling / preserve existing isolated flow only if explicitly requested]
### Existing Neynar Usage
- Package or files: [list or N/A]
- Action: [remove / keep only inside isolated surface]
### Environment Variables
- Remove from main app: [FC_*, FARCASTER_*, etc.]
- Keep only if isolated surface truly still needs them: [NEYNAR_API_KEY, etc. or N/A]### Potential Issues
- [ ] FID used as database primary key
- [ ] Farcaster colors in tailwind config
- [ ] `isInMiniApp` branches with unique else logic
- [ ] Components only meaningful inside Farcaster
- [ ] Farcaster code mixed into shared providers or root layoutDoes this analysis look correct? Ready to proceed with conversion?
Path Blib/wagmi.tsconfig/wagmi.tsproviders/wagmi-provider.tsxfarcasterMiniAppminiAppConnector@farcaster/miniapp-wagmi-connectorfarcasterMiniApp()miniAppConnector()connectorsimport { coinbaseWallet } from "wagmi/connectors";
coinbaseWallet({ appName: "<app name>" })coinbaseWallet'use client'
import React, { createContext, useContext, useMemo } from "react";
interface MiniAppContextType {
context: undefined;
ready: boolean;
isInMiniApp: boolean;
}
const MiniAppContext = createContext<MiniAppContextType | undefined>(undefined);
export function useMiniAppContext() {
const context = useContext(MiniAppContext);
if (context === undefined) {
throw new Error("useMiniAppContext must be used within a MiniAppProvider");
}
return context;
}
export default function MiniAppProvider({ children }: { children: React.ReactNode }) {
const value = useMemo(
() => ({
context: undefined,
ready: true,
isInMiniApp: false,
}),
[]
);
return <MiniAppContext.Provider value={value}>{children}</MiniAppContext.Provider>;
}Path Bsdk.quickAuth.getToken()useSignIn.tsimport sdk from "@farcaster/miniapp-sdk"sdk.quickAuth.getToken()useAccount()siweuseSignMessage()app/api/auth/sign-in/route.ts@farcaster/quick-authsiweviem| Original | Replacement |
|---|---|
| Remove entirely |
| |
| |
| Remove from the main app |
| Remove call and UI |
| Remove; wagmi handles wallet access |
| |
| |
| Replace with wagmi flow if the feature matters, otherwise remove |
| Remove call and UI unless there is a real app-specific swap feature outside Farcaster |
| Remove; auth handled by normal web auth |
| Remove entirely |
| Remove from the main app |
| Remove conditional and keep the non-Farcaster branch |
| Remove from the main app |
| Remove or replace with |
| Remove entirely |
| Remove entirely |
| Remove; wagmi handles wallet access |
isInMiniApp// BEFORE
if (isInMiniApp) {
sdk.actions.openUrl(url);
} else {
window.open(url, "_blank");
}
// AFTER
window.open(url, "_blank");Path Bsdk.contextcontext.locationcontext.clientsdk.actions.composeCast(...)sdk.actions.openMiniApp(...)lib/farcaster-readonly.tsconst HUB_URL = "https://hub.farcaster.xyz";
export async function getUserData(fid: number) {
const res = await fetch(`${HUB_URL}/v1/userDataByFid?fid=${fid}`);
if (!res.ok) throw new Error(`Hub user data fetch failed: ${res.status}`);
return res.json();
}
export async function getCastsByFid(fid: number, pageSize = 25) {
const res = await fetch(`${HUB_URL}/v1/castsByFid?fid=${fid}&pageSize=${pageSize}`);
if (!res.ok) throw new Error(`Hub casts fetch failed: ${res.status}`);
return res.json();
}.well-known/farcaster.jsonapp/.well-known/farcaster.json/route.tspublic/.well-known/farcaster.jsonapi/farcaster-manifest.ts.well-known<meta>property="fc:miniapp*"property="fc:frame*"Metadata.othergenerateMetadata@farcaster/miniapp-sdk@farcaster/miniapp-wagmi-connector@farcaster/miniapp-core@farcaster/frame-sdk@farcaster/frame-wagmi-connector@farcaster/quick-auth@farcaster/auth-kit@neynar/nodejs-sdk@neynar/react@neynar/nodejs-sdk@neynar/reactsiweapp/farcaster/pages/farcaster//api/farcaster/*/api/neynar/*app/farcaster/app/social/package.json@farcaster/miniapp-sdk@farcaster/miniapp-wagmi-connector@farcaster/miniapp-core@farcaster/frame-sdk@farcaster/frame-wagmi-connector@farcaster/quick-auth@farcaster/auth-kit@neynar/*@neynar/*siwe.env*NEYNAR_API_KEYNEXT_PUBLIC_NEYNAR_CLIENT_IDFARCASTER_*FC_*NEXT_PUBLIC_FC_*NEXT_PUBLIC_FARCASTER_*FARCASTER_*FC_*NEXT_PUBLIC_FC_*NEXT_PUBLIC_FARCASTER_*NEYNAR_*env.tsenv.mjstailwind.config.tstailwind.config.jsfarcaster: "#8B5CF6"npm install@farcaster
farcasterMiniApp
miniAppConnector
sdk.actions
sdk.quickAuth
sdk.context
fc:miniapp
fc:frame@neynar
NEYNAR_API_KEY
NEXT_PUBLIC_NEYNAR_CLIENT_ID
api.neynar.com@neynarnode_modulesnpx tsc --noEmitnpm run build## Conversion Complete — Path [X]: [Name]
**Files modified:** [count]
**Files deleted:** [count]
**Files created:** [count, if any]
**Packages removed:** [list]
**Packages added:** [list, if any]
### What was done
- [x] Removed Farcaster Mini App wagmi connector
- [x] Stubbed or removed Mini App provider/context
- [x] Replaced Mini App auth with normal web auth or removed it
- [x] Removed or replaced SDK action calls
- [x] Deleted manifest route
- [x] Removed Farcaster meta tags
- [x] Cleaned up dependencies and env vars- [x] Kept the main app as a normal web app
- [x] Confined remaining Farcaster functionality to a dedicated route/page
- [x] Preferred read-only Farcaster data where possible
- [x] Removed Farcaster host/runtime coupling from shared app infrastructure### Manual steps
- [ ] Run `npm install`
- [ ] Test wallet connection flow
- [ ] If FID migration is needed, migrate from FID-based identity to wallet address
- [ ] If Path B preserves a Farcaster-only area, verify it stays isolated from the main app shell
### Verification
- TypeScript: [pass/fail]
- Build: [pass/fail]
- Remaining Farcaster references: [none / list]@farcaster/frame-sdk@farcaster/miniapp-sdkisInMiniAppPath APath BPath APath BcoinbaseWallet