Skip to main content

Troubleshooting

Common issues and fixes when integrating ReadMeter.

Admin SDK–heavy apps (0 widget reads)

If almost all Firestore access uses firebase-admin, the browser widget will show ~0 reads. That is expected — the widget only sees client modular SDK calls.

Re-run readmeter init --yes so it vendors lib/readmeter-admin-firestore and (on Next.js) /api/readmeter-admin. Then wrap your Admin instance once:

import { instrumentAdminFirestore } from '@/lib/readmeter-admin-firestore'
export const db = instrumentAdminFirestore(getFirestore())

Hit a route that reads Firestore, then open /api/readmeter-admin. Stats are process-local (reset on server restart). Cloud Functions in a separate process are not included.

Widget visible but shows 0 reads

The widget appears in the corner but the read count stays at zero. This usually happens when your app uses the Firebase modular SDK (v9+) without the ReadMeter wrapper, or when reads happen only on the server (Admin SDK).

Why it happens

ReadMeter's widget patches the compat Firestore API (window.firebase.firestore). If your app uses only the modular SDK (import { getDoc, getDocs } from 'firebase/firestore'), the compat API is never loaded, so the patch never runs and ReadMeter.recordRead() is never called.

Solutions

  1. Re-run init — From your project folder, run readmeter init --yes (wires loader + rewrites imports). Recovery only: readmeter fix-imports --yes.
  2. Use the ReadMeter Firestore wrapper manually — Change your imports from firebase/firestore to the wrapper:
    // Before
    import { getDoc, getDocs, onSnapshot } from 'firebase/firestore'
    
    // After
    import { getDoc, getDocs, onSnapshot } from './lib/readmeter-firestore'
    The wrapper re-exports everything; only getDoc, getDocs, and onSnapshot are wrapped to call ReadMeter.recordRead().
  3. Bridge from an existing tracker — If you already track reads (e.g. a custom firestoreReadTracker.track()), add a one-liner to feed ReadMeter:
    // In your track() function, after updating your own state:
    window.ReadMeter?.recordRead({ reads: readCount, collection, type: 'getDocs', caller: featureName })

recordRead parameter contract

When bridging from your own tracker or calling ReadMeter.recordRead() manually, use this shape:

{
  reads: number,      // required — number of document reads
  collection: string, // required — collection name
  type?: string,      // optional — e.g. 'getDoc', 'getDocs', 'onSnapshot'
  caller?: string     // optional — e.g. feature name or 'file.tsx:42'
}

Build tools (Next.js, Vite, Webpack)

Prefer a source transform (webpack loader / Vite plugin), not a resolve.alias. The ReadMeter wrapper itself imports firebase/firestore; a blanket alias would recurse infinitely.

Recommended: run readmeter init --yes — it vendors lib/with-readmeter.cjs + loader and patches next.config / vite.config, and rewrites imports for Turbopack.

Next.js 16 + Turbopack: withReadMeter sets turbopack: {} so default next dev works. The webpack loader only runs with next dev --webpack; under Turbopack, tracking uses the import rewrites from init. If you hit a webpack/turbopack config error from an older install, re-run readmeter init --yes or add turbopack: {} to your config.

Next.js (what init adds to next.config.js):

// @readmeter-begin
module.exports = require('./lib/with-readmeter.cjs')(module.exports)
// @readmeter-end
// withReadMeter merges turbopack: {} so Next 16 Turbopack does not error

Server vs client reads

The browser widget tracks client-side reads only. Server-side Admin reads (SSR, Route Handlers, Server Components) need instrumentAdminFirestore and show up on /api/readmeter-admin, not in the corner badge.

Next steps