WebNest
Team/Md Arif Hossain/web3-blog

Repository

web3-blog

View on GitHub ↗
TypeScript0 stars0 forksweb3-blog-six.vercel.app

README

🌐 Web3 Blog Platform

A fully decentralized blogging platform built on blockchain technology, where writers truly own their content and readers support creators directly. Articles are stored permanently on IPFS with metadata on-chain, ensuring censorship resistance and true content ownership.

Web3 Blog Platform TypeScript Solidity Tests

🚀 Quick Start

# Clone and install
git clone https://github.com/yourusername/web3-blog.git
cd web3-blog

# Install dependencies
cd client && pnpm install
cd ../server && pnpm install

# Setup environment
cp client/.env.example client/.env.local
cp server/.env.example server/.env

# Start local blockchain
cd server && pnpm hardhat node &

# Deploy contract
pnpm deploy:local

# Start server
pnpm dev &

# Start client (new terminal)
cd client && pnpm dev

Visit http://localhost:3000 and connect your wallet!


📋 Table of Contents


✨ Features

🔐 True Ownership

  • Writers own content permanently on blockchain
  • Censorship-resistant with IPFS storage
  • Immutable publishing

📝 Rich Content

  • Novel editor with Markdown support
  • Image uploads to IPFS
  • Tag system (up to 10 tags)
  • Auto-save drafts
  • Reading time calculation

🔍 Discovery

  • Real-time search with debouncing
  • Multi-tag filtering
  • Pagination
  • Author profiles with stats
  • Reading progress bar

💬 Social

  • On-chain likes with animations
  • Decentralized comments
  • Share on social media
  • Author statistics

🛠️ Developer Experience

  • Multi-wallet support (RainbowKit)
  • Multi-network (Polygon, Base, localhost)
  • Full TypeScript
  • Comprehensive testing (68 tests)
  • Modular architecture

🏗️ Tech Stack

Frontend

  • Next.js 16 - React framework with App Router
  • TypeScript 5.7 - Type safety
  • Tailwind CSS 4 - Styling
  • shadcn/ui - Component library
  • Novel - Rich text editor
  • Jest + Playwright - Testing

Web3

  • wagmi v2.19 - React hooks for Ethereum
  • viem v2.43 - TypeScript Ethereum library
  • RainbowKit 2.2 - Wallet connection
  • ethers v6 - Blockchain interaction

Backend

  • Express - API server
  • Hardhat 2.20 - Contract development
  • Solidity 0.8.28 - Smart contracts
  • OpenZeppelin 5.4 - Secure libraries
  • Pinata - IPFS pinning
  • Jest + Supertest - API testing

📦 Installation

Prerequisites

  • Node.js 18+
  • pnpm (npm install -g pnpm)
  • Git
  • MetaMask or compatible wallet

Clone Repository

git clone https://github.com/yourusername/web3-blog.git
cd web3-blog

Install Dependencies

# Client
cd client
pnpm install

# Server
cd ../server
pnpm install

🔧 Environment Setup

📍 Getting Required Keys

1. WalletConnect Project ID (Required)

  1. Go to https://cloud.walletconnect.com
  2. Create account and new project
  3. Copy Project ID

2. Pinata JWT (Required for IPFS uploads)

  1. Go to https://app.pinata.cloud
  2. Create account
  3. Navigate to API Keys → New Key
  4. Enable "pinFileToIPFS" and "pinJSONToIPFS"
  5. Copy JWT token

3. Alchemy RPC (Optional, recommended for production)

  1. Go to https://dashboard.alchemy.com
  2. Create account and new app
  3. Select Polygon Amoy or Mainnet
  4. Copy HTTP URL

📝 Client Environment

Create client/.env.local:

# API & Site URLs
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_SITE_URL=http://localhost:3000

# WalletConnect (Required - get from cloud.walletconnect.com)
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here

# Contract Addresses (auto-filled for localhost)
NEXT_PUBLIC_CONTRACT_ADDRESS_LOCALHOST=0x5FbDB2315678afecb367f032d93F642f64180aa3
NEXT_PUBLIC_CONTRACT_ADDRESS_POLYGON_AMOY=0x0000000000000000000000000000000000000000
NEXT_PUBLIC_CONTRACT_ADDRESS_POLYGON=0x0000000000000000000000000000000000000000
NEXT_PUBLIC_CONTRACT_ADDRESS_BASE_SEPOLIA=0x0000000000000000000000000000000000000000
NEXT_PUBLIC_CONTRACT_ADDRESS_BASE=0x0000000000000000000000000000000000000000

