shipfolio 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1867,9 +1867,25 @@ var init_auth = __esm({
1867
1867
 
1868
1868
  // src/deployer/cloudflare.ts
1869
1869
  import ora6 from "ora";
1870
+ async function ensureProject(projectName) {
1871
+ try {
1872
+ await runWithOutput("npx", [
1873
+ "wrangler",
1874
+ "pages",
1875
+ "project",
1876
+ "create",
1877
+ projectName,
1878
+ "--production-branch=main"
1879
+ ]);
1880
+ } catch {
1881
+ }
1882
+ }
1870
1883
  async function deployToCloudflare(distDir, projectName) {
1871
1884
  const spinner = ora6("Deploying to Cloudflare Pages...").start();
1872
1885
  try {
1886
+ spinner.text = "Creating Cloudflare Pages project...";
1887
+ await ensureProject(projectName);
1888
+ spinner.text = "Uploading to Cloudflare Pages...";
1873
1889
  const output = await runWithOutput("npx", [
1874
1890
  "wrangler",
1875
1891
  "pages",
@@ -2159,7 +2175,7 @@ import { resolve } from "path";
2159
2175
  import { join as join6 } from "path";
2160
2176
  import * as p3 from "@clack/prompts";
2161
2177
  async function initCommand(options) {
2162
- logger.header("shipfolio v1.0.4");
2178
+ logger.header("shipfolio v1.0.5");
2163
2179
  logger.info("Detecting AI engines...");
2164
2180
  const engines = await detectEngines();
2165
2181
  const availableTypes = getAvailableEngineTypes(engines);
@@ -2247,13 +2263,18 @@ async function initCommand(options) {
2247
2263
  }
2248
2264
  }
2249
2265
  if (spec.deploy.platform !== "local") {
2250
- const url = await deploy(
2251
- outputDir,
2252
- spec.deploy.platform,
2253
- spec.deploy.projectName
2254
- );
2255
- if (url) {
2256
- spec.deploy.url = url;
2266
+ try {
2267
+ const url = await deploy(
2268
+ outputDir,
2269
+ spec.deploy.platform,
2270
+ spec.deploy.projectName
2271
+ );
2272
+ if (url) {
2273
+ spec.deploy.url = url;
2274
+ }
2275
+ } catch (err) {
2276
+ logger.error(`Deployment failed: ${err.message || err}`);
2277
+ logger.info("You can retry later with: npx shipfolio deploy --site " + outputDir);
2257
2278
  }
2258
2279
  }
2259
2280
  await writeJson(join6(outputDir, "shipfolio.config.json"), {
@@ -2608,7 +2629,7 @@ initLocale();
2608
2629
  var program = new Command();
2609
2630
  program.name("shipfolio").description(
2610
2631
  "Generate and deploy your personal portfolio site from local projects using AI"
2611
- ).version("1.0.4");
2632
+ ).version("1.0.5");
2612
2633
  program.command("init", { isDefault: true }).description("Generate a new portfolio site").option("-s, --scan <dirs...>", "Directories to scan for projects").option("-e, --engine <engine>", "AI engine: claude | codex | v0").option("-d, --deploy <platform>", "Deploy target: cloudflare | vercel | local").option("--style <theme>", "Theme: dark-minimal | light-clean | monochrome").option("--accent <hex>", "Accent color (hex)").option("--auto", "Skip prompts, use defaults").option("-o, --output <dir>", "Output directory", "./shipfolio-site").option("--no-pdf", "Skip PDF export").option("--no-preview", "Skip local preview").option("-v, --verbose", "Verbose output").action(initCommand);
2613
2634
  program.command("update").description("Update an existing portfolio site").requiredOption("--site <path>", "Path to existing site directory").option("-s, --scan <dirs...>", "Directories to scan for projects").option("--no-pdf", "Skip PDF export").option("--no-preview", "Skip preview").option("--no-deploy", "Skip deployment").action(updateCommand);
2614
2635
  program.command("spec").description("Generate spec and prompt files only").option("-s, --scan <dirs...>", "Directories to scan for projects").option("-o, --output <dir>", "Output directory for spec files", ".").action(specCommand);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/scanner/git.ts","../src/utils/fs.ts","../src/scanner/detectors/node.ts","../src/scanner/detectors/python.ts","../src/scanner/detectors/rust.ts","../src/scanner/detectors/go.ts","../src/scanner/detectors/generic.ts","../src/scanner/extractors.ts","../src/utils/logger.ts","../src/scanner/index.ts","../src/utils/i18n.ts","../src/interviewer/questions.ts","../src/interviewer/index.ts","../src/spec/builder.ts","../src/orchestrator/prompt-builder.ts","../src/utils/exec.ts","../src/orchestrator/detect.ts","../src/orchestrator/engines/claude.ts","../src/orchestrator/engines/codex.ts","../src/orchestrator/engines/v0.ts","../src/orchestrator/validator.ts","../src/orchestrator/index.ts","../src/deployer/auth.ts","../src/deployer/cloudflare.ts","../src/deployer/vercel.ts","../src/deployer/github.ts","../src/deployer/index.ts","../src/pdf/index.ts","../src/utils/draft.ts","../src/commands/init.ts","../src/index.ts","../src/commands/update.ts","../src/spec/diff.ts","../src/commands/spec.ts","../src/commands/deploy.ts","../src/commands/pdf.ts","../src/commands/preview.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allPaths: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n // Find git repos\n const repos = await findGitRepos(dir);\n allPaths.push(...repos);\n\n // Also find non-git project directories (with package.json, Cargo.toml, etc.)\n const nonGitDirs = await findNonGitProjects(dir, new Set(repos));\n allPaths.push(...nonGitDirs);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniquePaths = [...new Set(allPaths)];\n spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const projectPath of uniquePaths) {\n try {\n const project = await extractProjectMeta(projectPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n // Deduplicate IDs (same folder name in different parent dirs)\n const idCounts = new Map<string, number>();\n for (const project of projects) {\n const count = idCounts.get(project.id) || 0;\n if (count > 0) {\n project.id = `${project.id}-${count}`;\n }\n idCounts.set(project.id.replace(/-\\d+$/, \"\"), count + 1);\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function findNonGitProjects(\n rootPath: string,\n gitRepos: Set<string>\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const indicators = [\n \"*/package.json\",\n \"*/Cargo.toml\",\n \"*/go.mod\",\n \"*/pyproject.toml\",\n \"*/requirements.txt\",\n \"*/setup.py\",\n ];\n const found = new Set<string>();\n for (const pattern of indicators) {\n const matches = await glob(pattern, {\n cwd: rootPath,\n ignore: [\"**/node_modules/**\", \"**/vendor/**\"],\n });\n for (const match of matches) {\n const dir = `${rootPath}/${match.split(\"/\")[0]}`;\n if (!gitRepos.has(dir) && !found.has(dir)) {\n found.add(dir);\n }\n }\n }\n return [...found].sort();\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path (use folder name to keep it readable, but\n // append a hash suffix when the same folder name appears in multiple paths)\n const folderName = deriveNameFromPath(projectPath);\n const id = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n","const messages = {\n en: {\n // Project selection\n selectProjects: \"Select projects to include (space = select, enter = confirm):\",\n mergePrompt: \"Merge any related projects into one entry? (e.g. web + mobile)\",\n selectToMerge: \"Select projects to merge together (space = select, enter = confirm):\",\n mergedNamePrompt: \"Name for the merged entry:\",\n mergeNeedTwo: \"Need at least 2 projects to merge. Skipping.\",\n mergedResult: (names: string, target: string) => `Merged ${names} -> \"${target}\"`,\n mergeMore: \"Merge more projects?\",\n // Per-project\n configuring: (name: string) => `Configuring: ${name}`,\n descriptionFor: (name: string) => `Description for ${name} (enter to use auto-generated):`,\n descriptionPlaceholder: \"Auto-generate from README\",\n demoUrlFor: (name: string) => `Demo URL for ${name}:`,\n showSourceFor: (name: string) => `Show source code link for ${name}?`,\n roleFor: (name: string) => `Your role in ${name}:`,\n metricsFor: (name: string) => `Key metrics for ${name} (e.g. \"1k users, $5k MRR\"):`,\n optional: \"optional\",\n // Personal info\n personalInfo: \"Personal Information\",\n fullName: \"Your full name:\",\n nameRequired: \"Name is required\",\n tagline: \"Professional tagline (one line):\",\n taglinePlaceholder: \"Full-stack developer. I ship things.\",\n bio: \"Bio:\",\n bioAuto: \"Auto-generate from my projects\",\n bioManual: \"Write manually\",\n bioPrompt: \"Your bio (2-3 sentences):\",\n photoUrl: \"Photo URL (optional):\",\n githubUser: \"GitHub username or URL:\",\n twitterHandle: \"Twitter/X handle:\",\n linkedinUrl: \"LinkedIn URL:\",\n blogUrl: \"Blog URL:\",\n contactEmail: \"Contact email:\",\n // Design\n designPrefs: \"Design Preferences\",\n theme: \"Theme:\",\n accentColor: \"Accent color:\",\n customHex: \"Custom hex\",\n customHexPrompt: \"Custom accent color (hex):\",\n invalidHex: \"Enter a valid hex color\",\n font: \"Font:\",\n animationLevel: \"Animation level:\",\n // Sections\n sections: \"Sections\",\n additionalSections: \"Additional sections (Hero + Projects always included):\",\n // Engine\n aiEngine: \"AI Engine\",\n engineUsing: (name: string) => `Using ${name}`,\n engineSelect: \"AI engine to use:\",\n // Deploy\n deployment: \"Deployment\",\n deployTo: \"Deploy to:\",\n projectNamePrompt: \"Project name (used in URL):\",\n projectNameInvalid: \"Lowercase letters, numbers, and hyphens only\",\n configComplete: \"Configuration complete. Generating your site...\",\n // Draft\n draftFound: \"Found a saved draft from a previous session.\",\n draftLoadPrompt: \"Load draft? (skip re-entering previous answers)\",\n draftSaved: \"Draft saved. Your progress will be restored next time.\",\n draftCleared: \"Draft cleared.\",\n // Roles\n roleSolo: \"Solo\",\n roleLead: \"Lead\",\n roleContributor: \"Contributor\",\n // Themes\n themeDarkMinimal: \"Dark Minimal\",\n themeLightClean: \"Light Clean\",\n themeMonochrome: \"Monochrome\",\n themeCustom: \"Custom (AI decides)\",\n // Fonts\n fontInter: \"Inter\",\n fontJetBrains: \"JetBrains Mono\",\n fontSystem: \"System Default\",\n // Animations\n animSubtle: \"Subtle\",\n animModerate: \"Moderate\",\n animNone: \"None\",\n // Section names\n secSkills: \"Skills / Tech Stack\",\n secAbout: \"About Me\",\n secTimeline: \"Timeline / Changelog\",\n secBlog: \"Blog\",\n secMetrics: \"Metrics Dashboard\",\n secContact: \"Contact\",\n // Deploy platforms\n deployCloudflare: \"Cloudflare Pages\",\n deployVercel: \"Vercel\",\n deployLocal: \"Local only (no deploy)\",\n // Colors\n colorPurple: \"Purple\",\n colorGreen: \"Green\",\n colorOrange: \"Orange\",\n colorBlue: \"Blue\",\n colorRed: \"Red\",\n colorPink: \"Pink\",\n // Engines\n engineClaude: \"Claude Code\",\n engineCodex: \"Codex\",\n engineV0: \"v0 (Vercel)\",\n },\n zh: {\n selectProjects: \"选择要展示的项目 (空格 = 选择, 回车 = 确认):\",\n mergePrompt: \"是否要合并相关项目为一个条目? (如 web + mobile)\",\n selectToMerge: \"选择要合并的项目 (空格 = 选择, 回车 = 确认):\",\n mergedNamePrompt: \"合并后的名称:\",\n mergeNeedTwo: \"至少需要选择 2 个项目才能合并, 跳过.\",\n mergedResult: (names: string, target: string) => `已合并 ${names} -> \"${target}\"`,\n mergeMore: \"继续合并其他项目?\",\n configuring: (name: string) => `配置: ${name}`,\n descriptionFor: (name: string) => `${name} 的描述 (回车使用自动生成):`,\n descriptionPlaceholder: \"从 README 自动生成\",\n demoUrlFor: (name: string) => `${name} 的 Demo 地址:`,\n showSourceFor: (name: string) => `是否展示 ${name} 的源码链接?`,\n roleFor: (name: string) => `你在 ${name} 中的角色:`,\n metricsFor: (name: string) => `${name} 的关键指标 (如 \"1k 用户, $5k MRR\"):`,\n optional: \"可选\",\n personalInfo: \"个人信息\",\n fullName: \"你的全名:\",\n nameRequired: \"姓名不能为空\",\n tagline: \"职业标语 (一句话):\",\n taglinePlaceholder: \"全栈工程师, 持续交付.\",\n bio: \"个人简介:\",\n bioAuto: \"根据项目自动生成\",\n bioManual: \"手动填写\",\n bioPrompt: \"你的简介 (2-3句话):\",\n photoUrl: \"头像链接 (可选):\",\n githubUser: \"GitHub 用户名或链接:\",\n twitterHandle: \"Twitter/X 账号:\",\n linkedinUrl: \"LinkedIn 链接:\",\n blogUrl: \"博客链接:\",\n contactEmail: \"联系邮箱:\",\n designPrefs: \"设计偏好\",\n theme: \"主题:\",\n accentColor: \"强调色:\",\n customHex: \"自定义色值\",\n customHexPrompt: \"自定义强调色 (hex):\",\n invalidHex: \"请输入有效的 hex 颜色值\",\n font: \"字体:\",\n animationLevel: \"动画级别:\",\n sections: \"页面区块\",\n additionalSections: \"附加区块 (Hero + 项目展示 始终包含):\",\n aiEngine: \"AI 引擎\",\n engineUsing: (name: string) => `使用 ${name}`,\n engineSelect: \"选择 AI 引擎:\",\n deployment: \"部署\",\n deployTo: \"部署到:\",\n projectNamePrompt: \"项目名称 (用于 URL):\",\n projectNameInvalid: \"仅限小写字母, 数字和连字符\",\n configComplete: \"配置完成, 正在生成网站...\",\n draftFound: \"发现上次未完成的配置草稿.\",\n draftLoadPrompt: \"是否加载草稿? (跳过重复填写)\",\n draftSaved: \"草稿已保存, 下次运行时可恢复.\",\n draftCleared: \"草稿已清除.\",\n roleSolo: \"独立完成\",\n roleLead: \"主导开发\",\n roleContributor: \"参与贡献\",\n themeDarkMinimal: \"暗色极简\",\n themeLightClean: \"明亮简洁\",\n themeMonochrome: \"黑白\",\n themeCustom: \"自定义 (AI 决定)\",\n fontInter: \"Inter\",\n fontJetBrains: \"JetBrains Mono\",\n fontSystem: \"系统默认\",\n animSubtle: \"轻微\",\n animModerate: \"适中\",\n animNone: \"无\",\n secSkills: \"技术栈\",\n secAbout: \"关于我\",\n secTimeline: \"时间线\",\n secBlog: \"博客\",\n secMetrics: \"数据面板\",\n secContact: \"联系方式\",\n deployCloudflare: \"Cloudflare Pages\",\n deployVercel: \"Vercel\",\n deployLocal: \"仅本地 (不部署)\",\n colorPurple: \"紫色\",\n colorGreen: \"绿色\",\n colorOrange: \"橙色\",\n colorBlue: \"蓝色\",\n colorRed: \"红色\",\n colorPink: \"粉色\",\n engineClaude: \"Claude Code\",\n engineCodex: \"Codex\",\n engineV0: \"v0 (Vercel)\",\n },\n} as const;\n\nexport type Locale = \"en\" | \"zh\";\nexport type Messages = typeof messages.en;\n\nlet currentLocale: Locale = \"en\";\n\nexport function detectLocale(): Locale {\n const lang = (\n process.env.LANG ||\n process.env.LC_ALL ||\n process.env.LC_MESSAGES ||\n process.env.LANGUAGE ||\n \"\"\n ).toLowerCase();\n\n if (lang.startsWith(\"zh\")) return \"zh\";\n return \"en\";\n}\n\nexport function initLocale(): void {\n currentLocale = detectLocale();\n}\n\nexport function t(): Messages {\n return messages[currentLocale];\n}\n\nexport function getLocale(): Locale {\n return currentLocale;\n}\n","import type {\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport { t } from \"../utils/i18n.js\";\n\nexport const THEME_OPTIONS = (): { value: StyleConfig[\"theme\"]; label: string }[] => [\n { value: \"dark-minimal\", label: t().themeDarkMinimal },\n { value: \"light-clean\", label: t().themeLightClean },\n { value: \"monochrome\", label: t().themeMonochrome },\n { value: \"custom\", label: t().themeCustom },\n];\n\nexport const FONT_OPTIONS = (): { value: StyleConfig[\"font\"]; label: string }[] => [\n { value: \"Inter\", label: t().fontInter },\n { value: \"JetBrains Mono\", label: t().fontJetBrains },\n { value: \"system\", label: t().fontSystem },\n];\n\nexport const ANIMATION_OPTIONS = (): {\n value: StyleConfig[\"animationLevel\"];\n label: string;\n}[] => [\n { value: \"subtle\", label: t().animSubtle },\n { value: \"moderate\", label: t().animModerate },\n { value: \"none\", label: t().animNone },\n];\n\nexport const SECTION_OPTIONS = (): { value: SectionId; label: string }[] => [\n { value: \"skills\", label: t().secSkills },\n { value: \"about\", label: t().secAbout },\n { value: \"timeline\", label: t().secTimeline },\n { value: \"blog\", label: t().secBlog },\n { value: \"metrics\", label: t().secMetrics },\n { value: \"contact\", label: t().secContact },\n];\n\nexport const ENGINE_OPTIONS = (): { value: EngineType; label: string }[] => [\n { value: \"claude\", label: t().engineClaude },\n { value: \"codex\", label: t().engineCodex },\n { value: \"v0\", label: t().engineV0 },\n];\n\nexport const DEPLOY_OPTIONS = (): { value: DeployPlatform; label: string }[] => [\n { value: \"cloudflare\", label: t().deployCloudflare },\n { value: \"vercel\", label: t().deployVercel },\n { value: \"local\", label: t().deployLocal },\n];\n\nexport const ROLE_OPTIONS = (): {\n value: \"solo\" | \"lead\" | \"contributor\";\n label: string;\n}[] => [\n { value: \"solo\", label: t().roleSolo },\n { value: \"lead\", label: t().roleLead },\n { value: \"contributor\", label: t().roleContributor },\n];\n\nexport const DEFAULT_ACCENT_COLORS = (): { value: string; label: string }[] => [\n { value: \"#7c3aed\", label: t().colorPurple },\n { value: \"#10b981\", label: t().colorGreen },\n { value: \"#f97316\", label: t().colorOrange },\n { value: \"#3b82f6\", label: t().colorBlue },\n { value: \"#ef4444\", label: t().colorRed },\n { value: \"#ec4899\", label: t().colorPink },\n];\n","import * as p from \"@clack/prompts\";\nimport type {\n ProjectMeta,\n ProjectEntry,\n OwnerInfo,\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport {\n THEME_OPTIONS,\n FONT_OPTIONS,\n ANIMATION_OPTIONS,\n SECTION_OPTIONS,\n ENGINE_OPTIONS,\n DEPLOY_OPTIONS,\n ROLE_OPTIONS,\n DEFAULT_ACCENT_COLORS,\n} from \"./questions.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { t } from \"../utils/i18n.js\";\n\n/** ProjectMeta with optional children for merged groups */\ninterface MergeableMeta extends ProjectMeta {\n children?: ProjectMeta[];\n}\n\nfunction handleCancel(value: unknown): void {\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n}\n\nexport interface InterviewResult {\n projects: ProjectEntry[];\n owner: OwnerInfo;\n style: StyleConfig;\n sections: SectionId[];\n engine: EngineType;\n deploy: {\n platform: DeployPlatform;\n projectName: string;\n };\n}\n\nasync function runMergeStep(\n projects: MergeableMeta[]\n): Promise<MergeableMeta[]> {\n const shouldMerge = (await p.confirm({\n message: t().mergePrompt,\n initialValue: false,\n })) as boolean;\n handleCancel(shouldMerge);\n\n if (!shouldMerge) return projects;\n\n // Work on a mutable copy\n let remaining = [...projects];\n\n while (remaining.length >= 2) {\n const mergeIds = (await p.multiselect({\n message: t().selectToMerge,\n options: remaining.map((proj) => ({\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: proj.techStack.slice(0, 3).join(\", \"),\n })),\n required: true,\n })) as string[];\n handleCancel(mergeIds);\n\n if (mergeIds.length < 2) {\n logger.warn(t().mergeNeedTwo);\n break;\n }\n\n // Collect the projects being merged\n const toMerge = mergeIds.map(\n (id) => remaining.find((p) => p.id === id)!\n );\n\n // Ask for the merged entry name\n const defaultName = toMerge.map((p) => p.name).join(\" + \");\n const mergedName = (await p.text({\n message: t().mergedNamePrompt,\n placeholder: defaultName,\n defaultValue: defaultName,\n })) as string;\n handleCancel(mergedName);\n\n // Build the merged meta\n const merged = mergeProjects(toMerge, mergedName);\n\n // Remove merged items, add the new merged entry\n remaining = remaining.filter((p) => !mergeIds.includes(p.id));\n remaining.push(merged);\n\n logger.info(\n t().mergedResult(toMerge.map((p) => p.name).join(\", \"), mergedName)\n );\n\n if (remaining.length < 2) break;\n\n const more = (await p.confirm({\n message: t().mergeMore,\n initialValue: false,\n })) as boolean;\n handleCancel(more);\n\n if (!more) break;\n }\n\n return remaining;\n}\n\nfunction mergeProjects(\n projects: MergeableMeta[],\n name: string\n): MergeableMeta {\n // Flatten: if any project is itself a merged group, collect its children\n const allChildren: ProjectMeta[] = [];\n for (const proj of projects) {\n if (proj.children && proj.children.length > 0) {\n allChildren.push(...proj.children);\n } else {\n // Store the original as a child (strip children field)\n const { children, ...rest } = proj as MergeableMeta;\n allChildren.push(rest);\n }\n }\n\n // Combine tech stacks (deduplicated)\n const techStack = [\n ...new Set(allChildren.flatMap((p) => p.techStack)),\n ];\n\n // Combine languages\n const languages: Record<string, number> = {};\n for (const child of allChildren) {\n for (const [lang, count] of Object.entries(child.languages)) {\n languages[lang] = (languages[lang] || 0) + count;\n }\n }\n\n // Use earliest first commit, latest last commit\n const firstDates = allChildren\n .map((p) => p.firstCommitDate)\n .filter(Boolean)\n .sort();\n const lastDates = allChildren\n .map((p) => p.lastCommitDate)\n .filter(Boolean)\n .sort();\n\n // Sum commits\n const totalCommits = allChildren.reduce(\n (sum, p) => sum + p.totalCommits,\n 0\n );\n\n // Collect all remote URLs (pick first non-null)\n const remoteUrl =\n allChildren.find((p) => p.remoteUrl)?.remoteUrl || null;\n\n // Collect all demo URLs (pick first non-null)\n const demoUrl =\n allChildren.find((p) => p.demoUrl)?.demoUrl || null;\n\n // Concatenate README contents\n const readmeParts = allChildren\n .filter((p) => p.readmeContent)\n .map(\n (p) =>\n `--- ${p.name} ---\\n${p.readmeContent}`\n );\n const readmeContent =\n readmeParts.length > 0 ? readmeParts.join(\"\\n\\n\") : null;\n\n // Combine descriptions\n const descriptions = allChildren\n .map((p) => p.description)\n .filter(Boolean);\n const description = descriptions.join(\" | \");\n\n // Use first child's path as the \"primary\" local path\n const localPath = allChildren[0].localPath;\n\n const id = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath,\n description,\n techStack,\n languages,\n firstCommitDate: firstDates[0] || \"\",\n lastCommitDate: lastDates[lastDates.length - 1] || \"\",\n totalCommits,\n remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: allChildren[0].lastScannedCommit || \"\",\n children: allChildren,\n };\n}\n\nexport async function runInterview(\n scannedProjects: ProjectMeta[],\n availableEngines: EngineType[]\n): Promise<InterviewResult> {\n p.intro(\"shipfolio\");\n\n // -- Project Selection --\n logger.header(\"Project Selection\");\n\n const projectOptions = scannedProjects.map((proj) => {\n const techInfo = proj.techStack.slice(0, 3).join(\", \");\n const commitInfo = proj.totalCommits > 0 ? `${proj.totalCommits} commits` : \"no git\";\n return {\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: techInfo ? `${techInfo} | ${commitInfo}` : commitInfo,\n };\n });\n\n const selectedIds = (await p.multiselect({\n message: t().selectProjects,\n options: projectOptions,\n required: true,\n })) as string[];\n handleCancel(selectedIds);\n\n // Build the working list of selected project metas\n let selectedMetas: MergeableMeta[] = selectedIds.map(\n (id) => scannedProjects.find((p) => p.id === id)!\n );\n\n // -- Merge Step --\n if (selectedMetas.length >= 2) {\n selectedMetas = await runMergeStep(selectedMetas);\n }\n\n // -- Per-Project Details --\n const projectEntries: ProjectEntry[] = [];\n\n for (const meta of selectedMetas) {\n const displayName = meta.children\n ? `${meta.name} (${meta.children.length} sub-projects)`\n : meta.name;\n\n logger.plain(`\\n ${t().configuring(displayName)}`);\n\n const overrideDesc = (await p.text({\n message: t().descriptionFor(displayName),\n placeholder: meta.description?.slice(0, 80) || t().descriptionPlaceholder,\n defaultValue: \"\",\n })) as string;\n handleCancel(overrideDesc);\n\n const demoUrl = (await p.text({\n message: t().demoUrlFor(displayName),\n placeholder: meta.demoUrl || \"none\",\n defaultValue: meta.demoUrl || \"\",\n })) as string;\n handleCancel(demoUrl);\n\n const showSource = (await p.confirm({\n message: t().showSourceFor(displayName),\n initialValue: !!meta.remoteUrl,\n })) as boolean;\n handleCancel(showSource);\n\n const role = (await p.select({\n message: t().roleFor(displayName),\n options: ROLE_OPTIONS(),\n })) as \"solo\" | \"lead\" | \"contributor\";\n handleCancel(role);\n\n const metricsInput = (await p.text({\n message: t().metricsFor(displayName),\n placeholder: t().optional,\n defaultValue: \"\",\n })) as string;\n handleCancel(metricsInput);\n\n const metrics: ProjectEntry[\"metrics\"] = {};\n if (metricsInput) {\n metrics.custom = { summary: metricsInput };\n }\n\n projectEntries.push({\n ...meta,\n included: true,\n overrideDescription: overrideDesc || null,\n showSourceLink: showSource,\n demoUrl: demoUrl || meta.demoUrl,\n role,\n metrics,\n });\n }\n\n // -- Personal Info --\n logger.header(t().personalInfo);\n\n const name = (await p.text({\n message: t().fullName,\n validate: (v) => (v.length === 0 ? t().nameRequired : undefined),\n })) as string;\n handleCancel(name);\n\n const tagline = (await p.text({\n message: t().tagline,\n placeholder: t().taglinePlaceholder,\n })) as string;\n handleCancel(tagline);\n\n const bioChoice = (await p.select({\n message: t().bio,\n options: [\n { value: \"auto\", label: t().bioAuto },\n { value: \"manual\", label: t().bioManual },\n ],\n })) as string;\n handleCancel(bioChoice);\n\n let bio: string | \"auto\" = \"auto\";\n if (bioChoice === \"manual\") {\n bio = (await p.text({\n message: t().bioPrompt,\n })) as string;\n handleCancel(bio);\n }\n\n const photoUrl = (await p.text({\n message: t().photoUrl,\n placeholder: \"https://...\",\n defaultValue: \"\",\n })) as string;\n handleCancel(photoUrl);\n\n const github = (await p.text({\n message: t().githubUser,\n defaultValue: \"\",\n })) as string;\n handleCancel(github);\n\n const twitter = (await p.text({\n message: t().twitterHandle,\n defaultValue: \"\",\n })) as string;\n handleCancel(twitter);\n\n const linkedin = (await p.text({\n message: t().linkedinUrl,\n defaultValue: \"\",\n })) as string;\n handleCancel(linkedin);\n\n const blogUrl = (await p.text({\n message: t().blogUrl,\n defaultValue: \"\",\n })) as string;\n handleCancel(blogUrl);\n\n const email = (await p.text({\n message: t().contactEmail,\n defaultValue: \"\",\n })) as string;\n handleCancel(email);\n\n const owner: OwnerInfo = {\n name,\n tagline,\n bio,\n photoUrl: photoUrl || null,\n social: {\n github: github || undefined,\n twitter: twitter || undefined,\n linkedin: linkedin || undefined,\n blog: blogUrl || undefined,\n email: email || undefined,\n },\n };\n\n // -- Design Preferences --\n logger.header(t().designPrefs);\n\n const theme = (await p.select({\n message: t().theme,\n options: THEME_OPTIONS(),\n })) as StyleConfig[\"theme\"];\n handleCancel(theme);\n\n const accentColor = (await p.select({\n message: t().accentColor,\n options: [\n ...DEFAULT_ACCENT_COLORS(),\n { value: \"custom\", label: t().customHex },\n ],\n })) as string;\n handleCancel(accentColor);\n\n let finalAccent = accentColor;\n if (accentColor === \"custom\") {\n finalAccent = (await p.text({\n message: t().customHexPrompt,\n placeholder: \"#7c3aed\",\n validate: (v) =>\n /^#[0-9a-fA-F]{6}$/.test(v) ? undefined : t().invalidHex,\n })) as string;\n handleCancel(finalAccent);\n }\n\n const font = (await p.select({\n message: t().font,\n options: FONT_OPTIONS(),\n })) as StyleConfig[\"font\"];\n handleCancel(font);\n\n const animationLevel = (await p.select({\n message: t().animationLevel,\n options: ANIMATION_OPTIONS(),\n })) as StyleConfig[\"animationLevel\"];\n handleCancel(animationLevel);\n\n const style: StyleConfig = {\n theme,\n accentColor: finalAccent,\n font,\n animationLevel,\n };\n\n // -- Sections --\n logger.header(t().sections);\n\n const additionalSections = (await p.multiselect({\n message: t().additionalSections,\n options: SECTION_OPTIONS(),\n required: false,\n })) as SectionId[];\n handleCancel(additionalSections);\n\n const sections: SectionId[] = [\n \"hero\",\n \"projects\",\n ...additionalSections,\n ];\n\n // -- Engine Selection --\n logger.header(t().aiEngine);\n\n let engine: EngineType;\n if (availableEngines.length === 1) {\n engine = availableEngines[0];\n logger.info(t().engineUsing(engine));\n } else {\n const filteredEngineOptions = ENGINE_OPTIONS().filter((o) =>\n availableEngines.includes(o.value)\n );\n engine = (await p.select({\n message: t().engineSelect,\n options: filteredEngineOptions,\n })) as EngineType;\n handleCancel(engine);\n }\n\n // -- Deploy Target --\n logger.header(t().deployment);\n\n const deployPlatform = (await p.select({\n message: t().deployTo,\n options: DEPLOY_OPTIONS(),\n })) as DeployPlatform;\n handleCancel(deployPlatform);\n\n let projectName = \"\";\n if (deployPlatform !== \"local\") {\n projectName = (await p.text({\n message: t().projectNamePrompt,\n placeholder: \"my-shipfolio\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : t().projectNameInvalid,\n })) as string;\n handleCancel(projectName);\n }\n\n p.outro(t().configComplete);\n\n return {\n projects: projectEntries,\n owner,\n style,\n sections,\n engine,\n deploy: {\n platform: deployPlatform,\n projectName,\n },\n };\n}\n","import type { ShipfolioSpec } from \"./schema.js\";\nimport type { InterviewResult } from \"../interviewer/index.js\";\n\nexport function buildSpec(interview: InterviewResult): ShipfolioSpec {\n return {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n engine: interview.engine,\n framework: \"next\",\n style: interview.style,\n owner: interview.owner,\n projects: interview.projects,\n sections: interview.sections,\n deploy: {\n platform: interview.deploy.platform,\n projectName: interview.deploy.projectName,\n },\n };\n}\n","import type { ShipfolioSpec, ShipfolioConfig, SiteDiff } from \"../spec/schema.js\";\n\nconst FRESH_BUILD_TEMPLATE = `# Task\n\nGenerate a complete, production-ready personal portfolio website.\nAll data and design preferences are provided in the spec below.\nOutput a fully working Next.js project that builds and deploys as a static site.\n\n# Spec\n\n{{SPEC_JSON}}\n\n# Technical Requirements\n\n- Next.js 15 with App Router and TypeScript\n- Tailwind CSS v4 for styling\n- shadcn/ui components (initialize with \\`npx shadcn@latest init --yes\\`)\n- Static export: set \\`output: 'export'\\` in next.config.ts\n- Build command: \\`npm run build\\` producing \\`out/\\` directory\n- Zero external API calls at runtime -- all data is embedded in source\n- All project data in \\`src/data/projects.ts\\` as typed constants\n- Include \\`@media print\\` stylesheet in \\`src/app/globals.css\\` for PDF export\n- Responsive: mobile-first with Tailwind breakpoints (sm, md, lg, xl)\n- Lighthouse performance score 95+\n- Semantic HTML with ARIA labels and keyboard navigation\n- No emoji anywhere in text, UI, code, or comments\n- Use lucide-react for icons\n\n# Design Direction\n\n- Theme: {{THEME}}\n- Accent color: {{ACCENT_COLOR}}\n- Animation level: {{ANIMATION_LEVEL}}\n- Font: {{FONT}}\n\nDesign guidelines:\n- Typography-driven layout with large, bold headings\n- Generous whitespace between sections\n- Single accent color for interactive elements and highlights only\n- Project cards should feel substantial but clean\n- The site must look hand-crafted, not template-generated\n- Dark themes: use zinc/slate backgrounds, not pure black\n- Light themes: use warm whites and subtle grays\n\n# Content Generation\n\nFor each project in the spec:\n- Write a 2-3 sentence narrative description based on the README content and tech stack\n- Focus on what it does and why it matters\n- If user provided an override description, use that instead\n- Maintain consistent voice across all descriptions\n\nFor the bio (if set to \"auto\"):\n- Generate a professional, authentic bio based on the project portfolio\n- Emphasize shipping velocity and breadth\n- Tone: confident, direct, no buzzwords or fluff\n\n# Sections to Include\n\n{{SECTIONS_LIST}}\n\nHero and Projects are always included. Additional sections as specified.\n\n# Print / PDF Styles\n\nIn globals.css, add @media print rules:\n- Single-column layout\n- Hide navigation, footer, animations\n- Preserve background colors (user will print with backgrounds enabled)\n- Show link URLs inline: \\`a[href]::after { content: \" (\" attr(href) \")\"; }\\`\n- Avoid page breaks inside project cards\n- A4-friendly margins and font sizes\n\n# File Structure to Generate\n\n\\`\\`\\`\nnext.config.ts\npackage.json\ntailwind.config.ts\ntsconfig.json\npostcss.config.mjs\ncomponents.json\nsrc/app/layout.tsx\nsrc/app/page.tsx\nsrc/app/globals.css\nsrc/components/ui/ (shadcn components as needed)\nsrc/components/hero.tsx\nsrc/components/project-card.tsx\nsrc/components/project-grid.tsx\nsrc/components/skills.tsx\nsrc/components/about.tsx\nsrc/components/timeline.tsx\nsrc/components/contact.tsx\nsrc/components/navigation.tsx\nsrc/components/footer.tsx\nsrc/data/projects.ts\nsrc/data/owner.ts\nsrc/lib/utils.ts\npublic/favicon.svg\nshipfolio.config.json\n\\`\\`\\`\n\n# Important\n\n- Generate ALL files needed for the project to build successfully\n- Include all shadcn/ui component files that are referenced\n- The \\`package.json\\` must include all dependencies\n- \\`npm install && npm run build\\` must succeed without errors\n- Do not use next/image (incompatible with static export) -- use standard <img> tags\n- Do not use features that require a server (API routes, middleware, ISR)\n`;\n\nconst UPDATE_TEMPLATE = `# Task\n\nUpdate an existing portfolio website previously generated by shipfolio.\nYou must preserve the existing design system, layout structure, component\narchitecture, and any custom modifications the user has made.\n\n# Existing Site Configuration\n\n{{EXISTING_CONFIG_JSON}}\n\n# Changes to Apply\n\n## New Projects to Add\n{{NEW_PROJECTS}}\n\n## Projects to Update (new commits since last scan)\n{{UPDATED_PROJECTS}}\n\n## Projects to Remove\n{{REMOVED_PROJECTS}}\n\n## Updated Personal Info\n{{PERSONAL_INFO_DIFF}}\n\n# Rules\n\n1. Do NOT change the overall layout, color scheme, or design system\n2. Do NOT reorganize existing components or rename files\n3. Only modify files that need changes for the specified updates\n4. For new projects: follow the exact same card format and component pattern\n as existing project cards\n5. Preserve all custom CSS, custom components, and manual edits\n6. Update src/data/projects.ts with new/changed/removed project data\n7. Update src/data/owner.ts if personal info changed\n8. Update shipfolio.config.json with new timestamps and project list\n9. If a new section type is needed, create it following the existing\n component patterns and design tokens in the codebase\n10. No emoji anywhere\n\n# Technical Notes\n\n- The site uses Next.js 15 + Tailwind CSS + shadcn/ui\n- Static export via \\`output: 'export'\\` in next.config.ts\n- Do not break the build -- \\`npm run build\\` must succeed\n- Do not add new dependencies unless absolutely necessary\n- Keep the existing @media print styles working\n`;\n\nexport async function buildFreshPrompt(spec: ShipfolioSpec): Promise<string> {\n let template = FRESH_BUILD_TEMPLATE;\n\n const sectionsText = spec.sections\n .map((s) => `- ${s}`)\n .join(\"\\n\");\n\n template = template\n .replace(\"{{SPEC_JSON}}\", JSON.stringify(spec, null, 2))\n .replace(\"{{THEME}}\", spec.style.theme)\n .replace(\"{{ACCENT_COLOR}}\", spec.style.accentColor)\n .replace(\"{{ANIMATION_LEVEL}}\", spec.style.animationLevel)\n .replace(\"{{FONT}}\", spec.style.font)\n .replace(\"{{SECTIONS_LIST}}\", sectionsText);\n\n return template;\n}\n\nexport async function buildUpdatePrompt(\n existingConfig: ShipfolioConfig,\n diff: SiteDiff\n): Promise<string> {\n let template = UPDATE_TEMPLATE;\n\n const newProjectsText =\n diff.newProjects.length > 0\n ? diff.newProjects\n .map(\n (p) =>\n `- ${p.name}: ${p.description}\\n Tech: ${p.techStack.join(\", \")}\\n README excerpt: ${(p.readmeContent || \"\").slice(0, 500)}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const updatedProjectsText =\n diff.updatedProjects.length > 0\n ? diff.updatedProjects\n .map(\n (u) =>\n `- ${u.project.name}: ${u.newCommits} new commits\\n README changed: ${u.readmeChanged}\\n Dependencies changed: ${u.depsChanged}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const removedProjectsText =\n diff.removedProjects.length > 0\n ? diff.removedProjects.map((p) => `- ${p.name}`).join(\"\\n\")\n : \"None\";\n\n template = template\n .replace(\n \"{{EXISTING_CONFIG_JSON}}\",\n JSON.stringify(existingConfig, null, 2)\n )\n .replace(\"{{NEW_PROJECTS}}\", newProjectsText)\n .replace(\"{{UPDATED_PROJECTS}}\", updatedProjectsText)\n .replace(\"{{REMOVED_PROJECTS}}\", removedProjectsText)\n .replace(\"{{PERSONAL_INFO_DIFF}}\", \"No changes\");\n\n return template;\n}\n","import { execa, type Options as ExecaOptions } from \"execa\";\n\nexport async function run(\n command: string,\n args: string[],\n options?: ExecaOptions\n) {\n return execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n try {\n await execa(\"which\", [command]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function runWithOutput(\n command: string,\n args: string[],\n options?: ExecaOptions\n): Promise<string> {\n const result = await execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n return result.stdout;\n}\n","import { commandExists } from \"../utils/exec.js\";\nimport type { EngineType } from \"../spec/schema.js\";\n\nexport interface DetectedEngine {\n type: EngineType;\n available: boolean;\n}\n\nexport async function detectEngines(): Promise<DetectedEngine[]> {\n const results: DetectedEngine[] = [];\n\n // Check for v0 API key\n if (process.env.V0_API_KEY) {\n results.push({ type: \"v0\", available: true });\n }\n\n // Check for Claude Code CLI\n if (await commandExists(\"claude\")) {\n results.push({ type: \"claude\", available: true });\n }\n\n // Check for Codex CLI\n if (await commandExists(\"codex\")) {\n results.push({ type: \"codex\", available: true });\n }\n\n return results;\n}\n\nexport function getAvailableEngineTypes(engines: DetectedEngine[]): EngineType[] {\n return engines.filter((e) => e.available).map((e) => e.type);\n}\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nexport async function generateWithClaude(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Claude Code...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"claude\", [\n \"-p\",\n \"--permission-mode\", \"bypassPermissions\",\n ], {\n cwd: outputDir,\n input: fullPrompt,\n stdout: \"ignore\",\n stderr: \"pipe\",\n timeout: 600000, // 10 minute timeout\n });\n\n spinner.succeed(\"Site generated with Claude Code\");\n } catch (error) {\n spinner.fail(\"Claude Code generation failed\");\n throw error;\n }\n}\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nexport async function generateWithCodex(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Codex...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"codex\", [\"--quiet\", \"--full-auto\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 600000,\n });\n\n spinner.succeed(\"Site generated with Codex\");\n } catch (error) {\n spinner.fail(\"Codex generation failed\");\n throw error;\n }\n}\n","import OpenAI from \"openai\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\ninterface ExtractedFile {\n filename: string;\n content: string;\n}\n\nexport async function generateWithV0(\n prompt: string,\n outputDir: string,\n apiKey: string\n): Promise<void> {\n const spinner = ora(\"Generating site with v0...\").start();\n\n const client = new OpenAI({\n apiKey,\n baseURL: \"https://api.v0.dev/v1\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: \"v0-1.0-md\",\n messages: [\n {\n role: \"system\",\n content:\n \"Generate a complete Next.js 15 portfolio website using TypeScript, Tailwind CSS, and shadcn/ui. \" +\n \"Return all files with their paths clearly marked. Use ```tsx filename.tsx or ```ts filename.ts \" +\n \"code blocks with the filename on the same line as the opening backticks. \" +\n \"No emoji in any output.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(\"v0 returned empty response\");\n }\n\n spinner.text = \"Parsing v0 output...\";\n\n const files = extractFiles(content);\n if (files.length === 0) {\n throw new Error(\"No files extracted from v0 response\");\n }\n\n spinner.text = `Writing ${files.length} files...`;\n\n for (const file of files) {\n const filePath = join(outputDir, file.filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content, \"utf-8\");\n }\n\n // Ensure package.json exists with required deps\n const hasPkgJson = files.some((f) => f.filename === \"package.json\");\n if (!hasPkgJson) {\n await writeFile(\n join(outputDir, \"package.json\"),\n JSON.stringify(\n {\n name: \"shipfolio-site\",\n version: \"1.0.0\",\n private: true,\n scripts: {\n dev: \"next dev\",\n build: \"next build\",\n start: \"next start\",\n },\n dependencies: {\n next: \"^15.0.0\",\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"class-variance-authority\": \"^0.7.0\",\n clsx: \"^2.1.0\",\n \"tailwind-merge\": \"^2.6.0\",\n \"lucide-react\": \"^0.460.0\",\n },\n devDependencies: {\n typescript: \"^5.7.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n tailwindcss: \"^4.0.0\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n }\n\n spinner.succeed(`Site generated with v0 (${files.length} files)`);\n } catch (error) {\n spinner.fail(\"v0 generation failed\");\n throw error;\n }\n}\n\nfunction extractFiles(content: string): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n // Match code blocks with filename: ```tsx src/app/page.tsx or ```tsx filename=\"src/app/page.tsx\"\n const patterns = [\n // ```tsx src/app/page.tsx\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+([^\\n`]+)\\n([\\s\\S]*?)```/g,\n // ```tsx filename=\"src/app/page.tsx\"\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+filename=\"([^\"]+)\"\\n([\\s\\S]*?)```/g,\n // ```tsx {filename: \"src/app/page.tsx\"}\n /```(?:tsx?|jsx?|css|json|mjs|cjs).*?filename:\\s*\"([^\"]+)\".*?\\n([\\s\\S]*?)```/g,\n ];\n\n for (const pattern of patterns) {\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const filename = match[1].trim();\n const fileContent = match[2].trim();\n\n // Skip if filename looks like a description rather than a path\n if (\n filename.includes(\" \") &&\n !filename.includes(\"/\") &&\n !filename.includes(\".\")\n ) {\n continue;\n }\n\n // Clean up filename\n const cleanFilename = filename\n .replace(/^[\"']|[\"']$/g, \"\")\n .replace(/^\\.\\//g, \"\");\n\n if (cleanFilename && fileContent) {\n files.push({ filename: cleanFilename, content: fileContent });\n }\n }\n }\n\n return files;\n}\n","import { fileExists, join } from \"../utils/fs.js\";\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport async function validateGeneratedSite(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const requiredFiles = [\n \"package.json\",\n \"next.config.ts\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n ];\n\n // Also check common alternatives\n const alternativeChecks: [string, string[]][] = [\n [\"next.config.ts\", [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\"]],\n ];\n\n for (const file of requiredFiles) {\n const alternatives = alternativeChecks.find(([key]) => key === file);\n if (alternatives) {\n const anyExists = await Promise.any(\n alternatives[1].map(async (alt) => {\n if (await fileExists(join(siteDir, alt))) return true;\n throw new Error(\"not found\");\n })\n ).catch(() => false);\n if (!anyExists) {\n errors.push(`Missing: ${file} (or any alternative)`);\n }\n } else {\n if (!(await fileExists(join(siteDir, file)))) {\n errors.push(`Missing: ${file}`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\nexport async function validateBuildOutput(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n errors.push(\"Build output directory 'out/' not found\");\n return { valid: false, errors };\n }\n\n const indexHtml = join(outDir, \"index.html\");\n if (!(await fileExists(indexHtml))) {\n errors.push(\"Missing: out/index.html\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { generateWithClaude } from \"./engines/claude.js\";\nimport { generateWithCodex } from \"./engines/codex.js\";\nimport { generateWithV0 } from \"./engines/v0.js\";\nimport {\n validateGeneratedSite,\n validateBuildOutput,\n} from \"./validator.js\";\nimport { ensureDir } from \"../utils/fs.js\";\nimport { run } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EngineType } from \"../spec/schema.js\";\nimport ora from \"ora\";\n\nasync function runEngine(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n switch (engine) {\n case \"claude\":\n await generateWithClaude(prompt, outputDir);\n break;\n case \"codex\":\n await generateWithCodex(prompt, outputDir);\n break;\n case \"v0\": {\n const apiKey = process.env.V0_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"V0_API_KEY environment variable is required for v0 engine\"\n );\n }\n await generateWithV0(prompt, outputDir, apiKey);\n break;\n }\n }\n}\n\nexport async function generateSite(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n await ensureDir(outputDir);\n\n await runEngine(engine, prompt, outputDir);\n\n // Validate generated output\n let validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Generated site has issues:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n\n // Retry: feed validation errors back to the AI\n logger.info(\"Retrying generation with error feedback...\");\n const fixPrompt = [\n \"The previous generation was incomplete. The following required files are missing:\",\n ...validation.errors.map((e) => `- ${e}`),\n \"\",\n \"Please create ALL missing files. Here is the original specification:\",\n \"\",\n prompt,\n ].join(\"\\n\");\n\n await runEngine(engine, fixPrompt, outputDir);\n\n validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Still missing files after retry:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n }\n }\n}\n\nexport async function buildSite(siteDir: string): Promise<boolean> {\n const spinner = ora(\"Installing dependencies...\").start();\n\n try {\n await run(\"npm\", [\"install\"], { cwd: siteDir });\n spinner.text = \"Building site...\";\n await run(\"npm\", [\"run\", \"build\"], { cwd: siteDir });\n spinner.succeed(\"Site built successfully\");\n } catch (error: any) {\n spinner.fail(\"Build failed\");\n logger.error(error.stderr || error.message || String(error));\n return false;\n }\n\n // Validate build output\n const validation = await validateBuildOutput(siteDir);\n if (!validation.valid) {\n logger.error(\"Build output validation failed:\");\n for (const err of validation.errors) {\n logger.error(` ${err}`);\n }\n return false;\n }\n\n return true;\n}\n\nexport async function retryBuild(\n engine: EngineType,\n siteDir: string,\n buildError: string,\n originalPrompt: string\n): Promise<boolean> {\n logger.info(\"Retrying: feeding build error back to AI...\");\n\n const fixPrompt = `The site generation produced build errors. Fix the following errors without changing the overall design or structure:\\n\\n${buildError}\\n\\nOriginal prompt for context:\\n${originalPrompt.slice(0, 2000)}`;\n\n try {\n await runEngine(engine, fixPrompt, siteDir);\n return await buildSite(siteDir);\n } catch {\n return false;\n }\n}\n","import { run, commandExists, runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\n\nexport async function checkAuth(\n platform: DeployPlatform\n): Promise<boolean> {\n if (platform === \"local\") return true;\n\n try {\n if (platform === \"cloudflare\") {\n await runWithOutput(\"npx\", [\"wrangler\", \"whoami\"]);\n return true;\n }\n if (platform === \"vercel\") {\n await runWithOutput(\"npx\", [\"vercel\", \"whoami\"]);\n return true;\n }\n } catch {\n return false;\n }\n return false;\n}\n\nexport async function login(platform: DeployPlatform): Promise<void> {\n if (platform === \"cloudflare\") {\n logger.info(\"Opening Cloudflare login in browser...\");\n await run(\"npx\", [\"wrangler\", \"login\"], { stdio: \"inherit\" });\n } else if (platform === \"vercel\") {\n logger.info(\"Opening Vercel login in browser...\");\n await run(\"npx\", [\"vercel\", \"login\"], { stdio: \"inherit\" });\n }\n}\n\nexport async function ensureAuth(platform: DeployPlatform): Promise<void> {\n if (platform === \"local\") return;\n\n const isAuthed = await checkAuth(platform);\n if (!isAuthed) {\n await login(platform);\n // Verify login succeeded\n const nowAuthed = await checkAuth(platform);\n if (!nowAuthed) {\n throw new Error(`Authentication failed for ${platform}`);\n }\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToCloudflare(\n distDir: string,\n projectName: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Cloudflare Pages...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"wrangler\",\n \"pages\",\n \"deploy\",\n distDir,\n `--project-name=${projectName}`,\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.pages\\.dev/\n );\n const url = urlMatch?.[0] || `https://${projectName}.pages.dev`;\n\n spinner.succeed(`Deployed to Cloudflare Pages`);\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Cloudflare Pages deployment failed\");\n throw error;\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToVercel(\n distDir: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Vercel...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"vercel\",\n \"deploy\",\n distDir,\n \"--yes\",\n \"--prod\",\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.vercel\\.app/\n );\n const url = urlMatch?.[0] || output.trim().split(\"\\n\").pop() || \"\";\n\n spinner.succeed(\"Deployed to Vercel\");\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Vercel deployment failed\");\n throw error;\n }\n}\n","import { run, runWithOutput, commandExists } from \"../utils/exec.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport * as p from \"@clack/prompts\";\n\nexport async function setupGitHubAutoDeploy(\n siteDir: string,\n projectName: string\n): Promise<void> {\n const hasGh = await commandExists(\"gh\");\n if (!hasGh) {\n logger.info(\n \"GitHub CLI (gh) not found. Install it to enable auto-deploy setup.\"\n );\n return;\n }\n\n const shouldSetup = (await p.confirm({\n message: \"Set up GitHub auto-deploy? (push = redeploy)\",\n initialValue: false,\n })) as boolean;\n\n if (p.isCancel(shouldSetup) || !shouldSetup) return;\n\n const visibility = (await p.select({\n message: \"Repository visibility:\",\n options: [\n { value: \"private\", label: \"Private\" },\n { value: \"public\", label: \"Public\" },\n ],\n })) as string;\n\n if (p.isCancel(visibility)) return;\n\n try {\n // Init git if not already\n const gitDir = join(siteDir, \".git\");\n if (!(await fileExists(gitDir))) {\n await run(\"git\", [\"init\"], { cwd: siteDir });\n }\n\n // Create GitHub repo\n await run(\n \"gh\",\n [\n \"repo\",\n \"create\",\n projectName,\n `--${visibility}`,\n \"--source\",\n siteDir,\n \"--push\",\n ],\n { cwd: siteDir, stdio: \"inherit\" }\n );\n\n logger.success(`GitHub repository created: ${projectName}`);\n logger.info(\n \"Connect this repo in your Cloudflare Pages or Vercel dashboard for auto-deploy.\"\n );\n } catch (error: any) {\n logger.error(`GitHub setup failed: ${error.message}`);\n }\n}\n","import { ensureAuth } from \"./auth.js\";\nimport { deployToCloudflare } from \"./cloudflare.js\";\nimport { deployToVercel } from \"./vercel.js\";\nimport { setupGitHubAutoDeploy } from \"./github.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\nimport { join } from \"node:path\";\n\nexport async function deploy(\n siteDir: string,\n platform: DeployPlatform,\n projectName: string\n): Promise<string | null> {\n if (platform === \"local\") {\n logger.info(`Site built at ${join(siteDir, \"out/\")}`);\n logger.info(\"Run `npx serve ./out` in the site directory to preview.\");\n return null;\n }\n\n await ensureAuth(platform);\n\n const distDir = join(siteDir, \"out\");\n let url: string;\n\n if (platform === \"cloudflare\") {\n url = await deployToCloudflare(distDir, projectName);\n } else {\n url = await deployToVercel(distDir);\n }\n\n // Offer GitHub auto-deploy setup\n await setupGitHubAutoDeploy(siteDir, projectName);\n\n return url;\n}\n","import { createServer, type Server } from \"node:http\";\nimport { join } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function exportPdf(\n siteDir: string,\n outputPath?: string\n): Promise<string> {\n const distDir = join(siteDir, \"out\");\n const pdfPath = outputPath || join(distDir, \"shipfolio.pdf\");\n\n const spinner = ora(\"Exporting PDF...\").start();\n\n // Start a local server for the built site\n const server = await startStaticServer(distDir);\n const port = (server.address() as any)?.port || 3456;\n\n try {\n // Dynamic import to avoid requiring playwright at install time\n const { chromium } = await import(\"playwright\");\n\n const browser = await chromium.launch();\n const page = await browser.newPage();\n\n await page.goto(`http://localhost:${port}`, {\n waitUntil: \"networkidle\",\n });\n\n // Wait a moment for any CSS transitions to complete\n await page.waitForTimeout(1000);\n\n await page.pdf({\n path: pdfPath,\n format: \"A4\",\n printBackground: true,\n margin: {\n top: \"1cm\",\n right: \"1cm\",\n bottom: \"1cm\",\n left: \"1cm\",\n },\n });\n\n await browser.close();\n spinner.succeed(`PDF exported: ${pdfPath}`);\n return pdfPath;\n } catch (error: any) {\n spinner.fail(\"PDF export failed\");\n if (error.message?.includes(\"browserType.launch\")) {\n logger.error(\n \"Playwright browsers not installed. Run: npx playwright install chromium\"\n );\n } else {\n logger.error(error.message || String(error));\n }\n throw error;\n } finally {\n server.close();\n }\n}\n\nfunction startStaticServer(dir: string): Promise<Server> {\n return new Promise(async (resolve, reject) => {\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: dir,\n cleanUrls: true,\n });\n });\n\n server.listen(0, () => {\n resolve(server);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nexport async function startPreviewServer(\n siteDir: string,\n port: number = 3000\n): Promise<Server> {\n const distDir = join(siteDir, \"out\");\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: distDir,\n cleanUrls: true,\n });\n });\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n logger.info(`Preview: http://localhost:${port}`);\n resolve(server);\n });\n server.on(\"error\", reject);\n });\n}\n","import { readFile, writeFile, mkdir, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { logger } from \"./logger.js\";\nimport { t } from \"./i18n.js\";\n\nconst DRAFT_DIR = join(homedir(), \".shipfolio\");\nconst DRAFT_FILE = join(DRAFT_DIR, \"draft.json\");\n\nexport interface DraftData {\n timestamp: string;\n interviewResult: unknown;\n}\n\nexport async function saveDraft(interviewResult: unknown): Promise<void> {\n try {\n await mkdir(DRAFT_DIR, { recursive: true });\n const draft: DraftData = {\n timestamp: new Date().toISOString(),\n interviewResult,\n };\n await writeFile(DRAFT_FILE, JSON.stringify(draft, null, 2), \"utf-8\");\n logger.info(t().draftSaved);\n } catch {\n // Silent fail -- draft saving is best-effort\n }\n}\n\nexport async function loadDraft(): Promise<DraftData | null> {\n try {\n const content = await readFile(DRAFT_FILE, \"utf-8\");\n return JSON.parse(content) as DraftData;\n } catch {\n return null;\n }\n}\n\nexport async function clearDraft(): Promise<void> {\n try {\n await unlink(DRAFT_FILE);\n logger.info(t().draftCleared);\n } catch {\n // File may not exist\n }\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview, type InterviewResult } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite, retryBuild } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { writeJson, ensureDir } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { loadDraft, saveDraft, clearDraft } from \"../utils/draft.js\";\nimport { t } from \"../utils/i18n.js\";\n\ninterface InitOptions {\n scan?: string[];\n engine?: string;\n deploy?: string;\n style?: string;\n accent?: string;\n auto?: boolean;\n output?: string;\n noPdf?: boolean;\n noPreview?: boolean;\n verbose?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n logger.header(\"shipfolio v1.0.4\");\n\n // Step 1: Detect AI engines\n logger.info(\"Detecting AI engines...\");\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found.\");\n logger.plain(\"\");\n logger.plain(\" shipfolio requires one of the following:\");\n logger.plain(\" - Claude Code: npm install -g @anthropic-ai/claude-code\");\n logger.plain(\" - Codex: npm install -g @openai/codex\");\n logger.plain(\" - v0: Set V0_API_KEY environment variable\");\n logger.plain(\"\");\n process.exit(1);\n }\n\n logger.info(\n `Available engines: ${availableTypes.join(\", \")}`\n );\n\n // Step 2: Scan projects\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found. Specify a different directory with --scan.\");\n process.exit(1);\n }\n\n // Display scanned projects\n logger.header(`Found ${scannedProjects.length} projects:`);\n const tableRows = scannedProjects.map((proj) => [\n proj.name,\n proj.techStack.slice(0, 3).join(\", \"),\n proj.firstCommitDate?.slice(0, 10) || \"?\",\n `${proj.totalCommits} commits`,\n ]);\n logger.table(tableRows);\n logger.blank();\n\n // Step 3: Check for draft\n let interviewResult: InterviewResult;\n\n const draft = await loadDraft();\n if (draft) {\n logger.info(t().draftFound);\n const useDraft = (await p.confirm({\n message: t().draftLoadPrompt,\n initialValue: true,\n })) as boolean;\n\n if (!p.isCancel(useDraft) && useDraft) {\n interviewResult = draft.interviewResult as InterviewResult;\n await clearDraft();\n } else {\n interviewResult = await runInterview(scannedProjects, availableTypes);\n }\n } else {\n interviewResult = await runInterview(scannedProjects, availableTypes);\n }\n\n // Save draft in case later steps fail\n await saveDraft(interviewResult);\n\n // Step 4: Build spec\n const spec = buildSpec(interviewResult);\n\n // Step 5: Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Step 6: Generate site\n const outputDir = resolve(options.output || \"./shipfolio-site\");\n await ensureDir(outputDir);\n\n await generateSite(spec.engine, prompt, outputDir);\n\n // Step 7: Build\n let buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n buildSuccess = await retryBuild(spec.engine, outputDir, \"Build failed. Check missing files and fix errors.\", prompt);\n if (!buildSuccess) {\n logger.error(\"Build failed after retry. Check the output directory for details.\");\n process.exit(1);\n }\n }\n\n // Step 8: Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(outputDir);\n logger.blank();\n\n const proceed = (await p.confirm({\n message: \"Deploy now?\",\n initialValue: true,\n })) as boolean;\n\n server.close();\n\n if (p.isCancel(proceed) || !proceed) {\n if (spec.deploy.platform === \"local\") {\n // Already local, just exit\n } else {\n logger.info(\"Skipping deploy. Run `npx shipfolio deploy` later.\");\n }\n }\n }\n\n // Step 9: PDF export\n if (!options.noPdf) {\n try {\n await exportPdf(outputDir);\n } catch {\n logger.warn(\"PDF export skipped due to error.\");\n }\n }\n\n // Step 10: Deploy\n if (spec.deploy.platform !== \"local\") {\n const url = await deploy(\n outputDir,\n spec.deploy.platform,\n spec.deploy.projectName\n );\n if (url) {\n spec.deploy.url = url;\n }\n }\n\n // Save config for future updates\n await writeJson(join(outputDir, \"shipfolio.config.json\"), {\n ...spec,\n sitePath: outputDir,\n });\n\n // Clear draft on success\n await clearDraft();\n\n // Summary\n logger.header(\"Done.\");\n if (spec.deploy.url) {\n logger.info(`Site: ${spec.deploy.url}`);\n }\n logger.info(`Local: ${outputDir}`);\n logger.info(\n `Update: npx shipfolio update --site ${outputDir}`\n );\n}\n","import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { specCommand } from \"./commands/spec.js\";\nimport { deployCommand } from \"./commands/deploy.js\";\nimport { pdfCommand } from \"./commands/pdf.js\";\nimport { previewCommand } from \"./commands/preview.js\";\nimport { initLocale } from \"./utils/i18n.js\";\n\ninitLocale();\n\nconst program = new Command();\n\nprogram\n .name(\"shipfolio\")\n .description(\n \"Generate and deploy your personal portfolio site from local projects using AI\"\n )\n .version(\"1.0.4\");\n\n// Default command: init (fresh build)\nprogram\n .command(\"init\", { isDefault: true })\n .description(\"Generate a new portfolio site\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-e, --engine <engine>\", \"AI engine: claude | codex | v0\")\n .option(\"-d, --deploy <platform>\", \"Deploy target: cloudflare | vercel | local\")\n .option(\"--style <theme>\", \"Theme: dark-minimal | light-clean | monochrome\")\n .option(\"--accent <hex>\", \"Accent color (hex)\")\n .option(\"--auto\", \"Skip prompts, use defaults\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./shipfolio-site\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip local preview\")\n .option(\"-v, --verbose\", \"Verbose output\")\n .action(initCommand);\n\n// Update existing site\nprogram\n .command(\"update\")\n .description(\"Update an existing portfolio site\")\n .requiredOption(\"--site <path>\", \"Path to existing site directory\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip preview\")\n .option(\"--no-deploy\", \"Skip deployment\")\n .action(updateCommand);\n\n// Generate spec only (for use inside AI tools)\nprogram\n .command(\"spec\")\n .description(\"Generate spec and prompt files only\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-o, --output <dir>\", \"Output directory for spec files\", \".\")\n .action(specCommand);\n\n// Deploy existing site\nprogram\n .command(\"deploy\")\n .description(\"Deploy an existing built site\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-p, --platform <platform>\", \"Deploy platform: cloudflare | vercel\")\n .action(deployCommand);\n\n// Export PDF\nprogram\n .command(\"pdf\")\n .description(\"Export site to PDF\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-o, --output <path>\", \"PDF output path\")\n .action(pdfCommand);\n\n// Preview\nprogram\n .command(\"preview\")\n .description(\"Start local preview server\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"--port <port>\", \"Port number\", \"3000\")\n .action((opts) => previewCommand({ ...opts, port: parseInt(opts.port) }));\n\nprogram.parse();\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { computeDiff } from \"../spec/diff.js\";\nimport { buildUpdatePrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf, startPreviewServer } from \"../pdf/index.js\";\nimport { readJson, writeJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, ProjectEntry } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface UpdateOptions {\n site: string;\n scan?: string[];\n noPdf?: boolean;\n noPreview?: boolean;\n noDeploy?: boolean;\n}\n\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\n logger.header(\"shipfolio update\");\n\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n // Read existing config\n if (!(await fileExists(configPath))) {\n logger.error(\n \"shipfolio.config.json not found. This directory was not generated by shipfolio.\"\n );\n const fresh = (await p.confirm({\n message: \"Proceed with fresh build instead?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(fresh) || !fresh) {\n process.exit(0);\n }\n\n // Redirect to init\n const { initCommand } = await import(\"./init.js\");\n await initCommand({ output: siteDir });\n return;\n }\n\n const config = await readJson<ShipfolioConfig>(configPath);\n logger.info(\n `Site: ${config.deploy.projectName || \"local\"} (generated ${config.generatedAt.slice(0, 10)})`\n );\n logger.info(`Theme: ${config.style.theme}`);\n logger.info(`Projects: ${config.projects.length}`);\n\n // Detect engines\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found. See `npx shipfolio` for install instructions.\");\n process.exit(1);\n }\n\n // Scan for changes\n const scanDirs = options.scan?.map((d) => resolve(d)) ||\n [...new Set(config.projects.map((p) => {\n const parts = p.localPath.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n }))];\n\n const scannedProjects = await scanProjects(scanDirs);\n const diff = computeDiff(config, scannedProjects);\n\n // Display changes\n logger.header(\"Changes detected:\");\n\n if (diff.newProjects.length > 0) {\n logger.plain(\" New:\");\n for (const proj of diff.newProjects) {\n logger.plain(` + ${proj.name} ${proj.techStack.slice(0, 3).join(\", \")}`);\n }\n }\n\n if (diff.updatedProjects.length > 0) {\n logger.plain(\" Updated:\");\n for (const upd of diff.updatedProjects) {\n logger.plain(\n ` ~ ${upd.project.name} ${upd.newCommits} new commits`\n );\n }\n }\n\n if (diff.removedProjects.length > 0) {\n logger.plain(\" Removed:\");\n for (const proj of diff.removedProjects) {\n logger.plain(` - ${proj.name} (directory gone)`);\n }\n }\n\n if (\n diff.newProjects.length === 0 &&\n diff.updatedProjects.length === 0 &&\n diff.removedProjects.length === 0\n ) {\n logger.info(\"No changes detected.\");\n return;\n }\n\n // Confirm changes\n const proceed = (await p.confirm({\n message: \"Apply these changes?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(proceed) || !proceed) {\n process.exit(0);\n }\n\n // Build update prompt\n const engine = availableTypes.includes(config.engine)\n ? config.engine\n : availableTypes[0];\n\n const prompt = await buildUpdatePrompt(config, diff);\n\n // Generate updates\n await generateSite(engine, prompt, siteDir);\n\n // Build\n const buildSuccess = await buildSite(siteDir);\n if (!buildSuccess) {\n logger.error(\"Build failed. Check the site directory.\");\n process.exit(1);\n }\n\n // Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(siteDir);\n const ok = (await p.confirm({\n message: \"Looks good?\",\n initialValue: true,\n })) as boolean;\n server.close();\n if (p.isCancel(ok) || !ok) {\n logger.info(\"Update cancelled at preview.\");\n return;\n }\n }\n\n // PDF\n if (!options.noPdf) {\n try {\n await exportPdf(siteDir);\n } catch {\n logger.warn(\"PDF export skipped.\");\n }\n }\n\n // Deploy\n if (!options.noDeploy && config.deploy.platform !== \"local\") {\n await deploy(siteDir, config.deploy.platform, config.deploy.projectName);\n }\n\n // Update config\n const updatedConfig: ShipfolioConfig = {\n ...config,\n generatedAt: new Date().toISOString(),\n projects: [\n ...diff.unchangedProjects,\n ...diff.updatedProjects.map((u) => {\n const existing = config.projects.find(\n (p) => p.localPath === u.project.localPath\n );\n return {\n ...u.project,\n included: true,\n overrideDescription: existing?.overrideDescription || null,\n showSourceLink: existing?.showSourceLink ?? !!u.project.remoteUrl,\n role: existing?.role || \"solo\",\n metrics: existing?.metrics || {},\n } as ProjectEntry;\n }),\n ...diff.newProjects.map(\n (proj) =>\n ({\n ...proj,\n included: true,\n overrideDescription: null,\n showSourceLink: !!proj.remoteUrl,\n role: \"solo\" as const,\n metrics: {},\n }) as ProjectEntry\n ),\n ],\n };\n\n await writeJson(join(siteDir, \"shipfolio.config.json\"), updatedConfig);\n logger.success(\"Update complete.\");\n}\n","import type {\n ProjectMeta,\n ProjectEntry,\n ShipfolioConfig,\n SiteDiff,\n ProjectUpdate,\n} from \"./schema.js\";\n\nexport function computeDiff(\n oldConfig: ShipfolioConfig,\n newScan: ProjectMeta[]\n): SiteDiff {\n const oldProjectMap = new Map(\n oldConfig.projects.map((p) => [p.localPath, p])\n );\n const newProjectMap = new Map(newScan.map((p) => [p.localPath, p]));\n\n const newProjects: ProjectMeta[] = [];\n const updatedProjects: ProjectUpdate[] = [];\n const removedProjects: ProjectEntry[] = [];\n const unchangedProjects: ProjectEntry[] = [];\n\n // Check new and updated\n for (const [path, meta] of newProjectMap) {\n const oldProject = oldProjectMap.get(path);\n if (!oldProject) {\n newProjects.push(meta);\n } else if (meta.lastScannedCommit !== oldProject.lastScannedCommit) {\n const newCommits = meta.totalCommits - oldProject.totalCommits;\n updatedProjects.push({\n project: meta,\n newCommits: Math.max(newCommits, 0),\n readmeChanged: meta.readmeContent !== oldProject.readmeContent,\n depsChanged:\n JSON.stringify(meta.techStack) !==\n JSON.stringify(oldProject.techStack),\n });\n } else {\n unchangedProjects.push(oldProject);\n }\n }\n\n // Check removed\n for (const [path, project] of oldProjectMap) {\n if (!newProjectMap.has(path)) {\n removedProjects.push(project);\n }\n }\n\n return {\n newProjects,\n updatedProjects,\n removedProjects,\n unchangedProjects,\n };\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { writeJson, writeText } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface SpecOptions {\n scan?: string[];\n output?: string;\n}\n\nexport async function specCommand(options: SpecOptions): Promise<void> {\n logger.header(\"shipfolio spec\");\n\n // Detect engines (needed for interview but not for execution)\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n // Even if no engine is available, we can still generate spec\n // (user will use it inside their own AI session)\n const engineTypes =\n availableTypes.length > 0 ? availableTypes : ([\"claude\"] as const);\n\n // Scan\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found.\");\n process.exit(1);\n }\n\n logger.info(`Found ${scannedProjects.length} projects`);\n\n // Interview\n const interviewResult = await runInterview(\n scannedProjects,\n [...engineTypes]\n );\n\n // Build spec\n const spec = buildSpec(interviewResult);\n\n // Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Save outputs\n const outputDir = options.output || \".\";\n const specPath = resolve(outputDir, \"shipfolio-spec.json\");\n const promptPath = resolve(outputDir, \"shipfolio-prompt.md\");\n\n await writeJson(specPath, spec);\n await writeText(promptPath, prompt);\n\n logger.success(`Spec saved: ${specPath}`);\n logger.success(`Prompt saved: ${promptPath}`);\n logger.blank();\n logger.info(\n \"Use these files inside your Claude Code or Codex session to generate the site.\"\n );\n}\n","import { resolve } from \"node:path\";\nimport { deploy as deployFn } from \"../deployer/index.js\";\nimport { readJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, DeployPlatform } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface DeployOptions {\n site: string;\n platform?: string;\n}\n\nexport async function deployCommand(options: DeployOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n let platform: DeployPlatform;\n let projectName: string;\n\n if (await fileExists(configPath)) {\n const config = await readJson<ShipfolioConfig>(configPath);\n platform =\n (options.platform as DeployPlatform) || config.deploy.platform;\n projectName = config.deploy.projectName;\n } else {\n platform = (options.platform as DeployPlatform) || \"cloudflare\";\n projectName = (await p.text({\n message: \"Project name:\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n\n if (p.isCancel(projectName)) process.exit(0);\n }\n\n if (platform === \"local\") {\n logger.info(\"Deploy platform is set to local. Nothing to deploy.\");\n return;\n }\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n logger.error(\"Build output not found. Run `npm run build` in the site directory first.\");\n process.exit(1);\n }\n\n await deployFn(siteDir, platform, projectName);\n}\n","import { resolve } from \"node:path\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PdfOptions {\n site: string;\n output?: string;\n}\n\nexport async function pdfCommand(options: PdfOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n await exportPdf(siteDir, options.output);\n}\n","import { resolve } from \"node:path\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PreviewOptions {\n site: string;\n port?: number;\n}\n\nexport async function previewCommand(options: PreviewOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n const port = options.port || 3000;\n await startPreviewServer(siteDir, port);\n logger.info(\"Press Ctrl+C to stop.\");\n\n // Keep process alive\n await new Promise(() => {});\n}\n"],"mappings":"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","names":["glob","path","p","glob","p","p","execa","ora","execa","ora","writeFile","mkdir","join","ora","ora","ora","ora","p","join","join","ora","resolve","readFile","writeFile","mkdir","join","join","p","resolve","p","path","p","resolve","initCommand","resolve","resolve","p","resolve","resolve"]}
1
+ {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/scanner/git.ts","../src/utils/fs.ts","../src/scanner/detectors/node.ts","../src/scanner/detectors/python.ts","../src/scanner/detectors/rust.ts","../src/scanner/detectors/go.ts","../src/scanner/detectors/generic.ts","../src/scanner/extractors.ts","../src/utils/logger.ts","../src/scanner/index.ts","../src/utils/i18n.ts","../src/interviewer/questions.ts","../src/interviewer/index.ts","../src/spec/builder.ts","../src/orchestrator/prompt-builder.ts","../src/utils/exec.ts","../src/orchestrator/detect.ts","../src/orchestrator/engines/claude.ts","../src/orchestrator/engines/codex.ts","../src/orchestrator/engines/v0.ts","../src/orchestrator/validator.ts","../src/orchestrator/index.ts","../src/deployer/auth.ts","../src/deployer/cloudflare.ts","../src/deployer/vercel.ts","../src/deployer/github.ts","../src/deployer/index.ts","../src/pdf/index.ts","../src/utils/draft.ts","../src/commands/init.ts","../src/index.ts","../src/commands/update.ts","../src/spec/diff.ts","../src/commands/spec.ts","../src/commands/deploy.ts","../src/commands/pdf.ts","../src/commands/preview.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allPaths: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n // Find git repos\n const repos = await findGitRepos(dir);\n allPaths.push(...repos);\n\n // Also find non-git project directories (with package.json, Cargo.toml, etc.)\n const nonGitDirs = await findNonGitProjects(dir, new Set(repos));\n allPaths.push(...nonGitDirs);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniquePaths = [...new Set(allPaths)];\n spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const projectPath of uniquePaths) {\n try {\n const project = await extractProjectMeta(projectPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n // Deduplicate IDs (same folder name in different parent dirs)\n const idCounts = new Map<string, number>();\n for (const project of projects) {\n const count = idCounts.get(project.id) || 0;\n if (count > 0) {\n project.id = `${project.id}-${count}`;\n }\n idCounts.set(project.id.replace(/-\\d+$/, \"\"), count + 1);\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function findNonGitProjects(\n rootPath: string,\n gitRepos: Set<string>\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const indicators = [\n \"*/package.json\",\n \"*/Cargo.toml\",\n \"*/go.mod\",\n \"*/pyproject.toml\",\n \"*/requirements.txt\",\n \"*/setup.py\",\n ];\n const found = new Set<string>();\n for (const pattern of indicators) {\n const matches = await glob(pattern, {\n cwd: rootPath,\n ignore: [\"**/node_modules/**\", \"**/vendor/**\"],\n });\n for (const match of matches) {\n const dir = `${rootPath}/${match.split(\"/\")[0]}`;\n if (!gitRepos.has(dir) && !found.has(dir)) {\n found.add(dir);\n }\n }\n }\n return [...found].sort();\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path (use folder name to keep it readable, but\n // append a hash suffix when the same folder name appears in multiple paths)\n const folderName = deriveNameFromPath(projectPath);\n const id = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n","const messages = {\n en: {\n // Project selection\n selectProjects: \"Select projects to include (space = select, enter = confirm):\",\n mergePrompt: \"Merge any related projects into one entry? (e.g. web + mobile)\",\n selectToMerge: \"Select projects to merge together (space = select, enter = confirm):\",\n mergedNamePrompt: \"Name for the merged entry:\",\n mergeNeedTwo: \"Need at least 2 projects to merge. Skipping.\",\n mergedResult: (names: string, target: string) => `Merged ${names} -> \"${target}\"`,\n mergeMore: \"Merge more projects?\",\n // Per-project\n configuring: (name: string) => `Configuring: ${name}`,\n descriptionFor: (name: string) => `Description for ${name} (enter to use auto-generated):`,\n descriptionPlaceholder: \"Auto-generate from README\",\n demoUrlFor: (name: string) => `Demo URL for ${name}:`,\n showSourceFor: (name: string) => `Show source code link for ${name}?`,\n roleFor: (name: string) => `Your role in ${name}:`,\n metricsFor: (name: string) => `Key metrics for ${name} (e.g. \"1k users, $5k MRR\"):`,\n optional: \"optional\",\n // Personal info\n personalInfo: \"Personal Information\",\n fullName: \"Your full name:\",\n nameRequired: \"Name is required\",\n tagline: \"Professional tagline (one line):\",\n taglinePlaceholder: \"Full-stack developer. I ship things.\",\n bio: \"Bio:\",\n bioAuto: \"Auto-generate from my projects\",\n bioManual: \"Write manually\",\n bioPrompt: \"Your bio (2-3 sentences):\",\n photoUrl: \"Photo URL (optional):\",\n githubUser: \"GitHub username or URL:\",\n twitterHandle: \"Twitter/X handle:\",\n linkedinUrl: \"LinkedIn URL:\",\n blogUrl: \"Blog URL:\",\n contactEmail: \"Contact email:\",\n // Design\n designPrefs: \"Design Preferences\",\n theme: \"Theme:\",\n accentColor: \"Accent color:\",\n customHex: \"Custom hex\",\n customHexPrompt: \"Custom accent color (hex):\",\n invalidHex: \"Enter a valid hex color\",\n font: \"Font:\",\n animationLevel: \"Animation level:\",\n // Sections\n sections: \"Sections\",\n additionalSections: \"Additional sections (Hero + Projects always included):\",\n // Engine\n aiEngine: \"AI Engine\",\n engineUsing: (name: string) => `Using ${name}`,\n engineSelect: \"AI engine to use:\",\n // Deploy\n deployment: \"Deployment\",\n deployTo: \"Deploy to:\",\n projectNamePrompt: \"Project name (used in URL):\",\n projectNameInvalid: \"Lowercase letters, numbers, and hyphens only\",\n configComplete: \"Configuration complete. Generating your site...\",\n // Draft\n draftFound: \"Found a saved draft from a previous session.\",\n draftLoadPrompt: \"Load draft? (skip re-entering previous answers)\",\n draftSaved: \"Draft saved. Your progress will be restored next time.\",\n draftCleared: \"Draft cleared.\",\n // Roles\n roleSolo: \"Solo\",\n roleLead: \"Lead\",\n roleContributor: \"Contributor\",\n // Themes\n themeDarkMinimal: \"Dark Minimal\",\n themeLightClean: \"Light Clean\",\n themeMonochrome: \"Monochrome\",\n themeCustom: \"Custom (AI decides)\",\n // Fonts\n fontInter: \"Inter\",\n fontJetBrains: \"JetBrains Mono\",\n fontSystem: \"System Default\",\n // Animations\n animSubtle: \"Subtle\",\n animModerate: \"Moderate\",\n animNone: \"None\",\n // Section names\n secSkills: \"Skills / Tech Stack\",\n secAbout: \"About Me\",\n secTimeline: \"Timeline / Changelog\",\n secBlog: \"Blog\",\n secMetrics: \"Metrics Dashboard\",\n secContact: \"Contact\",\n // Deploy platforms\n deployCloudflare: \"Cloudflare Pages\",\n deployVercel: \"Vercel\",\n deployLocal: \"Local only (no deploy)\",\n // Colors\n colorPurple: \"Purple\",\n colorGreen: \"Green\",\n colorOrange: \"Orange\",\n colorBlue: \"Blue\",\n colorRed: \"Red\",\n colorPink: \"Pink\",\n // Engines\n engineClaude: \"Claude Code\",\n engineCodex: \"Codex\",\n engineV0: \"v0 (Vercel)\",\n },\n zh: {\n selectProjects: \"选择要展示的项目 (空格 = 选择, 回车 = 确认):\",\n mergePrompt: \"是否要合并相关项目为一个条目? (如 web + mobile)\",\n selectToMerge: \"选择要合并的项目 (空格 = 选择, 回车 = 确认):\",\n mergedNamePrompt: \"合并后的名称:\",\n mergeNeedTwo: \"至少需要选择 2 个项目才能合并, 跳过.\",\n mergedResult: (names: string, target: string) => `已合并 ${names} -> \"${target}\"`,\n mergeMore: \"继续合并其他项目?\",\n configuring: (name: string) => `配置: ${name}`,\n descriptionFor: (name: string) => `${name} 的描述 (回车使用自动生成):`,\n descriptionPlaceholder: \"从 README 自动生成\",\n demoUrlFor: (name: string) => `${name} 的 Demo 地址:`,\n showSourceFor: (name: string) => `是否展示 ${name} 的源码链接?`,\n roleFor: (name: string) => `你在 ${name} 中的角色:`,\n metricsFor: (name: string) => `${name} 的关键指标 (如 \"1k 用户, $5k MRR\"):`,\n optional: \"可选\",\n personalInfo: \"个人信息\",\n fullName: \"你的全名:\",\n nameRequired: \"姓名不能为空\",\n tagline: \"职业标语 (一句话):\",\n taglinePlaceholder: \"全栈工程师, 持续交付.\",\n bio: \"个人简介:\",\n bioAuto: \"根据项目自动生成\",\n bioManual: \"手动填写\",\n bioPrompt: \"你的简介 (2-3句话):\",\n photoUrl: \"头像链接 (可选):\",\n githubUser: \"GitHub 用户名或链接:\",\n twitterHandle: \"Twitter/X 账号:\",\n linkedinUrl: \"LinkedIn 链接:\",\n blogUrl: \"博客链接:\",\n contactEmail: \"联系邮箱:\",\n designPrefs: \"设计偏好\",\n theme: \"主题:\",\n accentColor: \"强调色:\",\n customHex: \"自定义色值\",\n customHexPrompt: \"自定义强调色 (hex):\",\n invalidHex: \"请输入有效的 hex 颜色值\",\n font: \"字体:\",\n animationLevel: \"动画级别:\",\n sections: \"页面区块\",\n additionalSections: \"附加区块 (Hero + 项目展示 始终包含):\",\n aiEngine: \"AI 引擎\",\n engineUsing: (name: string) => `使用 ${name}`,\n engineSelect: \"选择 AI 引擎:\",\n deployment: \"部署\",\n deployTo: \"部署到:\",\n projectNamePrompt: \"项目名称 (用于 URL):\",\n projectNameInvalid: \"仅限小写字母, 数字和连字符\",\n configComplete: \"配置完成, 正在生成网站...\",\n draftFound: \"发现上次未完成的配置草稿.\",\n draftLoadPrompt: \"是否加载草稿? (跳过重复填写)\",\n draftSaved: \"草稿已保存, 下次运行时可恢复.\",\n draftCleared: \"草稿已清除.\",\n roleSolo: \"独立完成\",\n roleLead: \"主导开发\",\n roleContributor: \"参与贡献\",\n themeDarkMinimal: \"暗色极简\",\n themeLightClean: \"明亮简洁\",\n themeMonochrome: \"黑白\",\n themeCustom: \"自定义 (AI 决定)\",\n fontInter: \"Inter\",\n fontJetBrains: \"JetBrains Mono\",\n fontSystem: \"系统默认\",\n animSubtle: \"轻微\",\n animModerate: \"适中\",\n animNone: \"无\",\n secSkills: \"技术栈\",\n secAbout: \"关于我\",\n secTimeline: \"时间线\",\n secBlog: \"博客\",\n secMetrics: \"数据面板\",\n secContact: \"联系方式\",\n deployCloudflare: \"Cloudflare Pages\",\n deployVercel: \"Vercel\",\n deployLocal: \"仅本地 (不部署)\",\n colorPurple: \"紫色\",\n colorGreen: \"绿色\",\n colorOrange: \"橙色\",\n colorBlue: \"蓝色\",\n colorRed: \"红色\",\n colorPink: \"粉色\",\n engineClaude: \"Claude Code\",\n engineCodex: \"Codex\",\n engineV0: \"v0 (Vercel)\",\n },\n} as const;\n\nexport type Locale = \"en\" | \"zh\";\nexport type Messages = typeof messages.en;\n\nlet currentLocale: Locale = \"en\";\n\nexport function detectLocale(): Locale {\n const lang = (\n process.env.LANG ||\n process.env.LC_ALL ||\n process.env.LC_MESSAGES ||\n process.env.LANGUAGE ||\n \"\"\n ).toLowerCase();\n\n if (lang.startsWith(\"zh\")) return \"zh\";\n return \"en\";\n}\n\nexport function initLocale(): void {\n currentLocale = detectLocale();\n}\n\nexport function t(): Messages {\n return messages[currentLocale];\n}\n\nexport function getLocale(): Locale {\n return currentLocale;\n}\n","import type {\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport { t } from \"../utils/i18n.js\";\n\nexport const THEME_OPTIONS = (): { value: StyleConfig[\"theme\"]; label: string }[] => [\n { value: \"dark-minimal\", label: t().themeDarkMinimal },\n { value: \"light-clean\", label: t().themeLightClean },\n { value: \"monochrome\", label: t().themeMonochrome },\n { value: \"custom\", label: t().themeCustom },\n];\n\nexport const FONT_OPTIONS = (): { value: StyleConfig[\"font\"]; label: string }[] => [\n { value: \"Inter\", label: t().fontInter },\n { value: \"JetBrains Mono\", label: t().fontJetBrains },\n { value: \"system\", label: t().fontSystem },\n];\n\nexport const ANIMATION_OPTIONS = (): {\n value: StyleConfig[\"animationLevel\"];\n label: string;\n}[] => [\n { value: \"subtle\", label: t().animSubtle },\n { value: \"moderate\", label: t().animModerate },\n { value: \"none\", label: t().animNone },\n];\n\nexport const SECTION_OPTIONS = (): { value: SectionId; label: string }[] => [\n { value: \"skills\", label: t().secSkills },\n { value: \"about\", label: t().secAbout },\n { value: \"timeline\", label: t().secTimeline },\n { value: \"blog\", label: t().secBlog },\n { value: \"metrics\", label: t().secMetrics },\n { value: \"contact\", label: t().secContact },\n];\n\nexport const ENGINE_OPTIONS = (): { value: EngineType; label: string }[] => [\n { value: \"claude\", label: t().engineClaude },\n { value: \"codex\", label: t().engineCodex },\n { value: \"v0\", label: t().engineV0 },\n];\n\nexport const DEPLOY_OPTIONS = (): { value: DeployPlatform; label: string }[] => [\n { value: \"cloudflare\", label: t().deployCloudflare },\n { value: \"vercel\", label: t().deployVercel },\n { value: \"local\", label: t().deployLocal },\n];\n\nexport const ROLE_OPTIONS = (): {\n value: \"solo\" | \"lead\" | \"contributor\";\n label: string;\n}[] => [\n { value: \"solo\", label: t().roleSolo },\n { value: \"lead\", label: t().roleLead },\n { value: \"contributor\", label: t().roleContributor },\n];\n\nexport const DEFAULT_ACCENT_COLORS = (): { value: string; label: string }[] => [\n { value: \"#7c3aed\", label: t().colorPurple },\n { value: \"#10b981\", label: t().colorGreen },\n { value: \"#f97316\", label: t().colorOrange },\n { value: \"#3b82f6\", label: t().colorBlue },\n { value: \"#ef4444\", label: t().colorRed },\n { value: \"#ec4899\", label: t().colorPink },\n];\n","import * as p from \"@clack/prompts\";\nimport type {\n ProjectMeta,\n ProjectEntry,\n OwnerInfo,\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport {\n THEME_OPTIONS,\n FONT_OPTIONS,\n ANIMATION_OPTIONS,\n SECTION_OPTIONS,\n ENGINE_OPTIONS,\n DEPLOY_OPTIONS,\n ROLE_OPTIONS,\n DEFAULT_ACCENT_COLORS,\n} from \"./questions.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { t } from \"../utils/i18n.js\";\n\n/** ProjectMeta with optional children for merged groups */\ninterface MergeableMeta extends ProjectMeta {\n children?: ProjectMeta[];\n}\n\nfunction handleCancel(value: unknown): void {\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n}\n\nexport interface InterviewResult {\n projects: ProjectEntry[];\n owner: OwnerInfo;\n style: StyleConfig;\n sections: SectionId[];\n engine: EngineType;\n deploy: {\n platform: DeployPlatform;\n projectName: string;\n };\n}\n\nasync function runMergeStep(\n projects: MergeableMeta[]\n): Promise<MergeableMeta[]> {\n const shouldMerge = (await p.confirm({\n message: t().mergePrompt,\n initialValue: false,\n })) as boolean;\n handleCancel(shouldMerge);\n\n if (!shouldMerge) return projects;\n\n // Work on a mutable copy\n let remaining = [...projects];\n\n while (remaining.length >= 2) {\n const mergeIds = (await p.multiselect({\n message: t().selectToMerge,\n options: remaining.map((proj) => ({\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: proj.techStack.slice(0, 3).join(\", \"),\n })),\n required: true,\n })) as string[];\n handleCancel(mergeIds);\n\n if (mergeIds.length < 2) {\n logger.warn(t().mergeNeedTwo);\n break;\n }\n\n // Collect the projects being merged\n const toMerge = mergeIds.map(\n (id) => remaining.find((p) => p.id === id)!\n );\n\n // Ask for the merged entry name\n const defaultName = toMerge.map((p) => p.name).join(\" + \");\n const mergedName = (await p.text({\n message: t().mergedNamePrompt,\n placeholder: defaultName,\n defaultValue: defaultName,\n })) as string;\n handleCancel(mergedName);\n\n // Build the merged meta\n const merged = mergeProjects(toMerge, mergedName);\n\n // Remove merged items, add the new merged entry\n remaining = remaining.filter((p) => !mergeIds.includes(p.id));\n remaining.push(merged);\n\n logger.info(\n t().mergedResult(toMerge.map((p) => p.name).join(\", \"), mergedName)\n );\n\n if (remaining.length < 2) break;\n\n const more = (await p.confirm({\n message: t().mergeMore,\n initialValue: false,\n })) as boolean;\n handleCancel(more);\n\n if (!more) break;\n }\n\n return remaining;\n}\n\nfunction mergeProjects(\n projects: MergeableMeta[],\n name: string\n): MergeableMeta {\n // Flatten: if any project is itself a merged group, collect its children\n const allChildren: ProjectMeta[] = [];\n for (const proj of projects) {\n if (proj.children && proj.children.length > 0) {\n allChildren.push(...proj.children);\n } else {\n // Store the original as a child (strip children field)\n const { children, ...rest } = proj as MergeableMeta;\n allChildren.push(rest);\n }\n }\n\n // Combine tech stacks (deduplicated)\n const techStack = [\n ...new Set(allChildren.flatMap((p) => p.techStack)),\n ];\n\n // Combine languages\n const languages: Record<string, number> = {};\n for (const child of allChildren) {\n for (const [lang, count] of Object.entries(child.languages)) {\n languages[lang] = (languages[lang] || 0) + count;\n }\n }\n\n // Use earliest first commit, latest last commit\n const firstDates = allChildren\n .map((p) => p.firstCommitDate)\n .filter(Boolean)\n .sort();\n const lastDates = allChildren\n .map((p) => p.lastCommitDate)\n .filter(Boolean)\n .sort();\n\n // Sum commits\n const totalCommits = allChildren.reduce(\n (sum, p) => sum + p.totalCommits,\n 0\n );\n\n // Collect all remote URLs (pick first non-null)\n const remoteUrl =\n allChildren.find((p) => p.remoteUrl)?.remoteUrl || null;\n\n // Collect all demo URLs (pick first non-null)\n const demoUrl =\n allChildren.find((p) => p.demoUrl)?.demoUrl || null;\n\n // Concatenate README contents\n const readmeParts = allChildren\n .filter((p) => p.readmeContent)\n .map(\n (p) =>\n `--- ${p.name} ---\\n${p.readmeContent}`\n );\n const readmeContent =\n readmeParts.length > 0 ? readmeParts.join(\"\\n\\n\") : null;\n\n // Combine descriptions\n const descriptions = allChildren\n .map((p) => p.description)\n .filter(Boolean);\n const description = descriptions.join(\" | \");\n\n // Use first child's path as the \"primary\" local path\n const localPath = allChildren[0].localPath;\n\n const id = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath,\n description,\n techStack,\n languages,\n firstCommitDate: firstDates[0] || \"\",\n lastCommitDate: lastDates[lastDates.length - 1] || \"\",\n totalCommits,\n remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: allChildren[0].lastScannedCommit || \"\",\n children: allChildren,\n };\n}\n\nexport async function runInterview(\n scannedProjects: ProjectMeta[],\n availableEngines: EngineType[]\n): Promise<InterviewResult> {\n p.intro(\"shipfolio\");\n\n // -- Project Selection --\n logger.header(\"Project Selection\");\n\n const projectOptions = scannedProjects.map((proj) => {\n const techInfo = proj.techStack.slice(0, 3).join(\", \");\n const commitInfo = proj.totalCommits > 0 ? `${proj.totalCommits} commits` : \"no git\";\n return {\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: techInfo ? `${techInfo} | ${commitInfo}` : commitInfo,\n };\n });\n\n const selectedIds = (await p.multiselect({\n message: t().selectProjects,\n options: projectOptions,\n required: true,\n })) as string[];\n handleCancel(selectedIds);\n\n // Build the working list of selected project metas\n let selectedMetas: MergeableMeta[] = selectedIds.map(\n (id) => scannedProjects.find((p) => p.id === id)!\n );\n\n // -- Merge Step --\n if (selectedMetas.length >= 2) {\n selectedMetas = await runMergeStep(selectedMetas);\n }\n\n // -- Per-Project Details --\n const projectEntries: ProjectEntry[] = [];\n\n for (const meta of selectedMetas) {\n const displayName = meta.children\n ? `${meta.name} (${meta.children.length} sub-projects)`\n : meta.name;\n\n logger.plain(`\\n ${t().configuring(displayName)}`);\n\n const overrideDesc = (await p.text({\n message: t().descriptionFor(displayName),\n placeholder: meta.description?.slice(0, 80) || t().descriptionPlaceholder,\n defaultValue: \"\",\n })) as string;\n handleCancel(overrideDesc);\n\n const demoUrl = (await p.text({\n message: t().demoUrlFor(displayName),\n placeholder: meta.demoUrl || \"none\",\n defaultValue: meta.demoUrl || \"\",\n })) as string;\n handleCancel(demoUrl);\n\n const showSource = (await p.confirm({\n message: t().showSourceFor(displayName),\n initialValue: !!meta.remoteUrl,\n })) as boolean;\n handleCancel(showSource);\n\n const role = (await p.select({\n message: t().roleFor(displayName),\n options: ROLE_OPTIONS(),\n })) as \"solo\" | \"lead\" | \"contributor\";\n handleCancel(role);\n\n const metricsInput = (await p.text({\n message: t().metricsFor(displayName),\n placeholder: t().optional,\n defaultValue: \"\",\n })) as string;\n handleCancel(metricsInput);\n\n const metrics: ProjectEntry[\"metrics\"] = {};\n if (metricsInput) {\n metrics.custom = { summary: metricsInput };\n }\n\n projectEntries.push({\n ...meta,\n included: true,\n overrideDescription: overrideDesc || null,\n showSourceLink: showSource,\n demoUrl: demoUrl || meta.demoUrl,\n role,\n metrics,\n });\n }\n\n // -- Personal Info --\n logger.header(t().personalInfo);\n\n const name = (await p.text({\n message: t().fullName,\n validate: (v) => (v.length === 0 ? t().nameRequired : undefined),\n })) as string;\n handleCancel(name);\n\n const tagline = (await p.text({\n message: t().tagline,\n placeholder: t().taglinePlaceholder,\n })) as string;\n handleCancel(tagline);\n\n const bioChoice = (await p.select({\n message: t().bio,\n options: [\n { value: \"auto\", label: t().bioAuto },\n { value: \"manual\", label: t().bioManual },\n ],\n })) as string;\n handleCancel(bioChoice);\n\n let bio: string | \"auto\" = \"auto\";\n if (bioChoice === \"manual\") {\n bio = (await p.text({\n message: t().bioPrompt,\n })) as string;\n handleCancel(bio);\n }\n\n const photoUrl = (await p.text({\n message: t().photoUrl,\n placeholder: \"https://...\",\n defaultValue: \"\",\n })) as string;\n handleCancel(photoUrl);\n\n const github = (await p.text({\n message: t().githubUser,\n defaultValue: \"\",\n })) as string;\n handleCancel(github);\n\n const twitter = (await p.text({\n message: t().twitterHandle,\n defaultValue: \"\",\n })) as string;\n handleCancel(twitter);\n\n const linkedin = (await p.text({\n message: t().linkedinUrl,\n defaultValue: \"\",\n })) as string;\n handleCancel(linkedin);\n\n const blogUrl = (await p.text({\n message: t().blogUrl,\n defaultValue: \"\",\n })) as string;\n handleCancel(blogUrl);\n\n const email = (await p.text({\n message: t().contactEmail,\n defaultValue: \"\",\n })) as string;\n handleCancel(email);\n\n const owner: OwnerInfo = {\n name,\n tagline,\n bio,\n photoUrl: photoUrl || null,\n social: {\n github: github || undefined,\n twitter: twitter || undefined,\n linkedin: linkedin || undefined,\n blog: blogUrl || undefined,\n email: email || undefined,\n },\n };\n\n // -- Design Preferences --\n logger.header(t().designPrefs);\n\n const theme = (await p.select({\n message: t().theme,\n options: THEME_OPTIONS(),\n })) as StyleConfig[\"theme\"];\n handleCancel(theme);\n\n const accentColor = (await p.select({\n message: t().accentColor,\n options: [\n ...DEFAULT_ACCENT_COLORS(),\n { value: \"custom\", label: t().customHex },\n ],\n })) as string;\n handleCancel(accentColor);\n\n let finalAccent = accentColor;\n if (accentColor === \"custom\") {\n finalAccent = (await p.text({\n message: t().customHexPrompt,\n placeholder: \"#7c3aed\",\n validate: (v) =>\n /^#[0-9a-fA-F]{6}$/.test(v) ? undefined : t().invalidHex,\n })) as string;\n handleCancel(finalAccent);\n }\n\n const font = (await p.select({\n message: t().font,\n options: FONT_OPTIONS(),\n })) as StyleConfig[\"font\"];\n handleCancel(font);\n\n const animationLevel = (await p.select({\n message: t().animationLevel,\n options: ANIMATION_OPTIONS(),\n })) as StyleConfig[\"animationLevel\"];\n handleCancel(animationLevel);\n\n const style: StyleConfig = {\n theme,\n accentColor: finalAccent,\n font,\n animationLevel,\n };\n\n // -- Sections --\n logger.header(t().sections);\n\n const additionalSections = (await p.multiselect({\n message: t().additionalSections,\n options: SECTION_OPTIONS(),\n required: false,\n })) as SectionId[];\n handleCancel(additionalSections);\n\n const sections: SectionId[] = [\n \"hero\",\n \"projects\",\n ...additionalSections,\n ];\n\n // -- Engine Selection --\n logger.header(t().aiEngine);\n\n let engine: EngineType;\n if (availableEngines.length === 1) {\n engine = availableEngines[0];\n logger.info(t().engineUsing(engine));\n } else {\n const filteredEngineOptions = ENGINE_OPTIONS().filter((o) =>\n availableEngines.includes(o.value)\n );\n engine = (await p.select({\n message: t().engineSelect,\n options: filteredEngineOptions,\n })) as EngineType;\n handleCancel(engine);\n }\n\n // -- Deploy Target --\n logger.header(t().deployment);\n\n const deployPlatform = (await p.select({\n message: t().deployTo,\n options: DEPLOY_OPTIONS(),\n })) as DeployPlatform;\n handleCancel(deployPlatform);\n\n let projectName = \"\";\n if (deployPlatform !== \"local\") {\n projectName = (await p.text({\n message: t().projectNamePrompt,\n placeholder: \"my-shipfolio\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : t().projectNameInvalid,\n })) as string;\n handleCancel(projectName);\n }\n\n p.outro(t().configComplete);\n\n return {\n projects: projectEntries,\n owner,\n style,\n sections,\n engine,\n deploy: {\n platform: deployPlatform,\n projectName,\n },\n };\n}\n","import type { ShipfolioSpec } from \"./schema.js\";\nimport type { InterviewResult } from \"../interviewer/index.js\";\n\nexport function buildSpec(interview: InterviewResult): ShipfolioSpec {\n return {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n engine: interview.engine,\n framework: \"next\",\n style: interview.style,\n owner: interview.owner,\n projects: interview.projects,\n sections: interview.sections,\n deploy: {\n platform: interview.deploy.platform,\n projectName: interview.deploy.projectName,\n },\n };\n}\n","import type { ShipfolioSpec, ShipfolioConfig, SiteDiff } from \"../spec/schema.js\";\n\nconst FRESH_BUILD_TEMPLATE = `# Task\n\nGenerate a complete, production-ready personal portfolio website.\nAll data and design preferences are provided in the spec below.\nOutput a fully working Next.js project that builds and deploys as a static site.\n\n# Spec\n\n{{SPEC_JSON}}\n\n# Technical Requirements\n\n- Next.js 15 with App Router and TypeScript\n- Tailwind CSS v4 for styling\n- shadcn/ui components (initialize with \\`npx shadcn@latest init --yes\\`)\n- Static export: set \\`output: 'export'\\` in next.config.ts\n- Build command: \\`npm run build\\` producing \\`out/\\` directory\n- Zero external API calls at runtime -- all data is embedded in source\n- All project data in \\`src/data/projects.ts\\` as typed constants\n- Include \\`@media print\\` stylesheet in \\`src/app/globals.css\\` for PDF export\n- Responsive: mobile-first with Tailwind breakpoints (sm, md, lg, xl)\n- Lighthouse performance score 95+\n- Semantic HTML with ARIA labels and keyboard navigation\n- No emoji anywhere in text, UI, code, or comments\n- Use lucide-react for icons\n\n# Design Direction\n\n- Theme: {{THEME}}\n- Accent color: {{ACCENT_COLOR}}\n- Animation level: {{ANIMATION_LEVEL}}\n- Font: {{FONT}}\n\nDesign guidelines:\n- Typography-driven layout with large, bold headings\n- Generous whitespace between sections\n- Single accent color for interactive elements and highlights only\n- Project cards should feel substantial but clean\n- The site must look hand-crafted, not template-generated\n- Dark themes: use zinc/slate backgrounds, not pure black\n- Light themes: use warm whites and subtle grays\n\n# Content Generation\n\nFor each project in the spec:\n- Write a 2-3 sentence narrative description based on the README content and tech stack\n- Focus on what it does and why it matters\n- If user provided an override description, use that instead\n- Maintain consistent voice across all descriptions\n\nFor the bio (if set to \"auto\"):\n- Generate a professional, authentic bio based on the project portfolio\n- Emphasize shipping velocity and breadth\n- Tone: confident, direct, no buzzwords or fluff\n\n# Sections to Include\n\n{{SECTIONS_LIST}}\n\nHero and Projects are always included. Additional sections as specified.\n\n# Print / PDF Styles\n\nIn globals.css, add @media print rules:\n- Single-column layout\n- Hide navigation, footer, animations\n- Preserve background colors (user will print with backgrounds enabled)\n- Show link URLs inline: \\`a[href]::after { content: \" (\" attr(href) \")\"; }\\`\n- Avoid page breaks inside project cards\n- A4-friendly margins and font sizes\n\n# File Structure to Generate\n\n\\`\\`\\`\nnext.config.ts\npackage.json\ntailwind.config.ts\ntsconfig.json\npostcss.config.mjs\ncomponents.json\nsrc/app/layout.tsx\nsrc/app/page.tsx\nsrc/app/globals.css\nsrc/components/ui/ (shadcn components as needed)\nsrc/components/hero.tsx\nsrc/components/project-card.tsx\nsrc/components/project-grid.tsx\nsrc/components/skills.tsx\nsrc/components/about.tsx\nsrc/components/timeline.tsx\nsrc/components/contact.tsx\nsrc/components/navigation.tsx\nsrc/components/footer.tsx\nsrc/data/projects.ts\nsrc/data/owner.ts\nsrc/lib/utils.ts\npublic/favicon.svg\nshipfolio.config.json\n\\`\\`\\`\n\n# Important\n\n- Generate ALL files needed for the project to build successfully\n- Include all shadcn/ui component files that are referenced\n- The \\`package.json\\` must include all dependencies\n- \\`npm install && npm run build\\` must succeed without errors\n- Do not use next/image (incompatible with static export) -- use standard <img> tags\n- Do not use features that require a server (API routes, middleware, ISR)\n`;\n\nconst UPDATE_TEMPLATE = `# Task\n\nUpdate an existing portfolio website previously generated by shipfolio.\nYou must preserve the existing design system, layout structure, component\narchitecture, and any custom modifications the user has made.\n\n# Existing Site Configuration\n\n{{EXISTING_CONFIG_JSON}}\n\n# Changes to Apply\n\n## New Projects to Add\n{{NEW_PROJECTS}}\n\n## Projects to Update (new commits since last scan)\n{{UPDATED_PROJECTS}}\n\n## Projects to Remove\n{{REMOVED_PROJECTS}}\n\n## Updated Personal Info\n{{PERSONAL_INFO_DIFF}}\n\n# Rules\n\n1. Do NOT change the overall layout, color scheme, or design system\n2. Do NOT reorganize existing components or rename files\n3. Only modify files that need changes for the specified updates\n4. For new projects: follow the exact same card format and component pattern\n as existing project cards\n5. Preserve all custom CSS, custom components, and manual edits\n6. Update src/data/projects.ts with new/changed/removed project data\n7. Update src/data/owner.ts if personal info changed\n8. Update shipfolio.config.json with new timestamps and project list\n9. If a new section type is needed, create it following the existing\n component patterns and design tokens in the codebase\n10. No emoji anywhere\n\n# Technical Notes\n\n- The site uses Next.js 15 + Tailwind CSS + shadcn/ui\n- Static export via \\`output: 'export'\\` in next.config.ts\n- Do not break the build -- \\`npm run build\\` must succeed\n- Do not add new dependencies unless absolutely necessary\n- Keep the existing @media print styles working\n`;\n\nexport async function buildFreshPrompt(spec: ShipfolioSpec): Promise<string> {\n let template = FRESH_BUILD_TEMPLATE;\n\n const sectionsText = spec.sections\n .map((s) => `- ${s}`)\n .join(\"\\n\");\n\n template = template\n .replace(\"{{SPEC_JSON}}\", JSON.stringify(spec, null, 2))\n .replace(\"{{THEME}}\", spec.style.theme)\n .replace(\"{{ACCENT_COLOR}}\", spec.style.accentColor)\n .replace(\"{{ANIMATION_LEVEL}}\", spec.style.animationLevel)\n .replace(\"{{FONT}}\", spec.style.font)\n .replace(\"{{SECTIONS_LIST}}\", sectionsText);\n\n return template;\n}\n\nexport async function buildUpdatePrompt(\n existingConfig: ShipfolioConfig,\n diff: SiteDiff\n): Promise<string> {\n let template = UPDATE_TEMPLATE;\n\n const newProjectsText =\n diff.newProjects.length > 0\n ? diff.newProjects\n .map(\n (p) =>\n `- ${p.name}: ${p.description}\\n Tech: ${p.techStack.join(\", \")}\\n README excerpt: ${(p.readmeContent || \"\").slice(0, 500)}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const updatedProjectsText =\n diff.updatedProjects.length > 0\n ? diff.updatedProjects\n .map(\n (u) =>\n `- ${u.project.name}: ${u.newCommits} new commits\\n README changed: ${u.readmeChanged}\\n Dependencies changed: ${u.depsChanged}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const removedProjectsText =\n diff.removedProjects.length > 0\n ? diff.removedProjects.map((p) => `- ${p.name}`).join(\"\\n\")\n : \"None\";\n\n template = template\n .replace(\n \"{{EXISTING_CONFIG_JSON}}\",\n JSON.stringify(existingConfig, null, 2)\n )\n .replace(\"{{NEW_PROJECTS}}\", newProjectsText)\n .replace(\"{{UPDATED_PROJECTS}}\", updatedProjectsText)\n .replace(\"{{REMOVED_PROJECTS}}\", removedProjectsText)\n .replace(\"{{PERSONAL_INFO_DIFF}}\", \"No changes\");\n\n return template;\n}\n","import { execa, type Options as ExecaOptions } from \"execa\";\n\nexport async function run(\n command: string,\n args: string[],\n options?: ExecaOptions\n) {\n return execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n try {\n await execa(\"which\", [command]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function runWithOutput(\n command: string,\n args: string[],\n options?: ExecaOptions\n): Promise<string> {\n const result = await execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n return result.stdout;\n}\n","import { commandExists } from \"../utils/exec.js\";\nimport type { EngineType } from \"../spec/schema.js\";\n\nexport interface DetectedEngine {\n type: EngineType;\n available: boolean;\n}\n\nexport async function detectEngines(): Promise<DetectedEngine[]> {\n const results: DetectedEngine[] = [];\n\n // Check for v0 API key\n if (process.env.V0_API_KEY) {\n results.push({ type: \"v0\", available: true });\n }\n\n // Check for Claude Code CLI\n if (await commandExists(\"claude\")) {\n results.push({ type: \"claude\", available: true });\n }\n\n // Check for Codex CLI\n if (await commandExists(\"codex\")) {\n results.push({ type: \"codex\", available: true });\n }\n\n return results;\n}\n\nexport function getAvailableEngineTypes(engines: DetectedEngine[]): EngineType[] {\n return engines.filter((e) => e.available).map((e) => e.type);\n}\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nexport async function generateWithClaude(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Claude Code...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"claude\", [\n \"-p\",\n \"--permission-mode\", \"bypassPermissions\",\n ], {\n cwd: outputDir,\n input: fullPrompt,\n stdout: \"ignore\",\n stderr: \"pipe\",\n timeout: 600000, // 10 minute timeout\n });\n\n spinner.succeed(\"Site generated with Claude Code\");\n } catch (error) {\n spinner.fail(\"Claude Code generation failed\");\n throw error;\n }\n}\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nexport async function generateWithCodex(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Codex...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"codex\", [\"--quiet\", \"--full-auto\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 600000,\n });\n\n spinner.succeed(\"Site generated with Codex\");\n } catch (error) {\n spinner.fail(\"Codex generation failed\");\n throw error;\n }\n}\n","import OpenAI from \"openai\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\ninterface ExtractedFile {\n filename: string;\n content: string;\n}\n\nexport async function generateWithV0(\n prompt: string,\n outputDir: string,\n apiKey: string\n): Promise<void> {\n const spinner = ora(\"Generating site with v0...\").start();\n\n const client = new OpenAI({\n apiKey,\n baseURL: \"https://api.v0.dev/v1\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: \"v0-1.0-md\",\n messages: [\n {\n role: \"system\",\n content:\n \"Generate a complete Next.js 15 portfolio website using TypeScript, Tailwind CSS, and shadcn/ui. \" +\n \"Return all files with their paths clearly marked. Use ```tsx filename.tsx or ```ts filename.ts \" +\n \"code blocks with the filename on the same line as the opening backticks. \" +\n \"No emoji in any output.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(\"v0 returned empty response\");\n }\n\n spinner.text = \"Parsing v0 output...\";\n\n const files = extractFiles(content);\n if (files.length === 0) {\n throw new Error(\"No files extracted from v0 response\");\n }\n\n spinner.text = `Writing ${files.length} files...`;\n\n for (const file of files) {\n const filePath = join(outputDir, file.filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content, \"utf-8\");\n }\n\n // Ensure package.json exists with required deps\n const hasPkgJson = files.some((f) => f.filename === \"package.json\");\n if (!hasPkgJson) {\n await writeFile(\n join(outputDir, \"package.json\"),\n JSON.stringify(\n {\n name: \"shipfolio-site\",\n version: \"1.0.0\",\n private: true,\n scripts: {\n dev: \"next dev\",\n build: \"next build\",\n start: \"next start\",\n },\n dependencies: {\n next: \"^15.0.0\",\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"class-variance-authority\": \"^0.7.0\",\n clsx: \"^2.1.0\",\n \"tailwind-merge\": \"^2.6.0\",\n \"lucide-react\": \"^0.460.0\",\n },\n devDependencies: {\n typescript: \"^5.7.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n tailwindcss: \"^4.0.0\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n }\n\n spinner.succeed(`Site generated with v0 (${files.length} files)`);\n } catch (error) {\n spinner.fail(\"v0 generation failed\");\n throw error;\n }\n}\n\nfunction extractFiles(content: string): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n // Match code blocks with filename: ```tsx src/app/page.tsx or ```tsx filename=\"src/app/page.tsx\"\n const patterns = [\n // ```tsx src/app/page.tsx\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+([^\\n`]+)\\n([\\s\\S]*?)```/g,\n // ```tsx filename=\"src/app/page.tsx\"\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+filename=\"([^\"]+)\"\\n([\\s\\S]*?)```/g,\n // ```tsx {filename: \"src/app/page.tsx\"}\n /```(?:tsx?|jsx?|css|json|mjs|cjs).*?filename:\\s*\"([^\"]+)\".*?\\n([\\s\\S]*?)```/g,\n ];\n\n for (const pattern of patterns) {\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const filename = match[1].trim();\n const fileContent = match[2].trim();\n\n // Skip if filename looks like a description rather than a path\n if (\n filename.includes(\" \") &&\n !filename.includes(\"/\") &&\n !filename.includes(\".\")\n ) {\n continue;\n }\n\n // Clean up filename\n const cleanFilename = filename\n .replace(/^[\"']|[\"']$/g, \"\")\n .replace(/^\\.\\//g, \"\");\n\n if (cleanFilename && fileContent) {\n files.push({ filename: cleanFilename, content: fileContent });\n }\n }\n }\n\n return files;\n}\n","import { fileExists, join } from \"../utils/fs.js\";\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport async function validateGeneratedSite(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const requiredFiles = [\n \"package.json\",\n \"next.config.ts\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n ];\n\n // Also check common alternatives\n const alternativeChecks: [string, string[]][] = [\n [\"next.config.ts\", [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\"]],\n ];\n\n for (const file of requiredFiles) {\n const alternatives = alternativeChecks.find(([key]) => key === file);\n if (alternatives) {\n const anyExists = await Promise.any(\n alternatives[1].map(async (alt) => {\n if (await fileExists(join(siteDir, alt))) return true;\n throw new Error(\"not found\");\n })\n ).catch(() => false);\n if (!anyExists) {\n errors.push(`Missing: ${file} (or any alternative)`);\n }\n } else {\n if (!(await fileExists(join(siteDir, file)))) {\n errors.push(`Missing: ${file}`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\nexport async function validateBuildOutput(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n errors.push(\"Build output directory 'out/' not found\");\n return { valid: false, errors };\n }\n\n const indexHtml = join(outDir, \"index.html\");\n if (!(await fileExists(indexHtml))) {\n errors.push(\"Missing: out/index.html\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { generateWithClaude } from \"./engines/claude.js\";\nimport { generateWithCodex } from \"./engines/codex.js\";\nimport { generateWithV0 } from \"./engines/v0.js\";\nimport {\n validateGeneratedSite,\n validateBuildOutput,\n} from \"./validator.js\";\nimport { ensureDir } from \"../utils/fs.js\";\nimport { run } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EngineType } from \"../spec/schema.js\";\nimport ora from \"ora\";\n\nasync function runEngine(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n switch (engine) {\n case \"claude\":\n await generateWithClaude(prompt, outputDir);\n break;\n case \"codex\":\n await generateWithCodex(prompt, outputDir);\n break;\n case \"v0\": {\n const apiKey = process.env.V0_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"V0_API_KEY environment variable is required for v0 engine\"\n );\n }\n await generateWithV0(prompt, outputDir, apiKey);\n break;\n }\n }\n}\n\nexport async function generateSite(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n await ensureDir(outputDir);\n\n await runEngine(engine, prompt, outputDir);\n\n // Validate generated output\n let validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Generated site has issues:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n\n // Retry: feed validation errors back to the AI\n logger.info(\"Retrying generation with error feedback...\");\n const fixPrompt = [\n \"The previous generation was incomplete. The following required files are missing:\",\n ...validation.errors.map((e) => `- ${e}`),\n \"\",\n \"Please create ALL missing files. Here is the original specification:\",\n \"\",\n prompt,\n ].join(\"\\n\");\n\n await runEngine(engine, fixPrompt, outputDir);\n\n validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Still missing files after retry:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n }\n }\n}\n\nexport async function buildSite(siteDir: string): Promise<boolean> {\n const spinner = ora(\"Installing dependencies...\").start();\n\n try {\n await run(\"npm\", [\"install\"], { cwd: siteDir });\n spinner.text = \"Building site...\";\n await run(\"npm\", [\"run\", \"build\"], { cwd: siteDir });\n spinner.succeed(\"Site built successfully\");\n } catch (error: any) {\n spinner.fail(\"Build failed\");\n logger.error(error.stderr || error.message || String(error));\n return false;\n }\n\n // Validate build output\n const validation = await validateBuildOutput(siteDir);\n if (!validation.valid) {\n logger.error(\"Build output validation failed:\");\n for (const err of validation.errors) {\n logger.error(` ${err}`);\n }\n return false;\n }\n\n return true;\n}\n\nexport async function retryBuild(\n engine: EngineType,\n siteDir: string,\n buildError: string,\n originalPrompt: string\n): Promise<boolean> {\n logger.info(\"Retrying: feeding build error back to AI...\");\n\n const fixPrompt = `The site generation produced build errors. Fix the following errors without changing the overall design or structure:\\n\\n${buildError}\\n\\nOriginal prompt for context:\\n${originalPrompt.slice(0, 2000)}`;\n\n try {\n await runEngine(engine, fixPrompt, siteDir);\n return await buildSite(siteDir);\n } catch {\n return false;\n }\n}\n","import { run, commandExists, runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\n\nexport async function checkAuth(\n platform: DeployPlatform\n): Promise<boolean> {\n if (platform === \"local\") return true;\n\n try {\n if (platform === \"cloudflare\") {\n await runWithOutput(\"npx\", [\"wrangler\", \"whoami\"]);\n return true;\n }\n if (platform === \"vercel\") {\n await runWithOutput(\"npx\", [\"vercel\", \"whoami\"]);\n return true;\n }\n } catch {\n return false;\n }\n return false;\n}\n\nexport async function login(platform: DeployPlatform): Promise<void> {\n if (platform === \"cloudflare\") {\n logger.info(\"Opening Cloudflare login in browser...\");\n await run(\"npx\", [\"wrangler\", \"login\"], { stdio: \"inherit\" });\n } else if (platform === \"vercel\") {\n logger.info(\"Opening Vercel login in browser...\");\n await run(\"npx\", [\"vercel\", \"login\"], { stdio: \"inherit\" });\n }\n}\n\nexport async function ensureAuth(platform: DeployPlatform): Promise<void> {\n if (platform === \"local\") return;\n\n const isAuthed = await checkAuth(platform);\n if (!isAuthed) {\n await login(platform);\n // Verify login succeeded\n const nowAuthed = await checkAuth(platform);\n if (!nowAuthed) {\n throw new Error(`Authentication failed for ${platform}`);\n }\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nasync function ensureProject(projectName: string): Promise<void> {\n try {\n await runWithOutput(\"npx\", [\n \"wrangler\",\n \"pages\",\n \"project\",\n \"create\",\n projectName,\n \"--production-branch=main\",\n ]);\n } catch {\n // Project may already exist, ignore error\n }\n}\n\nexport async function deployToCloudflare(\n distDir: string,\n projectName: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Cloudflare Pages...\").start();\n\n try {\n // Ensure the project exists before deploying\n spinner.text = \"Creating Cloudflare Pages project...\";\n await ensureProject(projectName);\n\n spinner.text = \"Uploading to Cloudflare Pages...\";\n const output = await runWithOutput(\"npx\", [\n \"wrangler\",\n \"pages\",\n \"deploy\",\n distDir,\n `--project-name=${projectName}`,\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.pages\\.dev/\n );\n const url = urlMatch?.[0] || `https://${projectName}.pages.dev`;\n\n spinner.succeed(`Deployed to Cloudflare Pages`);\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Cloudflare Pages deployment failed\");\n throw error;\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToVercel(\n distDir: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Vercel...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"vercel\",\n \"deploy\",\n distDir,\n \"--yes\",\n \"--prod\",\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.vercel\\.app/\n );\n const url = urlMatch?.[0] || output.trim().split(\"\\n\").pop() || \"\";\n\n spinner.succeed(\"Deployed to Vercel\");\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Vercel deployment failed\");\n throw error;\n }\n}\n","import { run, runWithOutput, commandExists } from \"../utils/exec.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport * as p from \"@clack/prompts\";\n\nexport async function setupGitHubAutoDeploy(\n siteDir: string,\n projectName: string\n): Promise<void> {\n const hasGh = await commandExists(\"gh\");\n if (!hasGh) {\n logger.info(\n \"GitHub CLI (gh) not found. Install it to enable auto-deploy setup.\"\n );\n return;\n }\n\n const shouldSetup = (await p.confirm({\n message: \"Set up GitHub auto-deploy? (push = redeploy)\",\n initialValue: false,\n })) as boolean;\n\n if (p.isCancel(shouldSetup) || !shouldSetup) return;\n\n const visibility = (await p.select({\n message: \"Repository visibility:\",\n options: [\n { value: \"private\", label: \"Private\" },\n { value: \"public\", label: \"Public\" },\n ],\n })) as string;\n\n if (p.isCancel(visibility)) return;\n\n try {\n // Init git if not already\n const gitDir = join(siteDir, \".git\");\n if (!(await fileExists(gitDir))) {\n await run(\"git\", [\"init\"], { cwd: siteDir });\n }\n\n // Create GitHub repo\n await run(\n \"gh\",\n [\n \"repo\",\n \"create\",\n projectName,\n `--${visibility}`,\n \"--source\",\n siteDir,\n \"--push\",\n ],\n { cwd: siteDir, stdio: \"inherit\" }\n );\n\n logger.success(`GitHub repository created: ${projectName}`);\n logger.info(\n \"Connect this repo in your Cloudflare Pages or Vercel dashboard for auto-deploy.\"\n );\n } catch (error: any) {\n logger.error(`GitHub setup failed: ${error.message}`);\n }\n}\n","import { ensureAuth } from \"./auth.js\";\nimport { deployToCloudflare } from \"./cloudflare.js\";\nimport { deployToVercel } from \"./vercel.js\";\nimport { setupGitHubAutoDeploy } from \"./github.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\nimport { join } from \"node:path\";\n\nexport async function deploy(\n siteDir: string,\n platform: DeployPlatform,\n projectName: string\n): Promise<string | null> {\n if (platform === \"local\") {\n logger.info(`Site built at ${join(siteDir, \"out/\")}`);\n logger.info(\"Run `npx serve ./out` in the site directory to preview.\");\n return null;\n }\n\n await ensureAuth(platform);\n\n const distDir = join(siteDir, \"out\");\n let url: string;\n\n if (platform === \"cloudflare\") {\n url = await deployToCloudflare(distDir, projectName);\n } else {\n url = await deployToVercel(distDir);\n }\n\n // Offer GitHub auto-deploy setup\n await setupGitHubAutoDeploy(siteDir, projectName);\n\n return url;\n}\n","import { createServer, type Server } from \"node:http\";\nimport { join } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function exportPdf(\n siteDir: string,\n outputPath?: string\n): Promise<string> {\n const distDir = join(siteDir, \"out\");\n const pdfPath = outputPath || join(distDir, \"shipfolio.pdf\");\n\n const spinner = ora(\"Exporting PDF...\").start();\n\n // Start a local server for the built site\n const server = await startStaticServer(distDir);\n const port = (server.address() as any)?.port || 3456;\n\n try {\n // Dynamic import to avoid requiring playwright at install time\n const { chromium } = await import(\"playwright\");\n\n const browser = await chromium.launch();\n const page = await browser.newPage();\n\n await page.goto(`http://localhost:${port}`, {\n waitUntil: \"networkidle\",\n });\n\n // Wait a moment for any CSS transitions to complete\n await page.waitForTimeout(1000);\n\n await page.pdf({\n path: pdfPath,\n format: \"A4\",\n printBackground: true,\n margin: {\n top: \"1cm\",\n right: \"1cm\",\n bottom: \"1cm\",\n left: \"1cm\",\n },\n });\n\n await browser.close();\n spinner.succeed(`PDF exported: ${pdfPath}`);\n return pdfPath;\n } catch (error: any) {\n spinner.fail(\"PDF export failed\");\n if (error.message?.includes(\"browserType.launch\")) {\n logger.error(\n \"Playwright browsers not installed. Run: npx playwright install chromium\"\n );\n } else {\n logger.error(error.message || String(error));\n }\n throw error;\n } finally {\n server.close();\n }\n}\n\nfunction startStaticServer(dir: string): Promise<Server> {\n return new Promise(async (resolve, reject) => {\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: dir,\n cleanUrls: true,\n });\n });\n\n server.listen(0, () => {\n resolve(server);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nexport async function startPreviewServer(\n siteDir: string,\n port: number = 3000\n): Promise<Server> {\n const distDir = join(siteDir, \"out\");\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: distDir,\n cleanUrls: true,\n });\n });\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n logger.info(`Preview: http://localhost:${port}`);\n resolve(server);\n });\n server.on(\"error\", reject);\n });\n}\n","import { readFile, writeFile, mkdir, unlink } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { logger } from \"./logger.js\";\nimport { t } from \"./i18n.js\";\n\nconst DRAFT_DIR = join(homedir(), \".shipfolio\");\nconst DRAFT_FILE = join(DRAFT_DIR, \"draft.json\");\n\nexport interface DraftData {\n timestamp: string;\n interviewResult: unknown;\n}\n\nexport async function saveDraft(interviewResult: unknown): Promise<void> {\n try {\n await mkdir(DRAFT_DIR, { recursive: true });\n const draft: DraftData = {\n timestamp: new Date().toISOString(),\n interviewResult,\n };\n await writeFile(DRAFT_FILE, JSON.stringify(draft, null, 2), \"utf-8\");\n logger.info(t().draftSaved);\n } catch {\n // Silent fail -- draft saving is best-effort\n }\n}\n\nexport async function loadDraft(): Promise<DraftData | null> {\n try {\n const content = await readFile(DRAFT_FILE, \"utf-8\");\n return JSON.parse(content) as DraftData;\n } catch {\n return null;\n }\n}\n\nexport async function clearDraft(): Promise<void> {\n try {\n await unlink(DRAFT_FILE);\n logger.info(t().draftCleared);\n } catch {\n // File may not exist\n }\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview, type InterviewResult } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite, retryBuild } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { writeJson, ensureDir } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport { loadDraft, saveDraft, clearDraft } from \"../utils/draft.js\";\nimport { t } from \"../utils/i18n.js\";\n\ninterface InitOptions {\n scan?: string[];\n engine?: string;\n deploy?: string;\n style?: string;\n accent?: string;\n auto?: boolean;\n output?: string;\n noPdf?: boolean;\n noPreview?: boolean;\n verbose?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n logger.header(\"shipfolio v1.0.5\");\n\n // Step 1: Detect AI engines\n logger.info(\"Detecting AI engines...\");\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found.\");\n logger.plain(\"\");\n logger.plain(\" shipfolio requires one of the following:\");\n logger.plain(\" - Claude Code: npm install -g @anthropic-ai/claude-code\");\n logger.plain(\" - Codex: npm install -g @openai/codex\");\n logger.plain(\" - v0: Set V0_API_KEY environment variable\");\n logger.plain(\"\");\n process.exit(1);\n }\n\n logger.info(\n `Available engines: ${availableTypes.join(\", \")}`\n );\n\n // Step 2: Scan projects\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found. Specify a different directory with --scan.\");\n process.exit(1);\n }\n\n // Display scanned projects\n logger.header(`Found ${scannedProjects.length} projects:`);\n const tableRows = scannedProjects.map((proj) => [\n proj.name,\n proj.techStack.slice(0, 3).join(\", \"),\n proj.firstCommitDate?.slice(0, 10) || \"?\",\n `${proj.totalCommits} commits`,\n ]);\n logger.table(tableRows);\n logger.blank();\n\n // Step 3: Check for draft\n let interviewResult: InterviewResult;\n\n const draft = await loadDraft();\n if (draft) {\n logger.info(t().draftFound);\n const useDraft = (await p.confirm({\n message: t().draftLoadPrompt,\n initialValue: true,\n })) as boolean;\n\n if (!p.isCancel(useDraft) && useDraft) {\n interviewResult = draft.interviewResult as InterviewResult;\n await clearDraft();\n } else {\n interviewResult = await runInterview(scannedProjects, availableTypes);\n }\n } else {\n interviewResult = await runInterview(scannedProjects, availableTypes);\n }\n\n // Save draft in case later steps fail\n await saveDraft(interviewResult);\n\n // Step 4: Build spec\n const spec = buildSpec(interviewResult);\n\n // Step 5: Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Step 6: Generate site\n const outputDir = resolve(options.output || \"./shipfolio-site\");\n await ensureDir(outputDir);\n\n await generateSite(spec.engine, prompt, outputDir);\n\n // Step 7: Build\n let buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n buildSuccess = await retryBuild(spec.engine, outputDir, \"Build failed. Check missing files and fix errors.\", prompt);\n if (!buildSuccess) {\n logger.error(\"Build failed after retry. Check the output directory for details.\");\n process.exit(1);\n }\n }\n\n // Step 8: Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(outputDir);\n logger.blank();\n\n const proceed = (await p.confirm({\n message: \"Deploy now?\",\n initialValue: true,\n })) as boolean;\n\n server.close();\n\n if (p.isCancel(proceed) || !proceed) {\n if (spec.deploy.platform === \"local\") {\n // Already local, just exit\n } else {\n logger.info(\"Skipping deploy. Run `npx shipfolio deploy` later.\");\n }\n }\n }\n\n // Step 9: PDF export\n if (!options.noPdf) {\n try {\n await exportPdf(outputDir);\n } catch {\n logger.warn(\"PDF export skipped due to error.\");\n }\n }\n\n // Step 10: Deploy\n if (spec.deploy.platform !== \"local\") {\n try {\n const url = await deploy(\n outputDir,\n spec.deploy.platform,\n spec.deploy.projectName\n );\n if (url) {\n spec.deploy.url = url;\n }\n } catch (err: any) {\n logger.error(`Deployment failed: ${err.message || err}`);\n logger.info(\"You can retry later with: npx shipfolio deploy --site \" + outputDir);\n }\n }\n\n // Save config for future updates\n await writeJson(join(outputDir, \"shipfolio.config.json\"), {\n ...spec,\n sitePath: outputDir,\n });\n\n // Clear draft on success\n await clearDraft();\n\n // Summary\n logger.header(\"Done.\");\n if (spec.deploy.url) {\n logger.info(`Site: ${spec.deploy.url}`);\n }\n logger.info(`Local: ${outputDir}`);\n logger.info(\n `Update: npx shipfolio update --site ${outputDir}`\n );\n}\n","import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { specCommand } from \"./commands/spec.js\";\nimport { deployCommand } from \"./commands/deploy.js\";\nimport { pdfCommand } from \"./commands/pdf.js\";\nimport { previewCommand } from \"./commands/preview.js\";\nimport { initLocale } from \"./utils/i18n.js\";\n\ninitLocale();\n\nconst program = new Command();\n\nprogram\n .name(\"shipfolio\")\n .description(\n \"Generate and deploy your personal portfolio site from local projects using AI\"\n )\n .version(\"1.0.5\");\n\n// Default command: init (fresh build)\nprogram\n .command(\"init\", { isDefault: true })\n .description(\"Generate a new portfolio site\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-e, --engine <engine>\", \"AI engine: claude | codex | v0\")\n .option(\"-d, --deploy <platform>\", \"Deploy target: cloudflare | vercel | local\")\n .option(\"--style <theme>\", \"Theme: dark-minimal | light-clean | monochrome\")\n .option(\"--accent <hex>\", \"Accent color (hex)\")\n .option(\"--auto\", \"Skip prompts, use defaults\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./shipfolio-site\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip local preview\")\n .option(\"-v, --verbose\", \"Verbose output\")\n .action(initCommand);\n\n// Update existing site\nprogram\n .command(\"update\")\n .description(\"Update an existing portfolio site\")\n .requiredOption(\"--site <path>\", \"Path to existing site directory\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip preview\")\n .option(\"--no-deploy\", \"Skip deployment\")\n .action(updateCommand);\n\n// Generate spec only (for use inside AI tools)\nprogram\n .command(\"spec\")\n .description(\"Generate spec and prompt files only\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-o, --output <dir>\", \"Output directory for spec files\", \".\")\n .action(specCommand);\n\n// Deploy existing site\nprogram\n .command(\"deploy\")\n .description(\"Deploy an existing built site\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-p, --platform <platform>\", \"Deploy platform: cloudflare | vercel\")\n .action(deployCommand);\n\n// Export PDF\nprogram\n .command(\"pdf\")\n .description(\"Export site to PDF\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-o, --output <path>\", \"PDF output path\")\n .action(pdfCommand);\n\n// Preview\nprogram\n .command(\"preview\")\n .description(\"Start local preview server\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"--port <port>\", \"Port number\", \"3000\")\n .action((opts) => previewCommand({ ...opts, port: parseInt(opts.port) }));\n\nprogram.parse();\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { computeDiff } from \"../spec/diff.js\";\nimport { buildUpdatePrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf, startPreviewServer } from \"../pdf/index.js\";\nimport { readJson, writeJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, ProjectEntry } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface UpdateOptions {\n site: string;\n scan?: string[];\n noPdf?: boolean;\n noPreview?: boolean;\n noDeploy?: boolean;\n}\n\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\n logger.header(\"shipfolio update\");\n\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n // Read existing config\n if (!(await fileExists(configPath))) {\n logger.error(\n \"shipfolio.config.json not found. This directory was not generated by shipfolio.\"\n );\n const fresh = (await p.confirm({\n message: \"Proceed with fresh build instead?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(fresh) || !fresh) {\n process.exit(0);\n }\n\n // Redirect to init\n const { initCommand } = await import(\"./init.js\");\n await initCommand({ output: siteDir });\n return;\n }\n\n const config = await readJson<ShipfolioConfig>(configPath);\n logger.info(\n `Site: ${config.deploy.projectName || \"local\"} (generated ${config.generatedAt.slice(0, 10)})`\n );\n logger.info(`Theme: ${config.style.theme}`);\n logger.info(`Projects: ${config.projects.length}`);\n\n // Detect engines\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found. See `npx shipfolio` for install instructions.\");\n process.exit(1);\n }\n\n // Scan for changes\n const scanDirs = options.scan?.map((d) => resolve(d)) ||\n [...new Set(config.projects.map((p) => {\n const parts = p.localPath.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n }))];\n\n const scannedProjects = await scanProjects(scanDirs);\n const diff = computeDiff(config, scannedProjects);\n\n // Display changes\n logger.header(\"Changes detected:\");\n\n if (diff.newProjects.length > 0) {\n logger.plain(\" New:\");\n for (const proj of diff.newProjects) {\n logger.plain(` + ${proj.name} ${proj.techStack.slice(0, 3).join(\", \")}`);\n }\n }\n\n if (diff.updatedProjects.length > 0) {\n logger.plain(\" Updated:\");\n for (const upd of diff.updatedProjects) {\n logger.plain(\n ` ~ ${upd.project.name} ${upd.newCommits} new commits`\n );\n }\n }\n\n if (diff.removedProjects.length > 0) {\n logger.plain(\" Removed:\");\n for (const proj of diff.removedProjects) {\n logger.plain(` - ${proj.name} (directory gone)`);\n }\n }\n\n if (\n diff.newProjects.length === 0 &&\n diff.updatedProjects.length === 0 &&\n diff.removedProjects.length === 0\n ) {\n logger.info(\"No changes detected.\");\n return;\n }\n\n // Confirm changes\n const proceed = (await p.confirm({\n message: \"Apply these changes?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(proceed) || !proceed) {\n process.exit(0);\n }\n\n // Build update prompt\n const engine = availableTypes.includes(config.engine)\n ? config.engine\n : availableTypes[0];\n\n const prompt = await buildUpdatePrompt(config, diff);\n\n // Generate updates\n await generateSite(engine, prompt, siteDir);\n\n // Build\n const buildSuccess = await buildSite(siteDir);\n if (!buildSuccess) {\n logger.error(\"Build failed. Check the site directory.\");\n process.exit(1);\n }\n\n // Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(siteDir);\n const ok = (await p.confirm({\n message: \"Looks good?\",\n initialValue: true,\n })) as boolean;\n server.close();\n if (p.isCancel(ok) || !ok) {\n logger.info(\"Update cancelled at preview.\");\n return;\n }\n }\n\n // PDF\n if (!options.noPdf) {\n try {\n await exportPdf(siteDir);\n } catch {\n logger.warn(\"PDF export skipped.\");\n }\n }\n\n // Deploy\n if (!options.noDeploy && config.deploy.platform !== \"local\") {\n await deploy(siteDir, config.deploy.platform, config.deploy.projectName);\n }\n\n // Update config\n const updatedConfig: ShipfolioConfig = {\n ...config,\n generatedAt: new Date().toISOString(),\n projects: [\n ...diff.unchangedProjects,\n ...diff.updatedProjects.map((u) => {\n const existing = config.projects.find(\n (p) => p.localPath === u.project.localPath\n );\n return {\n ...u.project,\n included: true,\n overrideDescription: existing?.overrideDescription || null,\n showSourceLink: existing?.showSourceLink ?? !!u.project.remoteUrl,\n role: existing?.role || \"solo\",\n metrics: existing?.metrics || {},\n } as ProjectEntry;\n }),\n ...diff.newProjects.map(\n (proj) =>\n ({\n ...proj,\n included: true,\n overrideDescription: null,\n showSourceLink: !!proj.remoteUrl,\n role: \"solo\" as const,\n metrics: {},\n }) as ProjectEntry\n ),\n ],\n };\n\n await writeJson(join(siteDir, \"shipfolio.config.json\"), updatedConfig);\n logger.success(\"Update complete.\");\n}\n","import type {\n ProjectMeta,\n ProjectEntry,\n ShipfolioConfig,\n SiteDiff,\n ProjectUpdate,\n} from \"./schema.js\";\n\nexport function computeDiff(\n oldConfig: ShipfolioConfig,\n newScan: ProjectMeta[]\n): SiteDiff {\n const oldProjectMap = new Map(\n oldConfig.projects.map((p) => [p.localPath, p])\n );\n const newProjectMap = new Map(newScan.map((p) => [p.localPath, p]));\n\n const newProjects: ProjectMeta[] = [];\n const updatedProjects: ProjectUpdate[] = [];\n const removedProjects: ProjectEntry[] = [];\n const unchangedProjects: ProjectEntry[] = [];\n\n // Check new and updated\n for (const [path, meta] of newProjectMap) {\n const oldProject = oldProjectMap.get(path);\n if (!oldProject) {\n newProjects.push(meta);\n } else if (meta.lastScannedCommit !== oldProject.lastScannedCommit) {\n const newCommits = meta.totalCommits - oldProject.totalCommits;\n updatedProjects.push({\n project: meta,\n newCommits: Math.max(newCommits, 0),\n readmeChanged: meta.readmeContent !== oldProject.readmeContent,\n depsChanged:\n JSON.stringify(meta.techStack) !==\n JSON.stringify(oldProject.techStack),\n });\n } else {\n unchangedProjects.push(oldProject);\n }\n }\n\n // Check removed\n for (const [path, project] of oldProjectMap) {\n if (!newProjectMap.has(path)) {\n removedProjects.push(project);\n }\n }\n\n return {\n newProjects,\n updatedProjects,\n removedProjects,\n unchangedProjects,\n };\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { writeJson, writeText } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface SpecOptions {\n scan?: string[];\n output?: string;\n}\n\nexport async function specCommand(options: SpecOptions): Promise<void> {\n logger.header(\"shipfolio spec\");\n\n // Detect engines (needed for interview but not for execution)\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n // Even if no engine is available, we can still generate spec\n // (user will use it inside their own AI session)\n const engineTypes =\n availableTypes.length > 0 ? availableTypes : ([\"claude\"] as const);\n\n // Scan\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found.\");\n process.exit(1);\n }\n\n logger.info(`Found ${scannedProjects.length} projects`);\n\n // Interview\n const interviewResult = await runInterview(\n scannedProjects,\n [...engineTypes]\n );\n\n // Build spec\n const spec = buildSpec(interviewResult);\n\n // Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Save outputs\n const outputDir = options.output || \".\";\n const specPath = resolve(outputDir, \"shipfolio-spec.json\");\n const promptPath = resolve(outputDir, \"shipfolio-prompt.md\");\n\n await writeJson(specPath, spec);\n await writeText(promptPath, prompt);\n\n logger.success(`Spec saved: ${specPath}`);\n logger.success(`Prompt saved: ${promptPath}`);\n logger.blank();\n logger.info(\n \"Use these files inside your Claude Code or Codex session to generate the site.\"\n );\n}\n","import { resolve } from \"node:path\";\nimport { deploy as deployFn } from \"../deployer/index.js\";\nimport { readJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, DeployPlatform } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface DeployOptions {\n site: string;\n platform?: string;\n}\n\nexport async function deployCommand(options: DeployOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n let platform: DeployPlatform;\n let projectName: string;\n\n if (await fileExists(configPath)) {\n const config = await readJson<ShipfolioConfig>(configPath);\n platform =\n (options.platform as DeployPlatform) || config.deploy.platform;\n projectName = config.deploy.projectName;\n } else {\n platform = (options.platform as DeployPlatform) || \"cloudflare\";\n projectName = (await p.text({\n message: \"Project name:\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n\n if (p.isCancel(projectName)) process.exit(0);\n }\n\n if (platform === \"local\") {\n logger.info(\"Deploy platform is set to local. Nothing to deploy.\");\n return;\n }\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n logger.error(\"Build output not found. Run `npm run build` in the site directory first.\");\n process.exit(1);\n }\n\n await deployFn(siteDir, platform, projectName);\n}\n","import { resolve } from \"node:path\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PdfOptions {\n site: string;\n output?: string;\n}\n\nexport async function pdfCommand(options: PdfOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n await exportPdf(siteDir, options.output);\n}\n","import { resolve } from \"node:path\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PreviewOptions {\n site: string;\n port?: number;\n}\n\nexport async function previewCommand(options: PreviewOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n const port = options.port || 3000;\n await startPreviewServer(siteDir, port);\n logger.info(\"Press Ctrl+C to stop.\");\n\n // Keep process alive\n await new Promise(() => {});\n}\n"],"mappings":"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","names":["glob","path","p","glob","p","p","execa","ora","execa","ora","writeFile","mkdir","join","ora","ora","ora","ora","p","join","join","ora","resolve","readFile","writeFile","mkdir","join","join","p","resolve","p","path","p","resolve","initCommand","resolve","resolve","p","resolve","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipfolio",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Generate and deploy your personal portfolio site from local projects using AI",
5
5
  "type": "module",
6
6
  "bin": {