[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"header-categories":3,"post-building-cli-tool-nodejs-npm":73,"parsed-post-9322b32b-bc2b-4502-a0c0-274bb931f841":143},{"success":4,"data":5},true,{"items":6,"pagination":70},[7,16,24,32,40,48,56,63],{"id":8,"name":9,"description":10,"parentId":11,"createdAt":12,"updatedAt":12,"parent":11,"children":13,"_count":14},"ai-future","AI & The Future","Artificial intelligence and emerging technology",null,"2026-07-24T06:02:45.990Z",[],{"posts":15},1,{"id":17,"name":18,"description":19,"parentId":11,"createdAt":20,"updatedAt":20,"parent":11,"children":21,"_count":22},"tools-productivity","Tools & Productivity","Developer tools and workflow optimization","2026-07-24T06:02:45.712Z",[],{"posts":23},7,{"id":25,"name":26,"description":27,"parentId":11,"createdAt":28,"updatedAt":28,"parent":11,"children":29,"_count":30},"career","Career & Growth","Professional development for developers","2026-07-24T06:02:45.486Z",[],{"posts":31},3,{"id":33,"name":34,"description":35,"parentId":11,"createdAt":36,"updatedAt":36,"parent":11,"children":37,"_count":38},"opinion","Opinion & Analysis","Industry analysis and technical opinions","2026-07-24T06:02:45.272Z",[],{"posts":39},6,{"id":41,"name":42,"description":43,"parentId":11,"createdAt":44,"updatedAt":44,"parent":11,"children":45,"_count":46},"tutorials","Tutorials","Step-by-step learning guides","2026-07-24T06:02:44.965Z",[],{"posts":47},21,{"id":49,"name":50,"description":51,"parentId":11,"createdAt":52,"updatedAt":52,"parent":11,"children":53,"_count":54},"software-engineering","Software Engineering","Best practices, patterns, and principles","2026-07-24T06:02:44.689Z",[],{"posts":55},24,{"id":57,"name":58,"description":59,"parentId":11,"createdAt":60,"updatedAt":60,"parent":11,"children":61,"_count":62},"devops-cloud","DevOps & Cloud","Infrastructure, deployment, and cloud computing","2026-07-24T06:02:44.453Z",[],{"posts":39},{"id":64,"name":65,"description":66,"parentId":11,"createdAt":67,"updatedAt":67,"parent":11,"children":68,"_count":69},"web-development","Web Development","Frontend and backend web development tutorials and guides","2026-07-24T06:02:44.169Z",[],{"posts":55},{"page":15,"limit":71,"total":71,"totalPages":15,"hasNext":72,"hasPrev":72},8,false,{"success":4,"data":74},{"id":75,"slug":76,"title":77,"excerpt":78,"content":79,"status":80,"visibility":81,"featuredImage":82,"canonicalUrl":11,"readingTime":83,"viewCount":84,"commentEnabled":4,"publishedAt":85,"scheduledAt":11,"createdAt":86,"updatedAt":87,"seoTitle":88,"seoDescription":78,"seoKeywords":11,"authorId":89,"author":90,"coAuthors":95,"tags":96,"categories":107,"comments":110,"_count":111,"relatedPosts":113},"9322b32b-bc2b-4502-a0c0-274bb931f841","building-cli-tool-nodejs-npm","Building a CLI Tool with Node.js: From Zero to NPM","Create a professional CLI tool with argument parsing, colorful output, progress indicators, and publish it to NPM for the world to use.","## Why Build a CLI?\n\nCLIs are the most underrated way to boost productivity. Instead of remembering complex commands, wrap them in a tool tailored to your workflow.\n\n## Project Setup\n\n```bash\nmkdir my-cli && cd my-cli\npnpm init\npnpm add commander chalk ora\npnpm add -D typescript @types\u002Fnode tsx\n```\n\n```json\n\u002F\u002F package.json\n{\n  \"name\": \"my-cli\",\n  \"version\": \"1.0.0\",\n  \"bin\": {\n    \"mycli\": \".\u002Fdist\u002Findex.js\"\n  },\n  \"type\": \"module\"\n}\n```\n\n## Basic Command Structure\n\n```typescript\n#!\u002Fusr\u002Fbin\u002Fenv node\n\u002F\u002F src\u002Findex.ts\nimport { Command } from 'commander'\nimport chalk from 'chalk'\n\nconst program = new Command()\n\nprogram\n  .name('mycli')\n  .description('My awesome CLI tool')\n  .version('1.0.0')\n\nprogram\n  .command('init')\n  .description('Initialize a new project')\n  .argument('[name]', 'Project name', 'my-project')\n  .option('-t, --template \u003Ctemplate>', 'Template to use', 'default')\n  .action(async (name, options) => {\n    console.log(chalk.blue(`Creating project: ${name}`))\n    console.log(chalk.gray(`Template: ${options.template}`))\n    await createProject(name, options.template)\n    console.log(chalk.green('✓ Done!'))\n  })\n\nprogram.parse()\n```\n\n## Progress Indicators\n\n```typescript\nimport ora from 'ora'\n\nasync function createProject(name: string, template: string) {\n  const spinner = ora('Creating project structure...').start()\n\n  await mkdir(name)\n  spinner.text = 'Installing dependencies...'\n\n  await installDeps(name)\n  spinner.text = 'Configuring...'\n\n  await configure(name, template)\n  spinner.succeed('Project created successfully!')\n}\n```\n\n::callout{icon=\"i-lucide-terminal\" color=\"primary\"}\nGood CLI UX means: progress feedback, clear error messages, and `--help` that actually helps. Treat your CLI like a UI.\n::\n\n## Interactive Prompts\n\n```typescript\nimport { input, select, confirm } from '@inquirer\u002Fprompts'\n\nasync function interactiveInit() {\n  const name = await input({\n    message: 'Project name:',\n    default: 'my-app',\n  })\n\n  const template = await select({\n    message: 'Choose a template:',\n    choices: [\n      { name: 'Minimal', value: 'minimal' },\n      { name: 'Full-stack (Nuxt)', value: 'nuxt' },\n      { name: 'API only', value: 'api' },\n    ],\n  })\n\n  const useDocker = await confirm({\n    message: 'Add Docker setup?',\n    default: true,\n  })\n\n  return { name, template, useDocker }\n}\n```\n\n## Error Handling\n\n```typescript\nprogram\n  .command('deploy')\n  .action(async () => {\n    try {\n      await deploy()\n    } catch (error) {\n      console.error(chalk.red('✗ Deploy failed:'))\n      console.error(chalk.gray((error as Error).message))\n      process.exit(1)\n    }\n  })\n```\n\n## Publishing to NPM\n\n```bash\n# Build\npnpm tsc\n\n# Test locally\nnpm link\nmycli --help\n\n# Publish\nnpm login\nnpm publish\n```\n\n## Tips\n\n- Always provide `--help` and `--version`\n- Use exit codes (0 = success, 1 = error)\n- Support piping (`stdin`\u002F`stdout`)\n- Add shell completions for power users\n- Write a good README with examples\n\nA well-crafted CLI is a gift to your future self and your team.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1618477388954-7852f32655ec?w=1200&q=80",9,2148,"2026-05-30T06:03:51.038Z","2026-07-24T06:03:51.041Z","2026-07-28T17:08:43.403Z","Building a CLI Tool with Node.js: From Zero to NPM | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":91,"bio":92,"id":89,"name":93,"avatarUrl":94},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[97,102],{"id":98,"name":99,"color":100,"description":101},"typescript","TypeScript","#3178c6","Typed superset of JavaScript",{"id":103,"name":104,"color":105,"description":106},"nodejs","Node.js","#339933","JavaScript runtime built on V8",[108,109],{"id":41,"name":42,"description":43},{"id":17,"name":18,"description":19},[],{"comments":112},0,[114,123,133],{"id":115,"slug":116,"title":117,"excerpt":118,"featuredImage":119,"viewCount":120,"readingTime":71,"publishedAt":121,"author":122},"2997028f-4d22-4eb7-9d86-894a54cb559a","building-type-safe-apis-nuxt3-prisma","Building Type-Safe APIs with Nuxt 3 and Prisma","Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085?w=1200&q=80",1922,"2026-07-23T06:02:46.910Z",{"id":89,"name":93,"avatarUrl":94},{"id":124,"slug":125,"title":126,"excerpt":127,"featuredImage":128,"viewCount":129,"readingTime":130,"publishedAt":131,"author":132},"da9e4553-8b0d-411e-b4ec-f9684017e163","mastering-tailwind-css-design-systems","Mastering Tailwind CSS: From Utility Classes to Design Systems","Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",257,10,"2026-07-21T06:02:49.268Z",{"id":89,"name":93,"avatarUrl":94},{"id":134,"slug":135,"title":136,"excerpt":137,"featuredImage":138,"viewCount":139,"readingTime":140,"publishedAt":141,"author":142},"50add5fc-4026-4267-b917-7f71ea9e35b0","complete-guide-vue3-composables","The Complete Guide to Vue 3 Composables","Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517694712202-14dd9538aa97?w=1200&q=80",990,12,"2026-07-19T06:02:51.753Z",{"id":89,"name":93,"avatarUrl":94},{"data":144,"body":146,"toc":358},{"title":145,"description":145},"",{"type":147,"children":148},"root",[149,158,164,170,183,193,199,208,214,222,241,247,255,261,269,275,283,289,348,353],{"type":150,"tag":151,"props":152,"children":154},"element","h2",{"id":153},"why-build-a-cli",[155],{"type":156,"value":157},"text","Why Build a CLI?",{"type":150,"tag":159,"props":160,"children":161},"p",{},[162],{"type":156,"value":163},"CLIs are the most underrated way to boost productivity. Instead of remembering complex commands, wrap them in a tool tailored to your workflow.",{"type":150,"tag":151,"props":165,"children":167},{"id":166},"project-setup",[168],{"type":156,"value":169},"Project Setup",{"type":150,"tag":171,"props":172,"children":177},"pre",{"className":173,"code":174,"language":175,"meta":145,"style":176},"language-bash","mkdir my-cli && cd my-cli\npnpm init\npnpm add commander chalk ora\npnpm add -D typescript @types\u002Fnode tsx\n","bash","undefined",[178],{"type":150,"tag":179,"props":180,"children":181},"code",{"__ignoreMap":145},[182],{"type":156,"value":174},{"type":150,"tag":171,"props":184,"children":188},{"className":185,"code":186,"language":187,"meta":145,"style":176},"language-json","\u002F\u002F package.json\n{\n  \"name\": \"my-cli\",\n  \"version\": \"1.0.0\",\n  \"bin\": {\n    \"mycli\": \".\u002Fdist\u002Findex.js\"\n  },\n  \"type\": \"module\"\n}\n","json",[189],{"type":150,"tag":179,"props":190,"children":191},{"__ignoreMap":145},[192],{"type":156,"value":186},{"type":150,"tag":151,"props":194,"children":196},{"id":195},"basic-command-structure",[197],{"type":156,"value":198},"Basic Command Structure",{"type":150,"tag":171,"props":200,"children":203},{"className":201,"code":202,"language":98,"meta":145,"style":176},"language-typescript","#!\u002Fusr\u002Fbin\u002Fenv node\n\u002F\u002F src\u002Findex.ts\nimport { Command } from 'commander'\nimport chalk from 'chalk'\n\nconst program = new Command()\n\nprogram\n  .name('mycli')\n  .description('My awesome CLI tool')\n  .version('1.0.0')\n\nprogram\n  .command('init')\n  .description('Initialize a new project')\n  .argument('[name]', 'Project name', 'my-project')\n  .option('-t, --template \u003Ctemplate>', 'Template to use', 'default')\n  .action(async (name, options) => {\n    console.log(chalk.blue(`Creating project: ${name}`))\n    console.log(chalk.gray(`Template: ${options.template}`))\n    await createProject(name, options.template)\n    console.log(chalk.green('✓ Done!'))\n  })\n\nprogram.parse()\n",[204],{"type":150,"tag":179,"props":205,"children":206},{"__ignoreMap":145},[207],{"type":156,"value":202},{"type":150,"tag":151,"props":209,"children":211},{"id":210},"progress-indicators",[212],{"type":156,"value":213},"Progress Indicators",{"type":150,"tag":171,"props":215,"children":217},{"className":201,"code":216,"language":98,"meta":145,"style":176},"import ora from 'ora'\n\nasync function createProject(name: string, template: string) {\n  const spinner = ora('Creating project structure...').start()\n\n  await mkdir(name)\n  spinner.text = 'Installing dependencies...'\n\n  await installDeps(name)\n  spinner.text = 'Configuring...'\n\n  await configure(name, template)\n  spinner.succeed('Project created successfully!')\n}\n",[218],{"type":150,"tag":179,"props":219,"children":220},{"__ignoreMap":145},[221],{"type":156,"value":216},{"type":150,"tag":223,"props":224,"children":227},"callout",{"color":225,"icon":226},"primary","i-lucide-terminal",[228],{"type":150,"tag":159,"props":229,"children":230},{},[231,233,239],{"type":156,"value":232},"Good CLI UX means: progress feedback, clear error messages, and ",{"type":150,"tag":179,"props":234,"children":236},{"className":235},[],[237],{"type":156,"value":238},"--help",{"type":156,"value":240}," that actually helps. Treat your CLI like a UI.",{"type":150,"tag":151,"props":242,"children":244},{"id":243},"interactive-prompts",[245],{"type":156,"value":246},"Interactive Prompts",{"type":150,"tag":171,"props":248,"children":250},{"className":201,"code":249,"language":98,"meta":145,"style":176},"import { input, select, confirm } from '@inquirer\u002Fprompts'\n\nasync function interactiveInit() {\n  const name = await input({\n    message: 'Project name:',\n    default: 'my-app',\n  })\n\n  const template = await select({\n    message: 'Choose a template:',\n    choices: [\n      { name: 'Minimal', value: 'minimal' },\n      { name: 'Full-stack (Nuxt)', value: 'nuxt' },\n      { name: 'API only', value: 'api' },\n    ],\n  })\n\n  const useDocker = await confirm({\n    message: 'Add Docker setup?',\n    default: true,\n  })\n\n  return { name, template, useDocker }\n}\n",[251],{"type":150,"tag":179,"props":252,"children":253},{"__ignoreMap":145},[254],{"type":156,"value":249},{"type":150,"tag":151,"props":256,"children":258},{"id":257},"error-handling",[259],{"type":156,"value":260},"Error Handling",{"type":150,"tag":171,"props":262,"children":264},{"className":201,"code":263,"language":98,"meta":145,"style":176},"program\n  .command('deploy')\n  .action(async () => {\n    try {\n      await deploy()\n    } catch (error) {\n      console.error(chalk.red('✗ Deploy failed:'))\n      console.error(chalk.gray((error as Error).message))\n      process.exit(1)\n    }\n  })\n",[265],{"type":150,"tag":179,"props":266,"children":267},{"__ignoreMap":145},[268],{"type":156,"value":263},{"type":150,"tag":151,"props":270,"children":272},{"id":271},"publishing-to-npm",[273],{"type":156,"value":274},"Publishing to NPM",{"type":150,"tag":171,"props":276,"children":278},{"className":173,"code":277,"language":175,"meta":145,"style":176},"# Build\npnpm tsc\n\n# Test locally\nnpm link\nmycli --help\n\n# Publish\nnpm login\nnpm publish\n",[279],{"type":150,"tag":179,"props":280,"children":281},{"__ignoreMap":145},[282],{"type":156,"value":277},{"type":150,"tag":151,"props":284,"children":286},{"id":285},"tips",[287],{"type":156,"value":288},"Tips",{"type":150,"tag":290,"props":291,"children":292},"ul",{},[293,312,317,338,343],{"type":150,"tag":294,"props":295,"children":296},"li",{},[297,299,304,306],{"type":156,"value":298},"Always provide ",{"type":150,"tag":179,"props":300,"children":302},{"className":301},[],[303],{"type":156,"value":238},{"type":156,"value":305}," and ",{"type":150,"tag":179,"props":307,"children":309},{"className":308},[],[310],{"type":156,"value":311},"--version",{"type":150,"tag":294,"props":313,"children":314},{},[315],{"type":156,"value":316},"Use exit codes (0 = success, 1 = error)",{"type":150,"tag":294,"props":318,"children":319},{},[320,322,328,330,336],{"type":156,"value":321},"Support piping (",{"type":150,"tag":179,"props":323,"children":325},{"className":324},[],[326],{"type":156,"value":327},"stdin",{"type":156,"value":329},"\u002F",{"type":150,"tag":179,"props":331,"children":333},{"className":332},[],[334],{"type":156,"value":335},"stdout",{"type":156,"value":337},")",{"type":150,"tag":294,"props":339,"children":340},{},[341],{"type":156,"value":342},"Add shell completions for power users",{"type":150,"tag":294,"props":344,"children":345},{},[346],{"type":156,"value":347},"Write a good README with examples",{"type":150,"tag":159,"props":349,"children":350},{},[351],{"type":156,"value":352},"A well-crafted CLI is a gift to your future self and your team.",{"type":150,"tag":354,"props":355,"children":356},"style",{},[357],{"type":156,"value":145},{"title":145,"searchDepth":359,"depth":359,"links":360},2,[361,362,363,364,365,366,367,368],{"id":153,"depth":359,"text":157},{"id":166,"depth":359,"text":169},{"id":195,"depth":359,"text":198},{"id":210,"depth":359,"text":213},{"id":243,"depth":359,"text":246},{"id":257,"depth":359,"text":260},{"id":271,"depth":359,"text":274},{"id":285,"depth":359,"text":288}]