@farcaster/create-mini-app
Version:
Create Farcaster Mini Apps with one command
110 lines (90 loc) • 3.18 kB
text/typescript
import { resolve } from 'node:path'
import { intro, log, outro, select, text } from '@clack/prompts'
import { init as initNeynar } from '@neynar/create-farcaster-mini-app'
import { default as fs } from 'fs-extra'
import pc from 'picocolors'
export type InitParameters = { name: string }
export async function init(params: InitParameters) {
intro('Welcome to Farcaster Mini Apps!')
const projectType = await select({
message: 'Select a template:',
options: [
{
value: 'basic',
label: 'Basic static site (Vite + TS + React + Wagmi)',
},
{
value: 'neynar',
label: 'Fully featured with Neynar integration (Next)',
},
],
})
if (projectType === 'neynar') {
await initNeynar()
return
}
const templateDir = resolve(import.meta.dirname, '../templates/default')
const displayName =
params.name ||
((await text({
message: 'Enter the name of your project',
validate(value) {
if (!value) return 'Please enter a name.'
return
},
})) as string)
const name = kebabcase(displayName)
const destDir = resolve(process.cwd(), name)
// Copy contents
fs.copySync(templateDir, destDir)
// Replace dotfiles
for (const file of fs.readdirSync(destDir)) {
if (!file.startsWith('_')) continue
fs.renameSync(resolve(destDir, file), resolve(destDir, `.${file.slice(1)}`))
}
// Replace package.json properties
const pkgJson = fs.readJsonSync(resolve(destDir, 'package.json'))
pkgJson.name = name
fs.writeJsonSync(resolve(destDir, 'package.json'), pkgJson, { spaces: 2 })
// Wrap up
log.success(`Project successfully scaffolded in ${pc.blue(destDir)}!`)
const pkgManager = detectPackageManager()
log.message('Next steps:')
log.step(`1. ${pc.blue(`cd ./${name}`)} - Navigate to project`)
log.step(
`2. ${pc.blue(pkgManagerInstallCommand(pkgManager))} - Install dependencies`,
)
log.step(
`3. ${pc.blue(pkgManagerRunCommand(pkgManager, 'dev'))} - Start dev server`,
)
log.step(`4. Head to ${pc.blue('http://localhost:5173')}`)
outro('Happy Mini App building!')
}
type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun'
function detectPackageManager(): PackageManager {
const userAgent = process.env.npm_config_user_agent
if (!userAgent) return 'npm'
if (userAgent.includes('bun')) return 'bun'
if (userAgent.includes('yarn')) return 'yarn'
if (userAgent.includes('pnpm')) return 'pnpm'
if (userAgent.includes('npm')) return 'npm'
return 'npm'
}
function pkgManagerInstallCommand(pkgManager: PackageManager) {
if (pkgManager === 'bun') return 'bun install'
if (pkgManager === 'yarn') return 'yarn'
if (pkgManager === 'pnpm') return 'pnpm install'
return 'npm install'
}
function pkgManagerRunCommand(pkgManager: PackageManager, command: string) {
if (pkgManager === 'bun') return `bun run ${command}`
if (pkgManager === 'yarn') return `yarn ${command}`
if (pkgManager === 'pnpm') return `pnpm ${command}`
return `npm run ${command}`
}
function kebabcase(str: string) {
return str
.replace(/([a-z])([A-Z])/g, '$1-$2')
.replace(/[\s_]+/g, '-')
.toLowerCase()
}