Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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) ──────────
Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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):**
Expand Down
22 changes: 5 additions & 17 deletions .github/workflows/copilot-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
12 changes: 3 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
```

Expand Down Expand Up @@ -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**
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 5 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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` |
Expand Down
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down Expand Up @@ -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).

Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):**
Expand Down
22 changes: 0 additions & 22 deletions apphosting.dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
22 changes: 0 additions & 22 deletions apphosting.prd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Loading
Loading