Creating a CLI Business Card 📇

Why #

While the 80's may be a bygone era to some, we can still embody the spirit by continuing the practice of business cards. What more appropriate way to show others your 'Silian Rail' fonts or eggshell white borders? [1]

In a future interview be sure to show the hiring manager your business card for extra dev-points. 😎

Inspiration #

In 2019 I attended a TypeScript meetup in Boston. One of the speakers was Gleb Bahmutov and the first thing he showed during his talk was his business card with npm. It was so neat and was a great introduction to the Boston tech scene.

You can view his business card on github.

This tutorial is recreating what he demonstrated.

Prerequisites #

You'll need access to the following:

If you do not have an npm account, you can create an account for free.

Final Code And Repo #

The GitHub repository of this project:

azemetre/npx-aaronzemetres

This is the code of our final card:

In our src/index.js file:

#! /usr/bin/env node

const boxen = require("boxen");
const { bold, blue } = require("chalk");

const lines = [
bold("Aaron Zemetres"),
"Software Engineer",
"",
bold(" Web: ") + blue("https://azemetre.com"),
bold(" Github: ") + blue("https://github.com/azemetre"),
bold(" Twitter: ") + blue("https://twitter.com/azemetre"),
];

const message = lines.join("\n");

const card = boxen(message, {
borderColor: "blue",
borderStyle: "double",
margin: 1,
padding: 1,
});

process.stdout.write(card + "\n\n");

And lastly, in our package.json file:

{
"name": "aaronzemetres",
"version": "1.0.0",
"description": "\"npx aaronzemetres\" - to see my business card",
"main": "./src/index.js",
"files": [
"src/"
],
"bin": {
"azemetre": "./src/index.js"
},
"scripts": {
"demo": "node ./src"
},
"repository": {
"type": "git",
"url": "git+https://github.com/azemetre/npx-aaronzemetres.git"
},
"keywords": [
"terminal",
"CLT",
"command-line-tool",
"node",
"npm",
"business-card",
"american-psycho"
],
"author": "Aaron Zemetres",
"license": "MIT",
"bugs": {
"url": "https://github.com/azemetre/npx-aaronzemetres/issues"
},
"homepage": "https://github.com/azemetre/npx-azemetre#readme",
"dependencies": {
"boxen": "^4.2.0",
"chalk": "^4.1.0"
}
}

The How And Why #

After installing all the prerequisites, let's create a new repository. If you're in your CLT, we can do this with the following command (substitute aaronzemetres with the username you'd like to use):

mkdir npx-aaronzemetres

We can go into our newly created directory with the following command:

cd npx-aaronzemetres

After entering the directory we can initialize a new node project with the following command:

npm init

You'll be prompted to answer some questions about the project, here is what the prompt should look when completed:

package name: (test) npx-aaronzemetres
version: (1.0.0)
description: new card, what do you think?
entry point: (index.js)
test command:
git repository:
keywords: npm, business-card, cli
license: (MIT)
About to write to /Users/azemetre/github/npx-aaronzemetres/package.json:

{
"name": "npx-aaronzemetres",
"version": "1.0.0",
"description": "new card, what do you think?",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"npm",
"business-card",
"cli"
],
"author": "Aaron Zemetres (https://azemetre.com)",
"license": "MIT"
}

Is this OK? (yes)

Some fields may not be the same as what you see above, but that's alright. We can fix it later.

After initializing a project let's add the dependencies we'll use, do this with the following command:

npm install boxen chalk

boxen will allow us to create the visual shape of our business card.

chalk will allow us to add some color to the content of our business card.

After installing our dependencies let's create the files we will need. Do this with the following command:

touch src/index.js

When we finish creating our src/index.js let's open it in our preferred editor. After opening, this is the code we will need to create our business card (be sure to read the code comments if you'd like to understand what is happening):

#! /usr/bin/env node

// we need to import our dependencies, if you'd like to use a different color,
// or multiple, or even different font options (such as italics) please refer
// to the available options located here:
// https://github.com/chalk/chalk#readme
const boxen = require("boxen");
const { bold, blue } = require("chalk");

// similar to an actual business card! You can replace my name with what you'd
// like to be referred to and your title in the next line. We include a blank
// line to give some white space then the last three lines could be our contact
// information. This could be your linkedin or your dribble accounts, your
// email, or what ever you'd like to include. I tend to keep it light, only
// linking my blog, github, and twitter account.
const lines = [
bold("Aaron Zemetres"),
"Software Engineer",
"",
bold(" Web: ") + blue("https://azemetre.com"),
bold(" Github: ") + blue("https://github.com/azemetre"),
bold(" Twitter: ") + blue("https://twitter.com/azemetre"),
];

const message = lines.join("\n");

// if you'd like less margin and padding feel free to tweak the numbers.
// some other borderStyles to try out:
// classic, doubleSingle, bold, round
// for a list of all available options can be found here:
// https://github.com/sindresorhus/boxen#api
const card = boxen(message, {
borderColor: "blue",
borderStyle: "double",
margin: 1,
padding: 1,
});

