Skip to main content

What is Blockchain Storage?

Every story you save in eStory is permanently pinned to IPFS (InterPlanetary File System), a decentralized storage network. Your story metadata—title, content, author wallet, audio URL, and timestamps—becomes an immutable record linked to your wallet address. This creates sovereign ownership: you control the data, and no central authority can delete or censor it.

Why Use Blockchain Storage?

Permanence

Stories are stored forever on IPFS nodes. Even if eStory shuts down, your data persists.

Censorship Resistance

No one can delete or alter your stories—not eStory, not governments, not hackers.

Proof of Authorship

Your wallet address cryptographically proves you authored the story at a specific time.

Data Portability

IPFS hashes let you retrieve your stories from any IPFS gateway—no lock-in.

How Stories Are Stored

1

Save Your Story

When you click Save Privately or Publish & Save, the following happens in parallel:
  1. Audio upload (if recorded): Original audio → Supabase Storage
  2. IPFS upload: Story metadata → Pinata IPFS pinning service
  3. Database save: Story record → Supabase PostgreSQL
  4. Vault encryption (optional): Encrypted copy → Local IndexedDB
2

IPFS Metadata Structure

Your story is encoded as JSON and uploaded to IPFS:
{
  "title": "Journal Entry - 3/4/2026",
  "content": "Your story text here...",
  "author": "0xYourWalletAddress",
  "audio": "https://supabase.co/storage/audio/abc123.webm",
  "date": "2026-03-04",
  "timestamp": "2026-03-04T18:32:11.000Z",
  "is_public": false,
  "app": "EStory DApp"
}
Two timestamps:
  • date: User-selected memory date (for backdating)
  • timestamp: Actual upload time (system clock)
3

Pinata Pinning

The metadata JSON is sent to Pinata (IPFS pinning service) via /api/ipfs/upload. Pinata:
  • Uploads the file to IPFS network
  • Returns a CID (Content Identifier) like QmXyz...
  • Keeps the file pinned (prevents garbage collection)
CID is a cryptographic hash of the content—changing even one character creates a different CID.
4

Database Record

The story is saved to Supabase stories table with:
  • author_id: Your user ID (UUID)
  • author_wallet: Your wallet address (Ethereum format)
  • ipfs_hash: The IPFS CID from Pinata
  • is_public: Visibility flag (true/false)
  • created_at: System timestamp
  • story_date: User-selected memory date
5

Success Confirmation

You see a toast notification: “Story saved & pinned to IPFS!”The IPFS hash is stored in your story metadata. You can retrieve it from any IPFS gateway:
https://gateway.pinata.cloud/ipfs/<your-CID>
https://ipfs.io/ipfs/<your-CID>
https://cloudflare-ipfs.com/ipfs/<your-CID>

IPFS Technical Details

Content Identifier (CID)

Every IPFS file gets a unique CID based on its content hash. Example CID:
QmYwAPJzv5CZsnAzt8auVkN6TkTvZGKq9Xv7jvLZMrk8Lx
Properties:
  • Deterministic: Same content → same CID
  • Tamper-proof: Changing content changes CID
  • Universal: Retrievable from any IPFS node

Pinning vs. Unpinning

ConceptExplanation
PinningTells IPFS nodes to keep the file cached permanently (prevents garbage collection)
UnpinningAllows IPFS to delete the file if space is needed
eStory uses Pinata to pin all stories, ensuring they never expire.

Data Availability

Public stories: Anyone with the CID can view the content via IPFS gateways.Private stories: The is_public: false flag in metadata is informational only. IPFS itself is public—privacy relies on:
  1. Not sharing the CID (keep it secret)
  2. Local Vault encryption (content encrypted before IPFS upload in future version)
Current implementation: IPFS metadata is not encrypted. If someone gets your CID, they can read the story. Use Local Vault for true privacy.

Blockchain Verification (Future)

Current State: Off-Chain Storage

Currently, IPFS hashes are stored in Supabase (centralized database). Authorship is proven by:
  • Wallet signature during login
  • author_wallet field in database

Future: On-Chain Attestation

Roadmap (Phase 2): Stories will be anchored on Base L2 blockchain:
  • IPFS CID stored in smart contract
  • Author wallet cryptographically linked on-chain
  • Timestamp immutably recorded in block
This enables third-party verification: “Did wallet 0xABC author this story at time T?”

Smart Contract Integration

eStory uses Base Sepolia testnet (chain ID: 84532) for Web3 features:

Deployed Contracts

