react-fathomv0.3.0
On this page
  1. Ways to Contribute
  2. Development Setup
  3. Prerequisites
  4. 1. Clone and Install
  5. 2. Development Workflow
  6. Project Structure
  7. Testing Guidelines
  8. Writing Tests
  9. Code Style
  10. Submitting a Pull Request
  11. Commit Messages
  12. Documentation
  13. Release Validation
  14. npm release channels

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

TypeDescription
Bug ReportsFound a bug? Open an issue with reproduction steps
Feature RequestsHave an idea? Discuss it in an issue first
Bug FixesPRs for documented issues are always welcome
DocumentationHelp improve docs, add examples, fix typos
TestsIncrease 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

bash
git clone https://github.com/ryanhefner/react-fathom.git
cd react-fathom
corepack enable
pnpm install --frozen-lockfile

2. Development Workflow

bash
# 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:check

Project 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.

bash
# 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.tsx

Writing Tests

tsx
// 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 format before committing)
  • Linting: ESLint catches common issues (run pnpm lint)
  • Naming:
    • Components: PascalCase (TrackClick.tsx)
    • Hooks: camelCase with use prefix (useFathom.ts)
    • Types: PascalCase (FathomClient)

Submitting a Pull Request

  1. Fork the repository
  2. Create a branch from main:
    bash
    git checkout -b fix/my-bug-fix
    # or
    git checkout -b feature/my-new-feature
  3. Make your changes with clear, focused commits
  4. Add or update tests for your changes
  5. Ensure CI passes:
    bash
    pnpm release:check
  6. 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 values

Prefixes: feat, fix, docs, test, refactor, chore, perf

Documentation

The docs site uses Next.js and Chakra UI and lives in the /docs directory.

bash
pnpm install --frozen-lockfile
pnpm --dir docs dev

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

bash
pnpm release:check

This 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 releaseVersion examplenpm dist-tag
Prerelease0.3.0-next.0next
Stable release0.3.0latest

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

By

Commune Software