create-foliokit 0.0.0-stage → 1.0.0

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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -2
  3. package/bin/index.js +6 -0
  4. package/package.json +50 -4
  5. package/src/cli.js +111 -0
  6. package/src/generator.js +133 -0
  7. package/src/prompts.js +44 -0
  8. package/src/utils/errors.js +7 -0
  9. package/src/utils/paths.js +12 -0
  10. package/src/utils/progress.js +5 -0
  11. package/src/utils/project-name.js +30 -0
  12. package/templates/default/.gitignore +20 -0
  13. package/templates/default/data.ts +227 -0
  14. package/templates/default/index.html +23 -0
  15. package/templates/default/package-lock.json +1280 -0
  16. package/templates/default/package.json +28 -0
  17. package/templates/default/public/avatar-placeholder.svg +10 -0
  18. package/templates/default/public/footer-heart.png +0 -0
  19. package/templates/default/public/love-always-wins.png +0 -0
  20. package/templates/default/public/project-placeholder.svg +10 -0
  21. package/templates/default/public/robots.txt +2 -0
  22. package/templates/default/public/stars-foreground-landscape.svg +202 -0
  23. package/templates/default/public/stars-foreground-portrait.svg +202 -0
  24. package/templates/default/public/stars-landscape.svg +322 -0
  25. package/templates/default/public/stars-portrait.svg +322 -0
  26. package/templates/default/scripts/generate-seo.mjs +34 -0
  27. package/templates/default/src/App.tsx +552 -0
  28. package/templates/default/src/BrandIcon.tsx +36 -0
  29. package/templates/default/src/ProjectMagazineGallery.css +90 -0
  30. package/templates/default/src/ProjectMagazineGallery.tsx +210 -0
  31. package/templates/default/src/main.tsx +10 -0
  32. package/templates/default/src/styles.css +536 -0
  33. package/templates/default/src/utils.ts +2 -0
  34. package/templates/default/src/vite-env.d.ts +1 -0
  35. package/templates/default/tests/portfolio.test.js +96 -0
  36. package/templates/default/tsconfig.app.json +21 -0
  37. package/templates/default/tsconfig.json +7 -0
  38. package/templates/default/tsconfig.node.json +16 -0
  39. package/templates/default/vite.config.ts +38 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Saurabh Pandey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,378 @@
