Hosting Websites on IPFS

mibii - Aug 26 - - Dev Community

Hey everyone! Today's post is all about tackling a head-scratcher I recently encountered while building a simple blog hosted on IPFS - the infamous "Content Security Policy" error. If you're new to decentralized tech like IPFS, this one's for you!

IPFS and the Decentralized Dream:

Imagine a world where websites aren't beholden to centralized servers. That's the promise of IPFS - the InterPlanetary File System. It's like BitTorrent for websites, where files are shared directly between users.

My Quest for Decentralized Blogging:

I decided to build a basic blog using IPFS. I whipped up some HTML, added a dash of Tailwind CSS for styling, and a sprinkle of JavaScript to make things dynamic. Locally, everything worked like a charm!

The CSP Roadblock:

Excitedly, I uploaded my masterpiece to IPFS, only to be greeted by a dreaded error in the browser console: "Refused to execute inline script because it violates the Content Security Policy." What the...?

Demystifying CSP:

Turns out, Content Security Policy (CSP) is a crucial browser security feature. It prevents malicious code from being injected into websites. IPFS gateways, the bridges between the regular web and the IPFS network, often enforce strict CSP rules.

The Fix: Separating Concerns

The solution involved a fundamental programming principle: separation of concerns. Instead of having my JavaScript directly within my HTML file, I created a separate .js file for it. Then, I updated my HTML to link to this external script.

Organize Your Project:

Create a new folder for your website. Give it a descriptive name like "my-ipfs-blog."
Inside that folder, you'll have two files:

  • index.html (for your website's structure and content)
  • blog.js (for your JavaScript code) The HTML File (index.html): This file is pretty much your standard HTML, but with one crucial addition:
<!DOCTYPE html>
<html>
<head>
    <title>My Awesome IPFS Blog</title> 
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    <h1>Welcome to my Decentralized Blog</h1> 
    <script src="blog.js"></script> <div class="container mx-auto px-4 py-8">
       <div class="max-w-3xl mx-auto bg-white rounded-lg shadow-md overflow-hidden">
           <img id="blog-image" src="" alt="Blog Post Image" class="w-full h-64 object-cover">
           <div class="p-6">
               <h1 id="blog-title" class="text-3xl font-bold text-gray-900 mb-4"></h1>
               <p class="text-gray-600 text-sm mb-2">
                   <span id="blog-date"></span> <span id="blog-author"></span>
               </p>
               <div id="blog-tags" class="mb-4"></div>
               <div id="blog-content" class="text-gray-700"></div>
           </div>
       </div>
   </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Html
The Key Line: The line is how you tell your HTML to load and execute the JavaScript code from your separate blog.js file.
The JavaScript File (blog.js):
This is where you put all your cool JavaScript logic. Here's an example:

window.addEventListener('DOMContentLoaded', (event) => {
  // Your JavaScript code from previous examples goes here
  console.log("Hello from blog.js!");

  //  ... (Your code to dynamically update the HTML content) ...
});
Enter fullscreen mode Exit fullscreen mode

Uploading to IPFS (the Folder):

Now, you've got your neatly organized folder ("my-ipfs-blog") with those two files inside.
Using IPFS CLI (Terminal):
Open your terminal.
Navigate to the directory where "my-ipfs-blog" is located using the cd command.
Type: ipfs add -r my-ipfs-blog
IPFS will give you a Content Identifier (CID), which is like your website's unique address.
Using IPFS Desktop (GUI):
Open IPFS Desktop.
Look for an option to "Import" or "Add."
Choose "Folder" and select your "my-ipfs-blog."
IPFS Desktop will handle the upload and provide you with the CID.
Sharing Your Decentralized Site:

You can now share your website's CID

That is my result
https://gateway.pinata.cloud/ipfs/QmQFpbrqj5JcvztGVoBcnBgaAodp59F5mzysHeZcbvL3K4/ with anyone!
And here is another my experience with necessary CSS to style the switch and handle the light theme
https://gateway.pinata.cloud/ipfs/QmQJo26XJ8ZjW2CP6WEh6cv3S71mpkzm4UPURqvCd48Etr/
https://gateway.pinata.cloud/ipfs/QmQReZxeA7UHfKhE6L78XCqsV26mFjddTNyzhfm5j8oSJP/

They'll be able to access it through the IPFS network.

Why This Separation (html and JavaScript) Is So Important

Content Security Policy (CSP): This separation is often mandatory for IPFS websites due to those strict security rules we talked about.
Clean Code: It's excellent programming practice to keep your HTML, CSS, and JavaScript separated for better organization and easier maintenance.
Caching Benefits: When you update your JavaScript (blog.js), browsers can cache the unchanged HTML file, making your website load faster for returning visitors.

Lessons Learned:

CSP is your friend: It protects users. Learn to work with it, not against it.
Structure matters: Separating code into logical units makes debugging and maintenance easier.
Decentralization takes work (but it's worth it!): While IPFS presents unique challenges, overcoming them is incredibly rewarding.

Until next time, happy coding!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .