Standalone React

Add WhatsApp login to any React app with a single component — no backend required.

How it works

The React SDK connects directly to loggin from the browser. You don't need a server. The SDK generates a short token, opens WhatsApp with a pre-filled message, and listens for verification via a server-sent event stream. Once the user taps Send in WhatsApp, onSuccess fires with their verified phone number.

On desktop, the SDK shows a scannable QR code. On mobile, it auto-opens WhatsApp so the user never has to leave the app.

Install

npm install @loggin/react

Option A — LogginButton (one line)

The simplest integration. Renders a styled button that opens the loggin modal automatically. Desktop shows a QR code; mobile auto-opens WhatsApp.

import { LogginButton } from '@loggin/react'

export function Page() {
  return (
    <LogginButton
      appKey="8XKPQ2WN"
      onSuccess={({ phone, token }) => console.log('Verified:', phone, token)}
    />
  )
}

Option B — LogginModal (custom trigger)

Mount the modal yourself when you want full control over when it appears — for example, triggered by your own button or a navigation event. The modal handles the QR code, countdown, expiry, and mobile auto-open internally.

import { useState } from 'react'
import { LogginModal } from '@loggin/react'

export function Page() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button onClick={() => setOpen(true)}>Log in with WhatsApp</button>

      {open && (
        <LogginModal
          appKey="8XKPQ2WN"
          onSuccess={({ phone, token }) => {
            setOpen(false)
            console.log('Verified:', phone, token)
          }}
          onClose={() => setOpen(false)}
        />
      )}
    </>
  )
}

Option C — useLogginAuth hook (fully custom UI)

For complete control over the UI. The hook manages the token lifecycle, SSE connection, countdown, and expiry — you decide what to render.

Hook API

statusstring"waiting" | "verified" | "expired"
waLinkstringPre-filled WhatsApp deep-link
secondsLeftnumberSeconds until token expires
phonestring | nullVerified phone number (after success)
reset() => voidGenerate a new token and restart

Example

import { useLogginAuth } from '@loggin/react'

export function LoginFlow() {
  const { status, waLink, secondsLeft, phone, reset } = useLogginAuth({ appKey: '8XKPQ2WN' })

  if (status === 'verified') return <p>Logged in as {phone}</p>
  if (status === 'expired')  return <button onClick={reset}>Try again</button>

  return (
    <div>
      <img src={`https://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(waLink)}`} />
      <a href={waLink}>Open WhatsApp</a>
      <p>Expires in {secondsLeft}s</p>
    </div>
  )
}

Need server-side sessions?

The SDK verifies the user entirely in the browser — no server required. But if you need to persist auth server-side (set an httpOnly cookie, write to a database, or start a server session), call your own server action from onSuccess:

import { LogginButton } from '@loggin/react'
import { loginAction } from './actions' // your server action

<LogginButton
  appKey="8XKPQ2WN"
  onSuccess={async ({ phone, token }) => {
    await loginAction(token)  // pass token, not phone
    router.push('/dashboard')
  }}
/>
Security: Pass token to your server action — not phone. The phone in onSuccess is a convenience for simple UI use (e.g. showing “logged in as +91...”). Your server should always derive the phone by calling verifyToken(token), which reads it directly from Loggin's database — not from the browser.
For Next.js apps, @loggin/nextjs provides a verifyToken helper and middleware to protect routes. See the With a Backend guide.