{"id":30732415,"url":"https://github.com/pskinnertech/nextjs15-arweave","last_synced_at":"2025-09-03T17:08:55.643Z","repository":{"id":286855125,"uuid":"962670103","full_name":"PSkinnerTech/Nextjs15-Arweave","owner":"PSkinnerTech","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-08T17:18:11.000Z","size":348,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T18:23:02.385Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PSkinnerTech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-08T13:55:55.000Z","updated_at":"2025-04-08T17:18:14.000Z","dependencies_parsed_at":"2025-04-08T18:24:54.196Z","dependency_job_id":"98d5941d-5739-4a00-b418-6c80f9e5b344","html_url":"https://github.com/PSkinnerTech/Nextjs15-Arweave","commit_stats":null,"previous_names":["pskinnertech/nextjs15-arweave"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PSkinnerTech/Nextjs15-Arweave","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PSkinnerTech%2FNextjs15-Arweave","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PSkinnerTech%2FNextjs15-Arweave/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PSkinnerTech%2FNextjs15-Arweave/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PSkinnerTech%2FNextjs15-Arweave/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PSkinnerTech","download_url":"https://codeload.github.com/PSkinnerTech/Nextjs15-Arweave/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PSkinnerTech%2FNextjs15-Arweave/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273477127,"owners_count":25112618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-03T17:06:32.913Z","updated_at":"2025-09-03T17:08:55.625Z","avatar_url":"https://github.com/PSkinnerTech.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Next.js Arweave Upload Demo\n\nThis project demonstrates how to upload files to the Arweave permaweb directly from a browser using Next.js 15, ArConnect wallet, and Turbo SDK.\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n# or\nbun dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nTo build the project, run:\n\n```bash\npnpm build\n# or\nnpm run build --no-lint\n# or\nyarn build --no-lint\n```\n\n## Client-Side Turbo SDK Implementation\n\nThis project features a fully client-side implementation for uploading files to the Arweave network directly from the browser using ArDrive's Turbo SDK. The key innovation here is making the Turbo SDK work in a browser environment through specific Next.js configurations.\n\n### Upload Flow\n\n1. **User connects wallet** - ArConnect browser extension is used for wallet connection\n2. **User selects file(s)** - Via drag \u0026 drop or file picker\n3. **Upload is initiated** - Client-side code handles the entire upload process\n4. **ArConnect signer is created** - Using the connected wallet\n5. **Turbo SDK client is initialized** - With the ArConnect signer\n6. **File is uploaded** - Using Turbo SDK's uploadFile method\n7. **URL is generated** - For permanent access to the uploaded file\n\n```\n┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐\n│   Browser   │     │  ArConnect  │     │  Turbo SDK  │     │   Arweave   │\n│    Client   │     │    Wallet   │     │             │     │   Network   │\n└──────┬──────┘     └──────┬──────┘     └──────┬──────┘     └──────┬──────┘\n       │                   │                   │                   │\n       │ Connect Wallet    │                   │                   │\n       │───────────────────\u003e                   │                   │\n       │                   │ Authorize         │                   │\n       │                   │\u003c──────────────────│                   │\n       │ Grant Permission  │                   │                   │\n       │\u003c───────────────────                   │                   │\n       │                   │                   │                   │\n       │ Select File       │                   │                   │\n       │────┐              │                   │                   │\n       │    │              │                   │                   │\n       │\u003c───┘              │                   │                   │\n       │                   │                   │                   │\n       │ Create ArConnect Signer               │                   │\n       │────────────────────────────────────────\u003e                  │\n       │                   │                   │ Initialize Turbo  │\n       │                   │                   │────┐              │\n       │                   │                   │    │              │\n       │                   │                   │\u003c───┘              │\n       │                   │                   │                   │\n       │                   │                   │ Upload File       │\n       │                   │                   │──────────────────\u003e│\n       │                   │                   │                   │\n       │                   │                   │ Transaction ID    │\n       │                   │                   │\u003c──────────────────│\n       │ Upload Complete   │                   │                   │\n       │\u003c─────────────────────────────────────────────────────────│\n       │                   │                   │                   │\n```\n\n### Making Turbo SDK Work in the Browser\n\nGetting the Turbo SDK to work in a client-side Next.js app required specific configurations:\n\n#### 1. Next.js Configuration\n\nThe `next.config.ts` file includes webpack overrides to handle Node.js dependencies that Turbo SDK depends on:\n\n```javascript\n// next.config.ts\nimport webpack from 'webpack';\n\nconst nextConfig = {\n  // Ensure static export for compatibility\n  output: 'export',\n  \n  // Disable React strict mode to avoid issues with certain dependencies\n  reactStrictMode: false,\n  \n  // Configure webpack for Turbo SDK compatibility\n  webpack: (config) =\u003e {\n    config.resolve.alias = {\n      ...config.resolve.alias,\n      // Replace problematic deps with browser versions\n      'bitcoinjs-lib': 'bitcoinjs-lib/dist/bitcoin.js',\n      'ecpair': 'ecpair/dist/ecpair.js',\n    };\n\n    // Add polyfills for Node.js built-ins\n    config.resolve.fallback = {\n      ...config.resolve.fallback,\n      fs: false,\n      path: false,\n      os: false,\n      crypto: require.resolve('crypto-browserify'),\n      stream: require.resolve('stream-browserify'),\n      buffer: require.resolve('buffer/'),\n    };\n\n    // Add plugins for browser polyfills\n    config.plugins.push(\n      new webpack.ProvidePlugin({\n        Buffer: ['buffer', 'Buffer'],\n        process: 'process/browser',\n      })\n    );\n\n    return config;\n  }\n};\n\nexport default nextConfig;\n```\n\n#### 2. Dependencies\n\nTo make the Turbo SDK work client-side, the project uses:\n\n```json\n\"dependencies\": {\n  \"@ar.io/sdk\": \"^3.9.1\",\n  \"@ardrive/turbo-sdk\": \"^1.23.4-alpha.1\",\n  \"@arweave-wallet-kit/browser-wallet-strategy\": \"^0.1.1\",\n  \"@arweave-wallet-kit/core\": \"^0.1.1\",\n  \"@arweave-wallet-kit/react\": \"^0.3.0\",\n  \"arweave-wallet-connector\": \"^1.0.2\",\n  \"bitcoinjs-lib\": \"^6.1.7\",\n  \"react-hot-toast\": \"^2.5.2\",\n  \"util\": \"^0.12.5\"\n},\n\"devDependencies\": {\n  \"arweave\": \"^1.15.7\",\n  \"browserify-fs\": \"^1.0.0\",\n  \"buffer\": \"^6.0.3\",\n  \"crypto-browserify\": \"^3.12.1\",\n  \"mime-types\": \"^3.0.1\",\n  \"node-polyfill-webpack-plugin\": \"^4.1.0\",\n  \"path-browserify\": \"^1.0.1\",\n  \"process\": \"^0.11.10\",\n  \"stream-browserify\": \"^3.0.0\"\n}\n```\n\n### Files Involved\n\n#### Core Application Files\n\n- `app/page.tsx` - Main entry point with routing setup\n- `app/components/DashboardPage.tsx` - Main upload interface \n- `app/utils/turboClient.ts` - Utility functions for Arweave uploads with Turbo SDK\n- `app/context/AuthContext.tsx` - Handles wallet connection state\n- `app/utils/arweaveWallet.ts` - Wallet utilities\n- `next.config.ts` - Webpack configuration for Turbo SDK browser compatibility\n\n#### Upload Process Files\n\n| File | Purpose |\n|------|---------|\n| **next.config.ts** | Configures webpack to support Turbo SDK in the browser |\n| **DashboardPage.tsx** | Provides the UI for file uploading; handles drag \u0026 drop, file selection, and displays upload progress |\n| **turboClient.ts** | Contains core upload functions using Turbo SDK: `uploadToArweave()` and `uploadFolderToArweave()` |\n| **AuthContext.tsx** | Manages wallet connection state using ArConnect |\n\n### The Turbo SDK Implementation\n\nThe client-side upload process is implemented as follows:\n\n#### 1. Setting up Turbo SDK with ArConnect\n\n```typescript\n// app/utils/turboClient.ts\nimport { TurboFactory, ArconnectSigner } from \"@ardrive/turbo-sdk\";\n\n// Request wallet permissions\nawait window.arweaveWallet.connect(['ACCESS_PUBLIC_KEY', 'SIGNATURE', 'SIGN_TRANSACTION']);\n\n// Get wallet address for logging\nconst walletAddress = await window.arweaveWallet.getActiveAddress();\n\n// Initialize Turbo SDK with ArConnect signer\nconst signer = new ArconnectSigner(window.arweaveWallet);\nconst turbo = TurboFactory.authenticated({ signer });\n```\n\n#### 2. File Upload Function\n\n```typescript\n// app/utils/turboClient.ts\nexport async function uploadToArweave(\n  file: File,\n  onProgress?: (percent: number) =\u003e void\n): Promise\u003c{ id: string; url: string }\u003e {\n  // Check if ArConnect is installed\n  if (!window.arweaveWallet) {\n    throw new Error('ArConnect wallet not found. Please install the ArConnect browser extension.');\n  }\n  \n  try {\n    // Request wallet permissions\n    if (onProgress) onProgress(5);\n    await window.arweaveWallet.connect(['ACCESS_PUBLIC_KEY', 'SIGNATURE', 'SIGN_TRANSACTION']);\n    if (onProgress) onProgress(10);\n    \n    // Get wallet address for logging\n    const walletAddress = await window.arweaveWallet.getActiveAddress();\n    console.log('Wallet address:', walletAddress);\n\n    // Initialize Turbo SDK with ArConnect signer\n    const signer = new ArconnectSigner(window.arweaveWallet);\n    const turbo = TurboFactory.authenticated({ signer });\n    \n    // Prepare data\n    if (onProgress) onProgress(20);\n    console.log('Reading file data...');\n    const data = await file.arrayBuffer();\n    \n    // Create transaction\n    if (onProgress) onProgress(30);\n    console.log('Creating transaction...'); \n    \n    // Submit transaction via Turbo SDK\n    console.log('Posting transaction to Arweave network via Turbo...');\n    const response = await turbo.uploadFile({ \n      fileStreamFactory: () =\u003e Buffer.from(data),\n      fileSizeFactory: () =\u003e data.byteLength,\n      dataItemOpts: {\n        tags: [\n          { name: 'Content-Type', value: getContentType(file) },\n          { name: 'App-Name', value: 'Arweave-Upload-Demo' },\n          { name: 'App-Version', value: '1.0.0' },\n          { name: 'Unix-Time', value: String(Date.now()) },\n          { name: 'Filename', value: file.name }\n        ]\n      }\n    });\n    \n    if (onProgress) onProgress(100);\n    console.log('Transaction posted successfully:', response.id);\n    \n    return {\n      id: response.id,\n      url: `https://arweave.net/${response.id}`\n    };\n  } catch (error: unknown) {\n    console.error('Upload error:', error);\n    throw new Error(`Upload error: ${error instanceof Error ? error.message : String(error)}`);\n  }\n}\n```\n\n### Key Benefits of Turbo SDK\n\n1. **Credit-based uploads** - Users don't need to own AR tokens directly\n2. **Lower cost** - Turbo provides cost-effective bundling of transactions\n3. **Better privacy** - Files go directly from user to Arweave via Turbo\n4. **Simplified architecture** - No need for API routes or server-side code\n5. **Better user experience** - Real-time progress updates and feedback\n6. **Static exports** - Compatible with Next.js static exports, making deployment simpler\n\n### Technical Considerations\n\n- **Wallet extension required** - Users must have ArConnect installed\n- **Browser compatibility** - Special webpack configuration required\n- **Alpha build** - Using latest alpha build (1.23.4-alpha.1) with improved browser support\n- **React 19 compatible** - Works with the latest Next.js 15.x and React 19\n- **Static export** - Works with Next.js static export mode (`output: 'export'`)\n\n## Components Overview\n\n### DashboardPage Component\n\nThe Dashboard page provides a complete UI for uploading files including:\n\n- File drag \u0026 drop interface\n- File selection via file picker\n- Upload progress tracking with percentage\n- Terminal-like interface for command feedback\n- Deployment URL display after successful uploads\n\n### TurboClient Utilities\n\nThe `turboClient.ts` utility provides several key functions:\n\n- `getContentType()` - Determines the correct MIME type for files\n- `formatBytes()` - Formats file sizes in human-readable form\n- `uploadToArweave()` - Handles file upload with progress tracking\n- `uploadFolderToArweave()` - Handles multiple file uploads\n\n## Learn More\n\n- [Arweave Documentation](https://docs.arweave.org/)\n- [ArConnect Documentation](https://docs.arconnect.io/)\n- [Turbo SDK Documentation](https://github.com/ardriveapp/turbo-sdk)\n- [Next.js Documentation](https://nextjs.org/docs)\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template\u0026filter=next.js\u0026utm_source=create-next-app\u0026utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.\n\n## Deploy on Arweave\n\nThis project includes scripts to deploy your Next.js app to the Arweave permaweb, providing permanent and decentralized hosting.\n\n### Prerequisites\n\n1. An Arweave wallet file (JWK format)\n2. Arweave tokens for transaction fees\n3. Next.js app configured for static export\n\n### Deployment Steps\n\n1. Copy your Arweave wallet file to the project root as `wallet.json`:\n   ```bash\n   cp your-wallet.json wallet.json\n   ```\n\n2. Run the deployment script:\n   ```bash\n   pnpm deploy\n   ```\n\n3. Once completed, your app will be permanently available on Arweave at the URL provided in the console output.\n\n### How it Works\n\nThe deployment process:\n1. Builds your Next.js app as a static site\n2. Uploads all files to Arweave using the Turbo service\n3. Creates an Arweave manifest to preserve the directory structure\n4. Returns a transaction ID that serves as the root of your deployed app\n\nYour app will be available at `https://arweave.net/[TRANSACTION_ID]`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpskinnertech%2Fnextjs15-arweave","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpskinnertech%2Fnextjs15-arweave","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpskinnertech%2Fnextjs15-arweave/lists"}