Skip to main content

Cloudflare IPFS Gateway Integration: Decentralized Content Delivery

RSS

Announcing IPFS (InterPlanetary File System) integration via Cloudflare Gateway. Serve images and assets from a decentralized network for improved resilience, censorship resistance, and content permanence.

Date: October 18, 2025
Reading time: 8 min read
Tags:
ipfs web3 decentralization cdn announcement

I’m excited to announce that jpfchang.org now supports IPFS (InterPlanetary File System) content delivery via Cloudflare’s IPFS Gateway! This integration allows images and static assets to be served from a decentralized network, improving content resilience, permanence, and censorship resistance.

🌐 What is IPFS?

IPFS is a peer-to-peer distributed file system that seeks to connect all computing devices with the same system of files. Unlike traditional web hosting (which uses location-based addressing like https://example.com/image.jpg), IPFS uses content addressing based on cryptographic hashes.

Key Concepts

  1. Content Identifiers (CIDs): Every piece of content gets a unique hash (e.g., QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco)
  2. Immutability: Content with the same CID is always identical - you can’t change it without changing the hash
  3. Decentralization: Files are distributed across many nodes rather than a single server
  4. Permanence: Content stays available as long as at least one node hosts it

Why IPFS Matters

  • Censorship Resistance: No single point of failure or control
  • Content Permanence: Archives and historical content remain accessible
  • Bandwidth Efficiency: Popular content cached by many nodes reduces origin load
  • Verifiability: CID proves content hasn’t been tampered with
  • Offline Access: IPFS nodes can sync content for offline availability

🚀 Technical Implementation

The integration uses Cloudflare’s IPFS Gateway (cloudflare-ipfs.com), which provides a bridge between traditional HTTP/HTTPS and the IPFS network. This approach gives us the benefits of IPFS without requiring users to run IPFS nodes or install browser extensions.

Architecture Components

1. IPFS Utility Library (src/lib/ipfs.ts)

Core functionality for working with IPFS:

import { getIpfsUrl, isValidCid } from '../lib/ipfs';

// Generate IPFS gateway URL
const url = getIpfsUrl('QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco');
// => 'https://cloudflare-ipfs.com/ipfs/QmXoy...'

// Validate CID format
isValidCid('QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco'); // true
isValidCid('invalid'); // false

Features:

  • CID validation (supports both CIDv0 Qm... and CIDv1 bafy... formats)
  • Multiple gateway support (Cloudflare, IPFS.io, Dweb.link, Pinata)
  • Path resolution within IPFS directories
  • Content mapping system for local-to-IPFS fallback
  • Gateway health checking (client-side)

2. IpfsImage Component (src/components/IpfsImage.astro)

Astro component for IPFS-enabled images:

---
import IpfsImage from '../components/IpfsImage.astro';
---

<!-- Serve image from IPFS -->
<IpfsImage
  cid="QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco"
  alt="Example IPFS image"
  loading="lazy"
/>

<!-- With path for directory content -->
<IpfsImage
  cid="QmDirectory..."
  path="/image.png"
  alt="Image from IPFS directory"
/>

<!-- Fallback to multiple gateways -->
<IpfsImage
  cid="QmExample..."
  alt="Resilient image"
  fallback={true}
/>

Props:

  • cid: IPFS Content Identifier (required if src not provided)
  • src: Local path fallback (used if cid not provided)
  • path: Optional path within IPFS content
  • gateway: Which IPFS gateway to use (defaults to Cloudflare)
  • fallback: Enable srcset with multiple gateways for resilience
  • Standard HTML image attributes: alt, width, height, loading, class

3. TypeScript Type Definitions

Updated src/env.d.ts with IPFS configuration types:

interface CloudflareEnv {
  // ... existing environment variables

  // IPFS Gateway configuration
  IPFS_GATEWAY?: string;
  IPFS_PINNING_SERVICE?: 'pinata' | 'web3storage' | 'nftstorage';
  IPFS_PINNING_API_KEY?: string;
  IPFS_PINNING_API_SECRET?: string;
}

📚 Usage Examples

Basic IPFS Image

---
import IpfsImage from '../components/IpfsImage.astro';
---

<article>
  <IpfsImage
    cid="QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"
    alt="IPFS Logo"
    class="w-64 h-64"
  />
</article>

Content Mapping (Local → IPFS)

For gradual migration, map local paths to IPFS CIDs in src/lib/ipfs.ts:

export const IPFS_CONTENT_MAP: Record<string, string> = {
  '/images/blog/article-1/hero.webp': 'QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco',
  '/images/blog/article-2/diagram.png': 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG',
};

// Use helper to automatically resolve
import { getAssetUrl } from '../lib/ipfs';

const imageUrl = getAssetUrl('/images/blog/article-1/hero.webp');
// Returns IPFS URL if mapped, otherwise returns local path

Multiple Gateway Fallback

For critical content, enable multiple gateways:

<IpfsImage
  cid="QmCriticalContent..."
  alt="Important diagram"
  fallback={true}
/>

<!-- Generates srcset with multiple gateways: -->
<!-- src="https://cloudflare-ipfs.com/ipfs/Qm..." -->
<!-- srcset="https://ipfs.io/ipfs/Qm... 2x, https://dweb.link/ipfs/Qm... 3x, ..." -->

Markdown Blog Posts

In markdown files, reference IPFS images using standard markdown syntax after adding content mapping:

![Hero Image](/images/blog/my-article/hero.webp)

Then add to IPFS_CONTENT_MAP:

'/images/blog/my-article/hero.webp': 'QmYourCID...'

🛠️ Gateway Options

The system supports multiple IPFS gateways:

GatewayURLBest For
Cloudflarecloudflare-ipfs.comPrimary (fastest, most reliable)
IPFS.ioipfs.ioFallback (official gateway)
Dweb.linkdweb.linkFallback (Protocol Labs)
Pinatagateway.pinata.cloudFallback (pinning service)

Switch gateways in code:

import { getIpfsUrl } from '../lib/ipfs';

// Use different gateway
const url = getIpfsUrl('QmCID...', null, 'ipfsio');
// => 'https://ipfs.io/ipfs/QmCID...'

Or set default via environment variable:

IPFS_GATEWAY=https://ipfs.io

🔐 Content Verification

One of IPFS’s most powerful features is built-in verification. When you fetch content by CID, the gateway automatically verifies that the content matches the hash. This provides:

  1. Tamper-proof: Content can’t be silently modified
  2. Trust-minimized: Don’t need to trust the gateway
  3. Self-authenticating: CID proves content authenticity

Example:

// This CID always resolves to the exact same content
const cid = 'QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG';

// Even if served from different gateways, content is identical and verified
getIpfsUrl(cid, null, 'cloudflare'); // Verified
getIpfsUrl(cid, null, 'ipfsio');     // Verified
getIpfsUrl(cid, null, 'dweb');       // Verified

🌍 Use Cases

1. Archival Content

Historical articles, important documentation, and research papers benefit from IPFS’s permanence:

// Archive a blog post on IPFS
// Even if jpfchang.org goes down, content remains accessible via CID
const archivedPost = 'QmArchivePostCID...';

2. User-Generated Content

Accept content submissions with cryptographic proof:

// User uploads image, gets CID
// Can verify the exact content was used
const userSubmission = 'QmUserImageCID...';

3. Large Media Files

Distribute bandwidth load across IPFS network:

// High-resolution images, videos served from distributed nodes
const largeImage = 'QmHighResImageCID...';

4. Content Attestation

Prove you published content at a specific time by anchoring CID on blockchain or distributed ledger.

📊 Performance Considerations

Pros

  • CDN-like performance: Cloudflare Gateway is globally distributed
  • Caching: Popular content cached across IPFS nodes
  • Reduced origin load: Content served from peers
  • Resilience: Multiple gateways provide fallback

Cons

  • ⚠️ First-fetch latency: Unpinned content may be slower on first request
  • ⚠️ Gateway dependency: This implementation still relies on HTTP gateways
  • ⚠️ Availability: Content needs at least one pinning node

Best Practices

  1. Pin important content: Use pinning services (Pinata, Web3.Storage, NFT.Storage)
  2. Warm the cache: Pre-fetch critical content after upload
  3. Use Cloudflare Gateway primarily: It’s fastest and most reliable
  4. Enable fallbacks: For critical images, use multiple gateways
  5. Lazy loading: Load IPFS images lazily to improve perceived performance

🔮 Future Enhancements

Planned improvements for IPFS integration:

1. Automated Pinning

Integrate with pinning services for automatic content upload:

// Upload to IPFS via API
const cid = await uploadToPinata(file, apiKey);
// Automatically update IPFS_CONTENT_MAP

2. Admin Panel

Web UI for managing IPFS content:

  • Upload images to IPFS
  • View all pinned content
  • Update content mappings
  • Monitor gateway health

3. IPNS (Mutable References)

Use IPNS for mutable content pointers:

// Point to latest version while keeping old versions
const latestVersion = 'ipns://k51qzi5uqu5...';

4. Direct IPFS Access

Add service worker for native IPFS protocol support:

// Access content directly via IPFS protocol (no gateway)
ipfs://QmCID...

5. Content Deduplication

Automatic detection of duplicate content:

// If image already exists on IPFS, reuse existing CID
const existingCid = await findExistingCid(fileHash);

🏗️ Technical Specifications

CID Format Support

CIDv0 (Legacy):

  • Format: Base58-encoded multihash (46 characters)
  • Example: QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG
  • Regex: /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/

CIDv1 (Modern):

  • Format: Multibase-encoded with explicit version, codec, hash
  • Example: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
  • Regex: /^b[a-z2-7]{58}$/

API Reference

Core Functions (src/lib/ipfs.ts):

// Validate CID
isValidCid(cid: string): boolean

// Generate gateway URL
getIpfsUrl(cid: string, path?: string, gateway?: IpfsGateway): string

// Generate multiple gateway URLs
getIpfsUrls(cid: string, path?: string, gateways?: IpfsGateway[]): string[]

// Extract CID from URL
extractCidFromUrl(url: string): string | null

// Get asset URL (with IPFS fallback)
getAssetUrl(localPath: string, gateway?: IpfsGateway): string

// Check gateway health (browser only)
checkGatewayHealth(gateway?: IpfsGateway, timeout?: number): Promise<boolean>

// Pinning service endpoint
getPinningServiceEndpoint(service: IpfsPinningService): string

Environment Variables

Optional configuration via Cloudflare environment:

# Custom IPFS gateway (defaults to cloudflare-ipfs.com)
IPFS_GATEWAY=https://ipfs.io

# Pinning service configuration
IPFS_PINNING_SERVICE=pinata
IPFS_PINNING_API_KEY=your_api_key
IPFS_PINNING_API_SECRET=your_api_secret

🎓 Learning Resources

Want to learn more about IPFS?

🤝 Community & Ecosystem

IPFS is backed by a vibrant ecosystem:

  • Protocol Labs: Core development team
  • Filecoin: Incentivized storage network built on IPFS
  • Brave Browser: Native IPFS support
  • Opera: Built-in IPFS resolver
  • Cloudflare: Free public gateway

💭 Why This Matters

This integration aligns with core principles of the decentralized web:

  1. Resilience: Content survives server outages, domain seizures, hosting shutdowns
  2. Ownership: True content ownership through cryptographic verification
  3. Permanence: Important information remains accessible long-term
  4. Trust-minimization: Don’t need to trust a central authority
  5. Open Access: Anyone can run an IPFS node and serve content

As researchers and developers, we should embrace technologies that make knowledge more accessible, permanent, and censorship-resistant.

📝 Try It Yourself

Want to add IPFS content to jpfchang.org?

  1. Upload your content to IPFS using a pinning service:

  2. Get the CID from the upload response

  3. Add to IPFS_CONTENT_MAP or use IpfsImage component directly

  4. Verify content loads from https://cloudflare-ipfs.com/ipfs/YOUR_CID

This IPFS integration complements other decentralized features:

  • [[Web3 Wallet Authentication]] - MetaMask/Brave Wallet/SafePal authentication
  • [[Cryptocurrency Payment Integration]] - USDC payments via NOWPayments
  • [[Building a Censorship-Resistant Blog]] - Technical architecture for resilience
  • [[Major Site Redesign]] - Latest visual updates

✉️ Feedback & Contributions

Have ideas for IPFS features? Found a bug? Want to contribute?

Let’s build a more decentralized, resilient web together! 🌐🚀


This integration is part of my commitment to Web3 and decentralized technologies. Check out my other articles on blockchain, cryptocurrency, and the decentralized web.