From 5fe54a80da79a7eeeb45118b021dad5d0ff469d0 Mon Sep 17 00:00:00 2001 From: veganbeef Date: Fri, 9 May 2025 14:08:06 -0700 Subject: [PATCH] feat: copy share url button and frames to mini app in cli text --- bin/init.js | 22 +++++++++++----------- package.json | 2 +- scripts/build.js | 18 +++++++++--------- scripts/deploy.js | 22 +++++++++++----------- scripts/dev.js | 20 ++++++++++---------- src/components/Demo.tsx | 17 +++++++++++++++++ 6 files changed, 59 insertions(+), 42 deletions(-) diff --git a/bin/init.js b/bin/init.js index 7f70a50..9bf99d0 100644 --- a/bin/init.js +++ b/bin/init.js @@ -27,15 +27,15 @@ function printWelcomeMessage() { console.log(` ${purple}╔═══════════════════════════════════════════════════╗${reset} ${purple}║ ║${reset} -${purple}║${reset} ${bright}Welcome to Frames v2 Quickstart by Neynar${reset} ${purple}║${reset} -${purple}║${reset} ${dim}The fastest way to build Farcaster Frames${reset} ${purple}║${reset} +${purple}║${reset} ${bright}Welcome to Mini Apps Quickstart by Neynar${reset} ${purple}║${reset} +${purple}║${reset} ${dim}the quickest way to build Farcaster mini apps${reset} ${purple}║${reset} ${purple}║ ║${reset} ${purple}╚═══════════════════════════════════════════════════╝${reset} ${blue}Version:${reset} ${SCRIPT_VERSION} ${blue}Repository:${reset} ${dim}${REPO_URL}${reset} -Let's create your Frame! 🚀 +Let's create your mini app! 🚀 `); } @@ -77,13 +77,13 @@ export async function init() { type: 'confirm', name: 'useNeynar', message: '🪐 Neynar is an API that makes it easy to build on Farcaster.\n\n' + - 'Benefits of using Neynar in your frame:\n' + + 'Benefits of using Neynar in your mini app:\n' + '- Pre-configured webhook handling (no setup required)\n' + - '- Automatic frame analytics in your dev portal\n' + + '- Automatic mini app analytics in your dev portal\n' + '- Send manual notifications from dev.neynar.com\n' + '- Built-in rate limiting and error handling\n\n' + `${purple}${bright}${italic}A demo API key is included if you would like to try out Neynar before signing up!${reset}\n\n` + - 'Would you like to use Neynar in your frame?', + 'Would you like to use Neynar in your mini app?', default: true } ]); @@ -172,7 +172,7 @@ export async function init() { { type: 'input', name: 'projectName', - message: 'What is the name of your frame?', + message: 'What is the name of your mini app?', default: defaultFrameName, validate: (input) => { if (input.trim() === '') { @@ -184,14 +184,14 @@ export async function init() { { type: 'input', name: 'description', - message: 'Give a one-line description of your frame (optional):', + message: 'Give a one-line description of your mini app (optional):', default: 'A Farcaster mini-app created with Neynar' }, { type: 'input', name: 'buttonText', - message: 'Enter the button text for your frame:', - default: 'Launch Frame', + message: 'Enter the button text for your mini app:', + default: 'Launch Mini App', validate: (input) => { if (input.trim() === '') { return 'Button text cannot be empty'; @@ -218,7 +218,7 @@ export async function init() { const projectDirName = projectName.replace(/\s+/g, '-').toLowerCase(); const projectPath = path.join(process.cwd(), projectDirName); - console.log(`\nCreating a new Frames v2 app in ${projectPath}`); + console.log(`\nCreating a new mini app in ${projectPath}`); // Clone the repository try { diff --git a/package.json b/package.json index 7df6749..0df22b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neynar/create-farcaster-mini-app", - "version": "1.2.23", + "version": "1.2.24", "type": "module", "private": false, "access": "public", diff --git a/scripts/build.js b/scripts/build.js index 9d98ba1..d070daf 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -194,7 +194,7 @@ async function main() { { type: 'input', name: 'domain', - message: 'Enter the domain where your frame will be deployed (e.g., example.com):', + message: 'Enter the domain where your mini app will be deployed (e.g., example.com):', validate: async (input) => { try { await validateDomain(input); @@ -211,11 +211,11 @@ async function main() { { type: 'input', name: 'frameName', - message: 'Enter the name for your frame (e.g., My Cool Frame):', + message: 'Enter the name for your mini app (e.g., My Cool Mini App):', default: process.env.NEXT_PUBLIC_FRAME_NAME, validate: (input) => { if (input.trim() === '') { - return 'Frame name cannot be empty'; + return 'Mini app name cannot be empty'; } return true; } @@ -227,8 +227,8 @@ async function main() { { type: 'input', name: 'buttonText', - message: 'Enter the text for your frame button:', - default: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT || 'Launch Frame', + message: 'Enter the text for your mini app button:', + default: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT || 'Launch Mini App', validate: (input) => { if (input.trim() === '') { return 'Button text cannot be empty'; @@ -300,7 +300,7 @@ async function main() { type: 'password', name: 'seedPhrase', message: 'Your farcaster custody account seed phrase is required to create a signature proving this app was created by you.\n' + - `⚠️ ${yellow}${italic}seed phrase is only used to sign the frame manifest, then discarded${reset} ⚠️\n` + + `⚠️ ${yellow}${italic}seed phrase is only used to sign the mini app manifest, then discarded${reset} ⚠️\n` + 'Seed phrase:', validate: async (input) => { try { @@ -324,7 +324,7 @@ async function main() { const fid = await lookupFidByCustodyAddress(accountAddress, neynarApiKey ?? 'FARCASTER_V2_FRAMES_DEMO'); // Generate and sign manifest - console.log('\n🔨 Generating frame manifest...'); + console.log('\n🔨 Generating mini app manifest...'); // Determine webhook URL based on environment variables const webhookUrl = neynarApiKey && neynarClientId @@ -332,7 +332,7 @@ async function main() { : `${domain}/api/webhook`; const metadata = await generateFarcasterMetadata(domain, fid, accountAddress, seedPhrase, webhookUrl); - console.log('\n✅ Frame manifest generated' + (seedPhrase ? ' and signed' : '')); + console.log('\n✅ Mini app manifest generated' + (seedPhrase ? ' and signed' : '')); // Read existing .env file or create new one const envPath = path.join(projectRoot, '.env'); @@ -395,7 +395,7 @@ async function main() { shell: process.platform === 'win32' }); - console.log('\n✨ Build complete! Your frame is ready for deployment. 🪐'); + console.log('\n✨ Build complete! Your mini app is ready for deployment. 🪐'); console.log('📝 Make sure to configure the environment variables from .env in your hosting provider'); } catch (error) { diff --git a/scripts/deploy.js b/scripts/deploy.js index b5bbabd..b0c7404 100755 --- a/scripts/deploy.js +++ b/scripts/deploy.js @@ -154,14 +154,14 @@ async function checkRequiredEnvVars() { const requiredVars = [ { name: 'NEXT_PUBLIC_FRAME_NAME', - message: 'Enter the name for your frame (e.g., My Cool Frame):', + message: 'Enter the name for your frame (e.g., My Cool Mini App):', default: process.env.NEXT_PUBLIC_FRAME_NAME, - validate: input => input.trim() !== '' || 'Frame name cannot be empty' + validate: input => input.trim() !== '' || 'Mini app name cannot be empty' }, { name: 'NEXT_PUBLIC_FRAME_BUTTON_TEXT', message: 'Enter the text for your frame button:', - default: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT ?? 'Launch Frame', + default: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT ?? 'Launch Mini App', validate: input => input.trim() !== '' || 'Button text cannot be empty' } ]; @@ -197,13 +197,13 @@ async function checkRequiredEnvVars() { // Check for seed phrase if (!process.env.SEED_PHRASE) { - console.log('\n🔑 Frame Manifest Signing'); - console.log('A signed manifest helps users trust your frame.'); + console.log('\n🔑 Mini App Manifest Signing'); + console.log('A signed manifest helps users trust your mini app.'); const { seedPhrase } = await inquirer.prompt([ { type: 'password', name: 'seedPhrase', - message: 'Enter your Farcaster custody account seed phrase to sign the frame manifest\n(optional -- leave blank to create an unsigned frame)\n\nSeed phrase:', + message: 'Enter your Farcaster custody account seed phrase to sign the mini app manifest\n(optional -- leave blank to create an unsigned mini app)\n\nSeed phrase:', default: null } ]); @@ -385,7 +385,7 @@ async function deployToVercel(useGitHub = false) { // Set up Vercel project console.log('\n📦 Setting up Vercel project...'); - console.log(' An initial deployment is required to get an assigned domain that can be used in the frame manifest\n'); + console.log(' An initial deployment is required to get an assigned domain that can be used in the mini app manifest\n'); console.log('\n⚠️ Note: choosing a longer, more unique project name will help avoid conflicts with other existing domains\n'); execSync('vercel', { cwd: projectRoot, @@ -577,7 +577,7 @@ async function deployToVercel(useGitHub = false) { } } - console.log('\n✨ Deployment complete! Your frame is now live at:'); + console.log('\n✨ Deployment complete! Your mini app is now live at:'); console.log(`🌐 https://${domain}`); console.log('\n📝 You can manage your project at https://vercel.com/dashboard'); @@ -590,13 +590,13 @@ async function deployToVercel(useGitHub = false) { async function main() { try { // Print welcome message - console.log('🚀 Vercel Frame Deployment'); - console.log('This script will deploy your frame to Vercel.'); + console.log('🚀 Vercel Mini App Deployment'); + console.log('This script will deploy your mini app to Vercel.'); console.log('\nThe script will:'); console.log('1. Check for required environment variables'); console.log('2. Set up a Vercel project (new or existing)'); console.log('3. Configure environment variables in Vercel'); - console.log('4. Deploy and build your frame (Vercel will run the build automatically)\n'); + console.log('4. Deploy and build your mini app (Vercel will run the build automatically)\n'); // Check for required environment variables await checkRequiredEnvVars(); diff --git a/scripts/dev.js b/scripts/dev.js index 8fe48c6..aa181e5 100755 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -100,30 +100,30 @@ async function startDev() { 💻 To test on desktop: 1. Open the localtunnel URL in your browser: ${tunnel.url} 2. Enter your IP address in the password field${ip ? `: ${ip}` : ''} (note that this IP may be incorrect if you are using a VPN) - 3. Click "Click to Submit" -- your frame should now load in the browser - 4. Navigate to the Warpcast Frame Developer Tools: https://warpcast.com/~/developers/frames - 5. Enter your frame URL: ${tunnel.url} - 6. Click "Preview" to launch your frame within Warpcast (note that it may take ~10 seconds to load) + 3. Click "Click to Submit" -- your mini app should now load in the browser + 4. Navigate to the Warpcast Mini App Developer Tools: https://warpcast.com/~/developers/mini-apps + 5. Enter your mini app URL: ${tunnel.url} + 6. Click "Preview" to launch your mini app within Warpcast (note that it may take ~10 seconds to load) -❗️ You will not be able to load your frame in Warpcast until ❗️ +❗️ You will not be able to load your mini app in Warpcast until ❗️ ❗️ you submit your IP address in the localtunnel password field ❗️ 📱 To test in Warpcast mobile app: 1. Open Warpcast on your phone - 2. Go to Settings > Developer > Frames + 2. Go to Settings > Developer > Mini Apps 4. Enter this URL: ${tunnel.url} 5. Click "Preview" (note that it may take ~10 seconds to load) `); } else { frameUrl = 'http://localhost:3000'; console.log(` -💻 To test your frame: - 1. Open the Warpcast Frame Developer Tools: https://warpcast.com/~/developers/frames - 2. Scroll down to the "Preview Frame" tool +💻 To test your mini app: + 1. Open the Warpcast Mini App Developer Tools: https://warpcast.com/~/developers/mini-apps + 2. Scroll down to the "Preview Mini App" tool 3. Enter this URL: ${frameUrl} - 4. Click "Preview" to test your frame (note that it may take ~5 seconds to load the first time) + 4. Click "Preview" to test your mini app (note that it may take ~5 seconds to load the first time) `); } diff --git a/src/components/Demo.tsx b/src/components/Demo.tsx index 4195087..1f81c58 100644 --- a/src/components/Demo.tsx +++ b/src/components/Demo.tsx @@ -34,6 +34,7 @@ export default function Demo( const [isContextOpen, setIsContextOpen] = useState(false); const [txHash, setTxHash] = useState(null); const [sendNotificationResult, setSendNotificationResult] = useState(""); + const [copied, setCopied] = useState(false); const { address, isConnected } = useAccount(); const chainId = useChainId(); @@ -289,6 +290,22 @@ export default function Demo( Send notification + +
+ +