Negate This

A future that could've been

New Twtxt Page

Published on by Negate This

I recently added a new page to my website that displays the contents of my twtxt file in a Twitter-like format. I did this as practice for what we’ve been learning in the Python course I’m taking in college, and also to have a page where I can throw out short-form thoughts for things that don’t merit a whole blog post. I decided to use the twtxt format because it’s super simple and has a wide network of people using it. Truth be told, though, I don’t completely understand how it works, so who knows if I’ve set it up correctly.

On the topic of how I’ve set it up, it’s quite simple. The twtxt.txt format looks like this:

2021-10-29T00:51:20-04:00       This is a test yo
2021-10-30T22:46:39-04:00       May do a write-up on how I got my site's twtxt page set up and built using Hugo. It's the Saturday before Halloween, though. Maybe Monday

Every line of the twtxt.txt file has an RFC 3339 formatted date-time string and then the “tweet”, delimited by a tab character ("\t"). This means parsing it should be incredibly simple.

My site is built using the static site generator, Hugo. It follows this folder structure:

|- archetypes/
|  |-
|- config.toml
|- content/
|  |- about/
|  |  |- ...
|  |- blogroll/
|  |  |- ...
|  |- bookmarks/
|  |  |- ...
|  |- gemini/
|  |  |- ...
|  |- posts/
|  |  |- ...
|  |- twtxt/
|  |  |-
|  |  |- twtxt.txt
|- data/
|  |- twtxt.json
|- layouts/
|- public/
|  |- ...
|- resources/
|- scripts/
|  |-
|- static/
|- themes/
|  |- personal-theme/
|  |  |- layouts/
|  |  |  |- twtxt/
|  |  |  |  |- single.html
|  |  |  |  |- ...
|  |  |  |- ...
|  |  |- ...

In the scripts folder, I have a Python script that parses through the twtxt.txt file found at "personal-site/content/twtxt/twtxt.txt", converts it to a JSON file with the format:

  "date": "2021-10-29T00:51:20-04:00",
  "content": "Test\n"
  "date": "2021-10-30T22:46:39-04:00",
  "content": "May do a write-up on how I got my site's twtxt page set up and built using Hugo. It's the Saturday before Halloween, though. Maybe Monday"

Then it places that file at "personal-site/data/twtxt.json". I’ve uploaded the code for the script to Gitea.

Now that the contents of the twtxt.txt file are in the JSON format, I should be able to extract the info from it to build out the page with Hugo. Hugo can iterate through JSON files using the range function. Since twtxt.json is found in the "data/" folder, iterating through it is just:

{{ range .Site.Data.twtxt }}

The JSON file’s keys are "date" and "content", so using that data is as simple as doing the following inside Hugo’s range function:

<p>{{ .content }}</p>
<p>{{ .date | time.Format "Jan 2, 2006" }}</p>

The time.Format "Jan 2, 2006" part after .date is simply formatting the date so that it’s easy to understand.

Make sure to close off the range function with {{ end }}.

Personally, I put all of the tweet data inside of a div so that it would be easier to style and organize, like this:

{{ range .Site.Data.twtxt }}
    <div class="tweet">
        <p>{{ .content }}</p>
        <p>{{ .date | time.Format "Jan 2, 2006" }}</p>
{{ end }}

From here, all I did was apply custom styling to the page and voila!

It’s important that the script is called before the site is rebuilt so that the page has the most up-to-date “tweets”. My site is hosted on, and I apply changes to it by doing them locally on my machine then pushing them to the server using git. I have a post-receive hook on the git server that does specified things after I push any changes. I can use this script to make sure to run my Python script before rebuilding the site.


cd $HOME/personal-site/scripts
cd $HOME/personal-site

That’s about all the steps I went through to make that new page. It was a lot of fun, especially the styling since it’s quite different from the rest of my site’s styling. It’s pretty bare-bones since it can only show my “tweets” and not other people on the whole twtxt “network”, but it’s really meant as a pretty representation of my twtxt.txt file rather than a timeline.