Skip to main content
  1. Blog/

Creating a listicle with Nushell and aichat and publishing it on a drupal site

·1407 words·7 mins

So I want to publish a listicle on my website.

It just so happens that listicles are among the content genres that are most effectively and convincingly assisted in their creation by generative artificial intelligence. I could explain why this is, but in this blog I will instead show you how to create a listicle and publish it - all without ever leaving your shell ๐Ÿคญ.

If you need ideas for listicles, I am sure GAI can help you with that too. I got the idea from my sons now former interest in the strange spectacle of wrestling.

And I am a little curious about these colorful personalities myself.

First, get the list of the best wrestlers.

For this I have coded my own Nushell custom command which uses "response_format":{"type":"json_object"}, which aichat does not. This allows me to cleanly get just the list items (the values) themselves, every time. No exceptions.

  def lls [
   ...prompt: string
  ] {

    if ($in | is-empty) and ($prompt | is-empty) { 'Please provide input' } else {

      let prompt = ( if not ($in | is-empty) and not ($prompt | is-empty) { ($prompt | str join ' ') ++ ' ' ++ $in }
                     else if not ($in | is-empty) and ($prompt | is-empty) { $in }
                     else { ($prompt | str join ' ') } )

      let system = "Output valid json."

      let payload = {"model":"gpt-3.5-turbo-0125",
                     "response_format":{"type":"json_object"},
                     "messages":[{"role":"system","content":$system},
                                 {"role":"user","content":$prompt}]}

      print 'Samlet prompt: ' $prompt "\n"

      let response = (http post
        --content-type application/json
        --full
        --headers [Content-Type application/json Authorization $"Bearer ($env.OPENAI_API_KEY)"]
        https://api.openai.com/v1/chat/completions
        $payload
       )

      $response | get body.choices.message.content.0 | from json | values | flatten | flatten | flatten | tee { to json | wl-copy } 

    }

  }

Running lls greatest wrestlers of all time list then gives

[
  "Hulk Hogan",
  "The Rock",
  "Stone Cold Steve Austin",
  "John Cena",
  "Ric Flair",
  "Shawn Michaels",
  "Undertaker",
  "Bret Hart",
  "Macho Man Randy Savage",
  "Andre the Giant"
]

I’ll just trust Sam Altman here, since I do not posses the knowledge to evaluate the list myself. So onwards with this list of GOATs in wrestling.

The next step is to enrich the list with a brief description of each subject on the list. I do this like so:

let enriched = p | from json | wrap subject | insert description { aichat short description of $in.subject }

(I wish commands like insert, upsert and update could run in parallel like par-each can, but I currently do not think that is possible. See also Speeding up ai-assisted content generation with Nushell par-each ยท Kiils)

