Contributing
How to contribute to the react-fathom project.
Contributions are welcome! Whether it's bug fixes, new features, documentation improvements, or examples.
Ways to Contribute
| Type | Description |
|---|---|
| Bug Reports | Found a bug? Open an issue with reproduction steps |
| Feature Requests | Have an idea? Discuss it in an issue first |
| Bug Fixes | PRs for documented issues are always welcome |
| Documentation | Help improve docs, add examples, fix typos |
| Tests | Increase test coverage or add edge case tests |
Development Setup
Prerequisites
- Node.js 20+ (the repository pins Node.js 24.21.0 in
.nvmrc) - pnpm 12.8.1 (managed through Corepack)
1. Clone and Install
git clone https://github.com/ryanhefner/react-fathom.git
cd react-fathom
corepack enable
pnpm install --frozen-lockfile2. Development Workflow
# Run tests in watch mode during development
pnpm exec vitest
# Run tests with coverage
pnpm test:ci
# Build the package
pnpm build
# Run every release validation, including a clean packed consumer
pnpm release:checkProject Structure
react-fathom/
├── src/
│ ├── index.ts # Main entry point
│ ├── FathomProvider.tsx # Core provider component
│ ├── FathomContext.tsx # React context
│ ├── types.ts # TypeScript definitions
│ ├── hooks/ # React hooks
│ │ ├── useFathom.ts
│ │ ├── useTrackOnClick.ts
│ │ ├── useTrackOnMount.ts
│ │ └── useTrackOnVisible.ts
│ ├── components/ # Declarative tracking components
│ │ ├── TrackClick.tsx
│ │ ├── TrackPageview.tsx
│ │ └── TrackVisible.tsx
│ ├── debug/ # Debug event-stream exports
│ ├── next/ # Next.js App and Pages Router exports
│ ├── react-router/ # React Router and Remix exports
│ ├── gatsby/ # Gatsby exports
│ ├── tanstack-router/ # TanStack Router exports
│ └── native/ # React Native exports
│ ├── index.ts
│ ├── FathomWebView.tsx
│ ├── createWebViewClient.ts
│ ├── NativeFathomProvider.tsx
│ ├── useNavigationTracking.ts
│ └── useAppStateTracking.ts
├── docs/ # Chakra UI documentation site
├── examples/ # Framework-specific example applications
├── scripts/ # Build and release verification
└── dist/ # Built output (generated)Testing Guidelines
We use Vitest for testing. All new features should include tests.
# Run all tests
pnpm test:ci
# Run tests in watch mode
pnpm exec vitest
# Run a focused test file
pnpm exec vitest run src/FathomProvider.test.tsxWriting Tests
// src/hooks/useMyHook.test.tsx
import { renderHook } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { useMyHook } from './useMyHook'
import { FathomProvider } from '../FathomProvider'
describe('useMyHook', () => {
it('should track events correctly', () => {
const mockClient = {
load: vi.fn(),
trackPageview: vi.fn(),
trackEvent: vi.fn(),
trackGoal: vi.fn(),
setSite: vi.fn(),
blockTrackingForMe: vi.fn(),
enableTrackingForMe: vi.fn(),
isTrackingEnabled: vi.fn(() => true),
}
const wrapper = ({ children }) => (
<FathomProvider client={mockClient}>{children}</FathomProvider>
)
const { result } = renderHook(() => useMyHook(), { wrapper })
result.current.doSomething()
expect(mockClient.trackEvent).toHaveBeenCalledWith('expected-event', {})
})
})Code Style
- TypeScript: All code should be fully typed
- Formatting: We use Prettier (run
pnpm formatbefore committing) - Linting: ESLint catches common issues (run
pnpm lint) - Naming:
- Components: PascalCase (
TrackClick.tsx) - Hooks: camelCase with
useprefix (useFathom.ts) - Types: PascalCase (
FathomClient)
- Components: PascalCase (
Submitting a Pull Request
- Fork the repository
- Create a branch from
main:bashgit checkout -b fix/my-bug-fix # or git checkout -b feature/my-new-feature - Make your changes with clear, focused commits
- Add or update tests for your changes
- Ensure CI passes:
bash
pnpm release:check - Submit a PR with a clear description of what and why
Commit Messages
Use clear, descriptive commit messages:
feat: add useTrackOnScroll hook for scroll tracking
fix: resolve duplicate pageview tracking in Next.js
docs: add troubleshooting section for ad blockers
test: add tests for native offline queue
refactor: simplify FathomContext default valuesPrefixes: feat, fix, docs, test, refactor, chore, perf
Documentation
The docs site uses Next.js and Chakra UI and lives in the /docs directory.
pnpm install --frozen-lockfile
pnpm --dir docs devWhen adding new features, please also update the relevant documentation pages.
Release Validation
Run the complete release gate before changing the package version or creating a release:
pnpm release:checkThis command checks formatting and lint, runs the full suite with coverage, builds every package entrypoint from a clean output directory, installs the packed tarball into an isolated ESM/CommonJS/NodeNext consumer, and creates a production build of the documentation site. Make the version bump as the final release commit after this command succeeds, then publish and tag that exact commit.
npm release channels
The Publish to npm GitHub Actions workflow supports two channels and validates
them before publishing:
| GitHub release | Version example | npm dist-tag |
|---|---|---|
| Prerelease | 0.3.0-next.0 | next |
| Stable release | 0.3.0 | latest |
To publish a preview, bump package.json to a prerelease version, commit it,
create the matching tag (for example v0.3.0-next.0), and publish a GitHub
prerelease. To publish the stable build, use a stable version and matching tag,
then publish a normal GitHub release. The workflow rejects a stable version on
next, a prerelease version on latest, or any mismatch between the GitHub tag
and package.json.
The workflow can also be run manually for recovery. Select the exact commit or
tag, enter its existing package.json version, and choose the matching npm
channel. npm versions are immutable, so an already-published version must never
be reused.
Publishing uses npm Trusted Publishing. Configure the npm package to trust
.github/workflows/publish.yml in this repository; no long-lived npm token is
required.
Last updated: October 8, 2026