Skip to content

Beta : Collect feedback with your own participants. Additional testers are arranged after checking availability.

Developer tools

Four SDKs, one version

Flutter, Expo, Web/React and Swift ship together and always carry the same version โ€” today 2.0. Each one brings the same tester experience into your app.

Published ยท 2.0

Flutter

For Flutter apps on Android and iOS.

Install ยท pub.dev
flutter pub add testerpaykit
Published ยท 2.0

Expo / React Native

For Expo and React Native apps.

Install ยท npm
npx expo install @testerpaykit/expo
npm
Published ยท 2.0

Web / React

For web apps built with React, Next.js or Vite.

Install ยท npm
npm install @testerpaykit/react
npm
Early access

Swift (iOS, macOS)

For native iOS and macOS apps, with a built-in SwiftUI tester experience.

Package
Swift Package โ€” on request

Not on a public package registry yet. Write to us and we send you the package.

What all four can do

  • โœ“Report a bug: form with screenshot and annotation, voice, quick actions
  • โœ“General feedback
  • โœ“Retest after a fix, with a verdict per step
  • โœ“Earnings in the tester menu, guided tour, German and English
  • โœ“Live link to Claude Code (beta): Claude sees the screen and your notes and can tap through your own app
  • โœ“Checklist "What to test": testers tick the steps off in the app

AI runs (auto test, AI retest after a fix) work with Flutter and Expo only.

At a glance

Feature Flutter Expo Web Swift
Bug report, feedback, retest โœ“โœ“โœ“โœ“
Live link to Claude Code (beta) โœ“โœ“โœ“โœ“
Checklist "What to test" โœ“โœ“โœ“โœ“
AI runs: auto test, AI retest โœ“โœ“โ€”โ€”

Quick examples

Flutter Initialize and wrap your app
import 'package:flutter/material.dart';
import 'package:testerpaykit/testerpaykit.dart';

final _navigatorKey = GlobalKey<NavigatorState>();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final tpk = await TesterPayKit.initialize(
    config: TesterPayKitConfig(
      projectId: '<project-uuid>',
      apiBaseUrl: 'https://api.testerpaykit.com',
      enableTesterMode: true,
    ),
  );
  runApp(MaterialApp(
    navigatorKey: _navigatorKey,
    navigatorObservers: [tpk.navigatorObserver],
    builder: (context, child) => TesterPayKitWrapper(
      sdk: tpk,
      navigatorKey: _navigatorKey,
      child: child ?? const SizedBox.shrink(),
    ),
    home: const HomeScreen(),
  ));
}
Expo Initialize and report on shake
import { TpkExpo, useShake } from '@testerpaykit/expo';
import { useEffect, useState } from 'react';

export function App() {
  const [tpk, setTpk] = useState<TpkExpo | null>(null);

  useEffect(() => {
    TpkExpo.init({
      projectId: '<project-uuid>',
      testerCode: '<tester-invite-code>',
    }).then(setTpk);
  }, []);

  useShake({
    enabled: !!tpk,
    onShake: () => {
      tpk?.submitBug({
        title: 'Shake-reported bug',
        description: 'Reported by shaking the device.',
        currentScreen: 'HomeScreen',
        severity: 'medium',
      });
    },
  });

  return null;
}
Web / React Mount the tester hub
import { useEffect, useState } from 'react';
import { TesterPayKit } from '@testerpaykit/sdk';
import { TesterPayKitApiClient } from '@testerpaykit/api-client';
import { IndexedDBAdapter } from '@testerpaykit/storage-browser';
import { TpkTesterHub } from '@testerpaykit/react';

export function Tpk({ screen }: { screen: string }) {
  const [sdk, setSdk] = useState<TesterPayKit | null>(null);
  useEffect(() => {
    const instance = new TesterPayKit({
      apiKey: '',
      projectId: '<project-uuid>',
      testerId: '<tester-invite-code>',
      deviceId: crypto.randomUUID(),
      storage: new IndexedDBAdapter(),
      apiClient: new TesterPayKitApiClient({ apiKey: '' }),
      deviceMetadata: { os: 'Web', osVersion: navigator.userAgent, deviceModel: 'browser', appVersion: '1.0.0', sdkVersion: '2.0.0', timezoneOffset: -new Date().getTimezoneOffset() },
      appMetadata: { bundleId: 'com.example.web', version: '1.0.0', buildNumber: '1' },
      autoStartSession: true,
    });
    void instance.init().then(() => setSdk(instance));
  }, []);
  return sdk ? <TpkTesterHub sdk={sdk} currentScreen={screen} /> : null;
}

The example also imports @testerpaykit/sdk, @testerpaykit/api-client and @testerpaykit/storage-browser; with pnpm, add them explicitly.

Swift Start a session, wrap your view
import SwiftUI
import TesterPayKit

let sdk = try await TesterPayKit.initialize(
    config: TesterPayKitConfig(
        projectId: "<project-uuid>",
        testerCode: "<tester-invite-code>",
        apiBaseURL: URL(string: "https://api.testerpaykit.com")!
    )
)
try await sdk.startSession()

ContentView()
    .tpkFeedbackOverlay()

Ready to integrate?

Create a project account and configure the SDK for your app. Existing accounts can sign in to the web console.