The Problem
Traditional websites require servers, hosting, and ongoing maintenance. They can go down, get censored, or simply disappear when someone stops paying the bills.
The Solution
Store the entire website as transaction calldata on Ethereum. The data becomes immutable and permanent - as long as Ethereum exists, so does your content.
Calldata is the cheapest way to store data on Ethereum. It's included in every transaction and is permanently stored by all archive nodes. Perfect for small HTML/CSS/JS files.
How It Works
User visits your domain
First visit to lespiss.com loads a simple HTML page that registers a service worker.
Service worker installs
The browser caches sw.js locally. This runs in the background and intercepts all future requests.
User visits a route
When visiting lespiss.com/808, the service worker intercepts the request before it hits any server.
Fetch from Ethereum
The service worker calls the Etherscan API to fetch the transaction calldata for the mapped tx hash.
Decode and serve
Calldata is decoded from hex -> base64 -> HTML and served directly to the browser. No server involved.
The Code
The service worker fetches routes from an inscribed manifest:
// Fetch manifest from your wallet's ethscriptions
async function getRoutes() {
const res = await fetch(
`https://api.ethscriptions.com/v2/ethscriptions?creator=${WALLET}`
);
for (const eth of data.result) {
if (eth.content_uri.includes('{"lespiss":')) {
return JSON.parse(content).lespiss;
}
}
}
self.addEventListener('fetch', event => {
const path = new URL(event.request.url).pathname.slice(1);
if (routes[path]) {
event.respondWith(serveFromEthereum(routes[path]));
}
});Inscribing Content
To inscribe HTML as calldata:
- Encode your HTML as base64
- Prepend with
data:text/html;base64, - Convert the entire string to hex
- Send as calldata in an Ethereum transaction (to yourself is fine)
- Note the tx hash and add it to your routes
Updating Content
Since calldata is immutable, you can't edit inscribed content. Instead:
- Inscribe new content with a new tx
- Inscribe a new manifest with updated routes
- Old versions remain accessible via direct tx hash
This creates a permanent version history. Every version of your site lives forever on Ethereum. No code deploys needed - just inscribe.
How Routes Work
The service worker loads routes from an inscribed manifest - a JSON ethscription that maps route names to tx hashes. When you visit /how, sw.js looks up the tx hash in the manifest and fetches that inscription.
// Manifest ethscription (inscribe to update routes)
{"lespiss":{
"how": "0x97d1...e916",
"previous": "0xbd10...2363"
}}The sw.js scans your wallet's ethscriptions for the latest manifest (identified by {"lespiss": prefix). Inscribe a new manifest to update routes - no code push needed.
Direct tx hash links (/0xabc123...) always load that specific inscription - perfect for version history archives.
What About Content?
Logos and images can be inscribed and load from separate calldata. Our chain logo does exactly this - inscribe once, use infinite times. Click it to see the ethscription.
You can also link to CDNs and external images, libraries, and other websites - but nothing ensures those links won't die. Onchain content is permanent.
Setting Up the Entry Point
The index.html registers the service worker, and sw.js fetches the manifest and routes requests to Ethereum calldata. Deploy once - updates happen via inscribed manifests. We use Cloudflare Pages for the entry point (any static host works - Vercel, Netlify, GitHub Pages - but CF is free with instant SSL).
Create a GitHub repo
Push your index.html, sw.js, and static assets to GitHub.
Connect to Cloudflare Pages
Go to dash.cloudflare.com -> Workers & Pages -> Create -> Pages -> Connect to Git.
Deploy
Leave build settings empty (static site). Click Deploy. You get a *.pages.dev URL instantly.
Add custom domain
In Pages project -> Custom Domains -> Add. If using Cloudflare DNS, it configures automatically with SSL.
Free tier, global CDN, instant SSL, auto-deploys on git push. Service workers require HTTPS - Cloudflare handles this automatically.
Cost
Inscribing content costs gas, but it's surprisingly cheap for permanent, censorship-resistant hosting:
- This page (11KB): $0.31
- Version History page (6KB): $0.18
- Route manifest update: $0.01
All hosted forever on Ethereum. No recurring fees, no renewal, no servers to maintain.
Source Code
The complete implementation is open source: