#!/usr/bin/env node import fs from 'fs'; import path from 'path'; import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; const EXCLUDE = [ '.git', 'node_modules', '.next', '.sisyphus', 'pnpm-lock.yaml', 'bin', ]; function copyRecursive(src, dest, replacements) { const stat = fs.statSync(src); if (stat.isDirectory()) { if (EXCLUDE.includes(path.basename(src))) return; fs.mkdirSync(dest, { recursive: true }); for (const entry of fs.readdirSync(src)) { copyRecursive(path.join(src, entry), path.join(dest, entry), replacements); } } else { let content = fs.readFileSync(src, 'utf-8'); for (const [key, value] of Object.entries(replacements)) { content = content.split(key).join(value); } fs.writeFileSync(dest, content); } } function main() { const projectName = process.argv[2]; if (!projectName) { console.error('Usage: node bin/init-template.js '); process.exit(1); } const targetDir = path.resolve(process.cwd(), projectName); if (fs.existsSync(targetDir)) { console.error(`Directory already exists: ${targetDir}`); process.exit(1); } const __dirname = path.dirname(fileURLToPath(import.meta.url)); const templateDir = path.resolve(__dirname, '..'); const replacements = { 'convex-next-saas': projectName, 'https://convex-backend.mentat.ovh': 'https://your-convex-backend.example.com', 'https://backend-site-olnjg91x5ervt6j6owwgnlha.mentat.ovh': 'https://your-convex-site.example.com', 'self-hosted-convex|01eea0ecf04bed0f70b73021564229f7f08eecff003f7294e5f9279faa4c19ffd5c501b0ac': 'self-hosted-convex|YOUR_ADMIN_KEY', 'http://localhost:3000': 'http://localhost:3000', 'SaaS Template': projectName, 'Create SaaS in a day!': `${projectName} — built with convex-next-saas`, }; console.log(`Creating ${projectName}...`); copyRecursive(templateDir, targetDir, replacements); execSync('git init', { cwd: targetDir, stdio: 'inherit' }); console.log('Installing dependencies...'); execSync('pnpm install', { cwd: targetDir, stdio: 'inherit' }); console.log(`\nDone! cd ${projectName} && pnpm dev --webpack`); } main();