A week ago on Hacker News someone shared their setup for an automated /now page. Their idea was nice but I felt like they didn’t take full advantage of Hugo. This is how I reimplemented some of that functionality in an alternative way.
Fun fact: Hugo supports downloading JSON, CSV, XML, Images and is also capable of processing them at render time.
Like the original blog I also used letterboxd becuase it’s free. (Usually I use Trakt + Showly but it requires a subscription). We create a simple shortcode and then call it from the markdown.
{{$data:=dict}}{{$url:="https://letterboxd.com/yourusername/rss/"}}{{withresources.GetRemote$url}}{{with.Err}}{{errorf"%s".}}{{else}}{{$data=.|transform.Unmarshal}}{{end}}{{else}}{{errorf"Unable to get remote resource %q"$url}}{{end}}{{with$data.channel.item}}<ulclass="consumed-list">{{rangefirst3.}}{{$title:=.filmTitle}}{{$year:=.filmYear}}{{$posterUrl:=index(findRE`(https://.+\.jpg)`.description)0}}<liclass="consumed-element"><ahref="https://www.themoviedb.org/movie/{{.movieId}}">{{with$thumbnail:=resources.GetRemote$posterUrl}}{{with.Err}}{{warnf"%s".}}<imgsrc="$posterUrl"width="100"loading="lazy"alt="Poster of {{$title}}">{{else}}{{$filter:=images.Process"resize 100x q90 webp"}}{{with.|images.Filter$filter}}<imgsrc="{{.RelPermalink}}"width="{{.Width}}"height="{{.Height}}"alt="Poster Image of {{$title}}"loading="lazy">{{end}}{{end}}{{end}}</a><p><ahref="https://www.themoviedb.org/movie/{{.movieId}}">{{$title}}</a> ({{$year}})</p></li>{{end}}</ul>{{end}}{{/* <pre>{{ debug.Dump $data }}</pre> */}}
This will automatically download and parse the RSS, download the posters from TMDB and optimize them.
{{$type:=(index.Params0)}}{{/* types: already-read currently-reading want-to-read https://openlibrary.org/dev/docs/api/mybooks */}}{{$data:=dict}}{{$url:=printf"https://openlibrary.org/people/mekBot/books/%s.json"$type}}{{withresources.GetRemote$url}}{{with.Err}}{{errorf"%s".}}{{else}}{{$data=.|transform.Unmarshal}}{{end}}{{else}}{{errorf"Unable to get remote resource %q"$url}}{{end}}{{/* {{ $data.reading_log_entries }} */}}{{with$data.reading_log_entries}}<ulclass="consumed-list">{{rangefirst3.}}{{$date:=index."logged_date"}}{{$title:=index."work""title"}}{{$url:=index."work""key"}}{{$year:=index."work""first_publish_year"}}{{$cover:=index."work""cover_id"|string}}{{$thumbnailUrl:=printf"https://covers.openlibrary.org/b/id/%s-L.jpg"$cover}}{{$authors:=index."work""author_names"}}<liclass="consumed-element"><ahref="https://openlibrary.org{{$url}}">{{with$thumbnail:=resources.GetRemote$thumbnailUrl}}{{with.Err}}{{warnf"%s".}}<imgsrc="https://covers.openlibrary.org/b/id/{{string$cover}}-S.jpg"width="100"loading="lazy"alt="Cover Image of {{$title}}">{{else}}{{$filter:=images.Process"resize 100x q90 webp"}}{{with.|images.Filter$filter}}<imgsrc="{{.RelPermalink}}"width="{{.Width}}"height="{{.Height}}"alt="Cover Image of {{$title}}"loading="lazy">{{end}}{{end}}{{end}}</a><div><ahref="https://openlibrary.org{{$url}}">{{$title}}</a> ({{$year}})
<p>written by <em>{{delimit$authors", "" and "}}</em></p></div></li>{{end}}</ul>{{end}}
Like before, it downloads the file, parses the JSON, looks up the cover and embeddeds it into the page.
It has some quirks like: the JSON orders the entries based the logged date when it was added in your “general” collection and not when it was moved in a specific collection, so when you change a book from “reading” to “finished reading” it won’t be in the first entry.