No servers, no DNS. Store a site on IPFS, set it on your name once, and it's served at yourname.gwei.domains.
Make a self-contained site — at minimum an index.html. Keep links relative and put assets (CSS, images) next to it. A single folder is ideal.
my-site/
index.html
style.css
IPFS is content-addressed: uploading produces a CID — a hash of the exact content. "Pinning" keeps it hosted so it stays reachable.
The easiest free option is BuidlGuidl's IPFS — no account, no key:
npx bgipfs upload config init -u https://upload.bgipfs.com # one-time
npx bgipfs upload ./my-site # -> CID: bafy...
Save the CID — that's all you need. Other options: Pinata, web3.storage, or your own kubo node (ipfs add -r --cid-version 1 ./my-site). Whatever you use, something has to keep the content pinned, or IPFS eventually garbage-collects it.
In the gwei.domains dapp:
bafy... or Qm...; an ipfs://... URL works too) and confirm the transaction.This stores the CID on-chain as an ENSIP-7 contenthash — the same standard ENS uses. The stored bytes start with 0xe301, the multicodec marker that means "this is IPFS."
Swarm is supported too — if your site lives on Swarm, paste a bzz://… reference in step 3 instead. It's stored the same way, with a Swarm codec marker. This guide walks through IPFS.
Open yourname.gwei.domains. The gateway reads your name's contenthash, decodes the CID, and reverse-proxies the content from a public IPFS gateway. That's the whole stack.
IPFS content is immutable, so any edit to your site produces a new CID. Re-pin, then Set Website again with the new CID — your name always resolves to whatever CID you last set. The old version stays reachable at its old CID.
A site doesn't have to live on a storage network at all. With web3:// the whole thing is stored in a smart contract and returned by a single eth_call — no pinning, nothing to garbage-collect, and the site is as durable as the chain it's on.
If you have one, paste its URL into the same Set Website field:
web3://0x6485B8B75a8Ad382340ABE333E1f6EE10E39f818:1/
The chain id after the colon is optional and defaults to 1. Mainnet and Sepolia are supported. Point at the root — a path can't be stored, since the record holds only a chain and an address.
This is stored differently from a CID. There's no multicodec for EVM contracts, so it can't be a contenthash; instead it goes in a contentcontract text record as an ERC-3770 address (eth:0x6485…), which is what ERC-6821 specifies. Any web3://-aware tool reads the same record.
The gateway then asks the contract how it wants to be called (resolveMode()) and serves the result: resource-request contracts (ERC-6944) return a status code, a body, and their own headers, so paths and query strings work normally; manual-mode contracts get the raw path as calldata. Auto mode isn't served yet.
contenthash wins. If your name has both records set, the gateway serves the contenthash and ignores the contract. Clear the website first (submit Set Website empty), then set the web3:// URL. The dapp shows a contract as shadowed when this is the case.
gwei name service · ownerless · gwei.domains