diff --git a/.eslintrc.json b/.eslintrc.json
index 3722418..24a1239 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,3 +1,32 @@
{
- "extends": ["next/core-web-vitals", "next/typescript"]
+ "extends": ["next/core-web-vitals", "next/typescript"],
+ "rules": {
+ // Disable img warnings since you're using them intentionally in specific contexts
+ "@next/next/no-img-element": "off",
+
+ // Allow @ts-ignore comments (though @ts-expect-error is preferred)
+ "@typescript-eslint/ban-ts-comment": "off",
+
+ // Allow explicit any types (sometimes necessary for dynamic imports and APIs)
+ "@typescript-eslint/no-explicit-any": "off",
+
+ // Allow unused variables that start with underscore
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "argsIgnorePattern": "^_",
+ "varsIgnorePattern": "^_",
+ "caughtErrorsIgnorePattern": "^_"
+ }
+ ],
+
+ // Make display name warnings instead of errors for dynamic components
+ "react/display-name": "warn",
+
+ // Allow module assignment for dynamic imports
+ "@next/next/no-assign-module-variable": "warn",
+
+ // Make exhaustive deps a warning instead of error for complex hooks
+ "react-hooks/exhaustive-deps": "warn"
+ }
}
diff --git a/package.json b/package.json
index 60cf744..e7340c5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@neynar/create-farcaster-mini-app",
- "version": "1.7.9",
+ "version": "1.7.10",
"type": "module",
"private": false,
"access": "public",
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index c42d41a..30368ab 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -22,7 +22,6 @@ export default async function RootLayout({
let session = null;
if (shouldUseSession) {
try {
- // @ts-ignore - auth module may not exist in all template variants
const authModule = eval('require("~/auth")');
session = await authModule.getSession();
} catch (error) {
diff --git a/src/app/providers.tsx b/src/app/providers.tsx
index d9c19fa..429a147 100644
--- a/src/app/providers.tsx
+++ b/src/app/providers.tsx
@@ -12,14 +12,12 @@ const WagmiProvider = dynamic(
}
);
-
-
export function Providers({
session,
children,
shouldUseSession = false,
}: {
- session: any | null;
+ session: unknown | null;
children: React.ReactNode;
shouldUseSession?: boolean;
}) {
@@ -34,18 +32,31 @@ export function Providers({
return Promise.resolve().then(() => {
// Use eval to avoid build-time module resolution
try {
- // @ts-ignore - These modules may not exist in all template variants
const nextAuth = eval('require("next-auth/react")');
const authKit = eval('require("@farcaster/auth-kit")');
-
- return ({ children }: { children: React.ReactNode }) => (
+
+ const AuthWrapper = ({
+ children,
+ }: {
+ children: React.ReactNode;
+ }) => (
- {children}
+
+ {children}
+
);
- } catch (error) {
+ AuthWrapper.displayName = 'AuthWrapper';
+ return AuthWrapper;
+ } catch (_error) {
// Fallback component when auth modules aren't available
- return ({ children }: { children: React.ReactNode }) => <>{children}>;
+ const FallbackWrapper = ({
+ children,
+ }: {
+ children: React.ReactNode;
+ }) => <>{children}>;
+ FallbackWrapper.displayName = 'FallbackWrapper';
+ return FallbackWrapper;
}
});
},
diff --git a/src/components/ui/tabs/ActionsTab.tsx b/src/components/ui/tabs/ActionsTab.tsx
index bc7880d..c633ed9 100644
--- a/src/components/ui/tabs/ActionsTab.tsx
+++ b/src/components/ui/tabs/ActionsTab.tsx
@@ -1,7 +1,7 @@
'use client';
import dynamic from 'next/dynamic';
-import { useCallback, useState, type ComponentType } from 'react';
+import { useCallback, useState } from 'react';
import { useMiniApp } from '@neynar/react';
import { ShareButton } from '../Share';
import { Button } from '../Button';
@@ -14,10 +14,9 @@ const NeynarAuthButton = dynamic(
() => {
return Promise.resolve().then(() => {
try {
- // @ts-ignore - NeynarAuthButton may not exist in all template variants
- const module = eval('require("../NeynarAuthButton/index")');
- return module.default || module.NeynarAuthButton;
- } catch (error) {
+ const authModule = eval('require("../NeynarAuthButton/index")');
+ return authModule.default || authModule.NeynarAuthButton;
+ } catch (_error) {
// Return null component when module doesn't exist
return () => null;
}
@@ -26,7 +25,6 @@ const NeynarAuthButton = dynamic(
{ ssr: false }
);
-
/**
* ActionsTab component handles mini app actions like sharing, notifications, and haptic feedback.
*
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 4938795..2666d8b 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -1,4 +1,4 @@
-import { type AccountAssociation } from '@farcaster/miniapp-node';
+import { type AccountAssociation } from '@farcaster/miniapp-core/src/manifest';
/**
* Application constants and configuration values.
@@ -22,25 +22,25 @@ export const APP_URL: string = process.env.NEXT_PUBLIC_URL!;
* The name of the mini app as displayed to users.
* Used in titles, headers, and app store listings.
*/
-export const APP_NAME: string = 'Starter Kit';
+export const APP_NAME = 'idk2';
/**
* A brief description of the mini app's functionality.
* Used in app store listings and metadata.
*/
-export const APP_DESCRIPTION: string = 'A demo of the Neynar Starter Kit';
+export const APP_DESCRIPTION = 'A Farcaster mini app created with Neynar';
/**
* The primary category for the mini app.
* Used for app store categorization and discovery.
*/
-export const APP_PRIMARY_CATEGORY: string = 'developer-tools';
+export const APP_PRIMARY_CATEGORY = '';
/**
* Tags associated with the mini app.
* Used for search and discovery in app stores.
*/
-export const APP_TAGS: string[] = ['neynar', 'starter-kit', 'demo'];
+export const APP_TAGS = ['neynar', 'starter-kit', 'demo'];
// --- Asset URLs ---
/**
@@ -65,21 +65,22 @@ export const APP_SPLASH_URL: string = `${APP_URL}/splash.png`;
* Background color for the splash screen.
* Used as fallback when splash image is loading.
*/
-export const APP_SPLASH_BACKGROUND_COLOR: string = "#f7f7f7";
+export const APP_SPLASH_BACKGROUND_COLOR: string = '#f7f7f7';
/**
* Account association for the mini app.
* Used to associate the mini app with a Farcaster account.
* If not provided, the mini app will be unsigned and have limited capabilities.
*/
-export const APP_ACCOUNT_ASSOCIATION: AccountAssociation | undefined = undefined;
+export const APP_ACCOUNT_ASSOCIATION: AccountAssociation | undefined =
+ undefined;
// --- UI Configuration ---
/**
* Text displayed on the main action button.
* Used for the primary call-to-action in the mini app.
*/
-export const APP_BUTTON_TEXT: string = 'Launch NSK';
+export const APP_BUTTON_TEXT = 'Launch Mini App';
// --- Integration Configuration ---
/**
@@ -89,7 +90,8 @@ export const APP_BUTTON_TEXT: string = 'Launch NSK';
* Neynar webhook endpoint. Otherwise, falls back to a local webhook
* endpoint for development and testing.
*/
-export const APP_WEBHOOK_URL: string = process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID
+export const APP_WEBHOOK_URL: string =
+ process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID
? `https://api.neynar.com/f/app/${process.env.NEYNAR_CLIENT_ID}/event`
: `${APP_URL}/api/webhook`;
@@ -100,7 +102,7 @@ export const APP_WEBHOOK_URL: string = process.env.NEYNAR_API_KEY && process.env
* When false, wallet functionality is completely hidden from the UI.
* Useful for mini apps that don't require wallet integration.
*/
-export const USE_WALLET: boolean = true;
+export const USE_WALLET = false;
/**
* Flag to enable/disable analytics tracking.
@@ -109,7 +111,7 @@ export const USE_WALLET: boolean = true;
* When false, analytics collection is disabled.
* Useful for privacy-conscious users or development environments.
*/
-export const ANALYTICS_ENABLED: boolean = true;
+export const ANALYTICS_ENABLED = true;
/**
* Required chains for the mini app.
@@ -117,7 +119,7 @@ export const ANALYTICS_ENABLED: boolean = true;
* Contains an array of CAIP-2 identifiers for blockchains that the mini app requires.
* If the host does not support all chains listed here, it will not render the mini app.
* If empty or undefined, the mini app will be rendered regardless of chain support.
- *
+ *
* Supported chains: eip155:1, eip155:137, eip155:42161, eip155:10, eip155:8453,
* solana:mainnet, solana:devnet
*/
diff --git a/src/lib/kv.ts b/src/lib/kv.ts
index eefc680..28f0982 100644
--- a/src/lib/kv.ts
+++ b/src/lib/kv.ts
@@ -1,16 +1,18 @@
-import { FrameNotificationDetails } from "@farcaster/miniapp-sdk";
-import { Redis } from "@upstash/redis";
-import { APP_NAME } from "./constants";
+import { MiniAppNotificationDetails } from '@farcaster/miniapp-sdk';
+import { Redis } from '@upstash/redis';
+import { APP_NAME } from './constants';
// In-memory fallback storage
-const localStore = new Map();
+const localStore = new Map();
// Use Redis if KV env vars are present, otherwise use in-memory
const useRedis = process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN;
-const redis = useRedis ? new Redis({
- url: process.env.KV_REST_API_URL!,
- token: process.env.KV_REST_API_TOKEN!,
-}) : null;
+const redis = useRedis
+ ? new Redis({
+ url: process.env.KV_REST_API_URL!,
+ token: process.env.KV_REST_API_TOKEN!,
+ })
+ : null;
function getUserNotificationDetailsKey(fid: number): string {
return `${APP_NAME}:user:${fid}`;
@@ -18,17 +20,17 @@ function getUserNotificationDetailsKey(fid: number): string {
export async function getUserNotificationDetails(
fid: number
-): Promise {
+): Promise {
const key = getUserNotificationDetailsKey(fid);
if (redis) {
- return await redis.get(key);
+ return await redis.get(key);
}
return localStore.get(key) || null;
}
export async function setUserNotificationDetails(
fid: number,
- notificationDetails: FrameNotificationDetails
+ notificationDetails: MiniAppNotificationDetails
): Promise {
const key = getUserNotificationDetailsKey(fid);
if (redis) {
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 89e8b8c..dffb165 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,6 +1,6 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
-import { type Manifest } from '@farcaster/miniapp-node';
+import { Manifest } from '@farcaster/miniapp-core/src/manifest';
import {
APP_BUTTON_TEXT,
APP_DESCRIPTION,
@@ -10,7 +10,8 @@ import {
APP_PRIMARY_CATEGORY,
APP_SPLASH_BACKGROUND_COLOR,
APP_SPLASH_URL,
- APP_TAGS, APP_URL,
+ APP_TAGS,
+ APP_URL,
APP_WEBHOOK_URL,
APP_ACCOUNT_ASSOCIATION,
APP_REQUIRED_CHAINS,
@@ -22,7 +23,7 @@ export function cn(...inputs: ClassValue[]) {
export function getMiniAppEmbedMetadata(ogImageUrl?: string) {
return {
- version: "next",
+ version: 'next',
imageUrl: ogImageUrl ?? APP_OG_IMAGE_URL,
ogTitle: APP_NAME,
ogDescription: APP_DESCRIPTION,
@@ -30,7 +31,7 @@ export function getMiniAppEmbedMetadata(ogImageUrl?: string) {
button: {
title: APP_BUTTON_TEXT,
action: {
- type: "launch_frame",
+ type: 'launch_frame',
name: APP_NAME,
url: APP_URL,
splashImageUrl: APP_SPLASH_URL,
@@ -46,24 +47,17 @@ export function getMiniAppEmbedMetadata(ogImageUrl?: string) {
export async function getFarcasterDomainManifest(): Promise {
return {
- accountAssociation: APP_ACCOUNT_ASSOCIATION,
+ accountAssociation: APP_ACCOUNT_ASSOCIATION!,
miniapp: {
- version: "1",
- name: APP_NAME ?? "Neynar Starter Kit",
- iconUrl: APP_ICON_URL,
+ version: '1',
+ name: APP_NAME ?? 'Neynar Starter Kit',
homeUrl: APP_URL,
+ iconUrl: APP_ICON_URL,
imageUrl: APP_OG_IMAGE_URL,
- buttonTitle: APP_BUTTON_TEXT ?? "Launch Mini App",
+ buttonTitle: APP_BUTTON_TEXT ?? 'Launch Mini App',
splashImageUrl: APP_SPLASH_URL,
splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
webhookUrl: APP_WEBHOOK_URL,
- description: APP_DESCRIPTION,
- primaryCategory: APP_PRIMARY_CATEGORY,
- tags: APP_TAGS,
- requiredChains: APP_REQUIRED_CHAINS.length > 0 ? APP_REQUIRED_CHAINS : undefined,
- ogTitle: APP_NAME,
- ogDescription: APP_DESCRIPTION,
- ogImageUrl: APP_OG_IMAGE_URL,
},
};
}