mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-11-16 08:08:56 -05:00
feat: copy share url button and frames to mini app in cli text
This commit is contained in:
parent
08091fc206
commit
5fe54a80da
22
bin/init.js
22
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 {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@neynar/create-farcaster-mini-app",
|
||||
"version": "1.2.23",
|
||||
"version": "1.2.24",
|
||||
"type": "module",
|
||||
"private": false,
|
||||
"access": "public",
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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)
|
||||
`);
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ export default function Demo(
|
||||
const [isContextOpen, setIsContextOpen] = useState(false);
|
||||
const [txHash, setTxHash] = useState<string | null>(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
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
onClick={async () => {
|
||||
if (context?.user?.fid) {
|
||||
const shareUrl = `${process.env.NEXT_PUBLIC_URL}/share/${context.user.fid}`;
|
||||
await navigator.clipboard.writeText(shareUrl);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}
|
||||
}}
|
||||
disabled={!context?.user?.fid}
|
||||
>
|
||||
{copied ? "Copied!" : "Copy share URL"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user