Skip to content

Instantly share code, notes, and snippets.

@michel47
Last active April 27, 2021 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michel47/63398a12fa8a8135c00b57a2ac0afd0d to your computer and use it in GitHub Desktop.
Save michel47/63398a12fa8a8135c00b57a2ac0afd0d to your computer and use it in GitHub Desktop.
seed for a gist
seed for a gist !
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html><meta charset="utf8">
<title>NFT Hostless webpage by Doctor I·T</title>
<div id=container class="content" contenteditable oninput="update(event);">
<img id=bot src=https://robohash.org/:qm>
<h3>Website: Go No Host with NFTs !</h3>
<p>
This is a hostless webpage on IPFS,
it is not specifically hosted on any server and can be just a simple page or a full fledged website.
<p>
You can have one too,
if you click on any part of the text you can modify this page and then when you click on the publish button it is uploaded to the network.
<p><code>&lt; WRITE WHAT EVER YOU LIKE ON THIS PAGE JUST CLICK THE TEXT TO EDIT IT &gt;</code></p>
<hr>
<img id=logo src=https://ipfs.blockring™.ml/ipfs/QmVFJEec5cD9nCmzx9ic6rGJSe8hDzMWEchcoxnZtG1QK8/drit-pin-logo.svg>
<p>This site can be edited to your liking,
and when you click <button onclick="publish(event);">publish</button> button,
the page is pushed to <a href=https://gateway.ipfs.io/ipfs/:qm/ contenteditable=false>IPFS</a> network.
<p>
You can share its link to anyone, the qmlink is :
<br>
<a id=permlink href=#>:location</a>
<p contenteditable=false>To make this page (and link) permanent, buy its <abbr title=non-fungible-token>NFT</abbr>
for <a href=https://www.drit.ml/cards/NFT45CHF title=NFT45CHF>5.--CHF</a>.
</div>
<br>
<div id=help>
<div class="content">
<h4>What is an NFT</h4>
<p>
Who is Responsible for Maintaining the Mona Lisa, Da Vinci?
<p>
When an artist creates a painting, that painting is not permanent by nature.
Typically, the artist will sell that painting to a buyer.
At that point, the buyer owns the painting and is then responsible for its permanence.
If the buyer enjoys the painting,
they will take care of it, maybe sell it to someone else,
and then that buyer will take care of it.
However, if the buyer doesn’t take care of it, it might be thrown away, severely damaged, or just forgotten about over time.
This is a very familiar, intuitive life of a physical asset.
<p>
NFTs are the equivalent to the "physical artwork", they are non-fungible, i.e. you can split it without altering its value.
<p>
how does this apply here ?
You edited this page and now you'd like to make this version permanent,
how to handle long-term storage of the page data ?
<br>NFT are expected to last forever;
however there is a cost for permanence,
this includes the cost to host the data,
and to deploy the infrastructure to access it.
</div>
<br>
<div class="content">
<h4>Where the page is located ?</h4>
<p>
The page can be found locally at
<a href=http://127.0.0.1:8080/ipfs/:qm/ contenteditable=false>ipfs://:qm/index.html</a>
<br><i>(assuming you run an IPFS node on <a target=_ipfs href=http://127.0.0.1:8080/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn contenteditable=false>127.0.0.1:8080</a>
and that you have <span id=origin>:origin</span> in the "Allow-Origins" list
)</i>
<h4>Now the neat part !</h4>
This webpage is also globally accessible on public gateways.
<br>
Any of the following URLs can be used to share the page:
<ul>
<li><a target=_ipfs href=https://gateway.ipfs.io/ipfs/:qm/ contenteditable=false>https://gateway.ipfs.io/ipfs/:qm/</a>
<li><a target=_ipfs href=https://cloudflare-ipfs.com/ipfs/:qm/ contenteditable=false>https://cloudflate-ipfs.com/ipfs/:qm/</a>
<li><a target=_ipfs href=https://gateway.pinata.cloud/ipfs/:qm/ contenteditable=false>https://gateway.pinata.cloud/ipfs/:qm/</a>
<li><a target=_ipfs href=https://ipfs.blockring™.ml/ipfs/:qm/ contenteditable=false>https://ipfs.blockring™.ml/ipfs/:qm/</a>
</ul>
<h4>It his page permanent ?</h4>
<p>If you run you own IPFS node and you pin the hash&nbsp;<code>:qm</code>, then yes,
otherwise you can buy the page as a Non-Fungible-Token, and we will manage it for you.
<img alt="gonohost" src=https://ipfs.blockring™.ml/ipfs/Qmcv344dHojbActa29vDKPfG5RdnkuYfQXfiJzPPtANotT/serverless.png>
<p> You can attached this site to a domain-name by doing the following :
<ul>
<li> add a CNAME record to example.com's DNS pointing to <a href=https://cloudflare-ipfs.com/ipfs/:qm/>cloudflare-ipfs.com</a>
<li> add a TXT recod to _dnslink.example.com with the value<br><code>dnslink=/ipfs/:qm</code>
</ul>
<!-- <small>note: previous hash was :prevhash</small> -->
<br>--&nbsp;<br><span contenteditable=false>This page is provided by <a href="https://www.drit.ml">Doctor I·T</a></span>
</div>
</div>
<style>
body {
background-color: #fef8e9;
background-image: URL(https://ipfs.blockring™.ml/ipfs/QmSoyQm59v121sGy75ReMZNe4GaMvVWvr3C87khfWiZjee/z-background.svg);
background-image: URL(https://gist.githubusercontent.com/DrI-T/80f8328d8de7ff8cc15942fa2dc637be/raw/z-background.svg);
/*background-image: URL(z-background.svg);*/
background-size: 100vw 100vh;
background-repeat: no-repeat;
background-attachment: fixed;
}
.content {
max-width: 680px;
margin: auto;
margin-top: 10vh;
margin-bottom: 64px;
padding: 1.2rem;
background-color: white;
opacity: 0.90;
box-shadow: 5px 5px 15px 2px rgba(4,3,5,0.9);
}
i { color: grey }
#bot { float: right; max-width: 160px; }
#logo { float: right; max-height: 100px; }
img[alt=gonohost] { max-width: 80%; margin: auto; }
</style>
<script>
var prevhash = ':qm';
let el = document.getElementById('origin');
el.innerText = el.innerText.replace(/:origin/,location.origin);
let permlink = document.getElementById('permlink');
permlink.innerHTML = permlink.innerHTML.replace(/:location/g,location.href);
permlink.href = location.href;
var html = document.getElementsByTagName('html')[0];
var templ = html.innerHTML;
function publish(ev) {
const api_url = 'http://127.0.0.1:5001/api/v0/';
const gw_url = 'https://ipfs.blockring™.ml'
//const gw_url = 'http://127.0.0.1:8080';
//return fetch(location.href).then(resp => resp.text()).then(buf => { console.log('buf:',buf); });
var html = document.getElementsByTagName('html')[0];
console.debug('prevhash:',prevhash);
let innerHTML = html.innerHTML.replace(RegExp(prevhash,'g'),':qm');
html.innerHTML = innerHTML;
var buf = `<!DOCTYPE html>${innerHTML}`;
let form = new FormData();
form.append('file',buf);
let headers = new Headers();
//headers.set('X-APIkey','fiThSGmvb2IJMCnsttKaXKTh6JwDbUeU')
//return fetch(api_url+'add/?pin=true',{method:'POST', body:form}).
return fetch(gw_url+'/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn/index.html',{method:'PUT', mode:'cors', body:buf}).
//then(resp => resp.json()).
then(resp => {
console.log('resp:',resp);
if (resp.ok) {
for (let pair of resp.headers.entries()) {
console.log(pair[0]+ ': '+ pair[1]);
}
let loc = resp.headers.get('Location');
let hash = resp.headers.get('Ipfs-Hash');
let obj = {};
if (loc != null) { obj.Path = loc; }
if (hash != null) { obj.Hash = hash; }
return obj;
} else {
if ( resp.headers.get(Content-Length) != 0 ) {
return resp.text().catch(resp => {
console.log(resp);
return console.error('err:',resp);
});
}
}
}).
then(obj => {
if (obj == "") { return Promise.reject(new Error('obj: empty!')) }
// window.stop(); return Promise.reject(new Error('REJECT n ABORT')); // STOP !
if (typeof(obj.Hash) != 'undefined') {
console.debug('resp.json:',obj);
let sc = document.getElementsByTagName('script')[0];
console.debug({'sc.innerHTML': sc.innerText.split('\n').splice(1)});
sc.innerHTML = sc.innerHTML.replace(RegExp(prevhash,'g'),obj.Hash);
let permlink = document.getElementById('permlink');
permlink.innerHTML = `${gw_url}/ipfs/:qm/`;
permlink.href = `${gw_url}/ipfs/:qm/`;
/*
let el = document.getElementById('container');
console.debug({ 'el.innerHTML': el.innerHTML.split('\n')});
el.innerHTML = el.innerHTML.replace(/:qm/g,obj.Hash);
*/
let els = document.getElementsByClassName('content');
for (let el of els) {
el.innerHTML = el.innerHTML.replace(/:qm/g,obj.Hash);
}
prevhash = obj.Hash; // keep track for future replace ;)
fetch(`https://gateway.ipfs.io/ipfs/${obj.Hash}/`,{method:'HEAD', mode:'no-cors'}).
then(resp => { console.info('resp:',resp); return resp; }).
catch(console.warn);
return obj.Hash;
} else {
// ipfs add -w -r index.html style.css js img --pin=true -Q
return Promise.reject('QmeQVu3NGEcjmzx1rVytrSV9Ht9sc3KgavnpyhaE8gBip1')
}
}).
catch(err => {
console.warn('err:',err);
});
}
publish({});
function update(ev) {
console.log('update.change:',ev);
}
</script>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment