diff --git a/.env b/.env index f3bff01..79dc491 100644 --- a/.env +++ b/.env @@ -1,28 +1,28 @@ # Database Configuration -DATABASE_URL="postgresql://postgres:password@localhost:5432/basednet" -POSTGRES_USER="postgres" -POSTGRES_PASSWORD="password" -POSTGRES_HOST="localhost" +DATABASE_URL="postgresql://neondb_owner:npg_loex42GnkyEf@ep-small-flower-a5hbgnie-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require" +POSTGRES_USER="neondb_owner" +POSTGRES_PASSWORD="npg_loex42GnkyEf" +POSTGRES_HOST="ep-small-flower-a5hbgnie-pooler.us-east-2.aws.neon.tech" POSTGRES_PORT="5432" -POSTGRES_DB="basednet" +POSTGRES_DB="neondb" # IPFS Configuration -IPFS_PROJECT_ID="" -IPFS_PROJECT_SECRET="" -IPFS_GATEWAY="https://ipfs.io/ipfs/" +IPFS_PROJECT_ID="971d5aadc982cc62695b" +IPFS_PROJECT_SECRET="11ed2bf0f5a3ec55c8aa8a515b4851deb4489837cdabf4e67681e00ce38af265" +IPFS_GATEWAY="turquoise-selected-locust-947.mypinata.cloud" # Authentication -INDIE_AUTH_CLIENT_ID="" -INDIE_AUTH_CLIENT_SECRET="" -INDIE_AUTH_REDIRECT_URI="http://localhost:3000/api/auth/callback" +INDIE_AUTH_CLIENT_ID="https://basednet.lol" +INDIE_AUTH_CLIENT_SECRET="a0cb2bbadb0befc7cedfe9f40a9355c52ad107dfdd628a7c009348de579fbb1a" +INDIE_AUTH_REDIRECT_URI="https://basednet.lol/callback" # API Keys & Security NEXTAUTH_SECRET="basednet-nextauth-secret-key-change-in-production" -NEXTAUTH_URL="http://localhost:3000" +NEXTAUTH_URL="https://basednet.lol" # Rate Limiting -UPSTASH_REDIS_REST_URL="" -UPSTASH_REDIS_REST_TOKEN="" +UPSTASH_REDIS_REST_URL="https://witty-stingray-45983.upstash.io" +UPSTASH_REDIS_REST_TOKEN="AbOfAAIjcDFhM2M1N2FhNzA3MjY0NTkwYWQ0YjRmNjQ2ODVjMGIwYnAxMA" # Federation ACTIVITY_PUB_DOMAIN="" @@ -35,8 +35,10 @@ ENABLE_FEDERATION=true ENABLE_CHAT=true # Services -PINATA_API_KEY="" -PINATA_SECRET_KEY="" +PINATA_API_KEY="971d5aadc982cc62695b" +PINATA_SECRET_KEY="11ed2bf0f5a3ec55c8aa8a515b4851deb4489837cdabf4e67681e00ce38af265" # Analytics & Monitoring -SENTRY_DSN="" +SENTRY_DSN="https://e8030cc6502f8f8391a6eefb8350b1f0@o4509050597605376.ingest.us.sentry.io/4509050617856000" +SENTRY_ORG="basednet" +SENTRY_PROJECT="basednet" diff --git a/.gitignore b/.gitignore index 3c3629e..81e83fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.vercel diff --git a/.history/.github/workflows/vercel-deploy_20250416040959.yml b/.history/.github/workflows/vercel-deploy_20250416040959.yml new file mode 100644 index 0000000..e69de29 diff --git a/.history/.github/workflows/vercel-deploy_20250416041009.yml b/.history/.github/workflows/vercel-deploy_20250416041009.yml new file mode 100644 index 0000000..8b7d242 --- /dev/null +++ b/.history/.github/workflows/vercel-deploy_20250416041009.yml @@ -0,0 +1,33 @@ +name: Deploy to Vercel + +on: + push: + branches: [main] + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Vercel CLI + run: npm install --global vercel@latest + + - name: Pull Vercel Environment Information + run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} + + - name: Build Project Artifacts + run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy Project Artifacts to Vercel + run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} \ No newline at end of file diff --git a/.history/GITHUB_DEPLOYMENT_20250416041344.md b/.history/GITHUB_DEPLOYMENT_20250416041344.md new file mode 100644 index 0000000..e69de29 diff --git a/.history/GITHUB_DEPLOYMENT_20250416041359.md b/.history/GITHUB_DEPLOYMENT_20250416041359.md new file mode 100644 index 0000000..eaf7b39 --- /dev/null +++ b/.history/GITHUB_DEPLOYMENT_20250416041359.md @@ -0,0 +1,97 @@ +# Deploying BasedNet using GitHub Actions and Vercel + +## Overview + +This document outlines an improved approach to deploying BasedNet to Vercel using GitHub Actions. This approach offers several advantages over direct deployment from a local machine: + +1. **Consistent Environment**: Builds happen in a clean Ubuntu environment, avoiding Windows-specific path issues +2. **Automated Workflow**: Deployments are triggered automatically when you push to the main branch +3. **Reproducible Builds**: Every build uses the same setup, reducing "works on my machine" problems +4. **Version Control**: Deployment configuration is tracked in version control + +## Prerequisites + +Before using this deployment method, you'll need: + +1. A GitHub account with your BasedNet code pushed to a repository +2. A Vercel account linked to your GitHub account +3. A Vercel project created for BasedNet + +## Setup Instructions + +### 1. Generate a Vercel API Token + +1. Log in to your [Vercel dashboard](https://vercel.com/dashboard) +2. Go to Settings → Tokens +3. Create a new token with "Full Account" scope +4. Copy the token value (you won't be able to see it again) + +### 2. Add the Vercel Token to GitHub Secrets + +1. Go to your GitHub repository +2. Navigate to Settings → Secrets and variables → Actions +3. Click "New repository secret" +4. Name: `VERCEL_TOKEN` +5. Value: Paste your Vercel API token +6. Click "Add secret" + +### 3. Initial Setup on Vercel + +1. From the Vercel dashboard, click "Add New..." → "Project" +2. Import your GitHub repository +3. Configure your project settings: + - Framework Preset: Next.js + - Root Directory: ./ + - Build Command: npm run build + - Output Directory: .next +4. Add all required environment variables from your `.env` file +5. Deploy once manually through the Vercel interface to set up the project + +### 4. Use GitHub Actions for Future Deployments + +After the initial setup, all future deployments will happen automatically through GitHub Actions when you push to the main branch. + +## How It Works + +The workflow file `.github/workflows/vercel-deploy.yml` defines the deployment process: + +1. Checkout the code from GitHub +2. Set up Node.js +3. Install dependencies +4. Install Vercel CLI +5. Pull environment variables from Vercel +6. Build the project +7. Deploy to Vercel + +## Troubleshooting + +If you encounter deployment issues: + +1. Check the GitHub Actions logs for detailed build information +2. Verify all required environment variables are set in Vercel +3. Ensure your Vercel token has the correct permissions +4. Check that the Node.js version in the workflow matches your project requirements + +## Manual Deployment + +You can also trigger a deployment manually: + +1. Go to your GitHub repository +2. Navigate to Actions → "Deploy to Vercel" workflow +3. Click "Run workflow" +4. Select the branch you want to deploy +5. Click "Run workflow" + +This will start the deployment process without requiring a code push. + +## Security Considerations + +The GitHub Actions workflow is configured to deploy only on pushes to the main branch and manual triggers. This prevents unauthorized deployments from feature branches. + +The Vercel token is stored securely in GitHub Secrets and is never exposed in logs or outputs. + +## Additional Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Vercel CLI Documentation](https://vercel.com/docs/cli) +- [Next.js Deployment Documentation](https://nextjs.org/docs/deployment) \ No newline at end of file diff --git a/.history/GITHUB_DEPLOYMENT_20250416143545.md b/.history/GITHUB_DEPLOYMENT_20250416143545.md new file mode 100644 index 0000000..c4a48f7 --- /dev/null +++ b/.history/GITHUB_DEPLOYMENT_20250416143545.md @@ -0,0 +1,115 @@ +# Deploying BasedNet using GitHub Actions and Vercel + +## Overview + +This document outlines an improved approach to deploying BasedNet to Vercel using GitHub Actions. This approach offers several advantages over direct deployment from a local machine: + +1. **Consistent Environment**: Builds happen in a clean Ubuntu environment, avoiding Windows-specific path issues +2. **Automated Testing & Linting**: Tests and linting are run before each deployment +3. **Automated Workflow**: Deployments are triggered automatically when you push to the main branch +4. **Reproducible Builds**: Every build uses the same setup, reducing "works on my machine" problems +5. **Version Control**: Deployment configuration is tracked in version control + +## Prerequisites + +Before using this deployment method, you'll need: + +1. A GitHub account with your BasedNet code pushed to a repository +2. A Vercel account linked to your GitHub account +3. A Vercel project created for BasedNet + +## Setup Instructions + +### 1. Generate a Vercel API Token + +1. Log in to your [Vercel dashboard](https://vercel.com/dashboard) +2. Go to Settings → Tokens +3. Create a new token with "Full Account" scope +4. Copy the token value (you won't be able to see it again) + +### 2. Add Required Secrets to GitHub + +1. Go to your GitHub repository +2. Navigate to Settings → Secrets and variables → Actions +3. Add the following repository secrets: + - `VERCEL_TOKEN`: Your Vercel API token + - `DATABASE_URL`: Your PostgreSQL connection string + - `DB_PASSWORD`: Your database password + +### 3. Initial Setup on Vercel + +1. From the Vercel dashboard, click "Add New..." → "Project" +2. Import your GitHub repository +3. Configure your project settings: + - Framework Preset: Next.js + - Root Directory: ./ + - Build Command: npm run build + - Output Directory: .next +4. Add all required environment variables from your `.env` file +5. Link your local project to Vercel by running: + ``` + npm run setup:github + ``` + +### 4. Use GitHub Actions for Future Deployments + +After the initial setup, all future deployments will happen automatically through GitHub Actions when you push to the main branch. + +## How It Works + +The workflow file `.github/workflows/deploy.yml` defines the deployment process: + +1. **Testing Stage**: + - Sets up a PostgreSQL service for testing + - Runs your test suite against the test database + - Ensures all tests pass before proceeding + +2. **Linting Stage**: + - Checks your code for style and potential issues + - Ensures code quality before deployment + +3. **Deployment Stage**: + - Only runs if both test and lint stages pass + - Only runs for pushes to the main branch + - Checkout the code from GitHub + - Set up Node.js + - Install dependencies + - Install Vercel CLI + - Pull environment variables from Vercel + - Build the project + - Deploy to Vercel + - Run any required database migrations + +## Troubleshooting + +If you encounter deployment issues: + +1. Check the GitHub Actions logs for detailed build information +2. Verify all required environment variables are set in Vercel +3. Ensure your Vercel token has the correct permissions +4. Check that the Node.js version in the workflow matches your project requirements +5. Look for test or linting errors that might be causing the deployment to fail + +## Manual Deployment + +You can also trigger a deployment manually: + +1. Go to your GitHub repository +2. Navigate to Actions → "Deploy Basednet" workflow +3. Click "Run workflow" +4. Select the branch you want to deploy +5. Click "Run workflow" + +This will start the deployment process without requiring a code push. + +## Security Considerations + +The GitHub Actions workflow is configured to deploy only on pushes to the main branch and manual triggers. This prevents unauthorized deployments from feature branches. + +The Vercel token and database credentials are stored securely in GitHub Secrets and are never exposed in logs or outputs. + +## Additional Resources + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Vercel CLI Documentation](https://vercel.com/docs/cli) +- [Next.js Deployment Documentation](https://nextjs.org/docs/deployment) \ No newline at end of file diff --git a/.history/jsconfig_20250420051006.json b/.history/jsconfig_20250420051006.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/jsconfig_20250420051012.json b/.history/jsconfig_20250420051012.json new file mode 100644 index 0000000..df83de4 --- /dev/null +++ b/.history/jsconfig_20250420051012.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + } +} \ No newline at end of file diff --git a/.history/next.config_20250416041158.js b/.history/next.config_20250416041158.js new file mode 100644 index 0000000..7d8184b --- /dev/null +++ b/.history/next.config_20250416041158.js @@ -0,0 +1,32 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + serverComponentsExternalPackages: [], // For better handling of server components + optimizeCss: true, // For CSS optimization + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419073603.js b/.history/next.config_20250419073603.js new file mode 100644 index 0000000..8817125 --- /dev/null +++ b/.history/next.config_20250419073603.js @@ -0,0 +1,31 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + serverExternalPackages: [], // For better handling of server components + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419073651.js b/.history/next.config_20250419073651.js new file mode 100644 index 0000000..5dd346a --- /dev/null +++ b/.history/next.config_20250419073651.js @@ -0,0 +1,33 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + serverExternalPackages: [], // For better handling of server components + swcMinify: true, // For minification of JavaScript and CSS files using SWC + + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419073856.js b/.history/next.config_20250419073856.js new file mode 100644 index 0000000..3eb3d89 --- /dev/null +++ b/.history/next.config_20250419073856.js @@ -0,0 +1,34 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + serverExternalPackages: [], // For better handling of server components + swcMinify: true, // For minification of JavaScript and CSS files using SWC + + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419075027.js b/.history/next.config_20250419075027.js new file mode 100644 index 0000000..ca4d161 --- /dev/null +++ b/.history/next.config_20250419075027.js @@ -0,0 +1,34 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + serverExternalPackages: ["@sentry/nextjs", "@upstash/ratelimit", "@upstash/redis", "cors", "dotenv", "firebase", "firebase-admin", "helmet", "ipfs-http-client", "next-auth", "pg", "rate-limiter-flexible", "zod"], // For better handling of server components + swcMinify: true, // For minification of JavaScript and CSS files using SWC +18 | + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419075052.js b/.history/next.config_20250419075052.js new file mode 100644 index 0000000..cebe6b4 --- /dev/null +++ b/.history/next.config_20250419075052.js @@ -0,0 +1,33 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + serverExternalPackages: ["@sentry/nextjs", "@upstash/ratelimit", "@upstash/redis", "cors", "dotenv", "firebase", "firebase-admin", "helmet", "ipfs-http-client", "next-auth", "pg", "rate-limiter-flexible", "zod"], // For better handling of server components + swcMinify: true, // For minification of JavaScript and CSS files using SWC + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250419125034.js b/.history/next.config_20250419125034.js new file mode 100644 index 0000000..d985c0c --- /dev/null +++ b/.history/next.config_20250419125034.js @@ -0,0 +1,32 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + swcMinify: true, // For minification of JavaScript and CSS files using SWC + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250420051033.js b/.history/next.config_20250420051033.js new file mode 100644 index 0000000..4a323fa --- /dev/null +++ b/.history/next.config_20250420051033.js @@ -0,0 +1,40 @@ +/** @type {import('next').NextConfig} */ +const path = require('path'); + +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + swcMinify: true, // For minification of JavaScript and CSS files using SWC + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, + + // Force alias resolution for Vercel build + webpack: (config) => { + config.resolve.alias['@'] = path.resolve(__dirname, 'src'); + return config; + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250505224626.js b/.history/next.config_20250505224626.js new file mode 100644 index 0000000..b3cbab1 --- /dev/null +++ b/.history/next.config_20250505224626.js @@ -0,0 +1,39 @@ +/** @type {import('next').NextConfig} */ +const path = require('path'); + +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, + + // Force alias resolution for Vercel build + webpack: (config) => { + config.resolve.alias['@'] = path.resolve(__dirname, 'src'); + return config; + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250505224826.js b/.history/next.config_20250505224826.js new file mode 100644 index 0000000..d65e2bd --- /dev/null +++ b/.history/next.config_20250505224826.js @@ -0,0 +1,39 @@ +/** @type {import('next').NextConfig} */ +import path from 'path'; + +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, + + // Force alias resolution for Vercel build + webpack: (config) => { + config.resolve.alias['@'] = path.resolve(__dirname, 'src'); + return config; + }, +}; + +// Exporting the configuration without Sentry for now +module.exports = nextConfig; diff --git a/.history/next.config_20250505224834.js b/.history/next.config_20250505224834.js new file mode 100644 index 0000000..1a96766 --- /dev/null +++ b/.history/next.config_20250505224834.js @@ -0,0 +1,39 @@ +/** @type {import('next').NextConfig} */ +import path from 'path'; + +const nextConfig = { + reactStrictMode: true, + + env: { + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, + NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'https://basednet.lol', + }, + + // Optimize for Vercel deployment + output: 'standalone', // Creates a standalone build that's optimized for Vercel + + experimental: { + // Enable modern features + optimizeCss: true, // For CSS optimization + }, + + // Disable unnecessary source maps in production + productionBrowserSourceMaps: false, + + // Improve build performance + swcMinify: true, + + // Disable image optimization if not needed (reduces build time) + images: { + unoptimized: process.env.NODE_ENV === 'development', + }, + + // Force alias resolution for Vercel build + webpack: (config) => { + config.resolve.alias['@'] = path.resolve(__dirname, 'src'); + return config; + }, +}; + +// Exporting the configuration without Sentry for now +export default nextConfig; diff --git a/.history/package_20250405034049.json b/.history/package_20250405034049.json new file mode 100644 index 0000000..807ae05 --- /dev/null +++ b/.history/package_20250405034049.json @@ -0,0 +1,69 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250416041633.json b/.history/package_20250416041633.json new file mode 100644 index 0000000..d88d6de --- /dev/null +++ b/.history/package_20250416041633.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250416121159.json b/.history/package_20250416121159.json new file mode 100644 index 0000000..30fa312 --- /dev/null +++ b/.history/package_20250416121159.json @@ -0,0 +1,72 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:fixed": "node scripts/setup-github-deploy-fixed.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250416124632.json b/.history/package_20250416124632.json new file mode 100644 index 0000000..880a809 --- /dev/null +++ b/.history/package_20250416124632.json @@ -0,0 +1,73 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:fixed": "node scripts/setup-github-deploy-fixed.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250416143445.json b/.history/package_20250416143445.json new file mode 100644 index 0000000..5c24c9b --- /dev/null +++ b/.history/package_20250416143445.json @@ -0,0 +1,57 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", diff --git a/.history/package_20250416143449.json b/.history/package_20250416143449.json new file mode 100644 index 0000000..35f42c5 --- /dev/null +++ b/.history/package_20250416143449.json @@ -0,0 +1,72 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "^15.2.4", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250419080200.json b/.history/package_20250419080200.json new file mode 100644 index 0000000..7aec747 --- /dev/null +++ b/.history/package_20250419080200.json @@ -0,0 +1,72 @@ +{{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250419081600.json b/.history/package_20250419081600.json new file mode 100644 index 0000000..54d6e61 --- /dev/null +++ b/.history/package_20250419081600.json @@ -0,0 +1,72 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + "prepare": "husky install" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250419124449.json b/.history/package_20250419124449.json new file mode 100644 index 0000000..e09a981 --- /dev/null +++ b/.history/package_20250419124449.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test", + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250419124537.json b/.history/package_20250419124537.json new file mode 100644 index 0000000..2a02019 --- /dev/null +++ b/.history/package_20250419124537.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.4.16", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "postcss": "^8.4.32", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "tailwindcss": "^3.4.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250419161722.json b/.history/package_20250419161722.json new file mode 100644 index 0000000..0b1726c --- /dev/null +++ b/.history/package_20250419161722.json @@ -0,0 +1,89 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "zod": "^3.22.0", + "tailwindcss": "^3.4.0", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250505224202.json b/.history/package_20250505224202.json new file mode 100644 index 0000000..5c9197f --- /dev/null +++ b/.history/package_20250505224202.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "autoprefixer": "^10.4.16", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "postcss": "^8.4.32", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "tailwindcss": "^3.4.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250505224639.json b/.history/package_20250505224639.json new file mode 100644 index 0000000..adbdb62 --- /dev/null +++ b/.history/package_20250505224639.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "autoprefixer": "^10.4.16", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "postcss": "^8.4.32", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "tailwindcss": "^3.4.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "eslint": "^8.56.0", + "eslint-config-next": "14.2.3", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/package_20250505224647.json b/.history/package_20250505224647.json new file mode 100644 index 0000000..8ecd15d --- /dev/null +++ b/.history/package_20250505224647.json @@ -0,0 +1,71 @@ +{ + "name": "basednet", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "db:migrate": "node scripts/migrate.js", + "db:seed": "node scripts/seed.js", + "setup": "node scripts/setup.js", + "setup:db": "node scripts/setup-db.js", + "setup:auth": "node scripts/setup-indieauth.js", + "setup:ipfs": "node scripts/setup-ipfs.js", + "setup:monitoring": "node scripts/setup-monitoring.js", + "setup:github": "node scripts/setup-github-deploy.js", + "setup:github:finalize": "node scripts/finalize-deployment-setup.js", + "check:env": "node scripts/check-env.js", + "check:launch": "node scripts/pre-launch-check.js", + "check:deployment": "node scripts/deployment-ready.js", + "deploy": "node scripts/deploy-vercel.js", + "deploy:github": "git push origin main", + "security:audit": "npm audit && npx snyk test" + }, + "dependencies": { + "@sentry/nextjs": "^7.120.3", + "@upstash/ratelimit": "^2.0.5", + "@upstash/redis": "^1.34.5", + "autoprefixer": "^10.4.16", + "cors": "^2.8.5", + "dotenv": "^16.4.7", + "firebase": "^11.4.0", + "firebase-admin": "^13.2.0", + "helmet": "^7.0.0", + "ipfs-http-client": "^56.0.0", + "next": "14.2.3", + "next-auth": "^4.24.5", + "pg": "^8.7.1", + "postcss": "^8.4.32", + "rate-limiter-flexible": "^3.0.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "tailwindcss": "^3.4.0", + "zod": "^3.22.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.1.0", + "@testing-library/react": "^14.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.0", + "@types/pg": "^8.11.11", + "@types/react": "^18.3.0", + "@types/react-dom": "^18.3.0", + "eslint": "^8.56.0", + "eslint-config-next": "14.2.3", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^15.0.0", + "msw": "^2.0.0", + "prettier": "^3.0.0", + "snyk": "^1.0.0", + "ts-jest": "^29.1.0", + "typescript": "^5.3.0" + } +} diff --git a/.history/scripts/deploy-vercel_20250318220349.js b/.history/scripts/deploy-vercel_20250318220349.js new file mode 100644 index 0000000..a085334 --- /dev/null +++ b/.history/scripts/deploy-vercel_20250318220349.js @@ -0,0 +1,157 @@ +const readline = require('readline'); +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + const childProcess = exec(command); + + childProcess.stdout.pipe(process.stdout); + childProcess.stderr.pipe(process.stderr); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + }); +} + +// Function to check if Vercel CLI is installed +async function checkVercelCli() { + try { + await runCommand('vercel --version'); + return true; + } catch (error) { + return false; + } +} + +// Main function +async function deployToVercel() { + console.log('BasedNet Vercel Deployment'); + console.log('========================='); + console.log('This script will help you deploy BasedNet to Vercel.'); + console.log(); + + // Check if Vercel CLI is installed + const vercelCliInstalled = await checkVercelCli(); + if (!vercelCliInstalled) { + console.log('Vercel CLI is not installed. Installing...'); + try { + await runCommand('npm install -g vercel'); + } catch (error) { + console.error('Error installing Vercel CLI:', error); + console.log('Please install Vercel CLI manually: npm install -g vercel'); + rl.close(); + return; + } + } + + // Check if user is logged in to Vercel + console.log('Checking Vercel login status...'); + rl.question('Do you need to log in to Vercel? (y/n): ', async (needLogin) => { + if (needLogin.toLowerCase() === 'y') { + try { + await runCommand('vercel login'); + } catch (error) { + console.error('Error logging in to Vercel:', error); + rl.close(); + return; + } + } + + // Ask about environment variables + console.log(); + console.log('Environment Variables'); + console.log('--------------------'); + console.log('BasedNet requires several environment variables to be set in Vercel.'); + console.log('You can set them up now or later in the Vercel dashboard.'); + + rl.question('Do you want to set up environment variables now? (y/n): ', async (setupEnv) => { + if (setupEnv.toLowerCase() === 'y') { + console.log('Please make sure your .env file is properly configured.'); + console.log('The script will read values from your .env file.'); + + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('.env file not found. Please run npm run setup first.'); + rl.close(); + return; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const envLines = envContent.split('\n'); + + for (const line of envLines) { + if (line.trim() && !line.startsWith('#')) { + const [key, value] = line.split('='); + if (key && value) { + const trimmedKey = key.trim(); + const trimmedValue = value.trim().replace(/^"(.*)"$/, '$1'); + + if (trimmedValue) { + try { + await runCommand(`vercel env add ${trimmedKey} production`); + } catch (error) { + console.error(`Error setting environment variable ${trimmedKey}:`, error); + } + } + } + } + } + } else { + console.log('Skipping environment variables setup. You can set them up later in the Vercel dashboard.'); + } + + // Deploy to Vercel + console.log(); + console.log('Deploying to Vercel'); + console.log('------------------'); + + rl.question('Do you want to deploy to Vercel now? (y/n): ', async (deploy) => { + if (deploy.toLowerCase() === 'y') { + try { + await runCommand('vercel --prod'); + + console.log(); + console.log('🎉 Deployment complete!'); + console.log(); + console.log('Your application is now live! You can access it at:'); + console.log('- The Vercel URL shown above in the deployment output'); + console.log('- Your Vercel dashboard: https://vercel.com/dashboard'); + console.log(' (Click on your project, then the "Visit" button)'); + console.log(); + console.log('Next steps:'); + console.log('1. Set up your custom domain in the Vercel dashboard'); + console.log('2. Configure any remaining environment variables'); + console.log('3. Verify all services are working correctly'); + console.log(); + console.log('For more information on accessing and verifying your deployment,'); + console.log('see the "Accessing Your Deployed Application" section in DEPLOYMENT.md'); + } catch (error) { + console.error('Error deploying to Vercel:', error); + } + } else { + console.log('Skipping deployment. You can deploy later with: vercel --prod'); + } + + rl.close(); + }); + }); + }); +} + +// Run the deployment +deployToVercel(); diff --git a/.history/scripts/deploy-vercel_20250419075347.js b/.history/scripts/deploy-vercel_20250419075347.js new file mode 100644 index 0000000..9d4da3e --- /dev/null +++ b/.history/scripts/deploy-vercel_20250419075347.js @@ -0,0 +1,166 @@ +const readline = require('readline'); +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); // Pipe to console + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); // Pipe to console + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`Command failed with exit code ${code}\nStdout: ${stdout}\nStderr: ${stderr}`)); + } + }); + }); +} + +// Function to check if Vercel CLI is installed +async function checkVercelCli() { + try { + await runCommand('vercel --version'); + return true; + } catch (error) { + return false; + } +} + +// Main function +async function deployToVercel() { + console.log('BasedNet Vercel Deployment'); + console.log('========================='); + console.log('This script will help you deploy BasedNet to Vercel.'); + console.log(); + + // Check if Vercel CLI is installed + const vercelCliInstalled = await checkVercelCli(); + if (!vercelCliInstalled) { + console.log('Vercel CLI is not installed. Installing...'); + try { + await runCommand('npm install -g vercel'); + } catch (error) { + console.error('Error installing Vercel CLI:', error); + console.log('Please install Vercel CLI manually: npm install -g vercel'); + rl.close(); + return; + } + } + + // Check if user is logged in to Vercel + console.log('Checking Vercel login status...'); + rl.question('Do you need to log in to Vercel? (y/n): ', async (needLogin) => { + if (needLogin.toLowerCase() === 'y') { + try { + await runCommand('vercel login'); + } catch (error) { + console.error('Error logging in to Vercel:', error); + rl.close(); + return; + } + } + + // Ask about environment variables + console.log(); + console.log('Environment Variables'); + console.log('--------------------'); + console.log('BasedNet requires several environment variables to be set in Vercel.'); + console.log('You can set them up now or later in the Vercel dashboard.'); + + rl.question('Do you want to set up environment variables now? (y/n): ', async (setupEnv) => { + if (setupEnv.toLowerCase() === 'y') { + console.log('Please make sure your .env file is properly configured.'); + console.log('The script will read values from your .env file.'); + + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('.env file not found. Please run npm run setup first.'); + rl.close(); + return; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const envLines = envContent.split('\n'); + + for (const line of envLines) { + if (line.trim() && !line.startsWith('#')) { + const [key, value] = line.split('='); + if (key && value) { + const trimmedKey = key.trim(); + const trimmedValue = value.trim().replace(/^"(.*)"$/, '$1'); + + if (trimmedValue) { + try { + await runCommand(`vercel env add ${trimmedKey} production`); + } catch (error) { + console.error(`Error setting environment variable ${trimmedKey}:`, error); + } + } + } + } + } + } else { + console.log('Skipping environment variables setup. You can set them up later in the Vercel dashboard.'); + } + + // Deploy to Vercel + console.log(); + console.log('Deploying to Vercel'); + console.log('------------------'); + + rl.question('Do you want to deploy to Vercel now? (y/n): ', async (deploy) => { + if (deploy.toLowerCase() === 'y') { + try { + await runCommand('vercel --prod'); + + console.log(); + console.log('🎉 Deployment complete!'); + console.log(); + console.log('Your application is now live! You can access it at:'); + console.log('- The Vercel URL shown above in the deployment output'); + console.log('- Your Vercel dashboard: https://vercel.com/dashboard'); + console.log(' (Click on your project, then the "Visit" button)'); + console.log(); + console.log('Next steps:'); + console.log('1. Set up your custom domain in the Vercel dashboard'); + console.log('2. Configure any remaining environment variables'); + console.log('3. Verify all services are working correctly'); + console.log(); + console.log('For more information on accessing and verifying your deployment,'); + console.log('see the "Accessing Your Deployed Application" section in DEPLOYMENT.md'); + } catch (error) { + console.error('Error deploying to Vercel:', error); + } + } else { + console.log('Skipping deployment. You can deploy later with: vercel --prod'); + } + + rl.close(); + }); + }); + }); +} + +// Run the deployment +deployToVercel(); diff --git a/.history/scripts/finalize-deployment-setup_20250416124339.js b/.history/scripts/finalize-deployment-setup_20250416124339.js new file mode 100644 index 0000000..e69de29 diff --git a/.history/scripts/finalize-deployment-setup_20250416124430.js b/.history/scripts/finalize-deployment-setup_20250416124430.js new file mode 100644 index 0000000..bf0d3a9 --- /dev/null +++ b/.history/scripts/finalize-deployment-setup_20250416124430.js @@ -0,0 +1,90 @@ +#!/usr/bin/env node +const { exec } = require('child_process'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + }); +} + +async function finalizeSetup() { + console.log('🚀 Finalizing BasedNet GitHub Deployment Setup'); + console.log('============================================'); + + try { + // Add all modified files + console.log('\nStep 1: Adding all deployment-related files to git'); + await runCommand('git add .github/workflows/ next.config.js vercel.json GITHUB_DEPLOYMENT.md package.json scripts/setup-github-deploy-fixed.js'); + console.log('✅ Files added to git'); + + // Commit changes + console.log('\nStep 2: Committing changes'); + await runCommand('git commit -m "Setup GitHub Actions workflow for Vercel deployment"'); + console.log('✅ Changes committed'); + + // Push to GitHub + console.log('\nStep 3: Pushing changes to GitHub'); + console.log('This will trigger the deployment workflow if you\'ve added the VERCEL_TOKEN secret to your GitHub repository'); + + rl.question('Push changes to GitHub now? (y/n): ', async (answer) => { + if (answer.toLowerCase() === 'y') { + try { + await runCommand('git push origin main'); + console.log('✅ Changes pushed to GitHub'); + console.log('\n🎉 Deployment setup complete!'); + console.log('\nNext steps:'); + console.log('1. Go to your GitHub repository: https://github.com/numbpill3d/basednet'); + console.log('2. Click on the "Actions" tab to monitor the deployment'); + console.log('3. Once deployment is complete, your site will be available at your Vercel URL'); + } catch (error) { + console.error('❌ Failed to push changes:', error.message); + console.log('You can push manually with: git push origin main'); + } + rl.close(); + } else { + console.log('You can push the changes later with: git push origin main'); + console.log('\nWhen you\'re ready to deploy, run: npm run deploy:github'); + rl.close(); + } + }); + } catch (error) { + console.error('❌ Setup finalization failed:', error.message); + console.log('You can try the steps manually:'); + console.log('1. git add .github/workflows/ next.config.js vercel.json GITHUB_DEPLOYMENT.md'); + console.log('2. git commit -m "Setup GitHub Actions workflow for Vercel deployment"'); + console.log('3. git push origin main'); + rl.close(); + } +} + +finalizeSetup(); \ No newline at end of file diff --git a/.history/scripts/fix-case-sensitivity_20250420050827.js b/.history/scripts/fix-case-sensitivity_20250420050827.js new file mode 100644 index 0000000..e69de29 diff --git a/.history/scripts/fix-case-sensitivity_20250420050841.js b/.history/scripts/fix-case-sensitivity_20250420050841.js new file mode 100644 index 0000000..1fcd571 --- /dev/null +++ b/.history/scripts/fix-case-sensitivity_20250420050841.js @@ -0,0 +1,129 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const { exec } = require('child_process'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}\nStdout: ${stdout}\nStderr: ${stderr}`)); + } + }); + }); +} + +// Function to find all TypeScript/JavaScript files +function findSourceFiles(dir, fileList = []) { + const files = fs.readdirSync(dir); + + files.forEach(file => { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + findSourceFiles(filePath, fileList); + } else if (/\.(ts|tsx|js|jsx)$/.test(file)) { + fileList.push(filePath); + } + }); + + return fileList; +} + +// Function to extract import statements from a file +function extractImports(filePath) { + const content = fs.readFileSync(filePath, 'utf8'); + const imports = []; + + // Match both relative imports and alias imports + const importRegex = /import\s+.*from\s+['"]([^'"]+)['"]/g; + let match; + + while ((match = importRegex.exec(content)) !== null) { + const importPath = match[1]; + + // Skip node_modules imports and absolute imports + if (!importPath.startsWith('.') && !importPath.startsWith('@/')) { + continue; + } + + imports.push({ + importPath, + sourceFile: filePath + }); + } + + return imports; +} + +// Function to resolve the real path on disk +function resolveRealPath(importPath, sourceFile) { + // Handle @/ alias + if (importPath.startsWith('@/')) { + return path.join(process.cwd(), 'src', importPath.substring(2)); + } + + // Handle relative imports + const sourceDir = path.dirname(sourceFile); + return path.join(sourceDir, importPath); +} + +// Function to check if a path exists (case-sensitive) +function pathExistsWithCorrectCase(pathToCheck) { + // Split the path into parts + const parts = pathToCheck.split(path.sep); + let currentPath = ''; + + // Check each part of the path + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + + // Skip empty parts (e.g., leading or trailing slashes) + if (!part) continue; + + // Add separator if not the first part + if (currentPath) { + currentPath = path.join(currentPath, part); + } else { + currentPath = part; + } + + // If this part doesn't exist, return false + if (!fs.existsSync(currentPath)) { + return { exists: false }; + } + + // Check if the case matches + const dir = path.dirname(currentPath); + const base = path.basename(currentPath); + + // Skip if we're at the root + if (dir === currentPath) continue; + diff --git a/.history/scripts/fix-case-sensitivity_20250420050843.js b/.history/scripts/fix-case-sensitivity_20250420050843.js new file mode 100644 index 0000000..2113143 --- /dev/null +++ b/.history/scripts/fix-case-sensitivity_20250420050843.js @@ -0,0 +1,134 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const { exec } = require('child_process'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}\nStdout: ${stdout}\nStderr: ${stderr}`)); + } + }); + }); +} + +// Function to find all TypeScript/JavaScript files +function findSourceFiles(dir, fileList = []) { + const files = fs.readdirSync(dir); + + files.forEach(file => { + const filePath = path.join(dir, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + findSourceFiles(filePath, fileList); + } else if (/\.(ts|tsx|js|jsx)$/.test(file)) { + fileList.push(filePath); + } + }); + + return fileList; +} + +// Function to extract import statements from a file +function extractImports(filePath) { + const content = fs.readFileSync(filePath, 'utf8'); + const imports = []; + + // Match both relative imports and alias imports + const importRegex = /import\s+.*from\s+['"]([^'"]+)['"]/g; + let match; + + while ((match = importRegex.exec(content)) !== null) { + const importPath = match[1]; + + // Skip node_modules imports and absolute imports + if (!importPath.startsWith('.') && !importPath.startsWith('@/')) { + continue; + } + + imports.push({ + importPath, + sourceFile: filePath + }); + } + + return imports; +} + +// Function to resolve the real path on disk +function resolveRealPath(importPath, sourceFile) { + // Handle @/ alias + if (importPath.startsWith('@/')) { + return path.join(process.cwd(), 'src', importPath.substring(2)); + } + + // Handle relative imports + const sourceDir = path.dirname(sourceFile); + return path.join(sourceDir, importPath); +} + +// Function to check if a path exists (case-sensitive) +function pathExistsWithCorrectCase(pathToCheck) { + // Split the path into parts + const parts = pathToCheck.split(path.sep); + let currentPath = ''; + + // Check each part of the path + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + + // Skip empty parts (e.g., leading or trailing slashes) + if (!part) continue; + + // Add separator if not the first part + if (currentPath) { + currentPath = path.join(currentPath, part); + } else { + currentPath = part; + } + + // If this part doesn't exist, return false + if (!fs.existsSync(currentPath)) { + return { exists: false }; + } + + // Check if the case matches + const dir = path.dirname(currentPath); + const base = path.basename(currentPath); + + // Skip if we're at the root + if (dir === currentPath) continue; + + // Get the actual case from the directory listing + try { + const entries = fs.readdirSync(dir); + const actualCase = entries.find(entry => entry.toLowerCase() === base.toLowerCase()); + diff --git a/.history/scripts/pre-launch-check_20250318200801.js b/.history/scripts/pre-launch-check_20250318200801.js new file mode 100644 index 0000000..20fcf3a --- /dev/null +++ b/.history/scripts/pre-launch-check_20250318200801.js @@ -0,0 +1,258 @@ +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error: ${error.message}`); + return reject(error); + } + resolve({ stdout, stderr }); + }); + }); +} + +// Function to check if a file exists +function fileExists(filePath) { + return fs.existsSync(path.join(__dirname, '..', filePath)); +} + +// Function to check environment variables +async function checkEnvironment() { + console.log('\n📋 Checking environment variables...'); + try { + const { stdout } = await runCommand('npm run check:env'); + console.log(stdout); + return !stdout.includes('Missing') && !stdout.includes('Empty'); + } catch (error) { + console.error('Failed to check environment variables.'); + return false; + } +} + +// Function to check database connection +async function checkDatabase() { + console.log('\n📋 Checking database connection...'); + + // Check if .env file exists and has database configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + try { + // Create a simple test script to check database connection + const testScript = ` + const { Pool } = require('pg'); + require('dotenv').config(); + + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, + }); + + async function testConnection() { + try { + const client = await pool.connect(); + const result = await client.query('SELECT NOW()'); + client.release(); + console.log('✅ Database connection successful'); + return true; + } catch (error) { + console.error('❌ Database connection failed:', error.message); + return false; + } finally { + await pool.end(); + } + } + + testConnection(); + `; + + const testScriptPath = path.join(__dirname, 'temp-db-test.js'); + fs.writeFileSync(testScriptPath, testScript); + + try { + const { stdout } = await runCommand('node ' + testScriptPath); + console.log(stdout); + const success = stdout.includes('Database connection successful'); + + // Clean up + fs.unlinkSync(testScriptPath); + + return success; + } catch (error) { + // Clean up + if (fs.existsSync(testScriptPath)) { + fs.unlinkSync(testScriptPath); + } + console.error('❌ Failed to test database connection:', error.message); + return false; + } + } catch (error) { + console.error('❌ Failed to check database:', error.message); + return false; + } +} + +// Function to check IPFS configuration +async function checkIpfs() { + console.log('\n📋 Checking IPFS configuration...'); + + // Check if .env file exists and has IPFS configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIpfsProjectId = envContent.includes('IPFS_PROJECT_ID=') && !envContent.includes('IPFS_PROJECT_ID=""'); + const hasIpfsProjectSecret = envContent.includes('IPFS_PROJECT_SECRET=') && !envContent.includes('IPFS_PROJECT_SECRET=""'); + + if (hasIpfsProjectId && hasIpfsProjectSecret) { + console.log('✅ IPFS configuration found'); + return true; + } else { + console.error('❌ IPFS configuration incomplete. Please run npm run setup:ipfs'); + return false; + } +} + +// Function to check authentication configuration +async function checkAuth() { + console.log('\n📋 Checking authentication configuration...'); + + // Check if .env file exists and has authentication configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIndieAuthClientId = envContent.includes('INDIE_AUTH_CLIENT_ID=') && !envContent.includes('INDIE_AUTH_CLIENT_ID=""'); + const hasIndieAuthClientSecret = envContent.includes('INDIE_AUTH_CLIENT_SECRET=') && !envContent.includes('INDIE_AUTH_CLIENT_SECRET=""'); + const hasNextAuthSecret = envContent.includes('NEXTAUTH_SECRET=') && !envContent.includes('NEXTAUTH_SECRET=""'); + + if (hasIndieAuthClientId && hasIndieAuthClientSecret && hasNextAuthSecret) { + console.log('✅ Authentication configuration found'); + return true; + } else { + console.error('❌ Authentication configuration incomplete. Please run npm run setup:auth'); + return false; + } +} + +// Function to check if the application builds successfully +async function checkBuild() { + console.log('\n📋 Checking if the application builds successfully...'); + + try { + console.log('Building the application (this may take a moment)...'); + await runCommand('npm run build'); + console.log('✅ Application builds successfully'); + return true; + } catch (error) { + console.error('❌ Application build failed:', error.message); + return false; + } +} + +// Function to check security +async function checkSecurity() { + console.log('\n📋 Checking security...'); + + try { + console.log('Running security audit...'); + const { stdout } = await runCommand('npm audit --json'); + + try { + const auditResult = JSON.parse(stdout); + const vulnerabilities = auditResult.vulnerabilities || {}; + const totalVulnerabilities = Object.values(vulnerabilities).reduce((sum, severity) => sum + severity, 0); + + if (totalVulnerabilities === 0) { + console.log('✅ No security vulnerabilities found'); + return true; + } else { + console.error(`❌ Found ${totalVulnerabilities} security vulnerabilities. Please run npm audit fix`); + return false; + } + } catch (parseError) { + console.error('❌ Failed to parse audit results:', parseError.message); + return false; + } + } catch (error) { + console.error('❌ Security audit failed:', error.message); + return false; + } +} + +// Main function +async function runPreLaunchCheck() { + console.log('🚀 BasedNet Pre-Launch Checklist'); + console.log('=============================='); + + let allChecksPass = true; + + // Check environment variables + const envCheck = await checkEnvironment(); + allChecksPass = allChecksPass && envCheck; + + // Check database connection + const dbCheck = await checkDatabase(); + allChecksPass = allChecksPass && dbCheck; + + // Check IPFS configuration + const ipfsCheck = await checkIpfs(); + allChecksPass = allChecksPass && ipfsCheck; + + // Check authentication configuration + const authCheck = await checkAuth(); + allChecksPass = allChecksPass && authCheck; + + // Check if the application builds successfully + const buildCheck = await checkBuild(); + allChecksPass = allChecksPass && buildCheck; + + // Check security + const securityCheck = await checkSecurity(); + allChecksPass = allChecksPass && securityCheck; + + // Summary + console.log('\n📋 Pre-Launch Checklist Summary'); + console.log('-----------------------------'); + console.log(`Environment Variables: ${envCheck ? '✅' : '❌'}`); + console.log(`Database Connection: ${dbCheck ? '✅' : '❌'}`); + console.log(`IPFS Configuration: ${ipfsCheck ? '✅' : '❌'}`); + console.log(`Authentication Configuration: ${authCheck ? '✅' : '❌'}`); + console.log(`Application Build: ${buildCheck ? '✅' : '❌'}`); + console.log(`Security Check: ${securityCheck ? '✅' : '❌'}`); + + if (allChecksPass) { + console.log('\n🎉 All checks passed! BasedNet is ready for launch.'); + console.log('\nNext steps:'); + console.log('1. Deploy to production: npm run deploy'); + console.log('2. Set up your custom domain'); + console.log('3. Configure monitoring and analytics'); + } else { + console.log('\n⚠️ Some checks failed. Please address the issues before launching.'); + } + + rl.close(); +} + +// Run the pre-launch check +runPreLaunchCheck(); diff --git a/.history/scripts/pre-launch-check_20250405022642.js b/.history/scripts/pre-launch-check_20250405022642.js new file mode 100644 index 0000000..629e75d --- /dev/null +++ b/.history/scripts/pre-launch-check_20250405022642.js @@ -0,0 +1,258 @@ +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error: ${error.message}`); + return reject(error); + } + resolve({ stdout, stderr }); + }); + }); +} + +// Function to check if a file exists +function fileExists(filePath) { + return fs.existsSync(path.join(__dirname, '..', filePath)); +} + +// Function to check environment variables +async function checkEnvironment() { + console.log('\n📋 Checking environment variables...'); + try { + const { stdout } = await runCommand('npm run check:env'); + console.log(stdout); + return !stdout.includes('Missing') && !stdout.includes('Empty'); + } catch (error) { + console.error('Failed to check environment variables.'); + return false; + } +} + +// Function to check database connection +async function checkDatabase() { + console.log('\n📋 Checking database connection...'); + + // Check if .env file exists and has database configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + try { + // Create a simple test script to check database connection + const testScript = ` + const { Pool } = require('pg'); + require('dotenv').config(); + + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, + }); + + async function testConnection() { + try { + const client = await pool.connect(); + const result = await client.query('SELECT NOW()'); + client.release(); + console.log('✅ Database connection successful'); + return true; + } catch (error) { + console.error('❌ Database connection failed:', error.message); + return false; + } finally { + await pool.end(); + } + } + + testConnection(); + `; + + const testScriptPath = 'temp-db-test.js'; // Relative path + fs.writeFileSync(path.join(__dirname, testScriptPath), testScript); // Write in script directory + + try { + const { stdout } = await runCommand('node ' + testScriptPath); // Execute with relative path + console.log(stdout); + const success = stdout.includes('Database connection successful'); + + // Clean up + fs.unlinkSync(testScriptPath); + + return success; + } catch (error) { + // Clean up + if (fs.existsSync(testScriptPath)) { + fs.unlinkSync(testScriptPath); + } + console.error('❌ Failed to test database connection:', error.message); + return false; + } + } catch (error) { + console.error('❌ Failed to check database:', error.message); + return false; + } +} + +// Function to check IPFS configuration +async function checkIpfs() { + console.log('\n📋 Checking IPFS configuration...'); + + // Check if .env file exists and has IPFS configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIpfsProjectId = envContent.includes('IPFS_PROJECT_ID=') && !envContent.includes('IPFS_PROJECT_ID=""'); + const hasIpfsProjectSecret = envContent.includes('IPFS_PROJECT_SECRET=') && !envContent.includes('IPFS_PROJECT_SECRET=""'); + + if (hasIpfsProjectId && hasIpfsProjectSecret) { + console.log('✅ IPFS configuration found'); + return true; + } else { + console.error('❌ IPFS configuration incomplete. Please run npm run setup:ipfs'); + return false; + } +} + +// Function to check authentication configuration +async function checkAuth() { + console.log('\n📋 Checking authentication configuration...'); + + // Check if .env file exists and has authentication configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIndieAuthClientId = envContent.includes('INDIE_AUTH_CLIENT_ID=') && !envContent.includes('INDIE_AUTH_CLIENT_ID=""'); + const hasIndieAuthClientSecret = envContent.includes('INDIE_AUTH_CLIENT_SECRET=') && !envContent.includes('INDIE_AUTH_CLIENT_SECRET=""'); + const hasNextAuthSecret = envContent.includes('NEXTAUTH_SECRET=') && !envContent.includes('NEXTAUTH_SECRET=""'); + + if (hasIndieAuthClientId && hasIndieAuthClientSecret && hasNextAuthSecret) { + console.log('✅ Authentication configuration found'); + return true; + } else { + console.error('❌ Authentication configuration incomplete. Please run npm run setup:auth'); + return false; + } +} + +// Function to check if the application builds successfully +async function checkBuild() { + console.log('\n📋 Checking if the application builds successfully...'); + + try { + console.log('Building the application (this may take a moment)...'); + await runCommand('npm run build'); + console.log('✅ Application builds successfully'); + return true; + } catch (error) { + console.error('❌ Application build failed:', error.message); + return false; + } +} + +// Function to check security +async function checkSecurity() { + console.log('\n📋 Checking security...'); + + try { + console.log('Running security audit...'); + const { stdout } = await runCommand('npm audit --json'); + + try { + const auditResult = JSON.parse(stdout); + const vulnerabilities = auditResult.vulnerabilities || {}; + const totalVulnerabilities = Object.values(vulnerabilities).reduce((sum, severity) => sum + severity, 0); + + if (totalVulnerabilities === 0) { + console.log('✅ No security vulnerabilities found'); + return true; + } else { + console.error(`❌ Found ${totalVulnerabilities} security vulnerabilities. Please run npm audit fix`); + return false; + } + } catch (parseError) { + console.error('❌ Failed to parse audit results:', parseError.message); + return false; + } + } catch (error) { + console.error('❌ Security audit failed:', error.message); + return false; + } +} + +// Main function +async function runPreLaunchCheck() { + console.log('🚀 BasedNet Pre-Launch Checklist'); + console.log('=============================='); + + let allChecksPass = true; + + // Check environment variables + const envCheck = await checkEnvironment(); + allChecksPass = allChecksPass && envCheck; + + // Check database connection + const dbCheck = await checkDatabase(); + allChecksPass = allChecksPass && dbCheck; + + // Check IPFS configuration + const ipfsCheck = await checkIpfs(); + allChecksPass = allChecksPass && ipfsCheck; + + // Check authentication configuration + const authCheck = await checkAuth(); + allChecksPass = allChecksPass && authCheck; + + // Check if the application builds successfully + const buildCheck = await checkBuild(); + allChecksPass = allChecksPass && buildCheck; + + // Check security + const securityCheck = await checkSecurity(); + allChecksPass = allChecksPass && securityCheck; + + // Summary + console.log('\n📋 Pre-Launch Checklist Summary'); + console.log('-----------------------------'); + console.log(`Environment Variables: ${envCheck ? '✅' : '❌'}`); + console.log(`Database Connection: ${dbCheck ? '✅' : '❌'}`); + console.log(`IPFS Configuration: ${ipfsCheck ? '✅' : '❌'}`); + console.log(`Authentication Configuration: ${authCheck ? '✅' : '❌'}`); + console.log(`Application Build: ${buildCheck ? '✅' : '❌'}`); + console.log(`Security Check: ${securityCheck ? '✅' : '❌'}`); + + if (allChecksPass) { + console.log('\n🎉 All checks passed! BasedNet is ready for launch.'); + console.log('\nNext steps:'); + console.log('1. Deploy to production: npm run deploy'); + console.log('2. Set up your custom domain'); + console.log('3. Configure monitoring and analytics'); + } else { + console.log('\n⚠️ Some checks failed. Please address the issues before launching.'); + } + + rl.close(); +} + +// Run the pre-launch check +runPreLaunchCheck(); diff --git a/.history/scripts/pre-launch-check_20250405023017.js b/.history/scripts/pre-launch-check_20250405023017.js new file mode 100644 index 0000000..405b10c --- /dev/null +++ b/.history/scripts/pre-launch-check_20250405023017.js @@ -0,0 +1,258 @@ +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error: ${error.message}`); + return reject(error); + } + resolve({ stdout, stderr }); + }); + }); +} + +// Function to check if a file exists +function fileExists(filePath) { + return fs.existsSync(path.join(__dirname, '..', filePath)); +} + +// Function to check environment variables +async function checkEnvironment() { + console.log('\n📋 Checking environment variables...'); + try { + const { stdout } = await runCommand('npm run check:env'); + console.log(stdout); + return !stdout.includes('Missing') && !stdout.includes('Empty'); + } catch (error) { + console.error('Failed to check environment variables.'); + return false; + } +} + +// Function to check database connection +async function checkDatabase() { + console.log('\n📋 Checking database connection...'); + + // Check if .env file exists and has database configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + try { + // Create a simple test script to check database connection + const testScript = ` + const { Pool } = require('pg'); + require('dotenv').config(); + + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, + }); + + async function testConnection() { + try { + const client = await pool.connect(); + const result = await client.query('SELECT NOW()'); + client.release(); + console.log('✅ Database connection successful'); + return true; + } catch (error) { + console.error('❌ Database connection failed:', error.message); + return false; + } finally { + await pool.end(); + } + } + + testConnection(); + `; + + const testScriptPath = 'temp-db-test.js'; // Relative path + fs.writeFileSync(path.join(__dirname, testScriptPath), testScript); // Write in script directory + + try { + const { stdout } = await runCommand(`node ${testScriptPath}`, { cwd: __dirname }); // Execute with relative path and cwd + console.log(stdout); + const success = stdout.includes('Database connection successful'); + + // Clean up + fs.unlinkSync(testScriptPath); + + return success; + } catch (error) { + // Clean up + if (fs.existsSync(testScriptPath)) { + fs.unlinkSync(testScriptPath); + } + console.error('❌ Failed to test database connection:', error.message); + return false; + } + } catch (error) { + console.error('❌ Failed to check database:', error.message); + return false; + } +} + +// Function to check IPFS configuration +async function checkIpfs() { + console.log('\n📋 Checking IPFS configuration...'); + + // Check if .env file exists and has IPFS configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIpfsProjectId = envContent.includes('IPFS_PROJECT_ID=') && !envContent.includes('IPFS_PROJECT_ID=""'); + const hasIpfsProjectSecret = envContent.includes('IPFS_PROJECT_SECRET=') && !envContent.includes('IPFS_PROJECT_SECRET=""'); + + if (hasIpfsProjectId && hasIpfsProjectSecret) { + console.log('✅ IPFS configuration found'); + return true; + } else { + console.error('❌ IPFS configuration incomplete. Please run npm run setup:ipfs'); + return false; + } +} + +// Function to check authentication configuration +async function checkAuth() { + console.log('\n📋 Checking authentication configuration...'); + + // Check if .env file exists and has authentication configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIndieAuthClientId = envContent.includes('INDIE_AUTH_CLIENT_ID=') && !envContent.includes('INDIE_AUTH_CLIENT_ID=""'); + const hasIndieAuthClientSecret = envContent.includes('INDIE_AUTH_CLIENT_SECRET=') && !envContent.includes('INDIE_AUTH_CLIENT_SECRET=""'); + const hasNextAuthSecret = envContent.includes('NEXTAUTH_SECRET=') && !envContent.includes('NEXTAUTH_SECRET=""'); + + if (hasIndieAuthClientId && hasIndieAuthClientSecret && hasNextAuthSecret) { + console.log('✅ Authentication configuration found'); + return true; + } else { + console.error('❌ Authentication configuration incomplete. Please run npm run setup:auth'); + return false; + } +} + +// Function to check if the application builds successfully +async function checkBuild() { + console.log('\n📋 Checking if the application builds successfully...'); + + try { + console.log('Building the application (this may take a moment)...'); + await runCommand('npm run build'); + console.log('✅ Application builds successfully'); + return true; + } catch (error) { + console.error('❌ Application build failed:', error.message); + return false; + } +} + +// Function to check security +async function checkSecurity() { + console.log('\n📋 Checking security...'); + + try { + console.log('Running security audit...'); + const { stdout } = await runCommand('npm audit --json'); + + try { + const auditResult = JSON.parse(stdout); + const vulnerabilities = auditResult.vulnerabilities || {}; + const totalVulnerabilities = Object.values(vulnerabilities).reduce((sum, severity) => sum + severity, 0); + + if (totalVulnerabilities === 0) { + console.log('✅ No security vulnerabilities found'); + return true; + } else { + console.error(`❌ Found ${totalVulnerabilities} security vulnerabilities. Please run npm audit fix`); + return false; + } + } catch (parseError) { + console.error('❌ Failed to parse audit results:', parseError.message); + return false; + } + } catch (error) { + console.error('❌ Security audit failed:', error.message); + return false; + } +} + +// Main function +async function runPreLaunchCheck() { + console.log('🚀 BasedNet Pre-Launch Checklist'); + console.log('=============================='); + + let allChecksPass = true; + + // Check environment variables + const envCheck = await checkEnvironment(); + allChecksPass = allChecksPass && envCheck; + + // Check database connection + const dbCheck = await checkDatabase(); + allChecksPass = allChecksPass && dbCheck; + + // Check IPFS configuration + const ipfsCheck = await checkIpfs(); + allChecksPass = allChecksPass && ipfsCheck; + + // Check authentication configuration + const authCheck = await checkAuth(); + allChecksPass = allChecksPass && authCheck; + + // Check if the application builds successfully + const buildCheck = await checkBuild(); + allChecksPass = allChecksPass && buildCheck; + + // Check security + const securityCheck = await checkSecurity(); + allChecksPass = allChecksPass && securityCheck; + + // Summary + console.log('\n📋 Pre-Launch Checklist Summary'); + console.log('-----------------------------'); + console.log(`Environment Variables: ${envCheck ? '✅' : '❌'}`); + console.log(`Database Connection: ${dbCheck ? '✅' : '❌'}`); + console.log(`IPFS Configuration: ${ipfsCheck ? '✅' : '❌'}`); + console.log(`Authentication Configuration: ${authCheck ? '✅' : '❌'}`); + console.log(`Application Build: ${buildCheck ? '✅' : '❌'}`); + console.log(`Security Check: ${securityCheck ? '✅' : '❌'}`); + + if (allChecksPass) { + console.log('\n🎉 All checks passed! BasedNet is ready for launch.'); + console.log('\nNext steps:'); + console.log('1. Deploy to production: npm run deploy'); + console.log('2. Set up your custom domain'); + console.log('3. Configure monitoring and analytics'); + } else { + console.log('\n⚠️ Some checks failed. Please address the issues before launching.'); + } + + rl.close(); +} + +// Run the pre-launch check +runPreLaunchCheck(); diff --git a/.history/scripts/pre-launch-check_20250405023311.js b/.history/scripts/pre-launch-check_20250405023311.js new file mode 100644 index 0000000..1f0ec34 --- /dev/null +++ b/.history/scripts/pre-launch-check_20250405023311.js @@ -0,0 +1,235 @@ +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Error: ${error.message}`); + return reject(error); + } + resolve({ stdout, stderr }); + }); + }); +} + +// Function to check if a file exists +function fileExists(filePath) { + return fs.existsSync(path.join(__dirname, '..', filePath)); +} + +// Function to check environment variables +async function checkEnvironment() { + console.log('\n📋 Checking environment variables...'); + try { + const { stdout } = await runCommand('npm run check:env'); + console.log(stdout); + return !stdout.includes('Missing') && !stdout.includes('Empty'); + } catch (error) { + console.error('Failed to check environment variables.'); + return false; + } +} + +// Function to check database connection +async function checkDatabase() { + console.log('\n📋 Checking database connection...'); + + // Check if .env file exists and has database configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + try { + // Directly test database connection + const { Pool } = require('pg'); + require('dotenv').config(); + + const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, + }); + + async function testConnection() { + try { + const client = await pool.connect(); + await client.query('SELECT NOW()'); + client.release(); + console.log('✅ Database connection successful'); + return true; + } catch (error) { + console.error('❌ Database connection failed:', error.message); + return false; + } finally { + await pool.end(); + } + } + + return await testConnection(); + } catch (error) { + console.error('❌ Failed to check database:', error.message); + return false; + } +} + +// Function to check IPFS configuration +async function checkIpfs() { + console.log('\n📋 Checking IPFS configuration...'); + + // Check if .env file exists and has IPFS configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIpfsProjectId = envContent.includes('IPFS_PROJECT_ID=') && !envContent.includes('IPFS_PROJECT_ID=""'); + const hasIpfsProjectSecret = envContent.includes('IPFS_PROJECT_SECRET=') && !envContent.includes('IPFS_PROJECT_SECRET=""'); + + if (hasIpfsProjectId && hasIpfsProjectSecret) { + console.log('✅ IPFS configuration found'); + return true; + } else { + console.error('❌ IPFS configuration incomplete. Please run npm run setup:ipfs'); + return false; + } +} + +// Function to check authentication configuration +async function checkAuth() { + console.log('\n📋 Checking authentication configuration...'); + + // Check if .env file exists and has authentication configuration + const envPath = path.join(__dirname, '../.env'); + if (!fs.existsSync(envPath)) { + console.error('❌ .env file not found. Please run npm run setup first.'); + return false; + } + + const envContent = fs.readFileSync(envPath, 'utf8'); + const hasIndieAuthClientId = envContent.includes('INDIE_AUTH_CLIENT_ID=') && !envContent.includes('INDIE_AUTH_CLIENT_ID=""'); + const hasIndieAuthClientSecret = envContent.includes('INDIE_AUTH_CLIENT_SECRET=') && !envContent.includes('INDIE_AUTH_CLIENT_SECRET=""'); + const hasNextAuthSecret = envContent.includes('NEXTAUTH_SECRET=') && !envContent.includes('NEXTAUTH_SECRET=""'); + + if (hasIndieAuthClientId && hasIndieAuthClientSecret && hasNextAuthSecret) { + console.log('✅ Authentication configuration found'); + return true; + } else { + console.error('❌ Authentication configuration incomplete. Please run npm run setup:auth'); + return false; + } +} + +// Function to check if the application builds successfully +async function checkBuild() { + console.log('\n📋 Checking if the application builds successfully...'); + + try { + console.log('Building the application (this may take a moment)...'); + await runCommand('npm run build'); + console.log('✅ Application builds successfully'); + return true; + } catch (error) { + console.error('❌ Application build failed:', error.message); + return false; + } +} + +// Function to check security +async function checkSecurity() { + console.log('\n📋 Checking security...'); + + try { + console.log('Running security audit...'); + const { stdout } = await runCommand('npm audit --json'); + + try { + const auditResult = JSON.parse(stdout); + const vulnerabilities = auditResult.vulnerabilities || {}; + const totalVulnerabilities = Object.values(vulnerabilities).reduce((sum, severity) => sum + severity, 0); + + if (totalVulnerabilities === 0) { + console.log('✅ No security vulnerabilities found'); + return true; + } else { + console.error(`❌ Found ${totalVulnerabilities} security vulnerabilities. Please run npm audit fix`); + return false; + } + } catch (parseError) { + console.error('❌ Failed to parse audit results:', parseError.message); + return false; + } + } catch (error) { + console.error('❌ Security audit failed:', error.message); + return false; + } +} + +// Main function +async function runPreLaunchCheck() { + console.log('🚀 BasedNet Pre-Launch Checklist'); + console.log('=============================='); + + let allChecksPass = true; + + // Check environment variables + const envCheck = await checkEnvironment(); + allChecksPass = allChecksPass && envCheck; + + // Check database connection + const dbCheck = await checkDatabase(); + allChecksPass = allChecksPass && dbCheck; + + // Check IPFS configuration + const ipfsCheck = await checkIpfs(); + allChecksPass = allChecksPass && ipfsCheck; + + // Check authentication configuration + const authCheck = await checkAuth(); + allChecksPass = allChecksPass && authCheck; + + // Check if the application builds successfully + const buildCheck = await checkBuild(); + allChecksPass = allChecksPass && buildCheck; + + // Check security + const securityCheck = await checkSecurity(); + allChecksPass = allChecksPass && securityCheck; + + // Summary + console.log('\n📋 Pre-Launch Checklist Summary'); + console.log('-----------------------------'); + console.log(`Environment Variables: ${envCheck ? '✅' : '❌'}`); + console.log(`Database Connection: ${dbCheck ? '✅' : '❌'}`); + console.log(`IPFS Configuration: ${ipfsCheck ? '✅' : '❌'}`); + console.log(`Authentication Configuration: ${authCheck ? '✅' : '❌'}`); + console.log(`Application Build: ${buildCheck ? '✅' : '❌'}`); + console.log(`Security Check: ${securityCheck ? '✅' : '❌'}`); + + if (allChecksPass) { + console.log('\n🎉 All checks passed! BasedNet is ready for launch.'); + console.log('\nNext steps:'); + console.log('1. Deploy to production: npm run deploy'); + console.log('2. Set up your custom domain'); + console.log('3. Configure monitoring and analytics'); + } else { + console.log('\n⚠️ Some checks failed. Please address the issues before launching.'); + } + + rl.close(); +} + +// Run the pre-launch check +runPreLaunchCheck(); diff --git a/.history/scripts/setup-github-deploy-fixed_20250416120933.js b/.history/scripts/setup-github-deploy-fixed_20250416120933.js new file mode 100644 index 0000000..e69de29 diff --git a/.history/scripts/setup-github-deploy-fixed_20250416121009.js b/.history/scripts/setup-github-deploy-fixed_20250416121009.js new file mode 100644 index 0000000..1406fe4 --- /dev/null +++ b/.history/scripts/setup-github-deploy-fixed_20250416121009.js @@ -0,0 +1,143 @@ +#!/usr/bin/env node +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + }); +} + +// Main function to set up GitHub deployment +async function setupGitHubDeploy() { + console.log('🚀 BasedNet GitHub Deployment Setup (Fixed Version)'); + console.log('=================================================='); + console.log('This script will help you set up GitHub Actions for deploying BasedNet to Vercel.'); + console.log(); + + try { + // Step 1: Verify Vercel CLI is installed and you're logged in + console.log('Step 1: Checking Vercel CLI installation and login status'); + try { + const { stdout } = await runCommand('vercel whoami'); + console.log(`✅ You are logged in to Vercel as: ${stdout.trim()}`); + } catch (error) { + console.log('⚠️ You need to log in to Vercel first.'); + console.log('Running: vercel login'); + await runCommand('vercel login'); + } + + // Step 2: Link project to Vercel (with --yes flag to avoid interactive prompts) + console.log('\nStep 2: Linking project to Vercel'); + try { + await runCommand('vercel link --yes'); + console.log('✅ Project linked to Vercel successfully.'); + } catch (error) { + console.error('❌ Failed to link project to Vercel:', error.message); + console.log('You can try manually with: vercel link --yes'); + } + + // Step 3: Generate Vercel token for GitHub Actions + console.log('\nStep 3: Setting up Vercel token for GitHub Actions'); + console.log('To deploy from GitHub Actions, you need to create a Vercel token:'); + console.log(' 1. Go to https://vercel.com/account/tokens'); + console.log(' 2. Click "Create" to create a new token'); + console.log(' 3. Name it "GitHub Actions" and set the scope to "Full Account"'); + console.log(' 4. Copy the generated token'); + + rl.question('\nDid you create and copy your Vercel token? (y/n): ', (answer) => { + if (answer.toLowerCase() === 'y') { + console.log('\nNow add this token to your GitHub repository:'); + console.log(' 1. Go to your GitHub repository: https://github.com/numbpill3d/basednet'); + console.log(' 2. Navigate to Settings → Secrets and variables → Actions'); + console.log(' 3. Click "New repository secret"'); + console.log(' 4. Name: VERCEL_TOKEN'); + console.log(' 5. Value: Paste your Vercel token'); + console.log(' 6. Click "Add secret"'); + + rl.question('\nDid you add the token to GitHub secrets? (y/n): ', async (addedSecret) => { + if (addedSecret.toLowerCase() === 'y') { + console.log('✅ Vercel token added to GitHub secrets.'); + + // Step 4: Push the workflow file to GitHub + console.log('\nStep 4: Pushing the GitHub Actions workflow file'); + console.log('The deployment workflow has been created at .github/workflows/vercel-deploy.yml'); + + rl.question('Do you want to commit and push the workflow file now? (y/n): ', async (pushNow) => { + if (pushNow.toLowerCase() === 'y') { + try { + await runCommand('git add .github/workflows/vercel-deploy.yml next.config.js vercel.json GITHUB_DEPLOYMENT.md'); + await runCommand('git commit -m "Add GitHub Actions workflow for Vercel deployment"'); + await runCommand('git push origin main'); + console.log('✅ Changes pushed to GitHub successfully.'); + finishSetup(); + } catch (error) { + console.error('❌ Failed to push changes:', error.message); + console.log('You can push manually with: git push origin main'); + finishSetup(); + } + } else { + console.log('You can push the changes later with: git add .github/ && git commit -m "Add GitHub Actions workflow" && git push origin main'); + finishSetup(); + } + }); + } else { + console.log('Please add the Vercel token to GitHub secrets before proceeding.'); + finishSetup(); + } + }); + } else { + console.log('Please create a Vercel token before proceeding with the deployment setup.'); + finishSetup(); + } + }); + } catch (error) { + console.error('❌ Setup failed:', error.message); + console.log('Please try again or follow the manual instructions in GITHUB_DEPLOYMENT.md'); + rl.close(); + } + + function finishSetup() { + console.log('\n🎉 GitHub Actions workflow for Vercel deployment is set up!'); + console.log('\nNext steps:'); + console.log('1. Ensure you\'ve pushed your workflow file to GitHub'); + console.log('2. Go to the Actions tab in your GitHub repository to monitor deployments'); + console.log('3. Set up your custom domain in the Vercel dashboard if needed'); + console.log('\nFor detailed instructions, see the GITHUB_DEPLOYMENT.md file.'); + rl.close(); + } +} + +// Run the setup +setupGitHubDeploy(); \ No newline at end of file diff --git a/.history/scripts/setup-github-deploy_20250416041424.js b/.history/scripts/setup-github-deploy_20250416041424.js new file mode 100644 index 0000000..e69de29 diff --git a/.history/scripts/setup-github-deploy_20250416041502.js b/.history/scripts/setup-github-deploy_20250416041502.js new file mode 100644 index 0000000..c57c4ce --- /dev/null +++ b/.history/scripts/setup-github-deploy_20250416041502.js @@ -0,0 +1,302 @@ +#!/usr/bin/env node +const { exec } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const readline = require('readline'); + +// Create readline interface +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +// Function to run a command +function runCommand(command) { + return new Promise((resolve, reject) => { + console.log(`Running: ${command}`); + let stdout = ''; + let stderr = ''; + + const childProcess = exec(command); + + childProcess.stdout.on('data', (data) => { + stdout += data; + process.stdout.write(data); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data; + process.stderr.write(data); + }); + + childProcess.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}`)); + } + }); + }); +} + +// Function to check if git is installed +async function checkGit() { + try { + await runCommand('git --version'); + return true; + } catch (error) { + return false; + } +} + +// Function to check if the directory is a git repository +async function isGitRepo() { + try { + await runCommand('git rev-parse --is-inside-work-tree'); + return true; + } catch (error) { + return false; + } +} + +// Function to check if Vercel CLI is installed +async function checkVercelCli() { + try { + await runCommand('vercel --version'); + return true; + } catch (error) { + return false; + } +} + +// Function to guide the user through setup +async function setupGitHubDeploy() { + console.log('🚀 BasedNet GitHub Deployment Setup'); + console.log('=================================='); + console.log('This script will help you set up GitHub Actions for deploying BasedNet to Vercel.'); + console.log(); + + // Check if git is installed + console.log('Checking if Git is installed...'); + const gitInstalled = await checkGit(); + if (!gitInstalled) { + console.error('❌ Git is not installed. Please install Git and try again.'); + console.log('You can download Git from: https://git-scm.com/downloads'); + rl.close(); + return; + } + console.log('✅ Git is installed.'); + + // Check if the directory is a git repository + console.log('\nChecking if the current directory is a Git repository...'); + const isRepo = await isGitRepo(); + if (!isRepo) { + console.log('⚠️ The current directory is not a Git repository.'); + rl.question('Do you want to initialize a Git repository? (y/n): ', async (initGit) => { + if (initGit.toLowerCase() === 'y') { + try { + await runCommand('git init'); + console.log('✅ Git repository initialized.'); + continueSetup(); + } catch (error) { + console.error('❌ Failed to initialize Git repository:', error); + rl.close(); + } + } else { + console.log('Please initialize a Git repository manually and run this script again.'); + rl.close(); + } + }); + } else { + console.log('✅ Current directory is a Git repository.'); + continueSetup(); + } + + async function continueSetup() { + console.log('\nChecking for GitHub remote...'); + try { + const { stdout } = await runCommand('git remote -v'); + const hasGitHubRemote = stdout.includes('github.com'); + + if (!hasGitHubRemote) { + console.log('⚠️ No GitHub remote found.'); + rl.question('Do you have a GitHub repository for this project? (y/n): ', (hasRepo) => { + if (hasRepo.toLowerCase() === 'y') { + rl.question('Please enter your GitHub repository URL: ', async (repoUrl) => { + try { + await runCommand(`git remote add origin ${repoUrl}`); + console.log('✅ GitHub remote added.'); + checkVercel(); + } catch (error) { + console.error('❌ Failed to add GitHub remote:', error); + rl.close(); + } + }); + } else { + console.log('\nYou need to create a GitHub repository for this project.'); + console.log('1. Go to https://github.com/new'); + console.log('2. Create a new repository'); + console.log('3. Follow the instructions to push an existing repository from the command line'); + console.log('\nAfter setting up your GitHub repository, run this script again.'); + rl.close(); + } + }); + } else { + console.log('✅ GitHub remote found.'); + checkVercel(); + } + } catch (error) { + console.error('❌ Failed to check Git remotes:', error); + rl.close(); + } + } + + async function checkVercel() { + console.log('\nChecking if Vercel CLI is installed...'); + const vercelCliInstalled = await checkVercelCli(); + + if (!vercelCliInstalled) { + console.log('⚠️ Vercel CLI is not installed.'); + rl.question('Do you want to install Vercel CLI globally? (y/n): ', async (installVercel) => { + if (installVercel.toLowerCase() === 'y') { + try { + await runCommand('npm install -g vercel'); + console.log('✅ Vercel CLI installed.'); + checkVercelSetup(); + } catch (error) { + console.error('❌ Failed to install Vercel CLI:', error); + rl.close(); + } + } else { + console.log('Please install Vercel CLI manually: npm install -g vercel'); + rl.close(); + } + }); + } else { + console.log('✅ Vercel CLI is installed.'); + checkVercelSetup(); + } + } + + async function checkVercelSetup() { + console.log('\nChecking if you are logged in to Vercel...'); + rl.question('Are you logged in to Vercel? (y/n): ', async (loggedIn) => { + if (loggedIn.toLowerCase() === 'n') { + console.log('Please log in to Vercel:'); + try { + await runCommand('vercel login'); + console.log('✅ Logged in to Vercel.'); + setupVercelProject(); + } catch (error) { + console.error('❌ Failed to log in to Vercel:', error); + rl.close(); + } + } else { + console.log('✅ Already logged in to Vercel.'); + setupVercelProject(); + } + }); + } + + async function setupVercelProject() { + console.log('\nSetting up Vercel project...'); + rl.question('Do you want to link this directory to a Vercel project? (y/n): ', async (linkProject) => { + if (linkProject.toLowerCase() === 'y') { + try { + await runCommand('vercel link'); + console.log('✅ Project linked to Vercel.'); + generateToken(); + } catch (error) { + console.error('❌ Failed to link project to Vercel:', error); + rl.close(); + } + } else { + console.log('Skipping Vercel project link. You will need to link your project manually.'); + generateToken(); + } + }); + } + + function generateToken() { + console.log('\nGenerating Vercel token for GitHub Actions...'); + console.log('Please follow these steps to create a Vercel token:'); + console.log('1. Go to https://vercel.com/account/tokens'); + console.log('2. Click "Create" to create a new token'); + console.log('3. Name it "GitHub Actions" and set the scope to "Full Account"'); + console.log('4. Copy the generated token'); + + rl.question('Have you created and copied your Vercel token? (y/n): ', (createdToken) => { + if (createdToken.toLowerCase() === 'y') { + console.log('\nNow you need to add this token to your GitHub repository secrets:'); + console.log('1. Go to your GitHub repository'); + console.log('2. Navigate to Settings → Secrets and variables → Actions'); + console.log('3. Click "New repository secret"'); + console.log('4. Name: VERCEL_TOKEN'); + console.log('5. Value: Paste your Vercel token'); + console.log('6. Click "Add secret"'); + + rl.question('Have you added the token to GitHub secrets? (y/n): ', (addedSecret) => { + if (addedSecret.toLowerCase() === 'y') { + console.log('✅ Vercel token added to GitHub secrets.'); + commitAndPush(); + } else { + console.log('Please add the Vercel token to GitHub secrets before deploying.'); + commitAndPush(); + } + }); + } else { + console.log('Please create a Vercel token before continuing.'); + rl.close(); + } + }); + } + + function commitAndPush() { + console.log('\nCommitting and pushing configuration files...'); + rl.question('Do you want to commit and push the GitHub Actions workflow and configuration files? (y/n): ', async (commitFiles) => { + if (commitFiles.toLowerCase() === 'y') { + try { + await runCommand('git add .github/ next.config.js vercel.json GITHUB_DEPLOYMENT.md'); + await runCommand('git commit -m "Add GitHub Actions workflow for Vercel deployment"'); + + rl.question('Do you want to push the changes to GitHub now? (y/n): ', async (pushChanges) => { + if (pushChanges.toLowerCase() === 'y') { + try { + await runCommand('git push origin main'); + console.log('✅ Changes pushed to GitHub.'); + completed(); + } catch (error) { + console.error('❌ Failed to push changes to GitHub:', error); + console.log('You can push the changes manually later with: git push origin main'); + completed(); + } + } else { + console.log('You can push the changes manually later with: git push origin main'); + completed(); + } + }); + } catch (error) { + console.error('❌ Failed to commit files:', error); + rl.close(); + } + } else { + console.log('Skipping commit and push. You can commit and push the files manually later.'); + completed(); + } + }); + } + + function completed() { + console.log('\n🎉 GitHub Actions workflow for Vercel deployment is set up!'); + console.log('\nNext steps:'); + console.log('1. If you haven\'t already, push your changes to GitHub: git push origin main'); + console.log('2. Check the Actions tab in your GitHub repository to monitor deployments'); + console.log('3. Set up your custom domain in the Vercel dashboard if needed'); + console.log('\nFor more information, see the GITHUB_DEPLOYMENT.md file.'); + + rl.close(); + } +} + +// Run the setup +setupGitHubDeploy(); \ No newline at end of file diff --git a/.history/src/app/api/auth/nextauth/route.ts_20250416003926.temp b/.history/src/app/api/auth/nextauth/route.ts_20250416003926.temp new file mode 100644 index 0000000..e69de29 diff --git a/.history/src/app/api/auth/nextauth/route.ts_20250416003952.temp b/.history/src/app/api/auth/nextauth/route.ts_20250416003952.temp new file mode 100644 index 0000000..35b70b2 --- /dev/null +++ b/.history/src/app/api/auth/nextauth/route.ts_20250416003952.temp @@ -0,0 +1,6 @@ +import NextAuth from 'next-auth/next'; +import { authOptions } from '@/lib/auth-options'; + +const handler = NextAuth(authOptions); + +export { handler as GET, handler as POST }; \ No newline at end of file diff --git a/.history/src/app/api/ipfs/route.ts_20250416040717.temp b/.history/src/app/api/ipfs/route.ts_20250416040717.temp new file mode 100644 index 0000000..e69de29 diff --git a/.history/src/app/api/ipfs/route.ts_20250416040727.temp b/.history/src/app/api/ipfs/route.ts_20250416040727.temp new file mode 100644 index 0000000..b7713ee --- /dev/null +++ b/.history/src/app/api/ipfs/route.ts_20250416040727.temp @@ -0,0 +1,62 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { getCurrentUser } from '../../../lib/auth'; +import { IpfsContentModel } from '../../../db/models/ipfs-content'; + +export async function GET(req: NextRequest) { + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } + + const url = new URL(req.url); + const limit = parseInt(url.searchParams.get('limit') || '10'); + const offset = parseInt(url.searchParams.get('offset') || '0'); + + const content = await IpfsContentModel.findByUser(user.id, limit, offset); + const stats = await IpfsContentModel.getContentStats(user.id); + + return NextResponse.json({ content, stats }); + } catch (error) { + console.error('Error fetching IPFS content:', error); + return NextResponse.json( + { error: 'Failed to fetch IPFS content' }, + { status: 500 } + ); + } +} + +export async function POST(req: NextRequest) { + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } + + const data = await req.json(); + const { cid, contentType, filename, size } = data; + + if (!cid) { + return NextResponse.json( + { error: 'CID is required' }, + { status: 400 } + ); + } + + const content = await IpfsContentModel.create( + user.id, + cid, + contentType, + filename, + size + ); + + return NextResponse.json({ content }, { status: 201 }); + } catch (error) { + console.error('Error creating IPFS content:', error); + return NextResponse.json( + { error: 'Failed to create IPFS content' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/.history/src/app/dashboard/page_20250316003619.tsx b/.history/src/app/dashboard/page_20250316003619.tsx new file mode 100644 index 0000000..c4976b1 --- /dev/null +++ b/.history/src/app/dashboard/page_20250316003619.tsx @@ -0,0 +1,346 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import Navigation from '../../components/Navigation'; +import { useAuth } from '../../contexts/AuthContext'; +import { api } from '../../lib/api'; + +interface IpfsContent { + id: number; + user_id: number; + cid: string; + content_type?: string; + filename?: string; + size?: number; + pinned: boolean; + created_at: string; +} + +interface ContentStats { + total: number; + pinned: number; + totalSize: number; +} + +export default function DashboardPage() { + const router = useRouter(); + const { isLoading: authLoading, isAuthenticated } = useAuth(); + + const [content, setContent] = useState([]); + const [stats, setStats] = useState({ total: 0, pinned: 0, totalSize: 0 }); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [newCid, setNewCid] = useState(''); + const [newFilename, setNewFilename] = useState(''); + const [newContentType, setNewContentType] = useState(''); + const [isSubmitting, setIsSubmitting] = useState(false); + + // Redirect if not authenticated + useEffect(() => { + if (!authLoading && !isAuthenticated) { + router.push('/'); + } + }, [authLoading, isAuthenticated, router]); + + // Fetch IPFS content + useEffect(() => { + if (isAuthenticated) { + fetchContent(); + } + }, [isAuthenticated]); + + const fetchContent = async () => { + setIsLoading(true); + setError(null); + + try { + const response = await api.ipfs.getContent(); + if (response.error) { + throw new Error(response.error); + } + + setContent(response.data?.content || []); + setStats(response.data?.stats || { total: 0, pinned: 0, totalSize: 0 }); + } catch (err) { + console.error('Error fetching IPFS content:', err); + setError((err as Error).message); + } finally { + setIsLoading(false); + } + }; + + const handleAddContent = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newCid) { + setError('CID is required'); + return; + } + + setIsSubmitting(true); + setError(null); + + try { + const response = await api.ipfs.createContent({ + cid: newCid, + filename: newFilename || undefined, + contentType: newContentType || undefined, + }); + + if (response.error) { + throw new Error(response.error); + } + + // Reset form + setNewCid(''); + setNewFilename(''); + setNewContentType(''); + + // Refresh content list + fetchContent(); + } catch (err) { + setError((err as Error).message); + } finally { + setIsSubmitting(false); + } + }; + + const handleTogglePin = async (cid: string, currentPinned: boolean) => { + try { + const response = await api.ipfs.updatePinStatus(cid, !currentPinned); + if (response.error) { + throw new Error(response.error); + } + + // Update local state + setContent(prevContent => + prevContent.map(item => + item.cid === cid ? { ...item, pinned: !currentPinned } : item + ) + ); + + // Update stats + setStats(prevStats => ({ + ...prevStats, + pinned: currentPinned + ? Math.max(0, prevStats.pinned - 1) + : prevStats.pinned + 1 + })); + } catch (err) { + setError((err as Error).message); + } + }; + + const handleDelete = async (cid: string) => { + if (!confirm('Are you sure you want to delete this content?')) { + return; + } + + try { + const response = await api.ipfs.deleteContent(cid); + if (response.error) { + throw new Error(response.error); + } + + // Refresh content list + fetchContent(); + } catch (err) { + setError((err as Error).message); + } + }; + + const formatFileSize = (bytes?: number) => { + if (bytes === undefined) return 'Unknown'; + if (bytes === 0) return '0 Bytes'; + + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + if (authLoading) { + return ( +
+ +
+
+ Loading... +
+
+
+
+
+
+ ); + } + + if (!isAuthenticated) { + return null; // Will redirect in useEffect + } + + return ( +
+ + +
+
+ IPFS Content Dashboard + × +
+
+ {error && ( +
+ Error: {error} +
+ )} + +
+
+

Content Stats

+ + + + + + + + + + + + + + + +
Total Files:{stats.total}
Pinned Files:{stats.pinned}
Total Size:{formatFileSize(stats.totalSize)}
+
+ +
+

Add New Content

+
+
+ + setNewCid(e.target.value)} + className="input-98" + style={{ width: '100%' }} + placeholder="Qm..." + required + /> +
+ +
+ + setNewFilename(e.target.value)} + className="input-98" + style={{ width: '100%' }} + placeholder="example.jpg" + /> +
+ +
+ + setNewContentType(e.target.value)} + className="input-98" + style={{ width: '100%' }} + placeholder="image/jpeg" + /> +
+ + +
+
+
+ +