ContractPurposeAddress
eStoryTokenERC20 $STORY token0xf9eDD76B...
StoryNFTERC721 story books0x6D37ebc5...
PrivateVerifiedMetricsCRE-attested insights0x158e08BC...
You can mint a Story Book NFT from multiple journal entries:
  1. Compile stories into a book (via /api/book/compile)
  2. Upload book metadata to IPFS
  3. Call StoryNFT.mintBook() with IPFS hash
  4. Pay 0.001 ETH mint fee
  5. Receive ERC721 token (tradable, provable ownership)
Code reference: /contracts/StoryNFT.sol

IPFS Upload API

Endpoint

POST /api/ipfs/upload
Authorization: Bearer <token>
Content-Type: application/json

{
  "metadata": {
    "title": "My Story",
    "content": "...",
    "author": "0x123..."
  }
}

Response

{
  "hash": "QmYwAPJzv5CZsnAzt8auVkN6TkTvZGKq9Xv7jvLZMrk8Lx",
  "url": "https://gateway.pinata.cloud/ipfs/Qm..."
}

Rate Limits

Pinata free tier: 1 GB storage + 100 pins/month. Exceeding this will cause 402 Payment Required errors.

Retrieving Your Stories from IPFS

Method 1: IPFS Gateway

Visit any public gateway with your CID:
https://ipfs.io/ipfs/<your-CID>
Response: Raw JSON metadata.

Method 2: IPFS Desktop Client

Install IPFS Desktop and fetch:
ipfs cat <your-CID>

Method 3: eStory Library

Your stories are indexed in the app’s Library page, with IPFS hashes stored in the database. Click any story to view its metadata including the IPFS link.

Storage Cost Breakdown

ComponentCostNotes
IPFS pinning (Pinata)Free (1 GB limit)Paid plans: $20/mo for 100 GB
Supabase databaseFree (500 MB limit)Paid plans: $25/mo for 8 GB
Supabase audio storageFree (1 GB limit)Paid plans: $25/mo for 100 GB
Base L2 gas fees~$0.01 per txOnly for future on-chain anchoring
For most users, the free tier is sufficient for 1000+ stories. Audio files (largest data) are stored in Supabase, not IPFS.

Data Redundancy & Backup

Your IPFS CID is stored in Supabase. You can:
  1. Download the story JSON from the database
  2. Re-pin it to a different IPFS service (e.g., Infura, Filebase)
  3. Or host your own IPFS node
The CID remains the same—IPFS is protocol-level, not vendor-locked.
IPFS acts as your backup. If you have the CIDs, you can:
  1. Query IPFS gateways to retrieve story metadata
  2. Reconstruct your library from IPFS data
  3. Re-import to a new database
Best practice: Export your IPFS hashes periodically (future feature: one-click export).
Stories saved while Vault is unlocked are also encrypted in IndexedDB (browser storage). This provides:
  • Offline access
  • Client-side encryption (AES-256-GCM)
  • Instant retrieval without network calls
See Local Vault for details.

Privacy Considerations

IPFS is public by design. Anyone with your CID can read the content. For private stories:
  1. Do not share the IPFS CID publicly
  2. Use Local Vault for encrypted local-only storage
  3. Set is_public: false to hide from public feeds (database-level)
Future enhancement: Encrypt story content before IPFS upload, storing only the ciphertext on-chain.

Comparison: IPFS vs. Traditional Storage

FeatureIPFS (Decentralized)AWS S3 (Centralized)
PermanenceForever (if pinned)Until you pay bills
CensorshipResistantVulnerable
Access controlPublic by defaultGranular permissions
CostPay for pinningPay for storage + bandwidth
SpeedVaries by nodeFast, consistent
OwnershipCryptographic proofAWS owns infrastructure

Troubleshooting

”Failed to pin to IPFS”

Causes:
  • Pinata API key missing/invalid
  • Rate limit exceeded
  • Network timeout
Solution: Check server logs for Pinata API errors. Verify PINATA_API_KEY and PINATA_API_SECRET in .env.

Story shows “IPFS hash: null”

Cause: IPFS upload failed but database save succeeded. Solution: This is a partial save. The story exists in Supabase but isn’t decentralized. Re-save the story to retry IPFS upload.

Can’t access IPFS gateway

Cause: Gateway downtime or network blocking. Solution: Try alternative gateways:
  • https://ipfs.io/ipfs/<CID>
  • https://cloudflare-ipfs.com/ipfs/<CID>
  • https://gateway.pinata.cloud/ipfs/<CID>

Next Steps

Local Vault

Add client-side encryption for true privacy before IPFS upload

Cognitive Insights

Extract AI insights from your blockchain-stored stories

Story Books (NFTs)

Mint ERC721 NFTs from your IPFS-backed stories

Build docs developers (and LLMs) love