Annotating my pages with microformats2 and h-entry

h-entry is an open microformat for datestamped content on the web. I was looking at ways to make my site a bit more open to syndication, and also as an alternative to RSS/Atom feeds. I haven’t seen major browsers pick up on these formats, but the main focus are IndieWeb readers, and I’m all for them.

Now, please note that this post isn’t much of a guide to implementing h-entry or other parts of the microformats2 spec on your site, as it is a summary of I went about implementing it for this website.

What it looks like

h-entry looks something like this, after parsing a HTML page:

{
  "items": [
    {
      "type": [
        "h-entry"
      ],
      "properties": {
        "name": [
          "My blog post"
        ],
        "author": [
          {
            "value": "John Smith"
          }
        ],
        "published": [
          "2020-01-01 12:00:00"
        ],
        "summary": [
          "A short summary of my blog post, and what you can do."
        ],
        "content": [
          {
            "value": "Starting paragraph of my blog post.",
            "html": "<p>Starting paragraph of my blog post.</p>"
          }
        ]
      }
    }
  ]
}

In short, there’s basically all of the information about the post, in a JSON object that could be easily be used as part of a different app. With that in mind, how does a parser go about doing this?

Elements of h-entry

h-entry itself is a what is known as a root class name. We can use it to define a h-entry, and it has a series of properties that the parser will determine, based on knowing that. Other root class names include:

  • h-adr
  • h-event
  • h-geo
  • h-item
  • h-product
  • h-recipe

You can find a more detailed list of these on the microformats2 page, along with examples and detailed descriptions.

Back to h-entry, we can establish this simply by naming it as a class:

<article class="h-entry">
...
</article>

and that’s it, our article is now parseable as it is, though it might not be very useful by itself. This is where we add some core h-entry properties!

h-entry properties

There’s quite an amount of these, so I’ll only go with the properties that I used for this site.

p-name

This represents the entry name or title. For the title, we just need to add this class to the element that contains it:

<h1 class="p-name">{post.frontmatter.title}</h1>

e-content

The full content of the entry in question i.e. the full body of the blog post:

<section class="e-content">...</section>

dt-published

The datestamp of when the entry was published:

<time class="dt-published" datetime="2020-09-29">29 September, 2020</time>

Implementing h-entry within a Gatsby content type

Let’s get topical! For this, I’m using Gatsby as my site generator, so in order to get this working for my blog post, I need to modify the template for the blog post’s render function (located in /src/templates/blog-post.js), which returns JSX as follows:

export default ({data}) => {
  const post = data.markdownRemark
  return (
    <Layout>
      <SEO title={post.frontmatter.title} description={post.excerpt} />
      <section className="h-entry">
        <h1 style={{marginBottom: `0.5rem`}} className="p-name">{post.frontmatter.title}</h1>
        { post.frontmatter.draft ? (
          `Draft`
        ) : (
          <time className="dt-published" dateTime={post.frontmatter.htmldate}>{post.frontmatter.date}</time>
        )}
        <section className="e-content" dangerouslySetInnerHTML={{ __html: post.html }} />
      </section>
    </Layout>
  )
}

You can see that the 2 section, the h1, and the time elements are updated as above to have the microformat2 elements defined via the className attribute. While I was able to get it working on these generic HTML elements, I wasn’t able to get it working for the time element, which was previously a separate element called <DateTime>. I couldn’t figure it out, so I reverted to using the base element that it represented.

Further reading

Implementing a microformat isn’t difficult, and can provide new ways for people to access your content. Give it a go!