Built with React + TypeScript on Aptos Shelby Network
Production URL: https://memories.ekkodev.xyz/
A decentralized photo album application powered by the Shelby Protocol, enabling users to store and manage their digital memories on the Aptos blockchain with permanent, censorship-resistant storage.
- Wallet Connection - Connect with any Aptos-compatible wallet
- Media Upload - Upload images and videos up to 500MB
- Decentralized Storage - Files stored on Shelby Network using erasure coding
- Gallery View - Beautiful masonry-style grid layout with borders
- Media Preview - Full-screen image and video preview
- Search & Filter - Find memories by title or filename
- Infinite Scroll - Seamless loading of large collections
- Expiration Control - Set custom expiration dates for your blobs
- Dark Mode - Built-in dark mode support
- React 18.3 - UI framework
- TypeScript 5.7 - Type safety
- Vite 6.0 - Build tool and dev server
- TailwindCSS 3.4 - Styling with custom design system
- @aptos-labs/ts-sdk - Aptos TypeScript SDK
- @aptos-labs/wallet-adapter-react - Wallet connection
- @shelby-protocol/sdk - Shelby Protocol for decentralized storage
- @shelby-protocol/react - React hooks for Shelby
- @tanstack/react-query - Server state management and caching
- dayjs - Date/time manipulation
- buffer - Node.js Buffer polyfill for browser
memories/
├── public/ # Static assets
├── src/
│ ├── components/ # React components
│ │ ├── Header.tsx # Top navigation with wallet connector
│ │ ├── Hero.tsx # Image carousel slider
│ │ ├── AlbumGrid.tsx # Main gallery grid with infinite scroll
│ │ ├── UploadModal.tsx # Upload dialog with preview
│ │ ├── SearchFilters.tsx # Search input component
│ │ └── Footer.tsx # Page footer
│ ├── hooks/ # Custom React hooks
│ │ └── useShelby.ts # Hooks for Shelby operations
│ ├── utils/ # Utility functions
│ │ └── shelby.ts # Shelby client setup & API calls
│ ├── assets/ # Images, logos, etc.
│ ├── App.tsx # Root component
│ ├── main.tsx # App entry point with providers
│ └── index.css # Global styles
├── index.html # HTML template
├── vite.config.js # Vite configuration
├── tailwind.config.cjs # Tailwind configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies and scripts
- Node.js 18+ and npm/yarn/pnpm
- Aptos wallet (Petra, Martian, Pontem, etc.)
# Install dependencies
npm install
# Copy environment variables (optional)
cp .env.example .envCreate a .env file in the root directory:
# Shelby API Key (optional, for rate limit increases)
VITE_SHELBY_API_KEY=your_api_key_here# Start dev server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Run linter
npm run lintThe dev server will start at http://localhost:5173
Root component that renders the main layout:
- Header with wallet connection
- Hero carousel section
- Album grid for displaying memories
- Footer
Application entry point with provider setup:
QueryClientProvider- React Query for data fetchingAptosWalletAdapterProvider- Wallet connection configured for ShelbyNet
Main gallery component featuring:
- Infinite scroll pagination (100 items per page)
- Lazy loading of blob content from Shelby API
- Search and filter functionality
- Image/video detection and preview
- Upload modal trigger
File upload interface with:
- Drag & drop support
- File type validation (images/videos only, max 500MB)
- Preview for selected files
- Custom expiration date picker
- Upload progress indicator
Shelby Protocol integration:
ShelbyClientinitialization with Reed-Solomon erasure codinggetAccountBlobs()- Fetch user's stored blobsuploadBlob()- Upload new blob (wrapper for SDK)
primary: #4ccce6 /* Cyan accent */
background-light: #fbfaf8 /* Light mode background */
background-dark: #111e21 /* Dark mode background */- Display Font: Inter (UI elements)
- Serif Font: Playfair Display (headings, titles)
Photo borders cycle through 5 subtle colors:
#f0e6d2(Cream)#e2ece9(Mint)#f5e1e1(Rose)#e1e5f5(Periwinkle)#f5f1e1(Champagne)
Get Account Blobs:
GET https://api.shelbynet.shelby.xyz/shelby/v1/blobs/{account}
Download Blob:
GET https://api.shelbynet.shelby.xyz/shelby/v1/blobs/{account}/{filename}
- Network: ShelbyNet (Aptos testnet)
- Provider: Reed-Solomon Erasure Coding (pure JS implementation)
- Default Expiration: 30 days from upload
- User selects file (image/video, max 500MB)
- File is validated and previewed
- User sets title and optional expiration date
- File is converted to
Uint8Array useUploadBlobshook from@shelby-protocol/reacthandles:- Erasure encoding (splitting into chunks)
- Transaction signing via wallet
- Upload to storage nodes
- On success, gallery refreshes to show new blob
The Vite config includes:
- Node.js polyfills for Buffer, global, process
- Terser minification with console removal
- COOP/COEP headers for SharedArrayBuffer support
- WASM asset handling
# Build
npm run build
# Output directory: ./dist
# Deploy contents to your hosting serviceFor the production site at https://memories.ekkodev.xyz/, deploy the dist/ folder using your preferred hosting provider (Vercel, Netlify, Cloudflare Pages, etc.).
- Ensure wallet is unlocked and on ShelbyNet
- Try refreshing the page and reconnecting
- Check browser console for errors
- Verify file size is under 500MB
- Ensure sufficient gas in wallet
- Check that file is valid image/video format
- Try again if network is congested
- Blob content is lazy-loaded from Shelby API
- Check browser console for failed fetch requests
- Verify account address is correct
- Some blobs may still be processing (check
isWrittenstatus)
MIT
Contributions are welcome! Please feel free to submit a Pull Request.
For issues related to:
- This App: Check GitHub Issues
- Shelby Protocol: Visit Shelby Documentation
- Aptos Wallet: Visit wallet provider's support page
Built with love for decentralized storage on the Aptos blockchain.