iStory is built on Next.js 15 and can be deployed to any Node.js hosting platform. This guide covers deployment to Vercel (recommended), smart contract deployment to Base Sepolia, and infrastructure setup.
Frontend Deployment
Vercel (Recommended)
Vercel provides the best experience for Next.js applications with zero-config deployment.
Build locally first
Ensure the build passes without errors
Deploy to production
Follow the prompts to link your project
Vercel automatically detects Next.js and uses the correct build command (npm run build) and start command (npm run start).
Environment Variables
Configure these in your Vercel project settings:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
GOOGLE_GENERATIVE_AI_API_KEY=your_google_gemini_key
ELEVENLABS_API_KEY=your_elevenlabs_key
ANTHROPIC_API_KEY=your_anthropic_key
NEXT_PUBLIC_PROJECT_ID=your_walletconnect_project_id
NEXT_PUBLIC_ESTORY_TOKEN_ADDRESS=0x...
NEXT_PUBLIC_STORY_PROTOCOL_ADDRESS=0x...
NEXT_PUBLIC_STORY_NFT_ADDRESS=0x...
NEXT_PUBLIC_VERIFIED_METRICS_ADDRESS=0x...
NEXT_PUBLIC_PRIVATE_VERIFIED_METRICS_ADDRESS=0x...
PINATA_API_KEY=your_pinata_api_key
PINATA_SECRET_API_KEY=your_pinata_secret
CRON_SECRET=your_cron_secret
RESEND_API_KEY=your_resend_api_key
Alternative Hosting
For other Node.js hosting platforms:
Build Production
Start Production Server
Docker (optional)
Ensure Node.js version is 18+ and all environment variables are properly configured before deployment.
Smart Contract Deployment
Prerequisites
Hardhat Setup Hardhat is pre-configured in the project
Base Sepolia Testnet access via MetaMask or similar wallet
Private Key Set in .env.local for deployment
Basescan API For contract verification
Deployment Steps
Configure environment
Add to .env.local: PRIVATE_KEY=your_wallet_private_key
BASESCAN_API_KEY=your_basescan_api_key
Deploy to Base Sepolia
npx hardhat run scripts/deploy.ts --network baseSepolia
This deploys three core contracts:
EStoryToken (ERC20) - $STORY token with 100M max supply
StoryProtocol - Tips and paywall payments
StoryNFT (ERC721) - Story books as NFTs with 0.001 ETH mint fee
Verify deployment
npx hardhat run scripts/verify-deployment.ts --network baseSepolia
Validates deployed ABIs match expected interfaces
Update configuration
Copy contract addresses to:
lib/contracts.ts
.env.local (as shown in Environment Variables section)
Deployment Script
The scripts/deploy.ts handles automated deployment:
import { ethers } from "hardhat" ;
async function main () {
const [ deployer ] = await ethers . getSigners ();
console . log ( "Deploying contracts with the account:" , deployer . address );
// 1. Deploy EStoryToken
const EStoryToken = await ethers . getContractFactory ( "EStoryToken" );
const token = await EStoryToken . deploy ( deployer . address );
await token . waitForDeployment ();
const tokenAddress = await token . getAddress ();
console . log ( `EStoryToken deployed to: ${ tokenAddress } ` );
// 2. Deploy StoryProtocol
const StoryProtocol = await ethers . getContractFactory ( "StoryProtocol" );
const protocol = await StoryProtocol . deploy ( tokenAddress , deployer . address );
await protocol . waitForDeployment ();
const protocolAddress = await protocol . getAddress ();
console . log ( `StoryProtocol deployed to: ${ protocolAddress } ` );
// 3. Deploy StoryNFT
const StoryNFT = await ethers . getContractFactory ( "StoryNFT" );
const nft = await StoryNFT . deploy ( deployer . address );
await nft . waitForDeployment ();
const nftAddress = await nft . getAddress ();
console . log ( `StoryNFT deployed to: ${ nftAddress } ` );
console . log ( " \n --- SAVE THESE ADDRESSES ---" );
console . log ( "Update lib/contracts.ts and .env.local with these addresses" );
}
main (). catch (( error ) => {
console . error ( error );
process . exitCode = 1 ;
});
Verification Script
The scripts/verify-deployment.ts ensures contracts are correctly deployed:
scripts/verify-deployment.ts
async function main () {
const tokenAddress = process . env . NEXT_PUBLIC_ESTORY_TOKEN_ADDRESS ;
const protocolAddress = process . env . NEXT_PUBLIC_STORY_PROTOCOL_ADDRESS ;
const nftAddress = process . env . NEXT_PUBLIC_STORY_NFT_ADDRESS ;
// Verify EStoryToken
const token = await ethers . getContractAt ( "EStoryToken" , tokenAddress );
const name = await token . name ();
const symbol = await token . symbol ();
const maxSupply = await token . MAX_SUPPLY ();
if ( name !== "eStoryToken" ) throw new Error ( `Expected name 'eStoryToken'` );
if ( symbol !== "ESTORY" ) throw new Error ( `Expected symbol 'ESTORY'` );
if ( maxSupply !== ethers . parseEther ( "100000000" )) throw new Error ( "MAX_SUPPLY mismatch" );
console . log ( "✓ EStoryToken verified successfully" );
// ... similar checks for StoryProtocol and StoryNFT
}
Contract Verification on Basescan
npx hardhat run scripts/verify.ts --network baseSepolia
This publishes and verifies your contract source code on Basescan, making it publicly viewable and auditable.
Database Setup (Supabase)
Run migrations
Execute SQL migrations in order:
001_create_weekly_reflections.sql
002_enable_rls_policies.sql
003_add_oauth_fields.sql
Create storage bucket
Create a public bucket named story-audio for audio file uploads
Configure authentication
Enable Google OAuth and/or email authentication in Supabase dashboard
Copy credentials
Add Supabase URL and keys to .env.local
Row Level Security (RLS) policies are critical for data privacy. Ensure they’re enabled and properly configured for all tables.
IPFS Setup (Pinata)
For decentralized file storage:
Generate API keys
Create API key and secret in Pinata dashboard
Configure in environment
PINATA_API_KEY=your_api_key
PINATA_SECRET_API_KEY=your_secret
Pre-Deployment Checklist
Run tests
npx vitest run
npx playwright test
Ensure all tests pass
Test production build
npm run build
npm run start
Verify the app runs correctly in production mode
Check environment variables
Ensure all required variables are set (use .env.example as reference)
Verify contracts
Run verify-deployment.ts to ensure contract ABIs are correct
Post-Deployment
Monitor Logs Use Vercel dashboard to monitor application logs and errors
Test Wallet Connection Connect MetaMask to Base Sepolia and test transactions
Verify API Routes Test authentication, AI endpoints, and social features
Check SEO Verify sitemap, robots.txt, and Open Graph images are working
Troubleshooting
Check that package.json scripts are correct:
"build": "next build"
"start": "next start"
"dev": "next dev -p 3000"
Never point these to Expo commands.
Environment variables not working
Ensure variables are set in Vercel project settings, not just .env.local. Public variables must start with NEXT_PUBLIC_.
Contract deployment fails
Verify private key is correctly formatted (no 0x prefix in .env.local)
Ensure wallet has enough Base Sepolia ETH for gas fees
Check network configuration in hardhat.config.ts
Configure allowed origins in next.config.mjs security headers. Ensure Supabase and API routes return correct CORS headers.
CI/CD Pipeline
Example GitHub Actions workflow:
.github/workflows/deploy.yml
name : Deploy to Production
on :
push :
branches : [ main ]
jobs :
deploy :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- uses : actions/setup-node@v3
with :
node-version : '18'
- run : npm install
- run : npm run lint
- run : npx vitest run
- run : npm run build
- uses : amondnet/vercel-action@v20
with :
vercel-token : ${{ secrets.VERCEL_TOKEN }}
vercel-org-id : ${{ secrets.ORG_ID }}
vercel-project-id : ${{ secrets.PROJECT_ID }}
vercel-args : '--prod'
Bundle Size Target: Keep pages under 500 kB First Load JS
Image Optimization Use Next.js <Image> component for automatic optimization
Code Splitting Dynamic imports for heavy components (Three.js, etc.)
Caching Leverage Vercel Edge caching for static assets
Run Lighthouse audits regularly to monitor Core Web Vitals. Target score: 70+ on mobile.