Lightweight long-form publishing from the terminal
Publishing on Nostr does not require a browser, an “app”, nor the 200 MB of JavaScript that usually come with them. Nostr is just signed events sent over websockets. A plain text protocol that a shell and a 10 MB binary can speak natively. This guide shows how to write and publish a long-form article (NIP-23, kind 30023) entirely from the terminal, using nak. No web client standing between you and the relays, no UI deciding for you which fields of the event exist or how they should be filled: your article is a plain file you own, and the command you run is the exact event that gets signed and published. It is faster, scriptable, works over SSH on a headless box, and survives just fine on a Raspberry Pi.
Note: This was originally just a snippet I was using as a reminder, but I thought it would be a good idea to publish it, as it only cost me a
nakcommand! 💪
💾 Pre-requisites
To follow this guide, you’ll need:
- A Unix-like system (linux, macOS) with a bash or similar (zsh, etc) shell.
nakinstalled in your$PATH.
📁 Preparation
First, you’ll need to prepare the eventual illustrative material that you’ll need for your article.
The easiest way is to host the images (and videos) on a Blossom relay/server, but you could also use IPFS (as long as you are able to pin the files on a persistent node), or direct traditional hosting.
📝 Writing
Write your article, using Markdown formatting, in a .md file, with your preferred editor:
nano -Sail my_article.md
Don’t include your article’s title, as it will need to be defined in a special field of the Nostr event at publication time. You should only have level 2 heading (##) or higher level.
📤 Publication
Set a few environment variables that will be needed for publication and/or eventual erratums:
export TITLE="My Article Title"
export ARTICLE_ID="my-article-slug-or-unique-id"
export ARTICLE_IMAGE="https://www.example.com/my-article-image.png"
And then run the following command:
nak event --auth --pow 12 --prompt-sec \
-k 30023 --content @my_article.md \
-d $ARTICLE_ID -t title="$TITLE" \
-t summary="A short summary of your article. It should be no longer than 2 or 3 phrases." \
-t published_at="<optional publication timestamp (in seconds) if you want it to be different than the event creation time>" \
-t image="$ARTICLE_IMAGE" \
-t t="<hashtag1>" -t t="<hashtag2>" -t t="<hashtag3>" \
wss://relay.primal.net wss://relay.damus.io wss://nos.lol
You can replace / add as many relays as you want. Ideally, those should be the same as the NIP-65 “write” relays of the author.
For the actual publication, you’ll be prompted to enter a private key, or better, avoid copy-pasting clear private keys and use a ncryptsec (NIP-49).
The event ID and created_at fields are automatically computed, and if some of the relays require authentication the --auth option ensure it is performed prior to publish.
The --pow argument is optional and is used to compute a Proof of Work according to NIP-13.
📝 Edition
To edit your article (even if it has already been published), you can simply re-publish it with the same ARTICLE_ID, as kind 30023 events are “replaceables”, the relays will simply keep the most recent version of a single "d" tag (unique identifier). Just edit the my_article.md file with your corrections / additions (you can also bring corrections to the TITLE or ARTICLE_IMAGE if you want/need to), and then:
nak event --auth --pow 12 --prompt-sec -k 30023 --content @my_article.md -d $ARTICLE_ID -t title="$TITLE" -t summary="Your short summary. Can also be corrected here" -t published_at="<same timestamp as original publication>" -t image="$ARTICLE_IMAGE" -t t="<hashtag1>" -t t="<hashtag2>" -t t="<newly added hashtag>" wss://relay.primal.net wss://relay.damus.io wss://nos.lol
Here is a helper script to fetch the content locally to edit it and re-publish it.
MY_EVENT=$(nak fetch $EVENT_NADDR) && \
TITLE=$(echo $MY_EVENT | jq -r '.tags[] | select(.[0]=="title") | .[1]') && \
ARTICLE_ID=$(echo $MY_EVENT | jq -r '.tags[] | select(.[0]=="d") | .[1]') && \
ARTICLE_IMAGE=$(echo $MY_EVENT | jq -r '.tags[] | select(.[0]=="image") | .[1]') && \
SUMMARY=$(echo $MY_EVENT | jq -r '.tags[] | select(.[0]=="summary") | .[1]') && \
PUBLISHED_AT=$(echo $MY_EVENT | jq -r '.tags[] | select(.[0]=="published_at") | .[1]') && \
TAGS=$(echo $MY_EVENT) | jq '.tags | map(select(.[0]=="t"))' && \
echo $MY_EVENT | jq -r .content > /tmp/my_article.md && \
nano -Sail /tmp/my_article.md && \
# If you need to edit the title, change the article's image, or add some tags, just edit the environment variables that were just defined above.
echo $MY_EVENT | nak event --auth --pow 12 --prompt-sec --confirm -k 30023 --content @/tmp/my_article.md -d $ARTICLE_ID -t title="$TITLE" -t summary="$SUMMARY" -t published_at="$PUBLISHED_AT" -t image="$ARTICLE_IMAGE" -t t="<newly added hashtag>" wss://relay.primal.net wss://relay.damus.io wss://nos.lol
# If you only have to do an edit in the article's content, then the following commands are enough:
echo $MY_EVENT=$(nak fetch $EVENT_NADDR) && \
echo $MY_EVENT | jq -r .content > /tmp/my_article.md && \
nano -Sail /tmp/my_article.md && \
echo $MY_EVENT | nak event --auth --pow 12 --prompt-sec --confirm --content @/tmp/my_article.md relay.primal.net relay.damus.io nos.lol
📨 Sharing
To share your article, you can add the --nevent option to the publication command, then copy this nevent, decode it with nak decode nevent..., and use the obtained values to encode a shareable adressable event:
nak encode naddr -d $ARTICLE_ID -a <author public key> -k 30023 -r wss://relay.primal.net -r wss://relay.damus.io -r wss://nos.lol
Mention all the relays that were successfully used for the publication, to maximise discoverability.
The obtained naddr can be directly mentioned in a kind 1 note, or shared with a renderer link, like for instance:
https://njump.me/<naddr>https://grimoire.rocks/run?cmd=open%20<naddr>https://fbo.network/en/articles/<naddr>
Final thoughts
Alright, fine: it might not be the most user-friendly way for Grandma to share her recipes, but if you, like me, are into computing minimalism, energy efficiency, and total independence, I don’t think you’ll find anything better!
Write a comment