Your IPFS Content

+ + {isLoading ? ( +
+
+
+ ) : content.length === 0 ? ( +

You don't have any IPFS content yet. Add some using the form above.

+ ) : ( + + + + + + + + + + + + + {content.map((item) => ( + + + + + + + + + ))} + +
FilenameCIDTypeSizePinnedActions
{item.filename || 'Unnamed'} + + {item.cid.substring(0, 10)}... + + {item.content_type || 'Unknown'}{formatFileSize(item.size)} + handleTogglePin(item.cid, item.pinned)} + aria-label={`Pin ${item.filename || 'content'}`} + /> + + +
+ )} +
+
+
+ ); +} diff --git a/.history/src/app/dashboard/page_20250416182558.tsx b/.history/src/app/dashboard/page_20250416182558.tsx new file mode 100644 index 0000000..a55fab9 --- /dev/null +++ b/.history/src/app/dashboard/page_20250416182558.tsx @@ -0,0 +1,555 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import Navigation from '../../components/Navigation'; +import { useAuth } from '../../contexts/AuthContext'; +import { api } from '../../lib/api'; + +interface IpfsContent { + id: number; + user_id: number; + cid: string; + content_type?: string; + filename?: string; + size?: number; + pinned: boolean; + created_at: string; +} + +interface ContentStats { + total: number; + pinned: number; + totalSize: number; +} + +export default function DashboardPage() { + const router = useRouter(); + const { isLoading: authLoading, isAuthenticated } = useAuth(); + + const [content, setContent] = useState([]); + const [stats, setStats] = useState({ total: 0, pinned: 0, totalSize: 0 }); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [newCid, setNewCid] = useState(''); + const [newFilename, setNewFilename] = useState(''); + const [newContentType, setNewContentType] = useState(''); + const [isSubmitting, setIsSubmitting] = useState(false); + const [activeTab, setActiveTab] = useState('content'); // 'content', 'upload', 'stats' + + // Redirect if not authenticated + useEffect(() => { + if (!authLoading && !isAuthenticated) { + router.push('/'); + } + }, [authLoading, isAuthenticated, router]); + + // Fetch IPFS content + useEffect(() => { + if (isAuthenticated) { + fetchContent(); + } + }, [isAuthenticated]); + + const fetchContent = async () => { + setIsLoading(true); + setError(null); + + try { + const response = await api.ipfs.getContent(); + if (response.error) { + throw new Error(response.error); + } + + setContent(response.data?.content || []); + setStats(response.data?.stats || { total: 0, pinned: 0, totalSize: 0 }); + } catch (err) { + console.error('Error fetching IPFS content:', err); + setError((err as Error).message); + } finally { + setIsLoading(false); + } + }; + + const handleAddContent = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newCid) { + setError('CID is required'); + return; + } + + setIsSubmitting(true); + setError(null); + + try { + const response = await api.ipfs.createContent({ + cid: newCid, + filename: newFilename || undefined, + contentType: newContentType || undefined, + }); + + if (response.error) { + throw new Error(response.error); + } + + // Reset form + setNewCid(''); + setNewFilename(''); + setNewContentType(''); + + // Refresh content list + fetchContent(); + } catch (err) { + setError((err as Error).message); + } finally { + setIsSubmitting(false); + } + }; + + const handleTogglePin = async (cid: string, currentPinned: boolean) => { + try { + const response = await api.ipfs.updatePinStatus(cid, !currentPinned); + if (response.error) { + throw new Error(response.error); + } + + // Update local state + setContent(prevContent => + prevContent.map(item => + item.cid === cid ? { ...item, pinned: !currentPinned } : item + ) + ); + + // Update stats + setStats(prevStats => ({ + ...prevStats, + pinned: currentPinned + ? Math.max(0, prevStats.pinned - 1) + : prevStats.pinned + 1 + })); + } catch (err) { + setError((err as Error).message); + } + }; + + const handleDelete = async (cid: string) => { + if (!confirm('Are you sure you want to delete this content?')) { + return; + } + + try { + const response = await api.ipfs.deleteContent(cid); + if (response.error) { + throw new Error(response.error); + } + + // Refresh content list + fetchContent(); + } catch (err) { + setError((err as Error).message); + } + }; + + const formatFileSize = (bytes?: number) => { + if (bytes === undefined) return 'Unknown'; + if (bytes === 0) return '0 Bytes'; + + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + const formatDate = (dateString: string) => { + const date = new Date(dateString); + return date.toLocaleString([], { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + }; + + if (authLoading) { + return ( +
+ +
+
+
+ + Loading... +
+
+
×
+
+
+
+
+

Connecting to IPFS network...

+
+
+
+ ); + } + + if (!isAuthenticated) { + return null; // Will redirect in useEffect + } + + return ( +
+ + +
+
+
+ 📡 + IPFS Content Dashboard +
+
+
_
+
+
×
+
+
+
+ {error && ( +
+ ⚠️ +
+

Error

+

{error}

+
+
+ )} + +
+
setActiveTab('content')} + > + Content +
+
setActiveTab('upload')} + > + Upload New +
+
setActiveTab('stats')} + > + Statistics +
+
+ + {activeTab === 'content' && ( +
+
+ + +
+
+ 📊 + {stats.total} Files | {formatFileSize(stats.totalSize)} +
+
+ + {isLoading ? ( +
+
+

Loading IPFS content...

+
+ ) : content.length === 0 ? ( +
+ ℹ️ +
+

No Content Found

+

You don't have any IPFS content yet. Add some using the Upload tab.

+ +
+
+ ) : ( + + + + + + + + + + + + + {content.map((item) => ( + + + + + + + + + ))} + +
FilenameCIDTypeSizePinnedActions
+ + {item.content_type?.startsWith('image/') ? '🖼️' : + item.content_type?.includes('html') ? '📄' : + item.content_type?.includes('css') ? '🎨' : + item.content_type?.includes('javascript') ? '📜' : '📁'} + + {item.filename || 'Unnamed'} + + + {item.content_type || 'Unknown'}{formatFileSize(item.size)} + handleTogglePin(item.cid, item.pinned)} + aria-label={`Pin ${item.filename || 'content'}`} + /> + + +
+ )} + +
+ Last refreshed: {new Date().toLocaleTimeString()} +
+
+ )} + + {activeTab === 'upload' && ( +
+
+
+
+ 📤 + Add New IPFS Content +
+
+
+
+
+ + setNewCid(e.target.value)} + style={{ width: '100%' }} + placeholder="Qm..." + required + /> +

+ Example: QmX7qUgLyYKzPb3hzK4g8rR5N1TE4aYxycpK1XNvCwHbKx +

+
+ +
+ + setNewFilename(e.target.value)} + style={{ width: '100%' }} + placeholder="example.jpg" + /> +
+ +
+ + setNewContentType(e.target.value)} + style={{ width: '100%' }} + placeholder="image/jpeg" + /> +