Why client needs contract addresses?

  • Client reads blockchain data directly (free, decentralized)
  • Reduces server load and latency
  • Works even if server is down (read-only mode)
  • True Web3: trustless, censorship-resistant

📝 Server Environment

Create server/.env:

# Network Configuration
NETWORK=localhost
NODE_ENV=development
PORT=3001

# CORS Configuration
CORS_ORIGINS=http://localhost:3000,http://localhost:3002
PRODUCTION_DOMAIN=

# Blockchain Configuration
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

# Contract Addresses by Network
CONTRACT_ADDRESS_LOCALHOST=0x5FbDB2315678afecb367f032d93F642f64180aa3
CONTRACT_ADDRESS_AMOY=
CONTRACT_ADDRESS_POLYGON=

# RPC URLs by Network
RPC_URL_LOCALHOST=http://127.0.0.1:8545
RPC_URL_AMOY=https://rpc-amoy.polygon.technology
RPC_URL_POLYGON=https://polygon-rpc.com

# IPFS Configuration (Required for production)
IPFS_GATEWAY=https://gateway.pinata.cloud/ipfs/
PINATA_JWT=your_pinata_jwt_here

For localhost development: Use the Hardhat default private key shown above (has test ETH).

For production: Use your own wallet private key with actual funds.


🏃 Running Locally

Step 1: Start Local Blockchain

cd server
pnpm hardhat node

Keep this terminal running. You'll see 20 test accounts with 10,000 ETH each.

Step 2: Deploy Smart Contract

In a new terminal:

cd server
pnpm deploy:local

Copy the deployed contract address from output:

BlogPlatform deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3

Step 3: Update Contract Address

The address is already in .env.local, but verify it matches:

NEXT_PUBLIC_CONTRACT_ADDRESS_LOCALHOST=0x5FbDB2315678afecb367f032d93F642f64180aa3

Step 4: Start Server

cd server
pnpm dev

Server runs at http://localhost:3001

Step 5: Start Client

cd client
pnpm dev

Client runs at http://localhost:3000

Step 6: Connect Wallet

  1. Open http://localhost:3000
  2. Click "Connect Wallet"
  3. If prompted, add Hardhat network:
  4. Import test account (use private key from Step 1)

✅ Ready to publish your first article!


🧪 Testing

Client Tests

cd client

# Unit tests (Jest)
pnpm test              # Watch mode
pnpm test:ci           # CI mode with coverage

# E2E tests (Playwright)
pnpm test:e2e          # Headless
pnpm test:e2e:ui       # UI mode
pnpm test:e2e:headed   # Headed browser

Client Test Coverage:

  • ✅ 6 unit tests (utils, IPFS helpers)
  • ✅ 10 E2E tests (navigation, forms)

Server Tests

cd server

# API tests
pnpm test              # All tests
pnpm test:api          # API unit tests only
pnpm test:e2e          # E2E workflow tests
pnpm test:coverage     # With coverage report

Server Test Results:

Test Suites: 2 passed, 2 total
Tests:       28 passed, 28 total
Coverage:    70.58% statements, 84.21% functions

Smart Contract Tests

cd server
pnpm test:contracts

Contract Test Results:

40 passing
Coverage: 100% statements, 95% branches

All Tests

# Run everything
pnpm test:all

Total: 68 tests passing


🚀 Deployment

Deploy to Polygon Amoy (Testnet)

1. Get Test MATIC

2. Deploy Contract

cd server

# Update .env with your wallet private key
PRIVATE_KEY=0xYourPrivateKeyHere

# Deploy
pnpm deploy:amoy

Save the deployed contract address!

3. Deploy Server (Vercel)

cd server
vercel --prod

Set these environment variables in Vercel dashboard:

NETWORK=amoy
CONTRACT_ADDRESS_AMOY=0xYourDeployedAddress
RPC_URL_AMOY=https://rpc-amoy.polygon.technology
PRIVATE_KEY=your_relayer_private_key
PINATA_JWT=your_pinata_jwt
CORS_ORIGINS=https://your-client-domain.vercel.app
PRODUCTION_DOMAIN=your-server-domain.vercel.app
IPFS_GATEWAY=https://gateway.pinata.cloud/ipfs/

4. Deploy Client (Vercel)

cd client
vercel --prod

Set these environment variables in Vercel dashboard:

