A decentralized music streaming platform built on Base chain. Purchase mixtape NFTs with USDC, stream music, track listening time, and compete on the leaderboard.
- NFT-Gated Access: Purchase mixtapes as ERC-1155 NFTs on Base
- USDC Payments: Buy mixtapes for $4.20 USDC
- Music Streaming: Stream audio directly on the site with custom player
- Listening Time Tracking: Track and display listening time
- Leaderboard: Compete with other listeners, ranked by total listening time
- ENS Integration: Display ENS names on leaderboard
- Collection Management: View your owned mixtapes
- Download Support: Download your purchased mixtapes (coming soon)
- Next.js 16 - React framework with App Router
- TypeScript - Type-safe development
- Tailwind CSS v4 - Utility-first styling
- Wagmi v2 - React hooks for Ethereum
- RainbowKit - Wallet connection UI
- Viem - TypeScript Ethereum library
- TanStack Query - Data fetching and caching
- Supabase - PostgreSQL database, storage, and edge functions
- Base Chain - L2 blockchain for low-cost transactions
- Solidity 0.8.20 - Smart contract language
- Foundry - Development framework
- OpenZeppelin - Secure contract libraries
mixtape/
├── app/ # Next.js app directory
│ ├── layout.tsx # Root layout with providers
│ ├── page.tsx # Landing page
│ ├── player/page.tsx # Music player
│ ├── collection/page.tsx # User's collection
│ └── leaderboard/page.tsx # Listening leaderboard
├── components/ # React components
│ ├── PurchaseCard.tsx # USDC payment UI
│ ├── MixtapePlayer.tsx # Audio player
│ ├── CollectionGrid.tsx # Display owned NFTs
│ └── LeaderboardTable.tsx # Rankings
├── hooks/ # Custom React hooks
│ ├── useUsdcTransfer.ts # USDC payments
│ ├── useMixtapePurchase.ts # Purchase orchestration
│ ├── useMixtapeOwnership.ts # NFT balance checking
│ ├── useAudioPlayer.ts # Audio controls
│ ├── useListeningTracker.ts # Time tracking
│ └── useEnsResolution.ts # ENS name lookup
├── lib/ # Shared utilities
│ ├── constants.ts # Contract addresses, ABIs
│ ├── wagmi-config.ts # Wagmi configuration
│ └── supabase.ts # Supabase client
├── providers/ # React context providers
│ └── Providers.tsx # Wagmi + RainbowKit wrapper
├── contracts/ # Smart contracts
│ ├── PizzaMixtapeNFT.sol # ERC-1155 NFT contract
│ ├── foundry.toml # Foundry config
│ └── script/Deploy.s.sol # Deployment script
└── supabase/ # Supabase configuration
├── migrations/ # Database schema
└── functions/ # Edge functions
├── mint-mixtape/ # Mint NFT after payment
└── verify-ownership/ # Generate signed URLs
- Node.js 18+
- npm or yarn
- Foundry (for smart contracts)
- Supabase CLI (for backend)
- Wallet with Base ETH and USDC for testing
- Clone the repository
cd mixtape- Install dependencies
npm install- Set up environment variables
Copy .env.example to .env and fill in the values:
cp .env.example .envRequired variables:
NEXT_PUBLIC_USDC_ADDRESS- USDC contract on Base (already set)NEXT_PUBLIC_NFT_CONTRACT_ADDRESS- Your deployed NFT contractNEXT_PUBLIC_TREASURY_ADDRESS- Wallet to receive paymentsNEXT_PUBLIC_WALLETCONNECT_PROJECT_ID- From WalletConnect CloudNEXT_PUBLIC_SUPABASE_URL- Your Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY- Your Supabase anonymous key
- Run the development server
npm run devOpen http://localhost:3000 to see the app.
cd contracts
# Install dependencies
forge install
# Deploy to Base Sepolia (testnet)
forge script script/Deploy.s.sol:DeployScript \
--rpc-url https://sepolia.base.org \
--broadcast \
--verify
# Deploy to Base Mainnet
forge script script/Deploy.s.sol:DeployScript \
--rpc-url $BASE_RPC_URL \
--broadcast \
--verifySee contracts/README.md for details.
# Link project
supabase link --project-ref your-project-ref
# Run migrations
supabase db push
# Create storage buckets
supabase storage create mixtape-audio --public false
supabase storage create mixtape-covers --public true
# Deploy edge functions
supabase functions deploy
# Set secrets
supabase secrets set MINTER_PRIVATE_KEY=0x...
supabase secrets set NFT_CONTRACT_ADDRESS=0x...
supabase secrets set TREASURY_ADDRESS=0x...See supabase/README.md for details.
Deploy to Vercel:
npm install -g vercel
vercelOr use the Vercel dashboard to import the GitHub repository.
Important: Add all environment variables in Vercel project settings.
- Connect your wallet using RainbowKit
- Ensure you have Base ETH (for gas) and USDC (for payment)
- Click "Buy Now" for $4.20 USDC
- Approve the USDC transfer in your wallet
- Wait for the transaction to confirm
- Your NFT will be minted automatically
- Access the player and start listening
- Navigate to the Player page
- The app verifies your NFT ownership
- Audio loads with signed URL from Supabase
- Listening time is tracked every 30 seconds
- Time is aggregated on your user profile
- View your rank on the Leaderboard
- Ranked by total listening time (all sessions combined)
- Updates every 30 seconds
- Displays ENS names if available
- Shows shortened addresses otherwise (0x1234...5678)
User → USDC Transfer → Treasury Wallet
↓
Backend Verifies Transaction
↓
Backend Mints NFT to User
↓
User Owns Mixtape
User Requests Audio → Backend Checks NFT Balance
↓
Balance > 0?
↓
Generate Signed URL (1hr expiry)
↓
User Streams Audio
↓
Track Time Every 30s → Update Database
User Plays Audio → Start Session in DB
↓
Track Time Every 30s
↓
Update Session + User Total Time
↓
Display on Leaderboard
- Private Keys: Never commit private keys. Use environment variables and Supabase secrets.
- USDC Verification: Backend verifies actual blockchain transactions before minting.
- NFT Ownership: Player checks NFT balance on-chain before streaming.
- Signed URLs: Audio URLs expire after 1 hour.
- Rate Limiting: Consider adding rate limits to prevent abuse.
- RLS Policies: Supabase Row Level Security protects user data.
npm run buildCheck for TypeScript errors and build issues.
cd contracts
forge test- Connect wallet on Base Sepolia testnet
- Get test USDC from faucet
- Purchase mixtape
- Verify NFT in collection
- Play mixtape
- Check listening time updates
- View leaderboard
- Ensure you have enough Base ETH for gas
- Check USDC balance is at least $4.20
- Verify treasury address is correct
- Check NFT ownership on BaseScan
- Verify Supabase edge function is deployed
- Check browser console for errors
- Ensure audio file is uploaded to Supabase Storage
- Check browser console for errors
- Verify Supabase edge function is deployed
- Ensure you're connected to the correct wallet
- Check that audio is actually playing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details
- PizzaDAO - Community and inspiration
- Base - L2 blockchain infrastructure
- Supabase - Backend services
- RainbowKit - Wallet connection UI
- Wagmi - React hooks for Ethereum
For issues, questions, or feedback:
- Open a GitHub issue
- Contact PizzaDAO community
Built with 🍕 by PizzaDAO