Merge pull request 'Remove Firebase and Vercel deployment options' (#8) from feature/remove-firebase-vercel into main
All checks were successful
CI / test (push) Successful in 3m40s
Deploy / deploy (push) Successful in 3m43s

Reviewed-on: #8
This commit is contained in:
Decobus 2025-07-18 08:04:13 +03:00
commit f9527a9d4e
9 changed files with 129 additions and 797 deletions

View file

@ -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": []
}

View file

@ -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: ""
NODE_OPTIONS: '--max-old-space-size=4096'
NEXT_TELEMETRY_DISABLED: 1

View file

@ -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: |

View file

@ -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
- 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

View file

@ -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

View file

@ -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

754
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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"