Prerequisite

  • Basic knowledge: NPM, Hugo, JavaScript, shell script
  • Pre-installed: VS Code, NPM CLI, Hugo CLI

Intro

Create a post using hugo CLI is a tedious work for me. Because I always create a post using archetype and placing it in nested folder. For example, when creating this post, I should type the command below in the terminal:

hugo new --kind develop posts/_developer/create-hugo-post-with-npm-script

The problem here is, I always forget how many kind of archetypes I already have, and what my folder structure looks like right now. Folder structure can be dynamic, can be adjusted very frequently. Furthermore, I really like the NPM SCRIPTS feature that VSCode provided at Explorer in side menu, screenshot shown below:

npm script in side menu

This feature, which I call it click to run script personally, is very convenient if the user can not memorize or forget scripts. But it seems to support node pack manager a.k.a NPM as far as I know. In order to using the “click to run script” feature combining with Hugo CLI, it is necessary to using NPM as a middleware, even though Hugo blog does not need NPM or any node packages at any time. So here we get start it.

Build Hugo Dev Server Script

First initialize NPM with npm init.

Then let’s try running hugo dev server through NPM, after adding this script into your package.json:

// package.json
"scripts": {
  "dev": "hugo serve -D",
}

Type npm run dev in your terminal, or just click the script to run at side bar:

npm run dev

Work like a charm! ✨

Build Create Post Script

So, NPM script called Hugo CLI perfectly. Then let’s trying to achieve final goal: create a post.

First we have to install two packages:

  1. @inquirer/prompts, which is used to make user-friendly interface in our terminal.
  2. inquirer-directory, make choose directory easier.

Then I create a JavaScript file createPost.js in root directory, build the post creation progress, here’s the code for your reference:

"use strict";
const inquirer = require("inquirer");
const { input, select, Separator, confirm } = require("@inquirer/prompts");
const { execSync } = require("child_process");
const inquirerDirectory = require("inquirer-directory");

const BASE_PATH = "./content";

inquirer.registerPrompt("directory", inquirerDirectory);

const exec = (commands) => {
  execSync(commands, { stdio: "inherit", shell: true });
};

/**
 * Create post script
 *
 * @see https://github.com/SBoudrias/Inquirer.js
 * @see https://github.com/nicksrandall/inquirer-directory
 */
(async function () {
  const archeType = await select({
    message: "Select a archetype",
    choices: [
      {
        name: "Basic",
        value: "basic",
        description: "Basic post",
      },
      {
        name: "Dev",
        value: "dev",
        description: "Post for developer.",
      },
      new Separator(),
      {
        name: "Garden",
        value: "garden",
        description: "Note for digital garden.",
      },
    ],
  });

  const title = await input({ message: "Enter your post title" });

  const directory = await inquirer.prompt({
    type: "directory",
    name: "path",
    message: "Please choose post directory.",
    basePath: BASE_PATH,
  });

  const answer = await confirm({ message: "Confirm create the post?", default: false });

  if (answer) {
    exec(`hugo new --kind ${archeType} ${directory.path}/${title}`);
    exec(`open ${BASE_PATH}/${directory.path}/${title}/index.md`);
  }
})();

In the script , I provided 3 question, and some actions:

  1. Select a archetype.
  2. Insert post title.
  3. Choose a directory.
  4. Confirm the creation.
  5. Execute the hugo post creation script.
  6. Finally, open the file we created.

After finish your crafted script, then add this to our package.json:

// package.json
"scripts": {
  "create": "node createPost.js"
}

Then run npm run create, here’s the execution result:

npm run create

That’s it! Happy coding.