Proof of concept of open badges as an HTML microformat.
CSS JavaScript
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

This is a simple proof of concept that converts a proposed badge microformat into a 0.5 JSON hosted badge assertion.

Why a Badge Microformat?

  • Humans first (machines second). Standard JSON badge assertions are the other way around.
  • For non-technical users, it's not hard to host arbitrary HTML via services like blogs, but it is non-trivial to host JSON.
  • Only one HTML page is required, rather than a machine-readable JSON blob hosted separately from an HTML page that uses the issuer API to point to the JSON blob.
  • The unity between metadata and presentation also helps ensure that the two don't fall out-of-sync.
  • See the blog post.

Proposed Badge Microformat

All fields are required.

  • p-name - name, formatted/full
  • u-image - badge image (square)
  • p-description - badge description, approximately one sentence
  • p-recipient - badge recipient, h-card. The recipient url should be either a mailto: or hmailto: link.
  • dt-issuance - date of badge issuance
  • u-issuer - origin of issuer
  • p-issuer-name - name of issuer

Note that I'm very new to microformats, so this specification is surely horrible in certain ways. Feedback is welcome.


<div id="silly-badge-for-foo-bar" class="h-badge">
  <h3 class="p-name">Silly Badge</h3>
  <img src="" class="u-image">
  <p class="p-description">A silly badge for silly people.</p>
    This badge is awarded to
    <a href="" class="p-recipient h-card">Foo Bar</a>
    <time datetime="2013-07-31" class="dt-issuance">July 31st 2013</time>
    <a href="" class="u-issuer p-issuer-name">Silly 
      Badge Corp</a>,
    in recognition of their awesomeness.

Multiple Badges Per Page

Multiple badges can be placed on a single page, but each h-badge must be given its own unique id. This id can then be specified in the hash portion of a URL to ensure that each individual badge has a unique URL.

The hmailto: scheme

There doesn't seem to be an existing way to represent a hashed email in HTML, and since the content of a hashed email address isn't very human-readable, I decided represent it via a bespoke URL scheme with the following format:



  • hash is the hex-encoded salted hash of the user's email,
  • hashfunc is the name of the hash function used (e.g., sha256), and
  • salt is the name of the salt appended to the user's email before hashing.

As an example, the hashed email for can be represented like so (ignoring extraneous whitespace):



One potential vulnerability of using a microformat for issuing badges is that third parties may be able to "spoof" badges on another domain, if third-party HTML is allowed. For instance, a bad actor could place an HTML-microformatted badge in a comment on a blog post at to appear as though issued it.

At the machine level, we can assert that u-issuer must be in an <a> tag that has no rel=nofollow attribute on it. Since content management systems always add nofollow to links provided by third parties, this should help ensure that badge microformats can't be spoofed.


  • This proof-of-concept "bridge" server provides an endpoint that allows HTML microformat badges other domains to be delivered as standard JSON badge assertions. However, as a result, the issuer origin will be whatever the origin of the bridge server is, rather than the origin of the site that hosts the badge HTML. This can only be resolved if and when the microformat is accepted natively by the Open Badges standard (and thus by badge backpacks).

  • At present HTML badges should only be hosted on pages that are also permalinks. This means that if they're hosted on blogs, they should appear "after the jump", in a section of a post that isn't visible on the front page of a blog. (In the future, there should be a way to optionally specify the permalink for a badge inside the badge itself. This way, regardless of where the badge is viewed, a pointer to its canonical location will always be available.)

  • There is currently no way to specify a criteria URL in the microformat; the bridge simply uses the URL of the page the microformat is hosted on as both the criteria and evidence. We might want to add an optional u-criteria field to the microformat to accommodate for this.

Quick Start

$ git clone
$ cd badge-microformat-fun
$ npm install
$ npm test
$ node app.js

Then visit http://localhost:3000 to use the bridge server.

Alternatively, you could just visit