Semi-automated hashtags for syndicated posts

I went out on a limb recently and decided to build a custom collection in Eleventy that aggregates my post tags and link tags (sourced from Matter). These tags then get appended to shared post or link titles when they're syndicated from my site.

The collection I built sits in my .eleventy.js file and looks like this:

eleventyConfig.addCollection('tagMap', (collection) => {
    const tags = {}
    collection.getAll().forEach((item) => {
      if (item.data.collections.posts) {
        item.data.collections.posts.forEach((post) => {
          const url = post.url.includes('http') ? post.url : `https://coryd.dev${post.url}`
          const tagString = [...new Set(post.data.tags.map((tag) => tagAliases[tag.toLowerCase()]))]
            .join(' ')
            .trim()
          if (tagString) tags[url] = tagString
        })
      }
      if (item.data.links) {
        item.data.links.forEach((link) => {
          const tagString = [...new Set(link.tags.map((tag) => tagAliases[tag.toLowerCase()]))]
            .join(' ')
            .trim()
          if (tagString) tags[link.url] = tagString
        })
      }
    })
    return tags
  })

This works by iterating through the posts and global link data available from collections.getAll() and then mapping each tag string to the associated url in a tags object. The tags object is returned and made available as tagMap.

Once the tagMap is available it's leveraged in a template that renders JSON feeds for my site — if tagMap is passed into the LiquidJS render tag for the feed it's leveraged to help populate the title.

The template:

{%- assign entries = data | normalizeEntries -%}
{
  "version": "https://jsonfeed.org/version/1",
  "title": "{{ title }}",
  "icon": "https://coryd.dev/static/images/avatar.webp",
  "home_page_url": "{{ site.url }}",
  "feed_url": "{{ site.url }}{{ permalink }}",
  "items": [{% for entry in entries limit: 20 -%}
    {
    "id": "{{ entry.url | btoa }}",
    "title": "{{ entry.title | escape }}",
    "url": "{{ entry.url }}",
    "content_text": "{{ entry.title | escape }}{% if tagMap %} {{ entry.url | tagLookup: tagMap }}{% endif %} {{ entry.url }}",
    "date_published": "{{ entry.date | stringToDate | dateToRfc822 }}"
    }{% if not forloop.last %},{% endif %}
  {%- endfor %}
  ]
}

Leveraging the template:

{% render "partials/feeds/json.liquid"
  permalink:'/feeds/follow'
  title:'Follow • Cory Dransfeldt'
  data:follow.posts
  updated:follow.posts[0].date_published
  site:site
  tagMap:collections.tagMap
%}

The exceedingly simple tagLookup filter:

tagLookup: (url, tagMap) => tagMap[url],

The static part of this whole setup is the tagAliases object referenced in my custom collection, which is a curated JSON object that maps tags I typically use between my blog and Matter to formatted hashtags to share and, as of writing, looks like this:

{
  "11ty": "#Eleventy",
  "accessibility": "#Accessibility",
  "development": "#WebDev",
  "eleventy": "#Eleventy",
  "email": "#Email",
  "fastmail": "#Email",
  "gmail": "#Email",
  "javascript": "#JavaScript",
  "last.fm": "#Music",
  "lastfm": "#Music",
  "music": "#Music",
  "react": "#JavaScript",
  "social media": "#Tech",
  "spotify": "#Music",
  "tech": "#Tech",
  "technology": "#Tech"
}

So, with all of this in place, when my site builds it generates the tagMap collection, which is passed into my json.liquid feed template, that then looks up the matching tags via tagLookup before being syndicated using a GitHub action. The result is the same syndication that was in place before, but with a few additional tags to help with discovery.

Reposts

  • Eleventy ???? v2.0.1

Likes

  • Chris Coleman
  • Eleventy ???? v2.0.1
  • fLaMEd
Cory Dransfeldt
Cory Dransfeldt

I'm a software developer in Camarillo, California. I enjoy hanging out with my beautiful family and 4 rescue dogs, technology, automation, music, writing, reading and tv and movies.