Skip to main content
The @bondify/react package gives you a set of idiomatic React primitives built on top of the Bondify Telegram auth flow. Wrap your app in <PulseProvider> once to configure your project ID, then drop <PulseButton> anywhere you need a sign-in button. For programmatic control — triggering auth from your own UI elements or reading auth state anywhere in the tree — reach for the usePulse hook. Everything is strongly typed, tree-shakable, and works with both Vite and Create React App.

Install

npm install @bondify/react

Basic setup

Wrap your login page (or your entire app) with <PulseProvider> and place <PulseButton> where you want the Telegram sign-in button rendered. On success, send user.proof to your backend for verification.
LoginPage.tsx
import { PulseProvider, PulseButton } from '@bondify/react';

export default function LoginPage() {
  return (
    <PulseProvider projectId="proj_xxxxxxxx">
      <PulseButton
        onSuccess={(user) => {
          // user.telegramId, user.name, user.username, user.proof
          fetch('/api/session', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ proof: user.proof }),
          });
        }}
        onError={(err) => console.error('Auth failed:', err)}
      />
    </PulseProvider>
  );
}
Never use the user object from onSuccess to establish trust on its own. The proof field is a signed JWT that must be verified by your server before you create a session. Treat all other fields as display-only convenience data.

Using the usePulse hook

The usePulse hook exposes the current auth state and imperative actions. Use it when you want to trigger sign-in from your own button, conditionally render authenticated UI, or sign the user out without re-rendering the full <PulseButton> component.
AuthStatus.tsx
import { PulseProvider, usePulse } from '@bondify/react';

function AuthStatus() {
  const { user, isAuthenticated, signIn, signOut } = usePulse();

  if (isAuthenticated) {
    return (
      <div>
        <p>Welcome, {user.name}!</p>
        <button onClick={signOut}>Sign out</button>
      </div>
    );
  }

  return (
    <button onClick={signIn}>
      Sign in with Telegram
    </button>
  );
}

export default function App() {
  return (
    <PulseProvider projectId="proj_xxxxxxxx">
      <AuthStatus />
    </PulseProvider>
  );
}
Call signIn() only inside a user-gesture handler (e.g. a click event). Browsers block the Telegram popup window if it is opened without a direct user interaction.

Persisting auth state

By default, PulseProvider holds auth state in memory and resets on page reload. To persist the session across reloads, pass a sessionStorage or localStorage-backed storage prop, or store the session token in a cookie from your backend after verifying the proof.
App.tsx
import { PulseProvider } from '@bondify/react';

export default function App() {
  return (
    <PulseProvider
      projectId="proj_xxxxxxxx"
      storage={localStorage}
    >
      <YourApp />
    </PulseProvider>
  );
}

PulseButton props

PropTypeDefaultDescription
onSuccess(user: PulseUser) => voidCalled when Telegram auth completes. Receives { telegramId, name, username, proof }
onError(err: Error) => voidCalled when auth fails or is cancelled
textstring"Sign in with Telegram"Custom button label
theme"light" | "dark"autoOverride the button colour scheme

usePulse return value

FieldTypeDescription
userPulseUser | nullThe authenticated user object, or null if signed out
isAuthenticatedbooleantrue when a verified session is active
signIn() => Promise<void>Triggers the Telegram auth flow programmatically
signOut() => voidClears the current session

Handling loading and error states

LoginPage.tsx
import { useState } from 'react';
import { PulseProvider, PulseButton } from '@bondify/react';

export default function LoginPage() {
  const [error, setError] = useState<string | null>(null);

  return (
    <PulseProvider projectId="proj_xxxxxxxx">
      {error && <p className="error">{error}</p>}
      <PulseButton
        onSuccess={async (user) => {
          const res = await fetch('/api/session', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ proof: user.proof }),
          });
          if (!res.ok) setError('Session creation failed.');
        }}
        onError={(err) => setError(err.message)}
      />
    </PulseProvider>
  );
}

Next steps

Verify the proof server-side

Every proof issued by Bondify must be verified by your Node.js backend before you create a user session. Learn how to call verifyProof() safely in Express or Fastify.

Next.js integration

Combine @bondify/react with Next.js Server Actions and the App Router for SSR-safe Telegram auth.

HTML Widget

Need a no-npm option? The drop-in script tag works on any static HTML page.