+ Common types: text/html, image/png, image/jpeg, application/pdf +

+
+ +
+ + +
+
+
+
+ +
+

How to use IPFS with BasedNet:

+
    +
  1. Add your content to IPFS using an IPFS node or service
  2. +
  3. Copy the resulting CID (Content Identifier)
  4. +
  5. Paste the CID in the form above
  6. +
  7. Add optional metadata like filename and content type
  8. +
  9. Click "Add Content" to register it with BasedNet
  10. +
+
+
+ )} + + {activeTab === 'stats' && ( +
+
+
+

+ 📊 + Content Statistics +

+ + + + + + + + + + + + + + + + + + + +
Total Files:{stats.total}
Pinned Files:{stats.pinned}
Total Size:{formatFileSize(stats.totalSize)}
Storage Usage:{stats.totalSize ? Math.round((stats.totalSize / (1024 * 1024 * 100)) * 100) : 0}%
+ +
+
+ + {Math.round((stats.totalSize / (1024 * 1024 * 100)) * 100) || 0}% +
+
+
+
+
+
+
+

+ 🔍 + Content Types +

+
+ + + + + + + + + {/* Content type statistics would go here in a real app */} + + + + + + + + + + + + + + + + + +
TypeCount
image/jpeg3
text/html5
application/pdf1
text/css2
+
+
+
+ +
+

+ 💡 + IPFS Tips +

+
    +
  • Pinning: Content marked as "pinned" will be kept in the network even if nobody is accessing it.
  • +
  • CID: Content Identifiers are unique fingerprints of your content based on its data.
  • +
  • Gateway: Access your content via https://ipfs.io/ipfs/[your-cid]
  • +
  • Storage: Your BasedNet account includes 100MB of pinned IPFS storage.
  • +
+
+
+ )} +
+ +
+
IPFS Management Console v1.0
+
{new Date().toLocaleString()}
+
+
+
+ ); +} diff --git a/.history/src/app/dashboard/page_20250418170836.tsx b/.history/src/app/dashboard/page_20250418170836.tsx new file mode 100644 index 0000000..045499c --- /dev/null +++ b/.history/src/app/dashboard/page_20250418170836.tsx @@ -0,0 +1,230 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import Navigation from '../../components/Navigation'; +import { useAuth } from '../../contexts/AuthContext'; +import { api } from '../../lib/api'; + +interface IpfsContent { + id: number; + user_id: number; + cid: string; + content_type?: string; + filename?: string; + size?: number; + pinned: boolean; + created_at: string; +} + +interface ContentStats { + total: number; + pinned: number; + totalSize: number; +} + +export default function DashboardPage() { + const router = useRouter(); + const { isLoading: authLoading, isAuthenticated } = useAuth(); + + const [content, setContent] = useState([]); + const [stats, setStats] = useState({ total: 0, pinned: 0, totalSize: 0 }); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [newCid, setNewCid] = useState(''); + const [newFilename, setNewFilename] = useState(''); + const [newContentType, setNewContentType] = useState(''); + const [isSubmitting, setIsSubmitting] = useState(false); + + useEffect(() => { + if (!authLoading && !isAuthenticated) { + router.push('/'); + } + }, [authLoading, isAuthenticated, router]); + + useEffect(() => { + if (isAuthenticated) { + fetchContent(); + } + }, [isAuthenticated]); + + const fetchContent = async () => { + setIsLoading(true); + setError(null); + + try { + const response = await api.ipfs.getContent(); + if (response.error) { + throw new Error(response.error); + } + + setContent(response.data?.content || []); + setStats(response.data?.stats || { total: 0, pinned: 0, totalSize: 0 }); + } catch (err) { + console.error('Error fetching IPFS content:', err); + setError((err as Error).message); + } finally { + setIsLoading(false); + } + }; + + const handleAddContent = async (e: React.FormEvent) => { + e.preventDefault(); + if (!newCid) { + setError('CID is required'); + return; + } + + setIsSubmitting(true); + setError(null); + + try { + const response = await api.ipfs.createContent({ + cid: newCid, + filename: newFilename || undefined, + contentType: newContentType || undefined, + }); + + if (response.error) { + throw new Error(response.error); + } + + setNewCid(''); + setNewFilename(''); + setNewContentType(''); + fetchContent(); + } catch (err) { + setError((err as Error).message); + } finally { + setIsSubmitting(false); + } + }; + + const handleTogglePin = async (cid: string, currentPinned: boolean) => { + try { + const response = await api.ipfs.updatePinStatus(cid, !currentPinned); + if (response.error) { + throw new Error(response.error); + } + + setContent(prevContent => + prevContent.map(item => + item.cid === cid ? { ...item, pinned: !currentPinned } : item + ) + ); + + setStats(prevStats => ({ + ...prevStats, + pinned: currentPinned + ? Math.max(0, prevStats.pinned - 1) + : prevStats.pinned + 1 + })); + } catch (err) { + setError((err as Error).message); + } + }; + + const handleDelete = async (cid: string) => { + if (!confirm('Are you sure you want to delete this content?')) { + return; + } + + try { + const response = await api.ipfs.deleteContent(cid); + if (response.error) { + throw new Error(response.error); + } + fetchContent(); + } catch (err) { + setError((err as Error).message); + } + }; + + const formatFileSize = (bytes?: number) => { + if (bytes === undefined) return 'Unknown'; + if (bytes === 0) return '0 Bytes'; + + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + if (authLoading) { + return ( +
+ +

Loading...

+
+ ); + } + + if (!isAuthenticated) { + return null; + } + + return ( +
+ + + {error && ( +
+ Error: {error} +
+ )} + +

Your IPFS Content

+ + {isLoading ? ( +

Loading...

+ ) : content.length === 0 ? ( +

You don't have any IPFS content yet.

+ ) : ( + + + + + + + + + + + + + {content.map((item) => ( + + + + + + + + + ))} + +
FilenameCIDTypeSizePinnedActions
{item.filename || 'Unnamed'} + + {item.cid.substring(0, 10)}... + + {item.content_type || 'Unknown'}{formatFileSize(item.size)} + handleTogglePin(item.cid, item.pinned)} + aria-label={`Pin ${item.filename || 'content'}`} + /> + + +
+ )} +
+ ); +} diff --git a/.history/src/app/global-error_20250405022059.js b/.history/src/app/global-error_20250405022059.js new file mode 100644 index 0000000..c743bcd --- /dev/null +++ b/.history/src/app/global-error_20250405022059.js @@ -0,0 +1,45 @@ +'use client'; + +import { useEffect } from 'react'; + +export default function GlobalError({ error, reset }) { + useEffect(() => { + // Log the error to an error reporting service + console.error('Global error caught:', error); + }, [error]); + + return ( + + +
+

Something went wrong!

+

We've encountered an unexpected error.

+ +
+ + + + ); +} diff --git a/.history/src/app/global-error_20250505224747.js b/.history/src/app/global-error_20250505224747.js new file mode 100644 index 0000000..fb9c8a3 --- /dev/null +++ b/.history/src/app/global-error_20250505224747.js @@ -0,0 +1,51 @@ +'use client'; + +import { useEffect } from 'react'; +import * as Sentry from '@sentry/nextjs'; + +export default function GlobalError({ error, reset }) { + useEffect(() => { + // Log the error to an error reporting service + console.error('Global error caught:', error); + + // Report to Sentry in production + if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) { + Sentry.captureException(error); + } + }, [error]); + + return ( + + +
+

Something went wrong!

+

We've encountered an unexpected error.

+ +
+ + + + ); +} diff --git a/.history/src/app/global-error_20250505224809.js b/.history/src/app/global-error_20250505224809.js new file mode 100644 index 0000000..1fd2576 --- /dev/null +++ b/.history/src/app/global-error_20250505224809.js @@ -0,0 +1,113 @@ +'use client'; + +import { useEffect } from 'react'; +import * as Sentry from '@sentry/nextjs'; + +export default function GlobalError({ error, reset }) { + useEffect(() => { + // Log the error to an error reporting service + console.error('Global error caught:', error); + + // Report to Sentry in production + if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) { + Sentry.captureException(error); + } + }, [error]); + + return ( + + +
+
+

Something went wrong!

+

We've encountered an unexpected error and our team has been notified.

+
+ + + Return to home + +
+ {process.env.NODE_ENV !== 'production' && ( +
+

Error details (only visible in development):

+
{error.message}
+
{error.stack}
+
+ )} +
+
+ + + + ); +} diff --git a/.history/src/app/layout_20250319102915.tsx b/.history/src/app/layout_20250319102915.tsx new file mode 100644 index 0000000..92cdb71 --- /dev/null +++ b/.history/src/app/layout_20250319102915.tsx @@ -0,0 +1,40 @@ +import type { Metadata } from 'next' +import React from 'react' +import { Inter, Roboto_Mono } from 'next/font/google' +import './globals.css' +import './win98.css' +import Providers from '@/components/Providers' + +const inter = Inter({ + subsets: ['latin'], + display: 'swap', + variable: '--font-inter', +}) + +const robotoMono = Roboto_Mono({ + subsets: ['latin'], + display: 'swap', + variable: '--font-roboto-mono', +}) + +export const metadata: Metadata = { + title: 'Basednet - The Next-Gen Indie Web Platform', + description: 'Create, customize, and host your personal website with P2P hosting, webrings, and AI-powered discovery on Basednet.', + keywords: ['indie web', 'personal website', 'webring', 'P2P hosting', 'IPFS', 'web3'], +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + + {children} + + + + ) +} diff --git a/.history/src/app/layout_20250418170738.tsx b/.history/src/app/layout_20250418170738.tsx new file mode 100644 index 0000000..3061138 --- /dev/null +++ b/.history/src/app/layout_20250418170738.tsx @@ -0,0 +1,40 @@ +import type { Metadata } from 'next' +import React from 'react' +import { Inter, Roboto_Mono } from 'next/font/google' +import './globals.css' +import './nekoweb.css' +import Providers from '@/components/Providers' + +const inter = Inter({ + subsets: ['latin'], + display: 'swap', + variable: '--font-inter', +}) + +const robotoMono = Roboto_Mono({ + subsets: ['latin'], + display: 'swap', + variable: '--font-roboto-mono', +}) + +export const metadata: Metadata = { + title: 'Basednet - The Next-Gen Indie Web Platform', + description: 'Create, customize, and host your personal website with P2P hosting, webrings, and AI-powered discovery on Basednet.', + keywords: ['indie web', 'personal website', 'webring', 'P2P hosting', 'IPFS', 'web3'], +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + + {children} + + + + ) +} diff --git a/.history/src/app/nekoweb_20250418170713.css b/.history/src/app/nekoweb_20250418170713.css new file mode 100644 index 0000000..e69de29 diff --git a/.history/src/app/nekoweb_20250418170722.css b/.history/src/app/nekoweb_20250418170722.css new file mode 100644 index 0000000..1a29bb1 --- /dev/null +++ b/.history/src/app/nekoweb_20250418170722.css @@ -0,0 +1,65 @@ +/* Nekoweb Style */ + +:root { + --nekoweb-background: #f8f0e3; + --nekoweb-text: #333; + --nekoweb-accent: #e6b8af; + --nekoweb-button-bg: #e6b8af; + --nekoweb-button-hover: #e0a89a; + --nekoweb-border: #ddd; +} + +body { + background-color: var(--nekoweb-background); + font-family: sans-serif; + color: var(--nekoweb-text); + line-height: 1.6; +} + +.nekoweb-button { + background-color: var(--nekoweb-button-bg); + color: var(--nekoweb-text); + border: 1px solid var(--nekoweb-border); + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + text-decoration: none; + transition: background-color 0.3s ease; +} + +.nekoweb-button:hover { + background-color: var(--nekoweb-button-hover); +} + +.nekoweb-container { + max-width: 800px; + margin: 20px auto; + padding: 20px; + border: 1px solid var(--nekoweb-border); + border-radius: 5px; + background-color: white; +} + +.nekoweb-section { + margin-bottom: 20px; +} + +.nekoweb-section h2 { + margin-top: 0; +} + +.nekoweb-section p { + margin-bottom: 10px; +} + +.nekoweb-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 20px; +} + +.nekoweb-grid-item { + border: 1px solid var(--nekoweb-border); + padding: 10px; + border-radius: 5px; +} \ No newline at end of file diff --git a/.history/src/app/page_20250319102637.tsx b/.history/src/app/page_20250319102637.tsx new file mode 100644 index 0000000..ebc7cad --- /dev/null +++ b/.history/src/app/page_20250319102637.tsx @@ -0,0 +1,234 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import Navigation from '@/components/Navigation'; +import { useAuth } from '@/contexts/AuthContext'; +import { api } from '@/lib/api'; + +interface Stats { + totalSites: number; + activeToday: number; + webrings: number; + ipfsNodes: number; +} + +export default function Home() { + const { isAuthenticated, user, profile } = useAuth(); + const [stats, setStats] = useState({ + totalSites: 88888, + activeToday: 1337, + webrings: 42, + ipfsNodes: 404 + }); + const [isLoading, setIsLoading] = useState(false); + + // Example of fetching data from the API + useEffect(() => { + if (isAuthenticated) { + setIsLoading(true); + // This is just a placeholder - in a real app, you'd fetch actual stats + api.ipfs.getContent() + .then(response => { + if (response.data?.stats) { + console.log('IPFS stats:', response.data.stats); + // Update stats with real data if available + } + }) + .catch(error => { + console.error('Error fetching IPFS stats:', error); + }) + .finally(() => { + setIsLoading(false); + }); + } + }, [isAuthenticated]); + + return ( +
+ {/* Navigation Bar */} + + + {/* ASCII Art Logo */} +
+
+ BASEDNET.EXE + × +
+
+
+{`
+ ▄▄▄▄    ▄▄▄        ██████ ▓█████ ▓█████▄  ███▄    █ ▓█████▄▄▄█████▓
+▓█████▄ ▒████▄    ▒██    ▒ ▓█   ▀ ▒██▀ ██▌ ██ ▀█   █ ▓█   ▀▓  ██▒ ▓▒
+▒██▒ ▄██▒██  ▀█▄  ░ ▓██▄   ▒███   ░██   █▌▓██  ▀█ ██▒▒███  ▒ ▓██░ ▒░
+▒██░█▀  ░██▄▄▄▄██   ▒   ██▒▒▓█  ▄ ░▓█▄   ▌▓██▒  ▐▌██▒▒▓█  ▄░ ▓██▓ ░ 
+░▓█  ▀█▓ ▓█   ▓██▒▒██████▒▒░▒████▒░▒████▓ ▒██░   ▓██░░▒████▒ ▒██▒ ░ 
+░▒▓███▀▒ ▒▒   ▓▒█░▒ ▒▓▒ ▒ ░░░ ▒░ ░ ▒▒▓  ▒ ░ ▒░   ▒ ▒ ░░ ▒░ ░ ▒ ░░   
+▒░▒   ░   ▒   ▒▒ ░░ ░▒  ░ ░ ░ ░  ░ ░ ▒  ▒ ░ ░░   ░ ▒░ ░ ░  ░   ░    
+ ░    ░   ░   ▒   ░  ░  ░     ░    ░ ░  ░    ░   ░ ░    ░    ░      
+ ░            ░  ░      ░     ░  ░   ░             ░    ░  ░         
+      ░                            ░                                   
+`}
+          
+

Web 1.0 Lives Forever

+ + {isAuthenticated && ( +
+

Welcome back, {profile?.display_name || user?.username}!

+
+ )} +
+
+ + {/* Main Content Grid */} +
+ {/* Active Sites Window */} +
+
+ Active Sites + × +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SiteLast UpdatedViews
cool-site-882 hours ago1,337
retro-haven5 hours ago420
pixel-dreams8 hours ago808
+
+
+ + {/* File Manager */} +
+
+ Site Manager + × +
+
+
+ + + +
+ {isAuthenticated ? ( + + + + + + + + + + + + + + + + + + + + + + + + + +
NameSizeType
📁 images--Folder
📄 index.html2.4 KBHTML
📄 style.css1.8 KBCSS
+ ) : ( +
+

Please log in to manage your site files.

+
+ )} +
+
+ + {/* Webring Navigator */} +
+
+ Webring Navigator + × +
+
+
+ + + +
+
+{` [Your Site] + ↓ + [Previous] → [Random] → [Next] + ↑ + [Return]`} +
+
+
+ + {/* Stats Window */} +
+
+ Network Stats + × +
+
+ {isLoading ? ( +
+ ) : ( + + + + + + + + + + + + + + + + + + + +
Total Sites:{stats.totalSites.toLocaleString()}
Active Today:{stats.activeToday.toLocaleString()}
Webrings:{stats.webrings.toLocaleString()}
IPFS Nodes:{stats.ipfsNodes.toLocaleString()}
+ )} +
+
+
+ + {/* Status Bar */} +
+
Connected to IPFS Network
+
+ + Syncing with {stats.ipfsNodes} peers +
+
+
+ ) +} diff --git a/.history/src/app/page_20250416182247.tsx b/.history/src/app/page_20250416182247.tsx new file mode 100644 index 0000000..7009c68 --- /dev/null +++ b/.history/src/app/page_20250416182247.tsx @@ -0,0 +1,435 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import Navigation from '@/components/Navigation'; +import { useAuth } from '@/contexts/AuthContext'; +import { api } from '@/lib/api'; + +interface Stats { + totalSites: number; + activeToday: number; + webrings: number; + ipfsNodes: number; +} + +export default function Home() { + const { isAuthenticated, user, profile } = useAuth(); + const [stats, setStats] = useState({ + totalSites: 88888, + activeToday: 1337, + webrings: 42, + ipfsNodes: 404 + }); + const [isLoading, setIsLoading] = useState(false); + const [currentTime, setCurrentTime] = useState(''); + + // Desktop icons state + const [desktopIcons] = useState([ + { name: 'My Website', icon: '🌐' }, + { name: 'Create Site', icon: '📝' }, + { name: 'Webrings', icon: '⭕' }, + { name: 'Help', icon: '❓' } + ]); + + // Update clock display + useEffect(() => { + const updateClock = () => { + const now = new Date(); + setCurrentTime(now.toLocaleString([], { + month: 'short', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + })); + }; + + updateClock(); + const intervalId = setInterval(updateClock, 1000); + return () => clearInterval(intervalId); + }, []); + + // Example of fetching data from the API + useEffect(() => { + if (isAuthenticated) { + setIsLoading(true); + // This is just a placeholder - in a real app, you'd fetch actual stats + api.ipfs.getContent() + .then(response => { + if (response.data?.stats) { + console.log('IPFS stats:', response.data.stats); + // Update stats with real data if available + } + }) + .catch(error => { + console.error('Error fetching IPFS stats:', error); + }) + .finally(() => { + setIsLoading(false); + }); + } + }, [isAuthenticated]); + + return ( +
+ {/* Desktop Icons */} +
+ {desktopIcons.map((icon, index) => ( +
+
{icon.icon}
+
{icon.name}
+
+ ))} +
+ + {/* ASCII Art Logo Window */} +
+
+
+ 📟 + BASEDNET.EXE +
+
+
_
+
+
×
+
+
+
+
+{`
+ ▄▄▄▄    ▄▄▄        ██████ ▓█████ ▓█████▄  ███▄    █ ▓█████▄▄▄█████▓
+▓█████▄ ▒████▄    ▒██    ▒ ▓█   ▀ ▒██▀ ██▌ ██ ▀█   █ ▓█   ▀▓  ██▒ ▓▒
+▒██▒ ▄██▒██  ▀█▄  ░ ▓██▄   ▒███   ░██   █▌▓██  ▀█ ██▒▒███  ▒ ▓██░ ▒░
+▒██░█▀  ░██▄▄▄▄██   ▒   ██▒▒▓█  ▄ ░▓█▄   ▌▓██▒  ▐▌██▒▒▓█  ▄░ ▓██▓ ░ 
+░▓█  ▀█▓ ▓█   ▓██▒▒██████▒▒░▒████▒░▒████▓ ▒██░   ▓██░░▒████▒ ▒██▒ ░ 
+░▒▓███▀▒ ▒▒   ▓▒█░▒ ▒▓▒ ▒ ░░░ ▒░ ░ ▒▒▓  ▒ ░ ▒░   ▒ ▒ ░░ ▒░ ░ ▒ ░░   
+▒░▒   ░   ▒   ▒▒ ░░ ░▒  ░ ░ ░ ░  ░ ░ ▒  ▒ ░ ░░   ░ ▒░ ░ ░  ░   ░    
+ ░    ░   ░   ▒   ░  ░  ░     ░    ░ ░  ░    ░   ░ ░    ░    ░      
+ ░            ░  ░      ░     ░  ░   ░             ░    ░  ░         
+      ░                            ░                                   
+`}
+          
+
+
💾
+
+

Web 1.0 Lives Forever

+

Create, host, and share your personal website with BasedNet

+ + {isAuthenticated && ( +

+ Welcome back, {profile?.display_name || user?.username}! +

+ )} +
+
+
+
+ System: Ready | Memory: 640K OK | {currentTime} +
+
+ + {/* Main Content Grid */} +
+ {/* Active Sites Window */} +
+
+
+ 🌐 + Active Sites +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+
Sites
+
Details
+
Preview
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SiteLast UpdatedViews
📄cool-site-882 hours ago1,337
📄retro-haven5 hours ago420
📄pixel-dreams8 hours ago808
📄win98-museum1 day ago1,024
📄digital-nostalgia2 days ago512
+
+
+ + + +
+
+
+ + {/* File Manager */} +
+
+
+ 📂 + Site Manager +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+ + + + +
+ + {isAuthenticated ? ( +
+
+ 📁 + images +
+
+ 📄 + index.html +
+
+ 📄 + style.css +
+
+ 📄 + script.js +
+
+ 📄 + about.html +
+
+ ) : ( +
+ ⚠️ +
+

Access Denied

+

Please log in to manage your site files.

+ +
+
+ )} + +
+ 5 items | 24.5 KB used | 5.00 MB free +
+
+
+ + {/* Webring Navigator */} +
+
+
+ + Webring Navigator +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+
+ +
+
+{` [Your Site] + ↓ + [Previous] → [Random] → [Next] + ↑ + [Return]`} +
+

+ Currently browsing: Retro Web Webring +

+

+ 42 sites in this webring | Position: 13/42 +

+
+ +
+ + +
+
+
+ + {/* Stats Window */} +
+
+
+ 📊 + System Information +
+
+
_
+
+
×
+
+
+
+
+
General
+
Network
+
IPFS
+
+
+ {isLoading ? ( +
+
+
+ ) : ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
System:BasedNet Web Platform v1.0
Registered Sites:{stats.totalSites.toLocaleString()}
Active Today:{stats.activeToday.toLocaleString()}
Webrings:{stats.webrings.toLocaleString()}
IPFS Nodes:{stats.ipfsNodes.toLocaleString()}
Server Time:{currentTime}
+ +
+
+ + 68% +
+
+
+
+
+ +
+ Last Updated: {new Date().toLocaleTimeString()} +
+ + )} +
+
+
+
+ + {/* Status Bar */} +
+
+ 📡 + Connected to IPFS Network +
+
+ + Syncing with {stats.ipfsNodes} peers +
+
+ BasedNet v1.0 | Memory Available: 640K | CPU: 133MHz +
+
+
+ ); +} diff --git a/.history/src/app/page_20250416182413.tsx b/.history/src/app/page_20250416182413.tsx new file mode 100644 index 0000000..27ec712 --- /dev/null +++ b/.history/src/app/page_20250416182413.tsx @@ -0,0 +1,451 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import Navigation from '@/components/Navigation'; +import { useAuth } from '@/contexts/AuthContext'; +import { api } from '@/lib/api'; + +interface Stats { + totalSites: number; + activeToday: number; + webrings: number; + ipfsNodes: number; +} + +export default function Home() { + const { isAuthenticated, user, profile } = useAuth(); + const [stats, setStats] = useState({ + totalSites: 88888, + activeToday: 1337, + webrings: 42, + ipfsNodes: 404 + }); + const [isLoading, setIsLoading] = useState(false); + const [currentTime, setCurrentTime] = useState(''); + + // Desktop icons state + const [desktopIcons] = useState([ + { name: 'My Website', icon: '🌐' }, + { name: 'Create Site', icon: '📝' }, + { name: 'Webrings', icon: '⭕' }, + { name: 'Help', icon: '❓' } + ]); + + // Update clock display + useEffect(() => { + const updateClock = () => { + const now = new Date(); + setCurrentTime(now.toLocaleString([], { + month: 'short', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + })); + }; + + updateClock(); + const intervalId = setInterval(updateClock, 1000); + return () => clearInterval(intervalId); + }, []); + + // Example of fetching data from the API + useEffect(() => { + if (isAuthenticated) { + setIsLoading(true); + // This is just a placeholder - in a real app, you'd fetch actual stats + api.ipfs.getContent() + .then(response => { + if (response.data?.stats) { + console.log('IPFS stats:', response.data.stats); + // Update stats with real data if available + } + }) + .catch(error => { + console.error('Error fetching IPFS stats:', error); + }) + .finally(() => { + setIsLoading(false); + }); + } + }, [isAuthenticated]); + + return ( +
+ {/* Desktop Icons */} +
+ {desktopIcons.map((icon, index) => ( +
+
{icon.icon}
+
{icon.name}
+
+ ))} +
+ + {/* ASCII Art Logo Window */} +
+
+
+ 📟 + BASEDNET.EXE +
+
+
_
+
+
×
+
+
+
+
+{`
+ ▄▄▄▄    ▄▄▄        ██████ ▓█████ ▓█████▄  ███▄    █ ▓█████▄▄▄█████▓
+▓█████▄ ▒████▄    ▒██    ▒ ▓█   ▀ ▒██▀ ██▌ ██ ▀█   █ ▓█   ▀▓  ██▒ ▓▒
+▒██▒ ▄██▒██  ▀█▄  ░ ▓██▄   ▒███   ░██   █▌▓██  ▀█ ██▒▒███  ▒ ▓██░ ▒░
+▒██░█▀  ░██▄▄▄▄██   ▒   ██▒▒▓█  ▄ ░▓█▄   ▌▓██▒  ▐▌██▒▒▓█  ▄░ ▓██▓ ░ 
+░▓█  ▀█▓ ▓█   ▓██▒▒██████▒▒░▒████▒░▒████▓ ▒██░   ▓██░░▒████▒ ▒██▒ ░ 
+░▒▓███▀▒ ▒▒   ▓▒█░▒ ▒▓▒ ▒ ░░░ ▒░ ░ ▒▒▓  ▒ ░ ▒░   ▒ ▒ ░░ ▒░ ░ ▒ ░░   
+▒░▒   ░   ▒   ▒▒ ░░ ░▒  ░ ░ ░ ░  ░ ░ ▒  ▒ ░ ░░   ░ ▒░ ░ ░  ░   ░    
+ ░    ░   ░   ▒   ░  ░  ░     ░    ░ ░  ░    ░   ░ ░    ░    ░      
+ ░            ░  ░      ░     ░  ░   ░             ░    ░  ░         
+      ░                            ░                                   
+`}
+          
+
+
💾
+
+

Web 1.0 Lives Forever

+

Create, host, and share your personal website with BasedNet

+ + {isAuthenticated && ( +

+ Welcome back, {profile?.display_name || user?.username}! +

+ )} +
+
+
+
+ System: Ready | Memory: 640K OK | {currentTime} +
+
+ + {/* Main Content Grid */} +
+ {/* Active Sites Window */} +
+
+
+ 🌐 + Active Sites +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+
Sites
+
Details
+
Preview
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SiteLast UpdatedViews
📄cool-site-882 hours ago1,337
📄retro-haven5 hours ago420
📄pixel-dreams8 hours ago808
📄win98-museum1 day ago1,024
📄digital-nostalgia2 days ago512
+
+
+ + + +
+
+
+ + {/* File Manager */} +
+
+
+ 📂 + Site Manager +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+ + + + +
+ + {isAuthenticated ? ( +
+
+ 📁 + images +
+
+ 📄 + index.html +
+
+ 📄 + style.css +
+
+ 📄 + script.js +
+
+ 📄 + about.html +
+
+ ) : ( +
+ ⚠️ +
+

Access Denied

+

Please log in to manage your site files.

+ +
+
+ )} + +
+ 5 items | 24.5 KB used | 5.00 MB free +
+
+
+ + {/* Webring Navigator */} +
+
+
+ + Webring Navigator +
+
+
_
+
+
×
+
+
+
+
+ + + +
+ +
+
+ +
+
+{` [Your Site] + ↓ + [Previous] → [Random] → [Next] + ↑ + [Return]`} +
+

+ Currently browsing: Retro Web Webring +

+

+ 42 sites in this webring | Position: 13/42 +

+
+ +
+ + +
+
+
+ + {/* Stats Window */} +
+
+
+ 📊 + System Information +
+
+
_
+
+
×
+
+
+
+
+
General
+
Network
+
IPFS
+
+
+ {isLoading ? ( +
+
+
+ ) : ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
System:BasedNet Web Platform v1.0
Registered Sites:{stats.totalSites.toLocaleString()}
Active Today:{stats.activeToday.toLocaleString()}
Webrings:{stats.webrings.toLocaleString()}
IPFS Nodes:{stats.ipfsNodes.toLocaleString()}
Server Time:{currentTime}
+ +
+
+ + 68% +
+
+
+
+
+ +
+ Last Updated: {new Date().toLocaleTimeString()} +
+ + )} +
+
+
+
+ + {/* Status Bar */} +
+
+ 📡 + Connected to IPFS Network +
+
+ + Syncing with {stats.ipfsNodes} peers +
+
+ BasedNet v1.0 | Memory Available: 640K | CPU: 133MHz +
+
+
+ ); +} diff --git a/.history/src/app/page_20250418170801.tsx b/.history/src/app/page_20250418170801.tsx new file mode 100644 index 0000000..eda4043 --- /dev/null +++ b/.history/src/app/page_20250418170801.tsx @@ -0,0 +1,76 @@ +'use client'; + +import React, { useEffect, useState } from 'react'; +import Navigation from '@/components/Navigation'; +import { useAuth } from '@/contexts/AuthContext'; +import { api } from '@/lib/api'; + +interface Stats { + totalSites: number; + activeToday: number; + webrings: number; + ipfsNodes: number; +} + +export default function Home() { + const { isAuthenticated, user, profile } = useAuth(); + const [stats, setStats] = useState({ + totalSites: 88888, + activeToday: 1337, + webrings: 42, + ipfsNodes: 404 + }); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (isAuthenticated) { + setIsLoading(true); + api.ipfs.getContent() + .then(response => { + if (response.data?.stats) { + console.log('IPFS stats:', response.data.stats); + } + }) + .catch(error => { + console.error('Error fetching IPFS stats:', error); + }) + .finally(() => { + setIsLoading(false); + }); + } + }, [isAuthenticated]); + + return ( +
+ +
+

Welcome to BasedNet

+

Your decentralized web experience.

+ {isAuthenticated && ( +

Welcome back, {profile?.display_name || user?.username}!

+ )} +
+
+
+

Browse Sites

+

Explore the BasedNet network.

+ Browse +
+
+

Webrings

+

Join a webring community.

+ Webrings +
+
+

My Dashboard

+

Manage your content.

+ {isAuthenticated ? ( + Dashboard + ) : ( +

Please log in to access your dashboard.

+ )} +
+
+
+ ); +} diff --git a/.history/src/app/profile/page_20250316002947.tsx b/.history/src/app/profile/page_20250316002947.tsx new file mode 100644 index 0000000..900b826 --- /dev/null +++ b/.history/src/app/profile/page_20250316002947.tsx @@ -0,0 +1,272 @@ +'use client'; + +import React, { useState, FormEvent } from 'react'; +import { useRouter } from 'next/navigation'; +import Navigation from '../../components/Navigation'; +import { useAuth } from '../../contexts/AuthContext'; +import { api } from '../../lib/api'; + +export default function ProfilePage() { + const router = useRouter(); + const { user, profile, isLoading, isAuthenticated, refreshUserData } = useAuth(); + + const [formData, setFormData] = useState({ + display_name: profile?.display_name || '', + bio: profile?.bio || '', + avatar_url: profile?.avatar_url || '', + custom_css: profile?.custom_css || '', + custom_html: profile?.custom_html || '', + }); + + const [socialLinks, setSocialLinks] = useState>( + profile?.social_links || { twitter: '', github: '', website: '' } + ); + + const [isSubmitting, setIsSubmitting] = useState(false); + const [error, setError] = useState(null); + const [successMessage, setSuccessMessage] = useState(null); + + // Redirect if not authenticated + React.useEffect(() => { + if (!isLoading && !isAuthenticated) { + router.push('/'); + } + }, [isLoading, isAuthenticated, router]); + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormData(prev => ({ ...prev, [name]: value })); + }; + + const handleSocialLinkChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setSocialLinks(prev => ({ ...prev, [name]: value })); + }; + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + setIsSubmitting(true); + setError(null); + setSuccessMessage(null); + + try { + const response = await api.profile.updateProfile({ + ...formData, + social_links: socialLinks + }); + + if (response.error) { + throw new Error(response.error); + } + + setSuccessMessage('Profile updated successfully!'); + await refreshUserData(); + } catch (err) { + setError((err as Error).message || 'Failed to update profile'); + } finally { + setIsSubmitting(false); + } + }; + + if (isLoading) { + return ( +
+ +
+
+ Loading... +
+
+
+
+
+
+ ); + } + + if (!isAuthenticated) { + return null; // Will redirect in useEffect + } + + return ( +
+ + +
+
+ User Profile + × +
+
+
+ {error && ( +
+ Error: {error} +
+ )} + + {successMessage && ( +
+ {successMessage} +
+ )} + +
+ + + Username cannot be changed +
+ +
+ + +
+ +
+ +