In json the enriched variable then looks something like:

  [
    {
      "subject": "Hulk Hogan",
      "description": "Hulk Hogan, born Terry Eugene Bollea on August 11, 1953, is an iconic American professional wrestler, television personality, actor, and musician. He gained worldwide fame in the 1980s and 1990s as the face of World Wrestling Federation (WWF, now WWE), becoming one of the most popular and recognizable figures in wrestling history. Known for his charismatic personality, signature moves, and catchphrases like \"Hulkamania\" and \"Whatcha gonna do brother?\", Hogan has a lasting legacy in the world of sports entertainment."
    },
    {
      "subject": "The Rock",
      "description": "Dwayne \"The Rock\" Johnson is an American actor, producer, and former professional wrestler. He gained fame as a WWE superstar before transitioning to a successful film career. Known for his charismatic personality and impressive physique, The Rock has starred in blockbuster movies such as the \"Fast & Furious\" series, \"Jumanji,\" and \"Moana.\" He is also a notable philanthropist and entrepreneur."
    },
    {
      "subject": "Stone Cold Steve Austin",
      "description": "Stone Cold Steve Austin, born Steven James Anderson, is a retired professional wrestler and actor who gained iconic status in the WWE during the late 1990s and early 2000s. Known for his rebellious anti-authority persona, Austin became a fan favorite with his trademark \"Austin 3:16\" catchphrase, intense in-ring style, and memorable feuds with Vince McMahon and other top superstars. He is one of the most popular and influential wrestlers in history, contributing significantly to WWE's \"Attitude Era.\""
    },
    ...

These descriptions confirm my suspicion that the best wrestlers are all highly entertaining personalities, as much as great athletes, if not more so.

This I then “convert” to markdown like so

let md = $enriched | each { $"\n## ($in.subject)\n\n($in.description)\n" } | to text

giving

  ## Hulk Hogan

  Hulk Hogan, born Terry Eugene Bollea on August 11, 1953, is an iconic American professional wrestler, television personality, actor, and musician. He gained worldwide fame in the 1980s and 1990s as the face of World Wrestling Federation (WWF, now WWE), becoming one of the most popular and recognizable figures in wrestling history. Known for his charismatic personality, signature moves, and catchphrases like "Hulkamania" and "Whatcha gonna do brother?", Hogan has a lasting legacy in the world of sports entertainment.


  ## The Rock

  Dwayne "The Rock" Johnson is an American actor, producer, and former professional wrestler. He gained fame as a WWE superstar before transitioning to a successful film career. Known for his charismatic personality and impressive physique, The Rock has starred in blockbuster movies such as the "Fast & Furious" series, "Jumanji," and "Moana." He is also a notable philanthropist and entrepreneur.


  ## Stone Cold Steve Austin

  Stone Cold Steve Austin, born Steven James Anderson, is a retired professional wrestler and actor who gained iconic status in the WWE during the late 1990s and early 2000s.
  ...

Then I edit this manually.

Next step is to ready the text for publishing on a drupal site. So I embed the markdown in json. And either manually or with ai assistance provide a title, and finally move the title before the content (only for my own viewing convenience)

let jsontc = $md | to json | wrap content | insert title { 'GOATs and OGs of wrestling' } | select title content

giving

  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
  โ”‚ title   โ”‚ GOATs and OGs of wrestling                                         โ”‚
  โ”‚ content โ”‚ "\n## Hulk Hogan\n\nHulk Hogan, born Terry Eugene Bollea on August โ”‚
  โ”‚         โ”‚  11, 1953, is an iconic American professional wrestler, television โ”‚
  โ”‚         โ”‚  personality, actor, and musician. He gained worldwide fame in the โ”‚
  โ”‚         โ”‚  1980s and 1990s as the face of World Wrestling Federation (WWF,   โ”‚
  โ”‚         โ”‚ now WWE), becoming one of the most popular and recognizable        โ”‚
  โ”‚         โ”‚ figures in wrestling history. Known for his charismatic            โ”‚
  โ”‚         โ”‚ personality, signature moves, and catchphrases like \"Hulkamania\" โ”‚
  โ”‚         โ”‚  and \"Whatcha gonna do brother?\", Hogan has a lasting legacy in  โ”‚

Now we need to get the payload for the drupal jsonapi ready:

  let payload = ( $jsontc | par-each {  ( { "data": {
                       "type": "node--listicle",
                       "attributes": {
                           "title": $jsontc.title,
                           "body": {
                               "value": ($jsontc.content | from json | pandoc --from markdown --to html),
                               "format": "ckeditor5"
                           }
                       },
                       "relationships": {
                              "uid": {
                                "data": {
                                  "type": "user--user",
                                  "id": 7d137122-c5f9-4313-b417-4a97cd5ba79f
                                }
                              },
                       }
               } } ) } )

The payload looks like this now:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚      โ”‚ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚
โ”‚ data โ”‚ โ”‚ type          โ”‚ node--listicle                                                              โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚ attributes    โ”‚ โ”‚ title โ”‚ GOATs and OGs of wrestling                                      โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚ body  โ”‚ โ”‚ value  โ”‚ <h2 id="hulk-hogan">Hulk Hogan</h2>                โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚ <p>Hulk Hogan,                                     โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚ born Terry Eugene Bollea on August 11, 1953, is an โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚  iconic                                            โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚ American professional wrestler, television         โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚ personality, actor, and                            โ”‚ โ”‚ โ”‚ โ”‚
โ”‚      โ”‚ โ”‚               โ”‚ โ”‚       โ”‚ โ”‚        โ”‚ musician. He gained                                โ”‚ โ”‚ โ”‚ โ”‚

which is what drupal expects.

Now all that is left is to send it to the drupal site:

( http post --content-type application/json 
                    --headers [Content-type application/vnd.api+json]
                    --headers [Accept application/vnd.api+json]
                    --user 'Lennart Kiil'
                    --password 'password here'
                    https://www.folkets.dk/jsonapi/node/listicle
                    $payload ) | from json

And now the listicle is online. In fact, you can read the translated, in Danish, version here:

GOATs and OGs of wrestling

PS. I forgot to mention, I also use pandoc in the above example. Pandoc is a great tool for converting between various text formats like html, markdown, plain and many more.