// this will display our business card we created above into a terminal shell.
// instead of adding new lines at the end, we could add a different message,
// for example if we wanted to say "Follow me on twitter" we would change the
// following line into process.stdout.write(card + "\nFollow me on twitter")
// the \n acts as a new line, it's visually pleasing to add some spacing to not
// cluster the content of our business card
process.stdout.write(card + "\n\n");

After creating our business card, let's open up our package.json file.

Let's edit it to be the following:

{
"name": "aaronzemetres",
"version": "1.0.0",
"description": "new card, what do you think?",
"main": "./src/index.js",
"files": [
"src/"
],
"bin": {
"azemetre": "./src/index.js"
},
"scripts": {
"demo": "node ./src"
},
"keywords": [
"terminal",
"CLT",
"command-line-tool",
"node",
"npm",
"business-card",
"american-psycho"
],
"author": "Aaron Zemetres",
"license": "MIT",
"dependencies": {
"boxen": "^4.2.0",
"chalk": "^4.1.0"
}
}

Let's talk about the properties we added to our package.json:

"main": "./src/index.js"

We need to declare our new entry point for the application, this is what the main is for. You can read more about the main property on npm.

"files": [
"src/"
]

Think of the files property as the inverse of a .gitignore file. This means the array should hold all the files that are needed for this package. You can read more about the files property on npm.

"bin": {
"azemetre": "./src/index.js"
}

The bin property is where we declare our executable script. Since we only have one executable, it allows us to run our node script. This is why in our src/index.js we have our first line as the following:

#!/usr/bin/env node

This ensures scripts are ran as a node executable. You can read more about the bin property on npm.

"scripts": {
"demo": "node ./src"
}

scripts property allows us to define scripts we may want to run as npm scripts. Typically these would be a test or start commands or maybe custom commands such as starting a linting process or auto-formatting our code. We currently created a demo, so we can see what our business card looks like before publishing to npm. This can be ran with the following command in our CLI:

npm run demo

You can read more about the scripts property on npm.

Testing Our Business Card #

After writing the above code we can test what our card looks like, let's do this with npm script we defined in our package.json. In our CLI, run the following command:

npm run demo

Hopefully you should see an output similar to this:

   ╔══════════════════════════════════════════════╗
║ ║
║ Aaron Zemetres ║
║ Software Engineer ║
║ ║
║ Web: https://azemetre.com ║
║ Github: https://github.com/azemetre ║
║ Twitter: https://twitter.com/azemetre ║
║ ║
╚══════════════════════════════════════════════╝

Wow! What a snazzy looking business card. Congratulations!

Publishing On npm #

Once you feel comfortable with how your business card looks and the content inside, we can publish our card to the npm registry.

We can easily do this with the following command:

npm publish

The output should look similar to the following:

npm notice
npm notice 📦 aaronzemetres@1.0.0
npm notice === Tarball Contents ===
npm notice 787B package.json
npm notice 1.1kB LICENSE
npm notice 418B README.md
npm notice 533B src/index.js
npm notice === Tarball Details ===
npm notice name: aaronzemetres
npm notice version: 1.0.0
npm notice package size: 1.6 kB
npm notice unpacked size: 2.8 kB
npm notice shasum: #######################################
npm notice integrity: sha512-################################
npm notice total files: 4
npm notice
+ aaronzemetres@1.0.0

There you have it, you've successfully deployed your first package on npm. You can read more about how the publish command works on npm.

Note Of Caution #

If you decide to make changes to your business card in the future, you will need to bump version numbers to avoid conflict. For example, you'd change the following property in your package.json:

"version": "1.0.1"

How To Run Your Library Anywhere #

Now whenever you're on a computer that has access to a version of npm >=5.2, you should be able to run the following command to display your business card (substitute your name where appropriate):

npx aaronzemetres

Voila, you should see your business card in all its terminal glory:

npx: installed 25 in 2.48s

╔══════════════════════════════════════════════╗
║ ║
║ Aaron Zemetres ║
║ Software Engineer ║
║ ║
║ Web: https://azemetre.com ║
║ Github: https://github.com/azemetre ║
║ Twitter: https://twitter.com/azemetre ║
║ ║
╚══════════════════════════════════════════════╝

Where To Go From Here #

We could set up automatic deployments to the npm registry. This way any future changes can automatically be deployed.

To learn about how to start automatic deployments, please refer to the following:

There are also libraries that attempt to do automatic deployments:

Many of these automated deployments work flows you find in popular libraries and frameworks utilize git tags. You can read more about git tags in the git book chapter on tagging

References and Additional Notes #

  1. Business card scene from American Psycho

The Hustle

Since you've made it this far, sharing this article on your favorite social media network would be highly appreciated 💖! For feedback or if you have any questions, please ping me on Twitter.

Published