1
- # Temporary Holding Version
1
+ # FolioKit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D22.12.0-brightgreen.svg)](package.json)
5
+ [![npm version](https://img.shields.io/npm/v/foliokit.svg)](https://www.npmjs.com/package/foliokit)
6
+
7
+ > A modern, zero-config CLI generator that scaffolds high-performance, customizable developer portfolios built with React 19, TypeScript, and Vite.
8
+
9
+ FolioKit enables developers to launch a sleek, production-ready portfolio in seconds. Instead of wrestling with complex UI code, your entire website—from bio and skills to featured projects and social links—is managed cleanly through a single configuration file: [`data.ts`](templates/default/data.ts).
10
+
11
+ ---
12
+
13
+ ## Features
14
+
15
+ - **Instant Scaffolding** — Create a complete portfolio project with one command (`npx foliokit`).
16
+ - **Single-File Customization** — Edit `data.ts` to update all content, projects, bio, skills, and layout ordering without touching React components.
17
+ - **Modern Tech Stack** — Built with React 19, TypeScript, and Vite for fast development and lightweight production bundles (~80 kB gzip).
18
+ - **Aesthetic Obsidian Theme** — Designed with a dark graphite palette, atmospheric canvas starfields, and metallic typography accents.
19
+ - **Interactive 3D Magazine Carousel** — Showcase featured projects in a perspective-lifted cover gallery with mouse-tilt, touch swipe, trackpad wheel gestures, and keyboard navigation.
20
+ - **Automatic Skill Icons** — Integrates with [Skill Icons](https://skillicons.dev) and Simple Icons for crisp vector technology and brand badges.
21
+ - **Dynamic Local Time & Clock** — Real-time digital clock synced to your configured IANA time zone.
22
+ - **Pre-Configured Content Sections** — Hero, About, Skills, Featured Projects, Work Experience, Education, Testimonials, and Contact.
23
+ - **Automated SEO & Social Sharing** — Build script automatically injects personalized OpenGraph tags, Twitter cards, canonical links, and generates a valid `sitemap.xml` and `robots.txt`.
24
+ - **Accessible & Responsive** — Verified across mobile (320px+), tablet, laptop, and ultra-wide screens. Full support for `prefers-reduced-motion` and WCAG touch targets.
25
+ - **Static Hosting Ready** — Zero-config static deployment on Vercel, Netlify, Cloudflare Pages, and GitHub Pages.
26
+
27
+ ---
28
+
29
+ ## Preview
30
+
31
+ <!-- Portfolio UI Preview Screenshot Placeholder -->
32
+ <!-- Place your screenshot here: ![FolioKit Preview](https://raw.githubusercontent.com/saurabhhdev/foliokit/main/preview.png) -->
33
+
34
+ The generated portfolio features a dark obsidian background (`#000000`), subtle starfield overlays, golden metallic accent highlights, and clean dotted framing inspired by modern developer terminals and developer tool aesthetic.
35
+
36
+ ---
37
+
38
+ ## Requirements
39
+
40
+ Before running FolioKit, ensure your environment meets these requirements:
41
+
42
+ - **Node.js**: Version `22.12.0` or higher
43
+ - **npm**: Version `10.0.0` or higher (or compatible `pnpm` / `yarn`)
44
+ - **Operating Systems**: macOS, Linux, and Windows 10/11
45
+
46
+ To verify your installed Node.js version, run:
47
+
48
+ ```bash
49
+ node --version
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Quick Start
55
+
56
+ Generate your developer portfolio in three steps:
57
+
58
+ ### 1. Run the CLI
59
+
60
+ ```bash
61
+ npx foliokit
62
+ ```
63
+
64
+ *Or install globally:*
65
+
66
+ ```bash
67
+ npm install -g foliokit
68
+ foliokit
69
+ ```
70
+
71
+ ### 2. Answer the Interactive Prompts
72
+
73
+ ```text
74
+ FOLIOKIT
75
+ Developer Portfolio Generator
76
+
77
+ ? What should your project be called? my-portfolio
78
+ ? Install dependencies? (Y/n) y
79
+ ```
80
+
81
+ - **Project name**: Enter a folder name using lowercase letters, numbers, and single hyphens (default: `my-portfolio`).
82
+ - **Install dependencies**: Choose whether FolioKit should automatically run `npm install` inside the created folder.
83
+
84
+ ### 3. Start Developing
85
+
86
+ ```bash
87
+ cd my-portfolio
88
+ npm run dev
89
+ ```
90
+
91
+ Open [http://localhost:5173](http://localhost:5173) in your browser to view your live portfolio.
92
+
93
+ ---
94
+
95
+ ## CLI Commands & Options
96
+
97
+ FolioKit provides a straightforward command-line interface:
98
+
99
+ | Command / Option | Description |
100
+ | :--- | :--- |
101
+ | `npx foliokit` | Runs the interactive project creation wizard in the current directory. |
102
+ | `foliokit create` | Explicit subcommand to start the setup wizard. |
103
+ | `-v, --version` | Outputs the current installed FolioKit version. |
104
+ | `-h, --help` | Displays help information, available flags, and usage syntax. |
105
+
106
+ ### Examples
107
+
108
+ ```bash
109
+ # Check installed CLI version
110
+ foliokit --version
111
+
112
+ # View usage guidelines
113
+ foliokit --help
114
+
115
+ # Create a new project
116
+ foliokit create
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Customization Guide (`data.ts`)
122
+
123
+ All portfolio content is centralized in the root `data.ts` file of your generated project. Open `data.ts` in your code editor to personalize your site.
124
+
125
+ ### 1. Personal Details & Hero
126
+
127
+ ```typescript
128
+ profile: {
129
+ name: 'Alex Rivera',
130
+ headline: 'Full Stack Engineer & Open Source Contributor',
131
+ introduction: "Hey, there! I'm a",
132
+ about: `I build scalable web applications and developer tools.
133
+
134
+ I specialize in React, Node.js, and distributed systems.`,
135
+ location: 'San Francisco, CA',
136
+ timeZone: 'America/Los_Angeles',
137
+ timeZoneLabel: 'PST',
138
+ profileImage: '/avatar-placeholder.svg', // or '/my-photo.jpg' placed in public/
139
+ quote: 'Build with curiosity. Share what you learn.',
140
+ }
141
+ ```
142
+
143
+ ### 2. Social Links
144
+
145
+ Add or update your social media profiles in the `socialIcons` array:
146
+
147
+ ```typescript
148
+ socialIcons: [
149
+ { label: 'GitHub', icon: 'github', url: 'https://github.com/your-username', color: '#f2f0e9' },
150
+ { label: 'LinkedIn', icon: 'linkedin', url: 'https://linkedin.com/in/your-username', color: '#0a66c2' },
151
+ { label: 'X', icon: 'x', url: 'https://x.com/your-username', color: '#f2f0e9' },
152
+ ]
153
+ ```
154
+
155
+ ### 3. Technical Skills
156
+
157
+ Add, remove, or reorder technologies. Icons are automatically fetched from [Skill Icons](https://skillicons.dev) using the `icon` identifier:
158
+
159
+ ```typescript
160
+ skills: [
161
+ { name: 'React', icon: 'react', category: 'Frontend' },
162
+ { name: 'TypeScript', icon: 'ts', category: 'Frontend' },
163
+ { name: 'Node.js', icon: 'nodejs', category: 'Backend' },
164
+ { name: 'PostgreSQL', icon: 'postgres', category: 'Backend' },
165
+ { name: 'Docker', icon: 'docker', category: 'Tools' },
166
+ ]
167
+ ```
168
+
169
+ ### 4. Featured Projects
170
+
171
+ Projects with `featured: true` appear prominently in the interactive 3D magazine gallery as well as the detailed project cards below:
172
+
173
+ ```typescript
174
+ projects: [
175
+ {
176
+ name: 'DevFlow',
177
+ category: 'DEVELOPER TOOLING',
178
+ description: 'An open-source terminal workflow engine designed to automate repetitive task pipelines.',
179
+ image: '/project-placeholder.svg', // Place your thumbnail in public/
180
+ imageAlt: 'DevFlow terminal preview',
181
+ technologies: [
182
+ { name: 'TypeScript', icon: 'ts' },
183
+ { name: 'Node.js', icon: 'nodejs' },
184
+ ],
185
+ liveUrl: 'https://devflow.example',
186
+ githubUrl: 'https://github.com/your-username/devflow',
187
+ featured: true,
188
+ },
189
+ ]
190
+ ```
191
+
192
+ ### 5. Work Experience & Education
193
+
194
+ ```typescript
195
+ experience: [
196
+ {
197
+ title: 'Senior Software Engineer',
198
+ organization: 'Acme Corp',
199
+ date: '2023 – Present',
200
+ description: 'Architected microservices and improved core API latency by 35%.',
201
+ },
202
+ ],
203
+ education: [
204
+ {
205
+ title: 'B.S. in Computer Science',
206
+ organization: 'University of California, Berkeley',
207
+ date: '2019 – 2023',
208
+ description: 'Focused on algorithms, distributed databases, and software engineering.',
209
+ },
210
+ ]
211
+ ```
212
+
213
+ ### 6. Optional Sections (Testimonials, Experience, Education)
214
+
215
+ Content sections render dynamically based on whether items exist in their array. To omit any optional section from the portfolio, simply leave its array empty:
216
+
217
+ ```typescript
218
+ // Leave empty to omit this section from the portfolio:
219
+ testimonials: [],
220
+ experience: [],
221
+ education: [],
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Images and Assets
227
+
228
+ All static visual assets live inside the `public/` directory of your generated project:
229
+
230
+ ```text
231
+ my-portfolio/
232
+ └── public/
233
+ ├── avatar-placeholder.svg
234
+ ├── project-placeholder.svg
235
+ ├── footer-heart.png
236
+ ├── love-always-wins.png
237
+ └── robots.txt
238
+ ```
239
+
240
+ ### How to Use Your Own Images:
241
+
242
+ 1. Copy your image into the `public/` folder (e.g. `public/my-photo.jpg`).
243
+ 2. In `data.ts`, reference the image with a leading slash:
244
+ ```typescript
245
+ profileImage: '/my-photo.jpg'
246
+ ```
247
+ 3. For project thumbnails, copy images to `public/` (recommended aspect ratio: `16:9` or `1200x675` px) and set `image: '/project-one.png'`.
248
+ 4. **Supported Formats**: SVG, WebP, PNG, JPG/JPEG.
249
+ 5. **Fallbacks**: If an image fails to load or is omitted, FolioKit automatically renders accessible fallback elements (e.g., initial-letter monogram badges for avatars).
250
+
251
+ ---
252
+
253
+ ## Project Structure
254
+
255
+ A portfolio generated by FolioKit has the following clean structure:
256
+
257
+ ```text
258
+ my-portfolio/
259
+ ├── data.ts # Central content configuration (edit this!)
260
+ ├── index.html # HTML entry point (title & metadata injected from data.ts)
261
+ ├── package.json # Project scripts and dependencies
262
+ ├── vite.config.ts # Vite configuration with automated metadata plugin
263
+ ├── tsconfig.json # TypeScript configuration
264
+ ├── public/ # Static assets (images, avatars, icons, robots.txt)
265
+ │ ├── avatar-placeholder.svg
266
+ │ └── project-placeholder.svg
267
+ ├── scripts/
268
+ │ └── generate-seo.mjs # Production SEO, canonical URL, and sitemap generator
269
+ └── src/
270
+ ├── main.tsx # React application entry point
271
+ ├── App.tsx # Main portfolio layout and section renderers
272
+ ├── styles.css # Responsive styles and theme variables
273
+ ├── utils.ts # Lightweight DOM helpers
274
+ ├── BrandIcon.tsx # Vector brand logo helper with fallbacks
275
+ ├── ProjectMagazineGallery.tsx # 3D interactive carousel
276
+ └── ProjectMagazineGallery.css # 3D perspective & carousel styling
277
+ ```
278
+
279
+ ---
280
+
281
+ ## Tech Stack
282
+
283
+ ### FolioKit CLI
284
+ - **Runtime**: [Node.js](https://nodejs.org) (>= 22.12.0)
285
+ - **CLI Framework**: [Commander.js](https://github.com/tj/commander.js)
286
+ - **Interactive Prompts**: [Inquirer.js](https://github.com/SBoudrias/Inquirer.js)
287
+ - **Terminal Styling**: [Chalk](https://github.com/chalk/chalk)
288
+ - **Terminal Spinners**: [Ora](https://github.com/sindresorhus/ora)
289
+
290
+ ### Generated Portfolio
291
+ - **UI Framework**: [React 19](https://react.dev)
292
+ - **Language**: [TypeScript](https://www.typescriptlang.org)
293
+ - **Bundler & Dev Server**: [Vite 8](https://vitejs.dev)
294
+ - **Icons**: [Lucide React](https://lucide.dev) & [Simple Icons](https://simpleicons.org)
295
+ - **Styling**: Native Modern CSS (CSS Grid, Flexbox, CSS Variables, 3D Transforms)
296
+
297
+ ---
298
+
299
+ ## Troubleshooting
300
+
301
+ ### 1. "Node.js version must be >=22.12.0"
302
+ - **Cause**: An older Node.js runtime is active in your terminal.
303
+ - **Solution**: Install or activate Node.js 22.12.0 or newer using [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm):
304
+ ```bash
305
+ nvm install 22
306
+ nvm use 22
307
+ ```
308
+
309
+ ### 2. Destination Folder Already Exists
310
+ - **Cause**: A folder with the specified project name already exists in your current directory.
311
+ - **Solution**: Choose a different name when prompted, or confirm the prompt to overwrite the existing folder.
312
+
313
+ ### 3. Dependency Installation Failed
314
+ - **Cause**: Network timeout or strict corporate proxy blocked `npm install`.
315
+ - **Solution**: Your generated project files are safely preserved. Navigate into the folder and manually install dependencies:
316
+ ```bash
317
+ cd my-portfolio
318
+ npm install
319
+ ```
320
+
321
+ ### 4. Development Port 5173 in Use
322
+ - **Cause**: Another local development server is running on port 5173.
323
+ - **Solution**: Vite automatically attempts the next available port (e.g. 5174). You can also specify a custom port:
324
+ ```bash
325
+ npm run dev -- --port 3000
326
+ ```
327
+
328
+ ### 5. TypeScript Error After Editing `data.ts`
329
+ - **Cause**: A required field was removed or a type mismatch was introduced.
330
+ - **Solution**: Check the terminal output or editor diagnostics. Run `npm test` inside the portfolio directory to validate your `data.ts` structure against the test suite.
331
+
332
+ ---
333
+
334
+ ## Contributing
335
+
336
+ Contributions, issues, and feature requests are welcome!
337
+
338
+ ### Development Workflow
339
+
340
+ 1. Fork the repository on GitHub.
341
+ 2. Clone your fork locally:
342
+ ```bash
343
+ git clone https://github.com/saurabhhdev/foliokit.git
344
+ cd foliokit
345
+ ```
346
+ 3. Install dependencies:
347
+ ```bash
348
+ npm install
349
+ ```
350
+ 4. Run CLI and generator tests:
351
+ ```bash
352
+ npm test
353
+ ```
354
+ 5. Test the default template:
355
+ ```bash
356
+ cd templates/default
357
+ npm test
358
+ npm run build
359
+ cd ../..
360
+ ```
361
+ 6. Create a feature branch (`git checkout -b feature/amazing-idea`), commit your changes, and submit a pull request.
362
+
363
+ ---
364
+
365
+ ## License
366
+
367
+ Distributed under the **MIT License**. See [`LICENSE`](LICENSE) for complete details.
368
+
369
+ Copyright (c) 2026 **Saurabh Pandey**.
370
+
371
+ ---
372
+
373
+ ## Author & Links
374
+
375
+ - **Author**: Saurabh Pandey
376
+ - **GitHub**: [@saurabhhdev](https://github.com/saurabhhdev)
377
+ - **Repository**: [https://github.com/saurabhhdev/foliokit](https://github.com/saurabhhdev/foliokit)
378
+ - **Issue Tracker**: [https://github.com/saurabhhdev/foliokit/issues](https://github.com/saurabhhdev/foliokit/issues)
package/bin/index.js ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from '../src/cli.js'
4
+ import { reportCliError } from '../src/utils/errors.js'
5
+
6
+ runCli().catch(reportCliError)
package/package.json CHANGED
@@ -1,6 +1,52 @@
1
1
  {
2
2
  "name": "create-foliokit",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Generate customizable React and TypeScript developer portfolios",
5
+ "type": "module",
6
+ "main": "./src/cli.js",
7
+ "exports": {
8
+ ".": "./src/cli.js",
9
+ "./generator": "./src/generator.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "author": "Saurabh Pandey",
13
+ "scripts": {
14
+ "test": "node --test tests"
15
+ },
16
+ "bin": {
17
+ "foliokit": "./bin/index.js"
18
+ },
19
+ "files": [
20
+ "bin/",
21
+ "src/",
22
+ "templates/",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22.12.0"
28
+ },
29
+ "keywords": [
30
+ "portfolio",
31
+ "developer-portfolio",
32
+ "react",
33
+ "typescript",
34
+ "cli",
35
+ "generator"
36
+ ],
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/saurabhhdev/foliokit.git"
40
+ },
41
+ "homepage": "https://github.com/saurabhhdev/foliokit#readme",
42
+ "bugs": {
43
+ "url": "https://github.com/saurabhhdev/foliokit/issues"
44
+ },
45
+ "license": "MIT",
46
+ "dependencies": {
47
+ "chalk": "^6.0.1",
48
+ "commander": "^15.0.0",
49
+ "inquirer": "^14.2.5",
50
+ "ora": "^9.4.1"
51
+ }
52
+ }
package/src/cli.js ADDED
@@ -0,0 +1,111 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { spawn } from 'node:child_process'
3
+ import { Command } from 'commander'
4
+ import chalk from 'chalk'
5
+ import inquirer from 'inquirer'
6
+ import { generatePortfolio } from './generator.js'
7
+ import { promptForProjectOptions } from './prompts.js'
8
+ import { getPackagePath } from './utils/paths.js'
9
+ import { createProgress } from './utils/progress.js'
10
+
11
+ const packageMetadata = JSON.parse(readFileSync(getPackagePath('package.json'), 'utf8'))
12
+
13
+ function showWelcome() {
14
+ console.log(chalk.bold.cyan('FOLIOKIT'))
15
+ console.log(chalk.dim('Developer Portfolio Generator'))
16
+ console.log()
17
+ }
18
+
19
+ async function startSetup() {
20
+ showWelcome()
21
+ const options = await promptForProjectOptions()
22
+
23
+ if (!options) {
24
+ console.log(chalk.yellow('Setup cancelled.'))
25
+ return
26
+ }
27
+
28
+ let projectPath
29
+ try {
30
+ projectPath = await generatePortfolio(options)
31
+ } catch (error) {
32
+ if (!(error instanceof Error) || error.code !== 'EEXIST') throw error
33
+ let overwrite
34
+ try {
35
+ ({ overwrite } = await inquirer.prompt([{
36
+ type: 'confirm',
37
+ name: 'overwrite',
38
+ message: `The folder ${options.projectName} already exists. Replace it?`,
39
+ default: false,
40
+ }]))
41
+ } catch (promptError) {
42
+ if (promptError instanceof Error && promptError.name === 'ExitPromptError') {
43
+ console.log(chalk.yellow('Setup cancelled. Existing project was left unchanged.'))
44
+ return
45
+ }
46
+ throw promptError
47
+ }
48
+ if (!overwrite) {
49
+ console.log(chalk.yellow('Existing project was left unchanged.'))
50
+ return
51
+ }
52
+ projectPath = await generatePortfolio({ ...options, overwrite: true })
53
+ }
54
+
55
+ let dependenciesInstalled = false
56
+ if (options.installDependencies) {
57
+ const windows = process.platform === 'win32'
58
+ const install = spawn(windows ? (process.env.ComSpec || 'cmd.exe') : 'npm', windows ? ['/d', '/s', '/c', 'npm.cmd install'] : ['install'], {
59
+ cwd: projectPath,
60
+ stdio: 'inherit',
61
+ shell: false,
62
+ })
63
+ const installation = createProgress('Installing dependencies...').start()
64
+ const result = await new Promise((resolve) => {
65
+ install.once('error', (error) => resolve({ code: 1, error }))
66
+ install.once('close', (code) => resolve({ code: code ?? 1 }))
67
+ })
68
+ dependenciesInstalled = result.code === 0
69
+ if (dependenciesInstalled) installation.succeed('Dependencies installed')
70
+ else installation.fail('Dependency installation failed')
71
+ if (!dependenciesInstalled) {
72
+ console.error(chalk.red('Dependency installation failed. Your generated project is still available.'))
73
+ if (result.error) console.error(chalk.dim(result.error.message))
74
+ console.error(`Run ${chalk.bold('npm install')} inside ${options.projectName} to try again.`)
75
+ }
76
+ }
77
+
78
+ const configuration = { ...options, projectPath }
79
+ console.log()
80
+ console.log(chalk.green('✔ Portfolio generated successfully!'))
81
+ console.log()
82
+ console.log(chalk.bold('Next steps:'))
83
+ console.log(` cd ${configuration.projectName}`)
84
+ if (!dependenciesInstalled) console.log(' npm install')
85
+ console.log(' npm run dev')
86
+ console.log()
87
+ console.log(`Customize your portfolio by editing ${chalk.bold('data.ts')}.`)
88
+ if (options.installDependencies && !dependenciesInstalled) process.exitCode = 1
89
+ }
90
+
91
+ export function createCli() {
92
+ const program = new Command()
93
+
94
+ program
95
+ .name('foliokit')
96
+ .description('Generate customizable developer portfolio websites')
97
+ .version(packageMetadata.version, '-v, --version')
98
+ .showHelpAfterError()
99
+ .action(startSetup)
100
+
101
+ program
102
+ .command('create')
103
+ .description('Create a portfolio project')
104
+ .action(startSetup)
105
+
106
+ return program
107
+ }
108
+
109
+ export async function runCli(argv = process.argv) {
110
+ await createCli().parseAsync(argv)
111
+ }