Domain Setup Guide
How to point your Web3 domain to a website, so it loads in OBIAN.
Overview
OBIAN resolves non-ICANN domains (like .eth, .blockchain, .agt, .b2b) to content. You have two hosting options:
Option A: IPFS (decentralized)
- Create your site, an HTML file or directory
- Upload it to IPFS, get a content identifier (CID)
- Publish to IPNS, get a stable name that auto-updates on future deploys
- Set a record on your domain, point it to the IPFS content
Option B: HTTP hosting (GitHub Pages, Vercel, any web server)
- Deploy your site to any HTTP host
- Set a redirect or A record on your domain, point it to the hosting URL
IPFS is fully decentralized but requires an IPFS node for deploys. HTTP hosting is simpler and supports multi-page sites with full CSS/JS/navigation natively. The browser handles both: IPFS content loads in an iframe, and HTTP sites load in a per-tab webview with scroll/form state preserved across tab switches. In both cases, the URL bar shows your Web3 domain name.
HTTP Hosting (GitHub Pages)
The simplest way to get a multi-page site behind a Web3 domain. No IPFS node needed.
Step 1: Create Your Site
Create your HTML/CSS/JS files as normal. Unlike IPFS, you can use multiple pages with navigation, links between pages work natively in the browser's webview.
Step 2: Deploy to GitHub Pages
- Create a GitHub repository (or use an existing one)
- Push your site files to a
gh-pagesbranch:git checkout --orphan gh-pages git rm -rf . # Copy your site files into the repo root git add . git commit -m "deploy site" git push origin gh-pages - GitHub Pages serves your site at
https://<username>.github.io/<repo>/
If Pages isn't enabled automatically, go to Settings → Pages and set the source to the gh-pages branch.
Step 3: Point Your Domain
Choose the method for your domain platform:
Freename: Use the Forward Domain option:
- Go to app.freename.io → Portfolio → select your domain
- Under domain settings, find Forward Domain
- Enter your GitHub Pages URL (e.g.,
https://username.github.io/repo/) - Save
Unstoppable Domains: Use Website Redirect:
- Go to unstoppabledomains.com → My Domains → select your domain
- Click Manage → Website
- Under Website Redirect, enter your GitHub Pages URL
- Save and confirm the transaction
Handshake: Use an A record or TXT redirect:
- A record: Point to your web server's IP (not applicable for GitHub Pages directly)
- TXT redirect: Set a TXT record with
dnslink=/ipns/...pointing to IPNS-published content (see IPFS section below)
Note on redirects: If your GitHub Pages uses a custom domain (e.g., example.com), the browser automatically detects the redirect and still shows your Web3 domain in the URL bar. For example, navigating within schmitz.agt shows schmitz.agt/about.html even though the content is served from schmitz.ai/web3-browser/about.html.
Other HTTP Hosts
Any HTTP host works, Vercel, Netlify, Cloudflare Pages, a VPS, etc. The setup is the same: deploy your site, then set a redirect record on your Web3 domain pointing to the hosting URL.
IPFS Hosting (Decentralized)
For fully decentralized hosting where content is stored on the IPFS network.
Step 1: Create Your Page
Create an HTML file. For a quick test, create my-site/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Web3 Site</title>
<style>
body {
font-family: system-ui, sans-serif;
background: #0a0a0a;
color: #e0e0e0;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
}
.container { text-align: center; max-width: 500px; }
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
p { color: #888; }
</style>
</head>
<body>
<div class="container">
<h1>Hello from IPFS</h1>
<p>This page is served from the decentralized web.</p>
</div>
</body>
</html>
Important: All CSS and JavaScript must be inline (in the HTML file) or included as relative files in the same directory. External CDN links won't load reliably from IPFS.
Step 2: Deploy to IPFS and IPNS
Prerequisites
- IPFS Desktop or
ipfs daemonrunning locally - Node.js installed
Deploy a single file
node scripts/deploy.js my-site/index.html mydomain.tld
Deploy a directory (for multi-page sites)
node scripts/deploy.js my-site/ mydomain.tld
What the deploy script does
- Uploads your file(s) to IPFS via your local IPFS node
- Publishes the CID to IPNS so the name stays constant across updates
- Prints the CID, IPNS key, and setup instructions for your domain type
Example output
[1/3] Uploading to IPFS...
index.html (542 bytes)
CID: QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg
[2/3] Publishing to IPNS (key: self)...
Key ID: k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo...
Published: k51qzi5uqu5... -> /ipfs/QmW3fKQG7hD1TB8r...
[3/3] Summary
IPFS: ipfs://QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg
IPNS: ipns://k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo...
Gateway: https://ipfs.io/ipns/k51qzi5uqu5...
Save the CID (starts with Qm or bafy) and the IPNS Key ID (starts with k51). You'll need one of these for the next step.
CID vs IPNS: Which to use?
| CID (static) | IPNS (auto-updating) | |
|---|---|---|
| Format | QmW3fKQG7hD1... | k51qzi5uqu5dkbm9... |
| Updates | Must change the domain record every time you deploy | Domain record stays the same forever |
| Speed | Instant (content is already pinned) | Slight delay (IPNS lookup adds ~1-2 seconds) |
| Recommended | One-off pages that won't change | Any site you plan to update |
We recommend IPNS for most use cases. Set it once, then every future node scripts/deploy.js automatically updates what the domain points to.
Set Your Domain Record
Choose the section below that matches where your domain is registered.
ENS Domains (.eth)
ENS domains store a content hash on the Ethereum blockchain.
Setup (one-time, requires a transaction):
- Go to app.ens.domains and connect your wallet
- Select your domain
- Click Edit Records → Content Hash
- Set to your IPNS key:
Or for a static CID:ipns://k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo...ipfs://QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg - Save and confirm the transaction in your wallet
Updating your site: If you used IPNS, just run the deploy script again. No transaction needed, the IPNS name automatically points to your new content.
Cost: One-time gas fee on Ethereum mainnet to set the content hash. Free updates after that if using IPNS.
Unstoppable Domains (.blockchain, .x, .unstoppable, .web3, .888, etc.)
Unstoppable Domains store records on the Polygon and Ethereum blockchains. The browser reads them directly from UD's ProxyReader smart contracts, no API key needed.
Supported TLDs: .888, .blockchain, .x, .unstoppable, .web3, .moon, .go, .super, .dream, .og, .hi, .tea, and 120+ more.
Setup (one-time, requires a transaction):
- Go to unstoppabledomains.com and log in
- Select your domain from My Domains
- Click Manage → Website
- Choose how to point your domain to content:
Option A: IPFS hash (recommended for static sites):
- Under IPFS Hash, paste your CID:
QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg - Click Save Changes and confirm the transaction
This sets the dweb.ipfs.hash record on-chain. You'll need to update it each time you deploy.
Option B: Redirect URL (simplest):
- Under Website Redirect, enter your IPNS gateway URL:
https://ipfs.io/ipns/k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo... - Click Save Changes and confirm the transaction
This sets the ipfs.redirect_domain.value record. The browser will fetch content from the redirect URL. Because it points to your IPNS name, future deploys auto-update without a new transaction.
Option C: IPFS hash via programmatic records (advanced):
If you manage records via UD's developer tools or a dApp, set these keys:
| Key | Value | Notes |
|---|---|---|
dweb.ipfs.hash | QmW3fKQG7hD1... or bafybeig... | IPFS CID (highest priority) |
ipfs.html.value | QmW3fKQG7hD1... | Legacy IPFS key (also works) |
dweb.arweave.hash | Arweave TX ID | For Arweave-hosted content |
ipfs.redirect_domain.value | https://example.com | HTTP redirect |
browser.redirect_url | https://example.com | Alternative redirect key |
The browser checks these keys in the order listed and uses the first non-empty value.
Updating your site:
- If you set an IPFS hash: update the record and sign a new transaction each time.
- If you set a redirect to an IPNS gateway URL: just run the deploy script again. No transaction needed.
Which chain? Most UD domains are minted on Polygon. The browser checks Polygon first, then falls back to Ethereum. You don't need to configure which chain, the browser finds your domain automatically.
Cost: Small gas fee on Polygon (typically < $0.01) per record update. Ethereum transactions cost more if your domain is on L1.
Freename Domains (.agt, .token, .metaverse, etc.)
Freename domains store records as on-chain data on the FNS smart contract. The browser resolves them via the Freename API and on-chain fallback across Polygon, Base, Aurora, Cronos, and BSC.
Prerequisites:
- Domain must be in your personal wallet (not Freename Custody)
- MetaMask connected to the correct network (usually Polygon)
Setup:
- Go to app.freename.io → Portfolio → select your domain
- Click the Records tab
- Under Web3 Records, click Add a Record
- Set:
- Type: IPFS
- Value: Your CID (e.g.,
QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg)
- Click Save Record
- Click Sign Transaction and confirm in MetaMask
Updating your site: You'll need to update the IPFS record and sign a new transaction each time. Freename's Web3 records use static CIDs, there's no native IPNS support in their Web3 record UI.
Alternative: IPNS via DNS TXT record:
If your Freename domain has DNS management (noto.network nameservers), you can set a TXT record instead:
- In the DNS Records section, click Add a Record
- Set:
- Type: TXT
- Host:
@ - Value:
dnslink=/ipns/k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo...
- Save
This gives you auto-updating content without signing new transactions on each deploy.
Custody wallet domains: If your domain is in Freename's Custody Wallet, you may not be able to sign record updates. Transfer the domain to your personal wallet first: Portfolio → select domain → Transfer → paste your wallet address → confirm via email OTP.
Cost: Small gas fee on Polygon (typically < $0.01) per record update.
Handshake Domains (.b2b, .performer, any non-ICANN TLD)
Handshake domains use traditional DNS records, served through the Handshake blockchain's root zone. The browser resolves them via DNS-over-HTTPS.
DNS delegation chain:
Handshake blockchain → TLD nameservers (e.g., Namebase)
→ Domain nameservers (e.g., Namecheap)
→ Your DNS records (A, TXT, CNAME)
Namecheap Setup
If your Handshake domain is managed through Namecheap (delegated via Namebase):
- Log into Namecheap → Domain List → select your domain
- Go to Advanced DNS
- Click Add New Record
- Set:
- Type: TXT Record
- Host:
@ - Value:
dnslink=/ipns/k51qzi5uqu5dkbm9dousj5w5i9qfleq6t9ffyhc19us5oo... - TTL: Automatic (or 1 minute for testing)
- Save
Important: Use @ as the Host, not the subdomain name. For example, for ai.b2b, the Host is @ (not ai). The subdomain is part of the zone that Namebase delegates to Namecheap, setting Host to ai would create a record for ai.ai.b2b.
Updating your site: Run the deploy script again. The IPNS name stays the same, so no DNS changes needed.
Using a static CID instead of IPNS:
Set the TXT value to:
dnslink=/ipfs/QmW3fKQG7hD1TB8rbZcXKfJ53HkdfMMrnzg4pbvdQB8drg
You'll need to update the DNS record every time you deploy.
Cost: Free (DNS records don't cost anything).
Other DNS Providers
The TXT record setup is the same regardless of DNS provider. The key details:
- Record type: TXT
- Host/Name:
@(or leave blank, depending on the provider) - Value:
dnslink=/ipns/{your-key-id}ordnslink=/ipfs/{your-cid}
Verifying Your Setup
Check DNS records (Handshake)
From a terminal, query your domain's TXT record through Handshake DNS:
nslookup -type=TXT yourdomain.tld 103.196.38.38
103.196.38.38 is a Handshake DNS resolver (a.hdns.io). You should see your dnslink value in the response.
Check Freename API
curl https://apis.freename.io/api/v1/resolver/FNS/yourdomain.tld
Look for your IPFS record in the records array.
Check IPFS content
Visit the IPFS gateway URL from the deploy output:
https://ipfs.io/ipns/{your-key-id}
If the page loads in a regular browser, it will load in OBIAN.
Check Unstoppable Domains records
UD records are stored on-chain. You can verify them at:
https://unstoppabledomains.com/d/{yourdomain.tld}
Or check the domain's page in your UD account under Manage → Website to confirm that IPFS hash or redirect URL fields are populated and the transaction was confirmed.
Test in OBIAN
- Run
npm run devfrom the project root - Type your domain in the URL bar (e.g.,
ai.b2b,receipt.agt,yourname.eth,example.blockchain) - The page should load with CSS and JavaScript working
Troubleshooting
"Resolution Failed" error
- ENS: Check that the content hash is set at app.ens.domains
- Unstoppable Domains: Check that your domain has records set at unstoppabledomains.com → My Domains → Manage → Website. Records must be saved on-chain (transaction confirmed).
- Freename: Check the API:
curl https://apis.freename.io/api/v1/resolver/FNS/yourdomain.tld - Handshake: Check DNS:
nslookup -type=TXT yourdomain.tld 103.196.38.38
Page loads but CSS/JS is broken
- External resources (CDNs, Google Fonts, etc.) may not load when content is served through IPFS
- Keep all CSS and JavaScript inline or as local files in the same directory
- Deploy the full directory:
node scripts/deploy.js my-site/(not just the HTML file)
Unstoppable Domains domain not resolving
- Make sure the transaction that set your records was confirmed on-chain (check your wallet history on Polygonscan or Etherscan)
- If your domain was recently minted, records may take a few minutes to be queryable via RPC
- The browser checks Polygon first, then Ethereum; if your domain is on Ethereum L1, resolution may be slightly slower
- Verify the domain has a
dweb.ipfs.hash,ipfs.redirect_domain.value, or another supported record set (crypto wallet addresses alone won't produce a website)
Freename domain not found on API
- The domain may be in Freename's Custody Wallet, transfer to your personal wallet
- The IPFS record may not be signed on-chain yet, check for a "Sign Transaction" button
- The
.agtTLD has known issues with the olderrslvr.freename.ioAPI, the browser usesapis.freename.iowhich indexes all chains
Namecheap TXT record not working
- Use
@as the Host, not the subdomain name - Wait 1-2 minutes after saving for propagation
- Verify directly:
nslookup -type=TXT yourdomain.tld dns1.registrar-servers.com
IPNS is slow or not resolving
- IPNS lookups add 1-2 seconds on first load; subsequent loads are cached
- Make sure your IPFS daemon is running and the IPNS key is published
- Check the gateway:
https://ipfs.io/ipns/{key-id}. If this loads, the browser will too
Quick Reference
IPFS Records
| Platform | Record Type | Value Format |
|---|---|---|
| ENS | Content Hash | ipns://{key-id} or ipfs://{cid} |
| Unstoppable Domains (IPFS) | IPFS Hash | {cid} (just the hash, no prefix) |
| Unstoppable Domains (redirect) | Website Redirect | https://ipfs.io/ipns/{key-id} |
| Freename (Web3) | IPFS | {cid} (just the hash, no prefix) |
| Freename (DNS) | TXT | dnslink=/ipns/{key-id} |
| Handshake (Namecheap) | TXT, Host: @ | dnslink=/ipns/{key-id} |
| Handshake (other DNS) | TXT | dnslink=/ipns/{key-id} |
HTTP Redirect Records
| Platform | Method | Value Format |
|---|---|---|
| Unstoppable Domains | Website Redirect | https://username.github.io/repo/ |
| Freename | Forward Domain | https://username.github.io/repo/ |
| Handshake | A record | Server IP address |