diff --git a/.env.example b/.env.example
index 8b4fa3af..e895149f 100644
--- a/.env.example
+++ b/.env.example
@@ -5,13 +5,7 @@
# ── Site ──────────────────────────────────────────
NEXT_PUBLIC_SITE_URL=http://localhost:3000
-# ── Firebase (analytics — public client config) ──
-NEXT_PUBLIC_FIREBASE_API_KEY=
-NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
-NEXT_PUBLIC_FIREBASE_PROJECT_ID=
-NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
-NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
-NEXT_PUBLIC_FIREBASE_APP_ID=
+# ── Google Analytics (GA4 measurement ID, e.g. G-XXXXXXXXXX) ──
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=
# ── AI (required for chat and insights) ──────────
diff --git a/.github/workflows/README.md b/.github/workflows/README.md
index 44d9ab1b..d6e1efec 100644
--- a/.github/workflows/README.md
+++ b/.github/workflows/README.md
@@ -10,13 +10,7 @@ The `copilot-test.yml` workflow provides a standardized testing environment for
Go to **Settings > Secrets and variables > Actions > Repository secrets** and add:
-**Firebase (Client-side):**
-- `NEXT_PUBLIC_FIREBASE_API_KEY`
-- `NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN`
-- `NEXT_PUBLIC_FIREBASE_PROJECT_ID`
-- `NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET`
-- `NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID`
-- `NEXT_PUBLIC_FIREBASE_APP_ID`
+**Google Analytics (Client-side):**
- `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID`
**Google Sheets (Server-side):**
diff --git a/.github/workflows/copilot-test.yml b/.github/workflows/copilot-test.yml
index d67e28be..e660c64a 100644
--- a/.github/workflows/copilot-test.yml
+++ b/.github/workflows/copilot-test.yml
@@ -31,13 +31,7 @@ jobs:
# Test XPUB for wallet testing
TEST_XPUB: ${{ vars.TEST_XPUB }}
- # Firebase (Client-side) - Public configuration
- NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
- NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
- NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
- NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
- NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
- NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
+ # Google Analytics (Client-side) - Public GA4 measurement ID
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
# Google Sheets (Server-side) - Private
@@ -77,13 +71,7 @@ jobs:
- name: Create .env.local file
run: |
cat > .env.local << EOF
- # Firebase (Client-side)
- NEXT_PUBLIC_FIREBASE_API_KEY="${NEXT_PUBLIC_FIREBASE_API_KEY}"
- NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN="${NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN}"
- NEXT_PUBLIC_FIREBASE_PROJECT_ID="${NEXT_PUBLIC_FIREBASE_PROJECT_ID}"
- NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET="${NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET}"
- NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID="${NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID}"
- NEXT_PUBLIC_FIREBASE_APP_ID="${NEXT_PUBLIC_FIREBASE_APP_ID}"
+ # Google Analytics (Client-side)
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID="${NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID}"
# Google Sheets (Server-side)
@@ -153,10 +141,10 @@ jobs:
echo "- ❌ GOOGLE_GENAI_API_KEY: Not configured" >> $GITHUB_STEP_SUMMARY
fi
- if [ -n "$NEXT_PUBLIC_FIREBASE_API_KEY" ]; then
- echo "- ✅ Firebase: Configured" >> $GITHUB_STEP_SUMMARY
+ if [ -n "$NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID" ]; then
+ echo "- ✅ Google Analytics: Configured" >> $GITHUB_STEP_SUMMARY
else
- echo "- ❌ Firebase: Not configured" >> $GITHUB_STEP_SUMMARY
+ echo "- ❌ Google Analytics: Not configured" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
diff --git a/AGENTS.md b/AGENTS.md
index 03266bd1..b41f63bd 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -165,13 +165,7 @@ Create a `.env` file in the project root with the following variables:
# Site Configuration
NEXT_PUBLIC_SITE_URL=http://localhost:3000
-# Firebase (required for analytics)
-NEXT_PUBLIC_FIREBASE_API_KEY=your_firebase_api_key
-NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
-NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
-NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
-NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
-NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
+# Google Analytics (GA4 measurement ID; required for analytics)
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX
# OpenAI / Genkit (required for AI features)
@@ -470,7 +464,7 @@ docker build -t bitsleuth-analyzer .
# Run container
docker run -p 3000:3000 \
-e OPENAI_API_KEY=your_key \
- -e NEXT_PUBLIC_FIREBASE_API_KEY=your_key \
+ -e NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX \
bitsleuth-analyzer
```
@@ -534,7 +528,7 @@ For detailed contribution guidelines, including documentation standards and file
### Common Issues
**Analytics Warning in Browser**
-- Ensure `NEXT_PUBLIC_FIREBASE_API_KEY` and `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` are set
+- Ensure `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` is set
- Restart dev server after adding environment variables
**AI Features Not Working**
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f17bd605..28322e84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,18 @@ All notable changes to BitSleuth - AI Bitcoin Wallet Analyzer will be documented
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Changed
+
+#### Analytics
+- Migrated analytics from the Firebase SDK to native Google Analytics (GA4) via
+ `@next/third-parties/google`. Analytics now requires only
+ `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID`; the other `NEXT_PUBLIC_FIREBASE_*`
+ variables (API key, app ID, auth domain, project ID, storage bucket, messaging
+ sender ID) are no longer needed and have been removed from config and docs.
+- Removed the `firebase` npm dependency (`@genkit-ai/firebase` is unaffected).
+
## [1.2.1] - 2026-06-12
### Added
diff --git a/CLAUDE.md b/CLAUDE.md
index f17138b4..7ab6544a 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -58,7 +58,7 @@ npm run dev:clean # Clean .next cache and start dev
| **Styling** | Tailwind CSS 4, shadcn/ui, Radix UI, Lucide Icons |
| **AI** | Genkit 1.24+, OpenAI GPT-4.1 Mini |
| **Bitcoin** | bitcoinjs-lib, bip32, secp256k1 |
-| **Data APIs** | Blockstream, mempool.space, CoinGecko, Firebase (analytics only) |
+| **Data APIs** | Blockstream, mempool.space, CoinGecko, Google Analytics (GA4) |
| **Testing** | Vitest (unit), Playwright (E2E) |
| **Build** | Turbopack |
@@ -114,7 +114,7 @@ src/
│ └── wallet-context.tsx # Global wallet state
│
├── hooks/
-│ ├── use-analytics.ts # Firebase analytics
+│ ├── use-analytics.ts # Google Analytics (GA4) event tracking
│ ├── use-chunk-retry.ts # Chunked data fetching
│ ├── use-mobile.tsx # Mobile detection
│ └── use-toast.ts # Toast notifications
@@ -125,7 +125,6 @@ src/
│ ├── market.ts # Market data service (CoinGecko)
│ ├── mempool.ts # Mempool data service
│ ├── newsService.ts # News API (CryptoCompare)
-│ ├── firebase.ts # Firebase initialization
│ ├── bitcoin-init.ts # Bitcoin library setup
│ ├── cache-utils.ts # Client-side caching
│ ├── chunk-retry-service.ts # Chunked retry logic
@@ -288,13 +287,7 @@ Required variables in `.env`:
# Site
NEXT_PUBLIC_SITE_URL=http://localhost:3000
-# Firebase (required for analytics)
-NEXT_PUBLIC_FIREBASE_API_KEY=...
-NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=...
-NEXT_PUBLIC_FIREBASE_PROJECT_ID=...
-NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=...
-NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=...
-NEXT_PUBLIC_FIREBASE_APP_ID=...
+# Google Analytics (GA4 measurement ID, required for analytics)
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=...
# OpenAI (required for AI features)
@@ -309,7 +302,7 @@ GOOGLE_SHEETS_PRIVATE_KEY=...
```
**Notes:**
-- Firebase keys are public client config (safe for browser)
+- The GA4 measurement ID is public client config (safe for browser)
- Missing optional keys show non-blocking warnings
- Copy `.env.example` as starting point
@@ -410,7 +403,7 @@ The codebase implements several performance optimizations:
| Issue | Solution |
|-------|----------|
| AI features not working | Ensure `npm run genkit:dev` is running and `OPENAI_API_KEY` is set |
-| Analytics warning | Set Firebase environment variables |
+| Analytics warning | Set `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` |
| Build errors | Run `npm run dev:clean` or delete `node_modules` and reinstall |
| Type errors | Run `npm run typecheck` for details |
| News not loading | Set `CRYPTOCOMPARE_API_KEY` |
diff --git a/README.md b/README.md
index 0e94b750..a2dcfe24 100644
--- a/README.md
+++ b/README.md
@@ -79,19 +79,13 @@ For VS Code users, install the recommended "Tailwind CSS IntelliSense" extension
## Environment variables
-Create a `.env` file in the project root. Only the public Firebase keys are required for analytics; other keys enable additional features.
+Create a `.env` file in the project root. Only the GA4 measurement ID is required for analytics; other keys enable additional features.
```env
# Site
NEXT_PUBLIC_SITE_URL=http://localhost:3000
-# Firebase (analytics; all are public client config)
-NEXT_PUBLIC_FIREBASE_API_KEY=
-NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=
-NEXT_PUBLIC_FIREBASE_PROJECT_ID=
-NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=
-NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
-NEXT_PUBLIC_FIREBASE_APP_ID=
+# Google Analytics (GA4 measurement ID, e.g. G-XXXXXXXXXX)
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=
# OpenAI / Genkit (required for AI features)
@@ -111,7 +105,7 @@ GOOGLE_SHEETS_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KE
```
Notes:
-- Without `NEXT_PUBLIC_FIREBASE_API_KEY` and `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID`, analytics will be disabled and a non-blocking warning will appear in-app.
+- Without `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID`, analytics will be disabled and a non-blocking warning will appear in-app.
- `COINGECKO_API_KEY` is optional and, when present, is added to CoinGecko requests.
- `CRYPTOCOMPARE_API_KEY` enables the News panel with live data; otherwise a helpful message is shown.
- Google Sheets export is optional; if unset, feedback stays local and the app continues to work.
@@ -157,7 +151,7 @@ Notes:
## Troubleshooting
-- Missing analytics warning: set `NEXT_PUBLIC_FIREBASE_API_KEY` and `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` and restart dev server.
+- Missing analytics warning: set `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` and restart dev server.
- News panel shows configuration message: set `CRYPTOCOMPARE_API_KEY`.
- Google Sheets export fails: verify sheet ID, service account email access, and private key formatting (preserve newlines).
diff --git a/SECURITY.md b/SECURITY.md
index 09efb8d8..cbb296b2 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -53,7 +53,7 @@ Send an email to **security@bitsleuth.ai** with the following information:
### Server-Side API Key Isolation
- Sensitive API keys (`OPENAI_API_KEY`, `GOOGLE_SHEETS_PRIVATE_KEY`, `COINGECKO_API_KEY`, `CRYPTOCOMPARE_API_KEY`) are server-side only, accessed via `process.env` (never prefixed with `NEXT_PUBLIC_`)
-- Firebase configuration keys (`NEXT_PUBLIC_FIREBASE_*`) are public client config designed by Google to be safe for browser exposure — they only enable anonymous analytics collection
+- The Google Analytics measurement ID (`NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID`) is public client config designed to be safe for browser exposure — it only enables anonymous analytics collection
### Security Headers
@@ -119,7 +119,7 @@ All blockchain data is fetched from public, read-only APIs:
## Environment Variables
**Public client configuration (safe for browser):**
-- `NEXT_PUBLIC_FIREBASE_*` — Firebase Analytics client config
+- `NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID` — Google Analytics (GA4) measurement ID
- `NEXT_PUBLIC_SITE_URL` — Application URL
**Server-side secrets (must not be exposed to client):**
diff --git a/apphosting.dev.yaml b/apphosting.dev.yaml
index d746d892..9a294522 100644
--- a/apphosting.dev.yaml
+++ b/apphosting.dev.yaml
@@ -8,24 +8,6 @@ runConfig:
# Environment variables and secrets
env:
- - variable: NEXT_PUBLIC_FIREBASE_API_KEY
- secret: NEXT_PUBLIC_FIREBASE_API_KEY
-
- - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
- secret: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
-
- - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
- secret: NEXT_PUBLIC_FIREBASE_PROJECT_ID
-
- - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
- secret: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
-
- - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
- secret: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
-
- - variable: NEXT_PUBLIC_FIREBASE_APP_ID
- secret: NEXT_PUBLIC_FIREBASE_APP_ID_DEV
-
- variable: NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
secret: NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID_DEV
@@ -46,7 +28,3 @@ env:
- variable: OPENAI_API_KEY
secret: OPENAI_API_KEY
-
- # Backward compatibility for deployments using the ChatGPT-specific key name
- - variable: OPENAI_CHATGPT_API_KEY
- secret: OPENAI_API_KEY
diff --git a/apphosting.prd.yaml b/apphosting.prd.yaml
index 7d0ebd58..d412ffa5 100644
--- a/apphosting.prd.yaml
+++ b/apphosting.prd.yaml
@@ -8,24 +8,6 @@ runConfig:
# Environment variables and secrets
env:
- - variable: NEXT_PUBLIC_FIREBASE_API_KEY
- secret: NEXT_PUBLIC_FIREBASE_API_KEY
-
- - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
- secret: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
-
- - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
- secret: NEXT_PUBLIC_FIREBASE_PROJECT_ID
-
- - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
- secret: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
-
- - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
- secret: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
-
- - variable: NEXT_PUBLIC_FIREBASE_APP_ID
- secret: NEXT_PUBLIC_FIREBASE_APP_ID
-
- variable: NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
secret: NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
@@ -46,7 +28,3 @@ env:
- variable: OPENAI_API_KEY
secret: OPENAI_API_KEY
-
- # Backward compatibility for deployments using the ChatGPT-specific key name
- - variable: OPENAI_CHATGPT_API_KEY
- secret: OPENAI_API_KEY
diff --git a/package-lock.json b/package-lock.json
index 4c887761..67a3d07d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"@genkit-ai/firebase": "^1.36.0",
"@genkit-ai/next": "^1.36.0",
"@hookform/resolvers": "^5.4.0",
+ "@next/third-parties": "^16.2.6",
"@opentelemetry/winston-transport": "^0.28.0",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
@@ -46,7 +47,6 @@
"dotenv": "^17.4.2",
"ecpair": "^3.0.1",
"embla-carousel-react": "^8.6.0",
- "firebase": "^12.13.0",
"genkit": "^1.36.0",
"google-auth-library": "^10.2.0",
"googleapis": "^171.0.0",
@@ -1030,630 +1030,6 @@
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@firebase/ai": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.13.0.tgz",
- "integrity": "sha512-nJJDQKqjAcbkZdZGT/5WTVLrGZ+pYhWbwKC90nNzmvtoRTtnOJaNS34fhKSHQeB9SALgD2kxuWT5I4AkytdZ/Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.4",
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x",
- "@firebase/app-types": "0.x"
- }
- },
- "node_modules/@firebase/analytics": {
- "version": "0.10.22",
- "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.22.tgz",
- "integrity": "sha512-8BSaq/QRGU1+xyi8L2PTLTJU7MH9aMA72RQdIxrbhWFauOZY9OXo8f2YDN/972xA8d588tlnNVEQ2Mo69pT9Ow==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/installations": "0.6.22",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/analytics-compat": {
- "version": "0.2.28",
- "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.28.tgz",
- "integrity": "sha512-lIAlqUUbBu93FJMlQfslryQtBwwzdzvp23ePC6FNgymXk6Ook5v4Uvc0vdutvoIeqmyA3LfP0ZeRFK8+11kOOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/analytics": "0.10.22",
- "@firebase/analytics-types": "0.8.4",
- "@firebase/component": "0.7.3",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/analytics-types": {
- "version": "0.8.4",
- "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.4.tgz",
- "integrity": "sha512-zQ+XTgkwH6CY/eUSHJRP7e4LxM30RCxlCmob5sy2axs25GE3Ny0XdgpDscMTHHQIGqWkxPXad4w2Mw9sCgT8zQ==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/app": {
- "version": "0.14.13",
- "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.13.tgz",
- "integrity": "sha512-H89Jeyp31+EZk9GPu6vaeL9mEmoXgM3nASB7UPBYYS/lqAks21mO1BU1dF8NbsVTL6tgGZkGUtiGJgxtDiwHkw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "idb": "7.1.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/app-check": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.11.4.tgz",
- "integrity": "sha512-G8EsbVJV9gSfoibx0dNoNOUrvr+PkL7J//+W/BST/oUassimkZeq9bjj3bKkB0pn4og5GMQ9qs7FefwP00kkgg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/app-check-compat": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.4.4.tgz",
- "integrity": "sha512-9iP0MvmaVagulNXmrca96U3tqNAI3j98wsC1z7rj62nnOTajlrHM//jjB9VoHqRw6/islMskp6RsKnM7vhLDqA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check": "0.11.4",
- "@firebase/app-check-types": "0.5.4",
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/app-check-interop-types": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.4.tgz",
- "integrity": "sha512-zz3i6e13B8BfWiLy8MABtTh8aGIACgKbf9UVnyHcWs+yQzJXgQcl8A46b0zfaiJHdQ+niF0ouAfcpuf+3LMPQg==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/app-check-types": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.4.tgz",
- "integrity": "sha512-xV7JsIyzVr15aA7f3Pi0rB9gdBuVubs89FGA8VkRYA4g0l78poADgdfrScgf7NndSg9mm7cR7PJyY0+t22KaGw==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/app-compat": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.13.tgz",
- "integrity": "sha512-pn3FvXwUR34kWPccDQfCKsNZcM2wD1OS+J1jeEgzM1ZNXoxR2NaF6e5DjDuRrnTwR6LN2XQQt0IqE6yKmgpCQg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app": "0.14.13",
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/app-types": {
- "version": "0.9.5",
- "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.5.tgz",
- "integrity": "sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/logger": "0.5.1"
- }
- },
- "node_modules/@firebase/auth": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.13.2.tgz",
- "integrity": "sha512-B4w0iS7MxRg28oIh2fJFTE6cM0lYdBrW19eHpc42jqEcloUjlYyVrpPqZvqA4+v9KFEVSKEs2SfWyta7hbzkJQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x",
- "@react-native-async-storage/async-storage": "^2.2.0 || ^3.0.0"
- },
- "peerDependenciesMeta": {
- "@react-native-async-storage/async-storage": {
- "optional": true
- }
- }
- },
- "node_modules/@firebase/auth-compat": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.6.7.tgz",
- "integrity": "sha512-XgKnOgY1Siq7gylAmLkYtHAlRxNeWEAspH+nO3gJZJnfHqoTHbr9UjJ3nHNFALYXV5CfpQlyPROyB2ztySBHBQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/auth": "1.13.2",
- "@firebase/auth-types": "0.13.1",
- "@firebase/component": "0.7.3",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/auth-interop-types": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.5.tgz",
- "integrity": "sha512-1Li/YuBDBAXcKv7BzY4U28gontUmAaw53sYiqbaVOMCFb2lFKK/c3CGMUWqtwe7+TXrl3poWnTCL5umYBg85Eg==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/auth-types": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.1.tgz",
- "integrity": "sha512-0c1Mnid0uMDfGJHeUS4zfvBa4/CedJXotGy/n/NZJnBjwiJawt0ZYU+wH2VAVLiRCEfG2ncCkAX3yd1/2nrB7g==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
- "node_modules/@firebase/component": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.3.tgz",
- "integrity": "sha512-wFofIaa2879ogD/WvkjYXJxRmfnL0scen6ORgaC3na1FNOR9ASIUANQdhqQcmWu/h77/pVHY7ch5flewa5Bcew==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/data-connect": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.7.1.tgz",
- "integrity": "sha512-2LbUU8mmSA63HknxQMmWHjpzuNLBKflvVwQc2tpoVKg0biWleNEJX031ELks0vzFs+dDjOUkCJR72RP6mQHFOg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/auth-interop-types": "0.2.5",
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/database": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.3.tgz",
- "integrity": "sha512-XwWCa+E4TvNGpGwXrycLRNfdogADwFcvuhyow6wDWma9W54roaQIhe+4PM0KiLsIftBdSCGI7OKCXrdSRHbIhw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.4",
- "@firebase/auth-interop-types": "0.2.5",
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "faye-websocket": "0.11.4",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/database-compat": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.4.tgz",
- "integrity": "sha512-3pK35F1MAgmqFJQlf2nhQl44vtAXQO1uaCaQOEUI9kCRtLFqi7N+QRKR7lFZPg+xIZIyubgxQaxY69YgfZRZWg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/database": "1.1.3",
- "@firebase/database-types": "1.0.20",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/database-types": {
- "version": "1.0.20",
- "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.20.tgz",
- "integrity": "sha512-kegbOk/w8iU64pr0q6k2ItyNGjnQBMHFhwS7ohdWI4W+pc0/zhhdGXTdFj6X1oxItRjPoYOsSQmERgBkn/ihxw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-types": "0.9.5",
- "@firebase/util": "1.15.1"
- }
- },
- "node_modules/@firebase/firestore": {
- "version": "4.15.0",
- "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.15.0.tgz",
- "integrity": "sha512-Fj9osqYkz2Rqr7kW3/A8BRd8CyJ7yA5K8YjhihRdyJWbL+FsELVcR6DpoCplrp1IyU+xeGgTubo1UOySXpY+EA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "@firebase/webchannel-wrapper": "1.0.6",
- "@grpc/grpc-js": "~1.9.0",
- "@grpc/proto-loader": "^0.7.8",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/firestore-compat": {
- "version": "0.4.10",
- "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.10.tgz",
- "integrity": "sha512-yMP3FADDjikdrQv4YmvL4EkIny6Hw+N+a2O5T40rlHiniyMpRPxgYkKiFOvMZnsqKLqBVnKqCAElC0pa/IZtdw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/firestore": "4.15.0",
- "@firebase/firestore-types": "3.0.4",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/firestore-types": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.4.tgz",
- "integrity": "sha512-jGn+JSS4X9zZsrfu7Yw66v5YRdOLD1oyQh4USR0xWl4CUqV/DA6bNIXRPpxH/cUl3iVTNiP6MN7g+EL42A4qfA==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
- "node_modules/@firebase/firestore/node_modules/@grpc/grpc-js": {
- "version": "1.9.16",
- "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.16.tgz",
- "integrity": "sha512-wE4Ut/olIzfKqp631XrG+wbF0v1vWFN4YL9FyXC2LJiG33DsV7PLzURjrCvY/6je2ntdRkeLpPDluzSRGaVltQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@grpc/proto-loader": "^0.7.8",
- "@types/node": ">=12.12.47"
- },
- "engines": {
- "node": "^8.13.0 || >=10.10.0"
- }
- },
- "node_modules/@firebase/functions": {
- "version": "0.13.5",
- "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.13.5.tgz",
- "integrity": "sha512-bWCx713f4kE/uFV7gdFOLBS7lDoiZj48MRkbAqe35gkXcCeWF4QjRNO07Jhmve7EJIoQOBczL29y2r8VRuN1kw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.4",
- "@firebase/auth-interop-types": "0.2.5",
- "@firebase/component": "0.7.3",
- "@firebase/messaging-interop-types": "0.2.5",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/functions-compat": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.4.5.tgz",
- "integrity": "sha512-10qlUXGY25G5/1g9UihqksPp2po+ZqSE7LEizsrdUP7vrTmkysXxGSZCDyojSEp6mQe/ecRDdDDI+z4XRdb4wQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/functions": "0.13.5",
- "@firebase/functions-types": "0.6.4",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/functions-types": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.4.tgz",
- "integrity": "sha512-zV6kgqtduR4rUAdC/ilS7kmb93XD7bEZoJDlVBZqlOw2uGGGCNBQBuleww2rr0Ulr3L9o2TDjumEt68/l1f9DQ==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/installations": {
- "version": "0.6.22",
- "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.22.tgz",
- "integrity": "sha512-ef6nn3GGQTdReCfotRMG77PJZu8CqEbiK5pEoBnM0gTu/Z9v0i/az2p3HABsa/1beQmmyh1OsOjf7P5+pgwdZw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/util": "1.15.1",
- "idb": "7.1.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/installations-compat": {
- "version": "0.2.22",
- "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.22.tgz",
- "integrity": "sha512-C/zpAuTP5S9OgKSPvXRupw3hoY/JZSlA1wFjD/Sb7LIQE0FNbcMdO8Y4KXVEkjVzma/DDDDIAzxEXqKMAzc88w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/installations": "0.6.22",
- "@firebase/installations-types": "0.5.4",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/installations-types": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.4.tgz",
- "integrity": "sha512-U2eFapdHwjb43Vx9o+Pmj4dFfvcHEK1IirEFLqMtWrTHvmdrS3gBpBD1kmJk/9HjsOtoHZxJ2Paoe79e+L1ZPg==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x"
- }
- },
- "node_modules/@firebase/logger": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.1.tgz",
- "integrity": "sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/messaging": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.13.0.tgz",
- "integrity": "sha512-GZoo0uGRvEbszo83xcgbjJp4FpkmBEr4l8Z4hi8gl+P1Spn/MTK3HapanMzSX4yUHuTEiF5hasWRxOaz+o5sxQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/installations": "0.6.22",
- "@firebase/messaging-interop-types": "0.2.5",
- "@firebase/util": "1.15.1",
- "idb": "7.1.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/messaging-compat": {
- "version": "0.2.27",
- "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.27.tgz",
- "integrity": "sha512-JNOiu1PPgdHzEPEtoFiNxQuu0x9bm4bfETSQCpGfcTlgWkhlSK7uh7nlsjC10TQLUNgYetLmuutaYTh8aeYLVA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/messaging": "0.13.0",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/messaging-interop-types": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.5.tgz",
- "integrity": "sha512-tUEKnaAP2Y/MNIqgnriPpV6e5l13Vs/+p2yrd6NGlncPJT9O3a8muYZtdnWe+IJ4fgKLHJVC79n/asxk/N5Msw==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/performance": {
- "version": "0.7.12",
- "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.12.tgz",
- "integrity": "sha512-fe7nV8teUU3OBHlMUZ9Lw4gLhCW2k4m5Uc3pfWGV+fl8uwJQBGp9Q3lqsJ+HSrFu3Q2pJyLAgrClPGSKyDeYgQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/installations": "0.6.22",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0",
- "web-vitals": "^4.2.4"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/performance-compat": {
- "version": "0.2.25",
- "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.25.tgz",
- "integrity": "sha512-q6NjTXpIPoFuUmCmMN/maCdTgzT6aExs9xZo+PxfVLj6uLVGvpyAD6XWjmcrb7jChsFBYbq7E5dyNDF7Zhy9kA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/performance": "0.7.12",
- "@firebase/performance-types": "0.2.4",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/performance-types": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.4.tgz",
- "integrity": "sha512-kJSEk7b0uhpcPRyL4SQ/GPujLqk52XNKcXlnsKDbWGAb9vugcLvOU3u6zfEdwd+d8hWJb5S5ZizV1JFFI0nkKg==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/remote-config": {
- "version": "0.8.4",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.8.4.tgz",
- "integrity": "sha512-lslywR5lGvHWTu4z/MPoYs3UwS3CKdeY+ELXY87087VsOpBpkD+9Orra23tA9GW683arPTDOM3CM6eKmtiOO3g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/installations": "0.6.22",
- "@firebase/logger": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/remote-config-compat": {
- "version": "0.2.25",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.25.tgz",
- "integrity": "sha512-FnA5S4IxFJAAFrCnYzWlO0FCaizlYdqhe42ygFMA+wE/mUP+w36iXzHyKj1OO1A+2gyMFjeRHyg8HhkJ6c5vRA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/logger": "0.5.1",
- "@firebase/remote-config": "0.8.4",
- "@firebase/remote-config-types": "0.5.1",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/remote-config-types": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.5.1.tgz",
- "integrity": "sha512-cX/1LT6KQwkXzck2eSzeKnuvXZCyr8qaPpDcikoJs7jmI+oBOXixpDLeDtWj1U6GNMkIoXrEDNoyT2Ypcyp5/A==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/storage": {
- "version": "0.14.3",
- "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.14.3.tgz",
- "integrity": "sha512-YX4/YL6P6/fufSSeGnVhjWddcIXbFq2cWIhMKFTZo1E/Rtcl2mJj/BYUQTwJfcE1Tl8un1FOya4L05jcSLN/Eg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/storage-compat": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.4.3.tgz",
- "integrity": "sha512-gruVqjtUGX8tEoeNbaWXZm0Zfcfcb7fvmDmBxV8yPAbWvExRnZYLO2+qw9idxNE7BvPXt5csyjSYHy//dAizxw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.7.3",
- "@firebase/storage": "0.14.3",
- "@firebase/storage-types": "0.8.4",
- "@firebase/util": "1.15.1",
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/storage-types": {
- "version": "0.8.4",
- "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.4.tgz",
- "integrity": "sha512-BT7cwxJOx8SWwlQfrlC+bD/Sk3Cw+1odCi8UZNFNWTVZoPsBnA5W+mqtZzVnvsdJpXCFGSGQ7R7vOR6dtM/BRA==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
- "node_modules/@firebase/util": {
- "version": "1.15.1",
- "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.15.1.tgz",
- "integrity": "sha512-LUdM4Wg7YM9Pq/49nGYySJA0CSQEKnGffFzWV8+6gXN7mGxn+FL1IqvFbuZUtAQcfZgHYDwCE1wwlK7rB7gl2g==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- },
- "engines": {
- "node": ">=20.0.0"
- }
- },
- "node_modules/@firebase/webchannel-wrapper": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.6.tgz",
- "integrity": "sha512-Vr/Mqu79dMwGRAyGbJ4uN4+BtXB3/mRTdzetD1daWNeG8QaWuzhhbG77GltO5c0yYmYls8i250iX73624GJd7Q==",
- "license": "Apache-2.0"
- },
"node_modules/@floating-ui/core": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
@@ -3879,6 +3255,19 @@
"node": ">= 10"
}
},
+ "node_modules/@next/third-parties": {
+ "version": "16.2.9",
+ "resolved": "https://registry.npmjs.org/@next/third-parties/-/third-parties-16.2.9.tgz",
+ "integrity": "sha512-JZPGQRN8eQs2WMfBXOf6Zjrma+JIN0KyA24MvmIa3bUI4BwTaJ1UlxmYVc5ri6l30LQ8fPv6Kmx20447hCltrg==",
+ "license": "MIT",
+ "dependencies": {
+ "third-party-capital": "1.0.20"
+ },
+ "peerDependencies": {
+ "next": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0-beta.0",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0"
+ }
+ },
"node_modules/@noble/ciphers": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.1.1.tgz",
@@ -11940,18 +11329,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/faye-websocket": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
- "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
- "license": "Apache-2.0",
- "dependencies": {
- "websocket-driver": ">=0.5.1"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
@@ -12091,42 +11468,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/firebase": {
- "version": "12.14.0",
- "resolved": "https://registry.npmjs.org/firebase/-/firebase-12.14.0.tgz",
- "integrity": "sha512-aEZ/lniDR1hOCYpx/x/V8Nrrqq9pepKDNkqP/4WGZFC69gTv6F59Z4/54W/SUP4L/hFlrRNmWj35aweQq+IHow==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/ai": "2.13.0",
- "@firebase/analytics": "0.10.22",
- "@firebase/analytics-compat": "0.2.28",
- "@firebase/app": "0.14.13",
- "@firebase/app-check": "0.11.4",
- "@firebase/app-check-compat": "0.4.4",
- "@firebase/app-compat": "0.5.13",
- "@firebase/app-types": "0.9.5",
- "@firebase/auth": "1.13.2",
- "@firebase/auth-compat": "0.6.7",
- "@firebase/data-connect": "0.7.1",
- "@firebase/database": "1.1.3",
- "@firebase/database-compat": "2.1.4",
- "@firebase/firestore": "4.15.0",
- "@firebase/firestore-compat": "0.4.10",
- "@firebase/functions": "0.13.5",
- "@firebase/functions-compat": "0.4.5",
- "@firebase/installations": "0.6.22",
- "@firebase/installations-compat": "0.2.22",
- "@firebase/messaging": "0.13.0",
- "@firebase/messaging-compat": "0.2.27",
- "@firebase/performance": "0.7.12",
- "@firebase/performance-compat": "0.2.25",
- "@firebase/remote-config": "0.8.4",
- "@firebase/remote-config-compat": "0.2.25",
- "@firebase/storage": "0.14.3",
- "@firebase/storage-compat": "0.4.3",
- "@firebase/util": "1.15.1"
- }
- },
"node_modules/flat-cache": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -13111,12 +12452,6 @@
"url": "https://opencollective.com/express"
}
},
- "node_modules/http-parser-js": {
- "version": "0.5.10",
- "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
- "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
- "license": "MIT"
- },
"node_modules/http-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
@@ -13177,12 +12512,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/idb": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
- "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
- "license": "ISC"
- },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -18223,6 +17552,12 @@
"utrie": "^1.0.2"
}
},
+ "node_modules/third-party-capital": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmjs.org/third-party-capital/-/third-party-capital-1.0.20.tgz",
+ "integrity": "sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA==",
+ "license": "ISC"
+ },
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -19204,41 +18539,12 @@
"node": ">= 8"
}
},
- "node_modules/web-vitals": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
- "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==",
- "license": "Apache-2.0"
- },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
- "node_modules/websocket-driver": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
- "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
- "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",
- "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
- "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
diff --git a/package.json b/package.json
index d56def81..11ffc15b 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"@genkit-ai/firebase": "^1.36.0",
"@genkit-ai/next": "^1.36.0",
"@hookform/resolvers": "^5.4.0",
+ "@next/third-parties": "^16.2.6",
"@opentelemetry/winston-transport": "^0.28.0",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
@@ -70,7 +71,6 @@
"dotenv": "^17.4.2",
"ecpair": "^3.0.1",
"embla-carousel-react": "^8.6.0",
- "firebase": "^12.13.0",
"genkit": "^1.36.0",
"google-auth-library": "^10.2.0",
"googleapis": "^171.0.0",
diff --git a/src/ai/flows/wallet-insights-chat.ts b/src/ai/flows/wallet-insights-chat.ts
index efce1270..33307c59 100644
--- a/src/ai/flows/wallet-insights-chat.ts
+++ b/src/ai/flows/wallet-insights-chat.ts
@@ -2311,7 +2311,7 @@ Return only a JSON object with an "answer" string and optional "followUpSuggesti
} catch (e: any) {
console.error("Error in walletInsightsChatFlow:", e);
const errorMessage = extractErrorMessage(e) || 'Unknown error';
- const isApiKeyError = errorMessage.includes('API key') || errorMessage.includes('OPENAI_API_KEY') || errorMessage.includes('OPENAI_CHATGPT_API_KEY') || errorMessage.includes('401') || errorMessage.includes('403');
+ const isApiKeyError = errorMessage.includes('API key') || errorMessage.includes('OPENAI_API_KEY') || errorMessage.includes('401') || errorMessage.includes('403');
const schemaError = isSchemaValidationError(e);
const formattingError = isFormattingError(e);
@@ -2330,7 +2330,7 @@ Return only a JSON object with an "answer" string and optional "followUpSuggesti
return {
answer: isApiKeyError
- ? "⚠️ **AI Service Configuration Issue**\n\nThe AI chat feature requires a valid OpenAI API key to be configured. Please contact the administrator to set up the OPENAI_API_KEY environment variable (or OPENAI_CHATGPT_API_KEY for backward compatibility).\n\nYou can still use other features of BitSleuth, such as transaction viewing, analysis charts, and security recommendations."
+ ? "⚠️ **AI Service Configuration Issue**\n\nThe AI chat feature requires a valid OpenAI API key to be configured. Please contact the administrator to set up the OPENAI_API_KEY environment variable.\n\nYou can still use other features of BitSleuth, such as transaction viewing, analysis charts, and security recommendations."
: schemaError || formattingError
? "I had trouble formatting that last response, but nothing is wrong with your question. Please try again and I'll keep the answer concise."
: `I'm sorry, I encountered an error while processing your request: ${errorMessage}\n\nPlease try again or rephrase your question.`,
diff --git a/src/ai/genkit.ts b/src/ai/genkit.ts
index 89570e44..35d713eb 100644
--- a/src/ai/genkit.ts
+++ b/src/ai/genkit.ts
@@ -12,16 +12,15 @@ if (process.env.NODE_ENV === 'production') {
}
}
-// Check for API key and fail fast if missing to avoid placeholder configuration
// Check for API key and warn if missing (don't throw to avoid build/import failures)
-const apiKey = process.env.OPENAI_API_KEY || process.env.OPENAI_CHATGPT_API_KEY;
+const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) {
console.warn(
- 'OPENAI_API_KEY (or OPENAI_CHATGPT_API_KEY) is missing. AI features will not work.'
+ 'OPENAI_API_KEY is missing. AI features will not work.'
);
}
-// OpenAI configuration - uses OPENAI_API_KEY (with OPENAI_CHATGPT_API_KEY as a fallback) from environment
+// OpenAI configuration - uses OPENAI_API_KEY from environment
export const ai = genkit({
plugins: [
openAI({
diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx
index 6f10d356..f28e268c 100644
--- a/src/app/(app)/layout.tsx
+++ b/src/app/(app)/layout.tsx
@@ -62,7 +62,7 @@ function AnalyticsWarning() {
// We check on mount to avoid hydration errors
React.useEffect(() => {
- setIsConfigured(!!process.env.NEXT_PUBLIC_FIREBASE_API_KEY && !!process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID);
+ setIsConfigured(!!process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID);
}, []);
if (isConfigured) {
@@ -74,7 +74,7 @@ function AnalyticsWarning() {
Analytics Not Configured
- Your Firebase environment variables are missing. To enable analytics, add NEXT_PUBLIC_FIREBASE_API_KEY and NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID to the .env file, then restart the development server.
+ Your Google Analytics measurement ID is missing. To enable analytics, add NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID to the .env file, then restart the development server.
)
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 9e7ca1b4..37435377 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -3,6 +3,7 @@ import { Suspense } from 'react';
import './globals.css';
import { Toaster } from '@/components/ui/toaster';
import { AnalyticsTracker } from '@/components/analytics-tracker';
+import { GoogleAnalytics } from '@next/third-parties/google';
import { WalletProviderWrapper } from '@/components/wallet-provider-wrapper';
import { ThemeProvider } from '@/components/theme-provider';
import { ErrorBoundary } from '@/components/error-boundary';
@@ -93,6 +94,7 @@ export default function RootLayout({
}>) {
const isTestMode = process.env.NODE_ENV === 'test';
const testXpub = isTestMode ? process.env.TEST_XPUB : undefined;
+ const gaId = process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID;
return (
@@ -168,6 +170,7 @@ export default function RootLayout({
+ {gaId && }