shipfolio 1.0.3 → 1.0.4
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 +52 -12
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1490,11 +1490,17 @@ async function generateWithClaude(prompt, outputDir) {
|
|
|
1490
1490
|
const fullPrompt = `${prompt}
|
|
1491
1491
|
|
|
1492
1492
|
Create all files in the current working directory. Do not ask questions, just generate all files.`;
|
|
1493
|
-
await execa2("claude", [
|
|
1493
|
+
await execa2("claude", [
|
|
1494
|
+
"-p",
|
|
1495
|
+
"--permission-mode",
|
|
1496
|
+
"bypassPermissions"
|
|
1497
|
+
], {
|
|
1494
1498
|
cwd: outputDir,
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1499
|
+
input: fullPrompt,
|
|
1500
|
+
stdout: "ignore",
|
|
1501
|
+
stderr: "pipe",
|
|
1502
|
+
timeout: 6e5
|
|
1503
|
+
// 10 minute timeout
|
|
1498
1504
|
});
|
|
1499
1505
|
spinner.succeed("Site generated with Claude Code");
|
|
1500
1506
|
} catch (error) {
|
|
@@ -1521,7 +1527,7 @@ Create all files in the current working directory. Do not ask questions, just ge
|
|
|
1521
1527
|
await execa3("codex", ["--quiet", "--full-auto", fullPrompt], {
|
|
1522
1528
|
cwd: outputDir,
|
|
1523
1529
|
stdio: "pipe",
|
|
1524
|
-
timeout:
|
|
1530
|
+
timeout: 6e5
|
|
1525
1531
|
});
|
|
1526
1532
|
spinner.succeed("Site generated with Codex");
|
|
1527
1533
|
} catch (error) {
|
|
@@ -1714,8 +1720,7 @@ var init_validator = __esm({
|
|
|
1714
1720
|
|
|
1715
1721
|
// src/orchestrator/index.ts
|
|
1716
1722
|
import ora5 from "ora";
|
|
1717
|
-
async function
|
|
1718
|
-
await ensureDir(outputDir);
|
|
1723
|
+
async function runEngine(engine, prompt, outputDir) {
|
|
1719
1724
|
switch (engine) {
|
|
1720
1725
|
case "claude":
|
|
1721
1726
|
await generateWithClaude(prompt, outputDir);
|
|
@@ -1734,12 +1739,33 @@ async function generateSite(engine, prompt, outputDir) {
|
|
|
1734
1739
|
break;
|
|
1735
1740
|
}
|
|
1736
1741
|
}
|
|
1737
|
-
|
|
1742
|
+
}
|
|
1743
|
+
async function generateSite(engine, prompt, outputDir) {
|
|
1744
|
+
await ensureDir(outputDir);
|
|
1745
|
+
await runEngine(engine, prompt, outputDir);
|
|
1746
|
+
let validation = await validateGeneratedSite(outputDir);
|
|
1738
1747
|
if (!validation.valid) {
|
|
1739
1748
|
logger.warn("Generated site has issues:");
|
|
1740
1749
|
for (const err of validation.errors) {
|
|
1741
1750
|
logger.warn(` ${err}`);
|
|
1742
1751
|
}
|
|
1752
|
+
logger.info("Retrying generation with error feedback...");
|
|
1753
|
+
const fixPrompt = [
|
|
1754
|
+
"The previous generation was incomplete. The following required files are missing:",
|
|
1755
|
+
...validation.errors.map((e) => `- ${e}`),
|
|
1756
|
+
"",
|
|
1757
|
+
"Please create ALL missing files. Here is the original specification:",
|
|
1758
|
+
"",
|
|
1759
|
+
prompt
|
|
1760
|
+
].join("\n");
|
|
1761
|
+
await runEngine(engine, fixPrompt, outputDir);
|
|
1762
|
+
validation = await validateGeneratedSite(outputDir);
|
|
1763
|
+
if (!validation.valid) {
|
|
1764
|
+
logger.warn("Still missing files after retry:");
|
|
1765
|
+
for (const err of validation.errors) {
|
|
1766
|
+
logger.warn(` ${err}`);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1743
1769
|
}
|
|
1744
1770
|
}
|
|
1745
1771
|
async function buildSite(siteDir) {
|
|
@@ -1764,6 +1790,21 @@ async function buildSite(siteDir) {
|
|
|
1764
1790
|
}
|
|
1765
1791
|
return true;
|
|
1766
1792
|
}
|
|
1793
|
+
async function retryBuild(engine, siteDir, buildError, originalPrompt) {
|
|
1794
|
+
logger.info("Retrying: feeding build error back to AI...");
|
|
1795
|
+
const fixPrompt = `The site generation produced build errors. Fix the following errors without changing the overall design or structure:
|
|
1796
|
+
|
|
1797
|
+
${buildError}
|
|
1798
|
+
|
|
1799
|
+
Original prompt for context:
|
|
1800
|
+
${originalPrompt.slice(0, 2e3)}`;
|
|
1801
|
+
try {
|
|
1802
|
+
await runEngine(engine, fixPrompt, siteDir);
|
|
1803
|
+
return await buildSite(siteDir);
|
|
1804
|
+
} catch {
|
|
1805
|
+
return false;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1767
1808
|
var init_orchestrator = __esm({
|
|
1768
1809
|
"src/orchestrator/index.ts"() {
|
|
1769
1810
|
"use strict";
|
|
@@ -2118,7 +2159,7 @@ import { resolve } from "path";
|
|
|
2118
2159
|
import { join as join6 } from "path";
|
|
2119
2160
|
import * as p3 from "@clack/prompts";
|
|
2120
2161
|
async function initCommand(options) {
|
|
2121
|
-
logger.header("shipfolio v1.0.
|
|
2162
|
+
logger.header("shipfolio v1.0.4");
|
|
2122
2163
|
logger.info("Detecting AI engines...");
|
|
2123
2164
|
const engines = await detectEngines();
|
|
2124
2165
|
const availableTypes = getAvailableEngineTypes(engines);
|
|
@@ -2177,8 +2218,7 @@ async function initCommand(options) {
|
|
|
2177
2218
|
await generateSite(spec.engine, prompt, outputDir);
|
|
2178
2219
|
let buildSuccess = await buildSite(outputDir);
|
|
2179
2220
|
if (!buildSuccess) {
|
|
2180
|
-
|
|
2181
|
-
buildSuccess = await buildSite(outputDir);
|
|
2221
|
+
buildSuccess = await retryBuild(spec.engine, outputDir, "Build failed. Check missing files and fix errors.", prompt);
|
|
2182
2222
|
if (!buildSuccess) {
|
|
2183
2223
|
logger.error("Build failed after retry. Check the output directory for details.");
|
|
2184
2224
|
process.exit(1);
|
|
@@ -2568,7 +2608,7 @@ initLocale();
|
|
|
2568
2608
|
var program = new Command();
|
|
2569
2609
|
program.name("shipfolio").description(
|
|
2570
2610
|
"Generate and deploy your personal portfolio site from local projects using AI"
|
|
2571
|
-
).version("1.0.
|
|
2611
|
+
).version("1.0.4");
|
|
2572
2612
|
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);
|
|
2573
2613
|
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);
|
|
2574
2614
|
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 { logger } from \"../../utils/logger.js\";\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 // Use claude CLI with --print flag for non-interactive mode\n // and direct it to create files in the output directory\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\", [\"-p\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 300000, // 5 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 { logger } from \"../../utils/logger.js\";\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: 300000,\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\nexport async function generateSite(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n await ensureDir(outputDir);\n\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 // Validate generated output\n const 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 // Could retry here, but for now just warn\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 generateSite(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 } 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.3\");\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 logger.info(\"Attempting retry...\");\n buildSuccess = await buildSite(outputDir);\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.3\");\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\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"]}
|