{"kind":"doc","doc":{"title":"Pure Internet: NFC","section":{"slug":"posts","name":"Posts"},"rkey":"1731984900000-pure-internet-nfc","cid":"bafkreie5ij7rghiderfncm6auo77ico5ybud2wf2c6usd6m2ljdh24ezli","renderKey":"bafkreie5ij7rghiderfncm6auo77ico5ybud2wf2c6usd6m2ljdh24ezli@2024-11-18T10:55:00Z@2025-05-23T14:09:00Z@Posts|","href":"/posts/1731984900000-pure-internet-nfc","publishedAt":"2024-11-18T10:55:00Z","updatedAt":"2025-05-23T14:09:00Z","tags":["web-development","nfc","data-urls","html","ipfs","egg","decentralized-web"],"description":"HTML, CSS & minimal JS combined with NFC tech to create serverless web experiences.","readingMinutes":2,"markdown":"Strip the web back to HTML, CSS, and a sprinkle of JavaScript. No build process, no stylesheets, no dependencies.\n\nWhat if you put it on an NFC card?\n\n## NFC\n\nMost modern phones can read NFC. Beyond contactless payments and transit cards, NFC can carry arbitrary data through NDEF (NFC Data Exchange Format) records.\n\nThe limits matter: a few kilobytes of storage per tag, and iOS handles NFC differently from Android. iOS only honors specific record types and demands an explicit user tap. Android reads more record types and supports background scanning.\n\n## Data URLs\n\nData URLs encode a file inline, usually as base64. They've been around forever, mostly for small images in CSS:\n\n```\nbackground-image: url(data:image/png;base64,iVBORw0KGgo...)\n```\n\nSince 2017, browsers refuse data URLs for top-level navigation. Good for security, fatal for the original idea.\n\n## First attempt\n\nPlan A: store an entire website as base64 on an NFC card. Tap to open. No server.\n\nTop-level navigation said no. Users can still copy and paste, but tap-to-open is dead:\n\n```\ndata:text/html;base64,PHRpdGxlPk9mZmxpbmU8L3RpdGxlPjxib2R5PjxoMT5PZmZsaW5lPC9oMT48cD5UaGlzIGlzIGEgd2ViIHBhZ2UsIGJ1dCBpdCdzIG5vdCBvbmxpbmUuPC9wPjxwPkl0IGlzIGVuY29kZWQgaW4gdGhlIFVSSSwgd2hpY2ggaXMgc3RvcmVkIG9uIHRoZSBORkMgY2FyZCB5b3UganVzdCBzY2FubmVkLjwvcD48cD5UaGFuayB5b3UgZm9yIHZpc2l0aW5nLjwvcD48L2JvZHk%2B\n```\n\nThe `file://` scheme hits the same security wall. Raw HTML text records need manual handling. Custom MIME types confuse most readers.\n\n## ENS + IPFS\n\nWorkaround: ENS name, an HTML file pinned to IPFS, an iframe to render the data URL, an NFC card storing an [eth.limo](http://eth.limo) URL, and base64 content in the hash.\n\nThe HTML:\n\n```\n<!doctype html>\n<html>\n  <head>\n    <title>PURE INTERNET</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  </head>\n  <body>\n    <iframe id=\"f\"></iframe>\n    <script>\n      const iframe = document.getElementById(\"f\");\n      iframe.src = location.hash\n        ? `data:text/html;base64,${location.hash.slice(1)}`\n        : \"data:text/html;base64,PHA+UFVSRSBJTlRFUk5FVDwvcD4=\";\n    </script>\n  </body>\n</html>\n```\n\nEncode the page as base64. Stick it on the NFC card as part of an [eth.limo](http://eth.limo) URL like `https://pureinternet.eth.limo/#VGhpcyBpcyBQdXJlIEludGVybmV0`. Tap loads the IPFS-pinned HTML through ENS. The script pulls the base64 from the hash and renders it in the iframe, which sidesteps the top-level data-URL block.\n\n## Is this pure internet?\n\nProbably the closest you can get. IPFS and ENS are still infrastructure, but the rest is HTML, CSS, JS, and a tag in your hand.\n\nThe hash trick generalizes. Any page can carry its content in the URL itself: no database, no storage, content that exists only as long as the URL does.","media":{},"series":{},"related":[{"title":"Pure Internet","href":"/posts/1731955749292-pure-internet","section":"posts","description":"Pure Internet is a running collection of small experiments in publishing with fewer layers.","publishedAt":"2024-11-18T10:49:00Z"},{"title":"Mint thyself","href":"/posts/1685948400001-mint-thyself","section":"posts","description":"A Zora HTML edition that embeds its own mint interface and can be minted from itself.","publishedAt":"2023-06-28T13:00:00Z"},{"title":"Pure Internet: no-html","href":"/posts/1740682611811-pure-internet-no-html","section":"posts","description":"A plain Markdown file hosted on Bluesky's blob storage and rendered directly by the browser.","publishedAt":"2025-02-27T10:56:00Z"},{"title":"orbz dot com","href":"/posts/1736537615834-orbz-dot-com","section":"posts","description":"orbz.fun reads Orbiter's onchain site registry and turns it into a StumbleUpon-style discovery tool.","publishedAt":"2025-01-10T11:33:00Z"},{"title":"Pure Internet: Bluesky","href":"/posts/1732585567703-pure-internet-bluesky","section":"posts","description":"Static-site hosting on Bluesky's AT Protocol using content-addressed blob storage.","publishedAt":"2024-11-25T17:46:00Z"},{"title":"Deploy html on Replit","href":"/posts/1691436904927-deploy-html-on-replit","section":"posts","description":"Replit is great but lacks HTML deployment.","publishedAt":"2023-09-07T13:15:00Z"}],"prev":{"title":"Pure Internet","href":"/posts/1731955749292-pure-internet"},"next":{"title":"Pure Internet: Bluesky","href":"/posts/1732585567703-pure-internet-bluesky"}}}