NEXT_PUBLIC_API_URL=https://your-server-domain.vercel.app
NEXT_PUBLIC_SITE_URL=https://your-client-domain.vercel.app
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id
NEXT_PUBLIC_CONTRACT_ADDRESS_POLYGON_AMOY=0xYourDeployedAddress

5. Verify Deployment

  • ✅ Visit server: https://your-server.vercel.app/
  • ✅ Check API docs: https://your-server.vercel.app/api-docs
  • ✅ Visit client: https://your-client.vercel.app/
  • ✅ Connect wallet and publish test article

Deploy to Polygon Mainnet

Same steps as Amoy, but:

  1. Use NETWORK=polygon
  2. Use mainnet RPC URLs
  3. Ensure wallet has real MATIC for gas
  4. Deploy with pnpm deploy:polygon

🏛️ Architecture

Hybrid Architecture

The platform uses a hybrid approach combining:

Client-Side (Decentralized)

  • Direct blockchain reads (free, no gas)
  • Wallet-signed transactions (user pays gas)
  • IPFS content fetching
  • Real-time updates

Benefits:

  • ✅ Trustless - no server dependency
  • ✅ Censorship-resistant
  • ✅ Privacy - direct blockchain interaction
  • ✅ Resilient - works if server is down

Server-Side (API)

  • Meta-transactions (gasless for users)
  • IPFS uploads (secure Pinata integration)
  • Relayer pattern (server pays gas)
  • REST API for convenience

Benefits:

  • ✅ Gasless onboarding
  • ✅ Better UX (no wallet confirmations for reads)
  • ✅ Secure IPFS uploads
  • ✅ Traditional API for integrations

Network Configuration

Environment-based network selection:

NETWORK=localhost  → Uses RPC_URL_LOCALHOST, CONTRACT_ADDRESS_LOCALHOST
NETWORK=amoy       → Uses RPC_URL_AMOY, CONTRACT_ADDRESS_AMOY
NETWORK=polygon    → Uses RPC_URL_POLYGON, CONTRACT_ADDRESS_POLYGON

Smart Contract Architecture

BlogPlatform.sol
├── Articles (create, update, delete)
├── Likes (like/unlike)
├── Comments (add, retrieve)
├── Author Management
└── Tag-based Filtering

Security:

  • ReentrancyGuard on state changes
  • Owner-only modifications
  • Input validation
  • Event emissions

Server Architecture

server/src/
├── server.ts          # Entry point (12 lines)
├── app.ts             # Express app setup
├── config/
│   ├── network.ts     # Blockchain configuration
│   ├── cors.ts        # CORS logic
│   └── swagger.ts     # API documentation
├── middleware/
│   ├── errorHandler.ts
│   └── signatureVerify.ts
├── controllers/       # Business logic
│   ├── articleController.ts
│   ├── commentController.ts
│   ├── likeController.ts
│   └── ipfsController.ts
└── routes/           # API routes
    ├── index.ts      # Root + API info
    ├── articles.ts
    ├── comments.ts
    ├── likes.ts
    └── ipfs.ts

📂 Project Structure

web3-blog/
├── client/                    # Next.js frontend
│   ├── src/
│   │   ├── app/              # App router pages
│   │   ├── components/       # React components
│   │   ├── config/           # Configuration
│   │   ├── hooks/            # Custom hooks
│   │   ├── lib/              # Utilities
│   │   └── types/            # TypeScript types
│   ├── e2e/                  # Playwright E2E tests
│   ├── __tests__/            # Jest unit tests
│   ├── playwright.config.ts
│   ├── jest.config.ts
│   └── package.json
│
├── server/                   # Express + Hardhat backend
│   ├── src/
│   │   ├── config/          # Configuration modules
│   │   ├── controllers/     # Business logic
│   │   ├── middleware/      # Express middleware
│   │   └── routes/          # API routes
│   ├── contracts/           # Solidity contracts
│   ├── scripts/             # Deployment scripts
│   ├── test/                # Jest + Supertest tests
│   └── package.json
│
└── README.md                # This file

🤝 Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing)
  5. Open Pull Request

Guidelines:

  • Follow TypeScript best practices
  • Write tests for new features
  • Update documentation
  • Use conventional commits
  • Ensure all tests pass

📄 License

MIT License - see LICENSE file for details.


🙏 Acknowledgments

  • Next.js, wagmi, viem teams
  • RainbowKit, shadcn/ui
  • OpenZeppelin, Hardhat
  • Pinata, Helia IPFS

Built with ❤️ by Md Arif Hossain

📧 hi@devarif.me | 🌐 devarif.me

← Back to profile