How To Create An npx Project Boilerplate Command (step-by-step)

No Comments

Do you want to learn how to set up an npx command to create a boilerplate for your project instantly? You might know this behavior by tools like Svelte or React, where you get the whole project structure with one simple command. In this post, I will show you how to create a typescript project and then convert it into an npx boilerplate (everything step-by-step)!

  1. Create the Boilerplate Project
  2. Convert it to an npx (npm) package
  3. Conclusion

Create the Boilerplate Project

Because the main focus of this post is to show you how to create the npx command that generates the boilerplate for you, we will skip the part about creating a boilerplate project. You can follow this process for whatever boilerplate you want to make installable.

In this post, we will create the typescript project that we created in this blog post. You can also easily install it by running the following command:

npx simple-ts-app my-app

After installing or following the original post, the project structure should look something like this:

my-app
├── node_modules
├── src
│   └── index.ts
├── .gitignore
├── nodemon.json
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json

Convert it to an npx (npm) package

To make the boilerplate installable, we have to create an installation script. Therefore we will create a folder called bin containing a file called install.mjs. In the install script, we will execute all the commands needed to set up the project. For the current boilerplate it could look something like this:

#!/usr/bin/env node
import { promisify } from "util";
import cp from "child_process";
import path from "path";
import fs, { existsSync, mkdirSync } from "fs";
// cli spinners
import ora from "ora";

// convert libs to promises
const exec = promisify(cp.exec);
const rm = promisify(fs.rm);

if (process.argv.length < 3) {
  console.log("You have to provide a name to your app.");
  console.log("For example :");
  console.log("    npx simple-ts-app my-app");
  process.exit(1);
}

const projectName = process.argv[2];
const currentPath = process.cwd();
const projectPath = path.join(currentPath, projectName);
// TODO: change to your boilerplate repo
const git_repo = "https://github.com/programonaut/simple-ts-app.git";

// create project directory
if (fs.existsSync(projectPath)) {
  console.log(`The file ${projectName} already exist in the current directory, please give it another name.`);
  process.exit(1);
}
else {
  fs.mkdirSync(projectPath);
}

try {
  const gitSpinner = ora("Downloading files...").start();
  // clone the repo into the project folder -> creates the new boilerplate
  await exec(`git clone --depth 1 ${git_repo} ${projectPath} --quiet`);
  gitSpinner.succeed();

  const cleanSpinner = ora("Removing useless files").start();
  // remove my git history
  const rmGit = rm(path.join(projectPath, ".git"), { recursive: true, force: true });
  // remove the installation file
  const rmBin = rm(path.join(projectPath, "bin"), { recursive: true, force: true });
  await Promise.all([rmGit, rmBin]);

  process.chdir(projectPath);
  // remove the packages needed for cli
  await exec("npm uninstall ora cli-spinners");
  cleanSpinner.succeed();

  const npmSpinner = ora("Installing dependencies...").start();
  await exec("npm install");
  npmSpinner.succeed();

  console.log("The installation is done!");
  console.log("You can now run your app with:");
  console.log(`    cd ${projectName}`);
  console.log(`    npm run dev`);

} catch (error) {
  // clean up in case of error, so the user does not have to do it manually
  fs.rmSync(projectPath, { recursive: true, force: true });
  console.log(error);
}

After creating the file install.mjs we have to make it available inside our package.json. If you used the npx command to set up the project, it is probably already there, but check anyway and add it if it is not. To make it available, we have to add it in the bin section like this:

{
  "name": "simple-ts-app",
  ...
  "bin": {
    "simple-ts-app": "bin/install.mjs"
  },
  ...
}

Afterward, you can make it locally available by running:

npm link

Or publicly available by running

npm login
npm publish

In both cases, you can run the npx command for your boilerplate project like this:

npx <package-name> my-app

Conclusion

In this post, we created an npx command to let you set up a boilerplate for a new project with one command! Thanks to npm, you can make either available only locally or for everyone publicly. In case you have any questions, feel free to write a comment or send me a mail at mail@programonaut.com. Additionally, you can find the GitHub Repository here.

If you liked this post, feel free to subscribe to my newsletter and get monthly updates regarding my posts!


Thank you to Leopold for creating an insightful guide regarding this topic. You can find his post here.

Discussion (0)

Add Comment

Your email address will not be published. Required fields are marked *