Pure Internet: NFC

Published 11/18/2024. Last updated 12/4/2024.

#nfc#web-development#data-urls

There's something appealing about stripping everything back to basics: HTML, CSS, and maybe a sprinkle of JavaScript. No fancy stylesheets, build processes, or dependencies. Just pure, simple, responsive web content.

What if we put some on an NFC card?

Understanding NFC

Near Field Communication (NFC) is built into most modern smartphones and enables short-range wireless communication. While most know it from contactless payments or transit cards, NFC can store and transmit various data types through NDEF (NFC Data Exchange Format) records.

There are limitations. Storage is capped at a few kilobytes, and iOS and Android handle NFC interactions differently. iOS is more restrictive, allowing specific record types and requiring explicit user interaction, while Android offers broader support and background reading capabilities.

Data URLs: A Brief History of Web Magic

This project centers on an old web feature: data URLs. These allow embedding small files directly into web pages by encoding their contents, typically in base64. You might have seen them when embedding small images in CSS.

background-image: url(data:image/png;base64,iVBORw0KGgo...)

Modern browsers restrict data URLs. You can't use a data URL for top-level navigation. This security measure is important for preventing certain attacks, but it presented a major obstacle to our pure internet vision.

The Original Vision

My original idea was to store an entire website as a base64-encoded string on an NFC card. Then, tap your phone for an instant website, no server required. But browser security policies sank this idea. Since 2017, you cannot use a data url for top-level navigation. But users can still copy/paste:

data:text/html;base64,PHRpdGxlPk9mZmxpbmU8L3RpdGxlPjxib2R5PjxoMT5PZmZsaW5lPC9oMT48cD5UaGlzIGlzIGEgd2ViIHBhZ2UsIGJ1dCBpdCdzIG5vdCBvbmxpbmUuPC9wPjxwPkl0IGlzIGVuY29kZWQgaW4gdGhlIFVSSSwgd2hpY2ggaXMgc3RvcmVkIG9uIHRoZSBORkMgY2FyZCB5b3UganVzdCBzY2FubmVkLjwvcD48cD5UaGFuayB5b3UgZm9yIHZpc2l0aW5nLjwvcD48L2JvZHk%2B

This setback led to exploring various workarounds:

  1. file:// scheme attempts faced security policy issues
  2. Manual intervention was required for raw HTML text records
  3. Custom MIME types confused NFC readers

ENS + IPFS

A viable solution emerged that approached the serverless concept while working within modern browser constraints. The approach uses:

  • An ENS (Ethereum Name Service) name
  • An HTML file pinned to IPFS
  • An iframe for data URL rendering
  • NFC card storing an eth.limo URL
  • Hash parameters with base64-encoded content

Here's how it works:

<!doctype html>
<html>
  <head>
    <title>PURE INTERNET</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
    <iframe id="f"></iframe>
    <script>
      const iframe = document.getElementById("f");
      iframe.src = location.hash
        ? `data:text/html;base64,${location.hash.slice(1)}`
        : "data:text/html;base64,PHA+UFVSRSBJTlRFUk5FVDwvcD4=";
    </script>
  </body>
</html>
  1. The website content is base64-encoded.
  2. The encoded content is stored on an NFC card as part of an eth.limo URL (ex `https://pureinternet.eth.limo/#VGhpcyBpcyBQdXJlIEludGVybmV0`
  3. When tapped, this URL loads our IPFS-pinned HTML through ENS
  4. The HTML file reads the base64 content from the URL's hash parameter
  5. An iframe renders the decoded content, bypassing top-level navigation restrictions

Is This Pure Internet?

This might be the closest we can get to pure internet. While not perfect—we still rely on IPFS and ENS infrastructure—it achieves some key goals:

  • Minimal server dependencies
  • No build process
  • Basic HTML, CSS, and JavaScript
  • Works within modern security constraints
  • Maintains the spirit of local-first, "offline" web content

This opens up interesting possibilities. The iframe technique could be applied to any page, allowing content to exist purely in its URL hash. No database or storage—just ephemeral web content that persists only as long as its URL. In a web built on complex stacks and permanent data stores, there's something appealing about content that exists nowhere except the URL you're holding.