diff --git a/.claude/settings.local.json b/.claude/settings.local.json index db61623..7547e5d 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -17,7 +17,9 @@ "Bash(git reset:*)", "Bash(git checkout:*)", "WebFetch(domain:cheatingchelsea.com)", - "Bash(npm install:*)" + "Bash(npm install:*)", + "Bash(npm run typecheck:*)", + "Bash(rm:*)" ], "deny": [] } diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 5c7ee16..f445e68 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -6,6 +6,10 @@ on: pull_request: branches: [ main, master ] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: test: runs-on: self-hosted @@ -13,33 +17,24 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Cache Next.js build - uses: actions/cache@v3 - with: - path: ${{ github.workspace }}/.next/cache - key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.[jt]s', '**/*.[jt]sx') }} - restore-keys: | - ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}- - - name: Install dependencies - run: npm ci + run: npm ci --prefer-offline --no-audit --no-fund + env: + NODE_OPTIONS: '--max-old-space-size=4096' + UV_THREADPOOL_SIZE: 16 - - name: Run linting - run: npm run lint - - - name: Run type checking - run: npm run typecheck + - name: Run linting and type checking in parallel + run: | + npm run lint & + npm run typecheck & + wait + env: + NODE_OPTIONS: '--max-old-space-size=4096' - name: Build application run: npm run build env: # Use empty string for YOUTUBE_API_KEY during CI build - YOUTUBE_API_KEY: "" \ No newline at end of file + YOUTUBE_API_KEY: "" + NODE_OPTIONS: '--max-old-space-size=4096' + NEXT_TELEMETRY_DISABLED: 1 \ No newline at end of file diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index 1dc61d8..1e92609 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -5,6 +5,10 @@ on: branches: [ main, master ] workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: deploy: runs-on: self-hosted @@ -12,30 +16,19 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Cache Next.js build - uses: actions/cache@v3 - with: - path: ${{ github.workspace }}/.next/cache - key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.[jt]s', '**/*.[jt]sx') }} - restore-keys: | - ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}- - - name: Install dependencies - run: npm ci + run: npm ci --prefer-offline --no-audit --no-fund + env: + NODE_OPTIONS: '--max-old-space-size=4096' + UV_THREADPOOL_SIZE: 16 - name: Build application run: npm run build env: # Access YouTube API key from repository secrets YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY }} + NODE_OPTIONS: '--max-old-space-size=4096' + NEXT_TELEMETRY_DISABLED: 1 - name: Deploy to S3 (if configured) run: | diff --git a/CLAUDE.md b/CLAUDE.md index e6c79c9..f8246d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -This is a Next.js 15.3.3 application with TypeScript, React 18, and Firebase hosting. The app exposes harmful activities and supports Kristen Jacobs through a GoFundMe campaign. +This is a Next.js 15.3.3 application with TypeScript, React 18, and multiple deployment options. The app exposes harmful activities and supports Kristen Jacobs through a GoFundMe campaign. ## Essential Commands @@ -15,7 +15,8 @@ npm run genkit:dev # Start Genkit AI development server npm run genkit:watch # Start Genkit with file watching # Production -npm run build # Build the Next.js application +npm run build # Build with git commit hash injection +npm run build:static # Standard Next.js build npm run start # Start production server # Quality Checks @@ -23,8 +24,8 @@ npm run lint # Run Next.js linting npm run typecheck # Run TypeScript type checking # Deployment -npm run deploy:s3 # Deploy to AWS S3 bucket -npm run create-s3-bucket # Create S3 bucket for deployment +npm run deploy:s3 # Deploy to AWS S3 bucket (requires S3_BUCKET_NAME env var) +npm run create-s3-bucket # Interactive S3 bucket setup ``` ## Architecture Overview @@ -32,24 +33,71 @@ npm run create-s3-bucket # Create S3 bucket for deployment ### App Structure - **App Router**: Uses Next.js App Router in `src/app/` - **Pages**: Homepage, Gallery (YouTube videos), Dadvocate (curated videos), Long Story -- **Static Generation**: Pages use static generation with ISR for external data -- **Deployment**: Supports Static hosting (S3), Firebase App Hosting, and Vercel +- **Static Export**: Configured with `output: 'export'` for static hosting +- **Deployment**: AWS S3 static hosting ### Key Patterns 1. **UI Components**: Full shadcn/ui component library in `src/components/ui/` 2. **Styling**: Tailwind CSS with custom theme, use `cn()` utility for class merging -3. **Data Fetching**: Server-side fetching in page components with fallback data -4. **Environment Variables**: Only `YOUTUBE_API_KEY` is used +3. **Data Fetching**: Server-side fetching with fallback data, 1-hour cache for YouTube API +4. **Environment Variables**: `YOUTUBE_API_KEY` (required), `S3_BUCKET_NAME` (for deployment) 5. **Path Alias**: Use `@/` for imports from `src/` directory +### Build & Deployment Details +- **Version Tracking**: Build process injects git commit hash into footer via `scripts/set-git-commit.js` +- **Static Files**: Build outputs to `out/` directory for S3 deployment +- **Build Errors**: TypeScript and ESLint errors are ignored (configured in next.config.ts) +- **S3 Deployment**: Uses dotenv-cli to load environment variables from `.env.local` +- **Pre-commit Hooks**: Husky installed for running lint checks before commits + ### Development Notes -- **Build Configuration**: TypeScript and ESLint errors are ignored during builds -- **YouTube API**: Gallery and Dadvocate pages fetch video data with 1-hour cache -- **AI Integration**: Genkit setup exists but is minimally implemented +- **No Testing Framework**: Project currently has no test setup +- **AI Integration**: Genkit configured with Google AI (Gemini 2.0 Flash) but minimally implemented - **Theme**: Dark/light mode support via next-themes -- **Pre-commit**: Husky runs linting before commits +- **Image Optimization**: Configured for YouTube thumbnails and placeholder images ### Adding Features -- New pages: Create directory in `src/app/` with `page.tsx` and metadata export +- New pages: Create directory in `src/app/` with `page.tsx` and export metadata - New components: Add to `src/components/` or use existing shadcn/ui components -- API integration: Use server components with async/await and error handling \ No newline at end of file +- YouTube videos: Update video IDs in gallery/page.tsx or dadvocate/page.tsx, then rebuild + +## Git Workflow & Pull Requests + +### Creating Pull Requests with tea +Use the `tea` command instead of `gh` for all Git operations. When creating PRs: + +```bash +# Create PR with title only (description must be added via web UI) +tea pr create --title "Your PR title" + +# With additional options +tea pr create --title "Your PR title" --base main --head feature-branch + +# Note: tea does not support setting PR description via CLI +# You must add the description through the web interface after creation +``` + +### PR Description Template +After creating a PR with tea, add this description format via the web UI: + +```markdown +## Summary +- Brief bullet points of what this PR does + +## Changes +- Detailed list of changes made +- Files modified/added/deleted +- Implementation details + +## Test plan +- [ ] Steps to test the changes +- [ ] What to verify + +🤖 Generated with [Claude Code](https://claude.ai/code) +``` + +## Code Style Guidelines +- Always use 'tea' instead of 'gh' for Git operations +- Follow existing code patterns and conventions +- Use TypeScript strict mode practices +- Maintain consistent formatting with Prettier/ESLint \ No newline at end of file diff --git a/README.md b/README.md index ac01785..0f0fcc6 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ A Next.js application built to expose harmful activities and support Kristen Jac - **Language**: TypeScript - **UI Components**: shadcn/ui component library - **Styling**: Tailwind CSS with custom theming -- **Hosting**: Supports Static hosting (S3), Firebase App Hosting, and Vercel +- **Hosting**: AWS S3 static hosting - **AI Integration**: Google Genkit (minimal implementation) ## 📋 Prerequisites @@ -89,14 +89,6 @@ This application supports multiple deployment platforms: ### Static Hosting (AWS S3) The project includes CI/CD workflow for automatic deployment to AWS S3. -### Firebase App Hosting -Deploy using Firebase CLI: -```bash -firebase deploy -``` - -### Vercel -Deploy directly from Git repository through Vercel dashboard or CLI. ## 📁 Project Structure diff --git a/apphosting.yaml b/apphosting.yaml deleted file mode 100644 index a55af7b..0000000 --- a/apphosting.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# Settings to manage and configure a Firebase App Hosting backend. -# https://firebase.google.com/docs/app-hosting/configure - -runConfig: - # Increase this value if you'd like to automatically spin up - # more instances in response to increased traffic. - maxInstances: 1 diff --git a/package-lock.json b/package-lock.json index 08d33db..9af84c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,6 @@ "date-fns": "^3.6.0", "dotenv": "^16.5.0", "embla-carousel-react": "^8.6.0", - "firebase": "^11.9.1", "genkit": "^1.13.0", "lucide-react": "^0.475.0", "next": "15.3.3", @@ -59,6 +58,7 @@ "aws-cdk-lib": "^2.189.1", "constructs": "^10.4.2", "cross-env": "^7.0.3", + "dotenv-cli": "^8.0.0", "esbuild": "^0.25.5", "eslint": "^9.30.0", "eslint-config-next": "15.3.4", @@ -163,21 +163,6 @@ "kuler": "^2.0.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "dev": true, @@ -381,538 +366,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@firebase/ai": { - "version": "1.4.0", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" - } - }, - "node_modules/@firebase/analytics": { - "version": "0.10.16", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/installations": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/analytics-compat": { - "version": "0.2.22", - "license": "Apache-2.0", - "dependencies": { - "@firebase/analytics": "0.10.16", - "@firebase/analytics-types": "0.8.3", - "@firebase/component": "0.6.17", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/analytics-types": { - "version": "0.8.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app": { - "version": "0.13.1", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/app-check": { - "version": "0.10.0", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/app-check-compat": { - "version": "0.3.25", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check": "0.10.0", - "@firebase/app-check-types": "0.5.3", - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/app-check-interop-types": { - "version": "0.3.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app-check-types": { - "version": "0.5.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app-compat": { - "version": "0.4.1", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app": "0.13.1", - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/app-types": { - "version": "0.9.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app/node_modules/idb": { - "version": "7.1.1", - "license": "ISC" - }, - "node_modules/@firebase/auth-compat": { - "version": "0.5.27", - "license": "Apache-2.0", - "dependencies": { - "@firebase/auth": "1.10.7", - "@firebase/auth-types": "0.13.0", - "@firebase/component": "0.6.17", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/auth-compat/node_modules/@firebase/auth": { - "version": "1.10.7", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^1.18.1" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } - } - }, - "node_modules/@firebase/auth-interop-types": { - "version": "0.2.4", - "license": "Apache-2.0" - }, - "node_modules/@firebase/auth-types": { - "version": "0.13.0", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/component": { - "version": "0.6.17", - "license": "Apache-2.0", - "dependencies": { - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/data-connect": { - "version": "0.3.9", - "license": "Apache-2.0", - "dependencies": { - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/database": { - "version": "1.0.19", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "faye-websocket": "0.11.4", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/database-compat": { - "version": "2.0.10", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/database": "1.0.19", - "@firebase/database-types": "1.0.14", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/database-types": { - "version": "1.0.14", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-types": "0.9.3", - "@firebase/util": "1.12.0" - } - }, - "node_modules/@firebase/firestore": { - "version": "4.7.17", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "@firebase/webchannel-wrapper": "1.0.3", - "@grpc/grpc-js": "~1.9.0", - "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/firestore-compat": { - "version": "0.3.52", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/firestore": "4.7.17", - "@firebase/firestore-types": "3.0.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/firestore-types": { - "version": "3.0.3", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/functions": { - "version": "0.12.8", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.17", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/functions-compat": { - "version": "0.3.25", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/functions": "0.12.8", - "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/functions-types": { - "version": "0.6.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/installations": { - "version": "0.6.17", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/util": "1.12.0", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/installations-compat": { - "version": "0.2.17", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/installations": "0.6.17", - "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/installations-types": { - "version": "0.5.3", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x" - } - }, - "node_modules/@firebase/installations/node_modules/idb": { - "version": "7.1.1", - "license": "ISC" - }, - "node_modules/@firebase/logger": { - "version": "0.4.4", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/messaging": { - "version": "0.12.21", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/installations": "0.6.17", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.12.0", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/messaging-compat": { - "version": "0.2.21", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/messaging": "0.12.21", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/messaging/node_modules/idb": { - "version": "7.1.1", - "license": "ISC" - }, - "node_modules/@firebase/performance": { - "version": "0.7.6", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/installations": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0", - "web-vitals": "^4.2.4" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/performance-compat": { - "version": "0.2.19", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/performance": "0.7.6", - "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/performance-types": { - "version": "0.2.3", - "license": "Apache-2.0" - }, - "node_modules/@firebase/remote-config": { - "version": "0.6.4", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/installations": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/remote-config-compat": { - "version": "0.2.17", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/remote-config": "0.6.4", - "@firebase/remote-config-types": "0.4.0", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/remote-config-types": { - "version": "0.4.0", - "license": "Apache-2.0" - }, - "node_modules/@firebase/storage": { - "version": "0.13.13", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/storage-compat": { - "version": "0.3.23", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/storage": "0.13.13", - "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/storage-types": { - "version": "0.8.3", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/util": { - "version": "1.12.0", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.3", - "license": "Apache-2.0" - }, "node_modules/@floating-ui/core": { "version": "1.7.1", "license": "MIT", @@ -1395,74 +848,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.1.0", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.1.0", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.2", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.1.0" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.2", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.1.0" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "license": "ISC", @@ -1947,10 +1332,11 @@ }, "node_modules/@next/swc-linux-x64-gnu": { "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.3.tgz", + "integrity": "sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -1961,10 +1347,11 @@ }, "node_modules/@next/swc-linux-x64-musl": { "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.3.tgz", + "integrity": "sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==", "cpu": [ "x64" ], - "license": "MIT", "optional": true, "os": [ "linux" @@ -4346,18 +3733,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.9.2", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "license": "BSD-2-Clause" @@ -6011,6 +5386,32 @@ "url": "https://dotenvx.com" } }, + "node_modules/dotenv-cli": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-8.0.0.tgz", + "integrity": "sha512-aLqYbK7xKOiTMIRf1lDPbI+Y+Ip/wo5k3eyp6ePysVaSqbyxjyK3dK35BTxG+rmd7djf5q2UPs4noPNH+cj0Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6", + "dotenv": "^16.3.0", + "dotenv-expand": "^10.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "dotenv": "cli.js" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/dotprompt": { "version": "1.1.1", "license": "ISC", @@ -7170,16 +6571,6 @@ "reusify": "^1.0.4" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/fd-slicer": { "version": "1.1.0", "dev": true, @@ -7269,62 +6660,6 @@ "micromatch": "^4.0.2" } }, - "node_modules/firebase": { - "version": "11.9.1", - "license": "Apache-2.0", - "dependencies": { - "@firebase/ai": "1.4.0", - "@firebase/analytics": "0.10.16", - "@firebase/analytics-compat": "0.2.22", - "@firebase/app": "0.13.1", - "@firebase/app-check": "0.10.0", - "@firebase/app-check-compat": "0.3.25", - "@firebase/app-compat": "0.4.1", - "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.10.7", - "@firebase/auth-compat": "0.5.27", - "@firebase/data-connect": "0.3.9", - "@firebase/database": "1.0.19", - "@firebase/database-compat": "2.0.10", - "@firebase/firestore": "4.7.17", - "@firebase/firestore-compat": "0.3.52", - "@firebase/functions": "0.12.8", - "@firebase/functions-compat": "0.3.25", - "@firebase/installations": "0.6.17", - "@firebase/installations-compat": "0.2.17", - "@firebase/messaging": "0.12.21", - "@firebase/messaging-compat": "0.2.21", - "@firebase/performance": "0.7.6", - "@firebase/performance-compat": "0.2.19", - "@firebase/remote-config": "0.6.4", - "@firebase/remote-config-compat": "0.2.17", - "@firebase/storage": "0.13.13", - "@firebase/storage-compat": "0.3.23", - "@firebase/util": "1.12.0" - } - }, - "node_modules/firebase/node_modules/@firebase/auth": { - "version": "1.10.7", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.17", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.12.0", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^1.18.1" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } - } - }, "node_modules/flat-cache": { "version": "4.0.1", "dev": true, @@ -8028,10 +7363,6 @@ "node": ">= 0.8" } }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "license": "MIT" - }, "node_modules/http-proxy-agent": { "version": "5.0.0", "dev": true, @@ -11923,33 +11254,10 @@ "node": ">= 8" } }, - "node_modules/web-vitals": { - "version": "4.2.4", - "license": "Apache-2.0" - }, "node_modules/webidl-conversions": { "version": "3.0.1", "license": "BSD-2-Clause" }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "license": "Apache-2.0", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "license": "MIT", diff --git a/package.json b/package.json index 0f57edf..c918fea 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "start": "next start", "lint": "next lint", "typecheck": "tsc --noEmit", - "deploy:s3": "npm run build && aws s3 sync out/ s3://$S3_BUCKET_NAME --delete", + "deploy:s3": "npm run build && dotenv -e .env.local -- aws s3 sync out/ s3://$S3_BUCKET_NAME --delete", "create-s3-bucket": "node scripts/create-s3-bucket.js", "prepare": "husky install" }, @@ -45,7 +45,6 @@ "date-fns": "^3.6.0", "dotenv": "^16.5.0", "embla-carousel-react": "^8.6.0", - "firebase": "^11.9.1", "genkit": "^1.13.0", "lucide-react": "^0.475.0", "next": "15.3.3", @@ -67,6 +66,7 @@ "aws-cdk-lib": "^2.189.1", "constructs": "^10.4.2", "cross-env": "^7.0.3", + "dotenv-cli": "^8.0.0", "esbuild": "^0.25.5", "eslint": "^9.30.0", "eslint-config-next": "15.3.4", diff --git a/tsconfig.json b/tsconfig.json index c133409..9aed7fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2017", + "target": "ES2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, @@ -13,6 +13,7 @@ "isolatedModules": true, "jsx": "preserve", "incremental": true, + "tsBuildInfoFile": ".next/types/tsbuildinfo", "plugins": [ { "name": "next"