React (Vite)

Add the chat widget to a React app built with Vite, or any client-rendered React app.

A Vite app has no server of its own, so the token route lives in your existing backend. Everything else is one provider.

Install

npm install @ticketping/chat-widget@next

v2 is on the next tag until 2.0.0 is released.

Add the provider

Wrap your app and pass the signed-in user, or null. Get your publishable key (pk_...) from Settings → Widgets. It’s public.

src/main.tsx:

tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { TicketpingProvider } from '@ticketping/chat-widget/react'
import { App } from './App'
import { useCurrentUser } from './auth'

async function getToken() {
  const res = await fetch('/api/ticketping-token', { method: 'POST', credentials: 'include' })
  if (!res.ok) throw new Error(`Ticketping token request failed (${res.status})`)
  return res.text()
}

function Root() {
  const user = useCurrentUser()

  return (
    <TicketpingProvider
      publishableKey="pk_..."
      user={user ? { id: user.id, email: user.email, name: user.name } : null}
      getToken={getToken}
    >
      <App />
    </TicketpingProvider>
  )
}

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <Root />
  </StrictMode>
)

useCurrentUser stands for however your app knows who’s signed in. The provider follows the user prop: it identifies on sign-in, switches when a different user signs in, and logs out when user becomes null.

The React adapter ships with 2.0. If a prop name here doesn’t match your installed beta, check the package README; the core JavaScript API works the same in every version.

Add the token route

Add POST /api/ticketping-token to the backend your app already talks to. It checks who’s signed in and returns a signed token as text:

If the API is on another origin (for example api.acme.com), change the URL in getToken, keep credentials: 'include', and allow your app’s origin with credentials in the API’s CORS settings. If your API authenticates with a bearer token instead of cookies, send that header in getToken.

During development, Vite can proxy the route to your backend so it stays same-origin:

vite.config.ts:

ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: { proxy: { '/api': 'http://localhost:8000' } }
})

Set the secret

Get the identity secret from Settings → API → Identity secret and set it on the backend:

bash
TICKETPING_IDENTITY_SECRET=tpis_...

Never put it in a VITE_ variable. Those are bundled into the browser code.

Check that it works

  1. Sign in to your app on localhost and open the browser console.
  2. Run await (await fetch('/api/ticketping-token', { method: 'POST', credentials: 'include' })).text() and copy the token.
  3. Paste it into the token validator under Settings → API → Identity secret. It shows the claims, or says exactly what to fix.
  4. Reload and send a message. The dashboard shows it with the user’s name, a Verified badge and a TEST tag.

Use the widget from your components

tsx
import { useTicketping } from '@ticketping/chat-widget/react'

export function HelpButton() {
  const { unreadCount, open } = useTicketping()
  return <button onClick={open}>Help{unreadCount > 0 ? ` (${unreadCount})` : ''}</button>
}

useTicketping() returns the same values as on Next.js: live unreadCount and isOpen, the open and navigation methods, and a client for the rest of the JavaScript API. user may use id or userId. The other provider props match the init options in Configuration, and they are read once.

Copy prompt for your AI coding agent

prompt
Add the Ticketping chat widget (v2) to this React (Vite) app.

Docs index: https://ticketping.com/llms.txt
This page as Markdown: https://ticketping.com/docs/react-vite.md

1. Install @ticketping/chat-widget@next.
2. In src/main.tsx, wrap the app in <TicketpingProvider publishableKey="pk_..." user={user} getToken={getToken}>
   from '@ticketping/chat-widget/react'. user is { id, email, name } for the signed-in user from this app's
   existing auth state, or null. getToken POSTs to /api/ticketping-token with credentials: 'include' and returns
   res.text(); throw if !res.ok. Ask me for the publishable key (starts with pk_). It's public.
3. Find this app's backend and add POST /api/ticketping-token using the code for that stack from
   https://ticketping.com/docs/authentication.md: 401 when signed out, otherwise a plain-text HS256 JWT
   { sub: String(user id), email, name, exp: now + 300 } signed with the TICKETPING_IDENTITY_SECRET env var.
   If the backend is on another origin, set up CORS with credentials for this app's origin, or a Vite dev proxy.
4. Add TICKETPING_IDENTITY_SECRET= to the backend's env file (not committed). Never use a VITE_ variable for it.
5. Tell me how to verify: sign in on localhost, fetch a token from the console, and paste it into the
   token validator at Settings → API → Identity secret.