Code Examples

Complete integration examples for common frameworks and use cases.

Next.js App Router

Full integration with Next.js 14+ App Router and server components.

1. Create Support Provider

components/SupportProvider.tsxtsx
// components/SupportProvider.tsx
'use client'

import { SupportWidget } from '@supportflow/react'
import { useAuth } from '@/hooks/useAuth'

export function SupportProvider({ children }: { children: React.ReactNode }) {
  const { user, isAuthenticated } = useAuth()

  return (
    <>
      {children}
      {isAuthenticated && user && (
        <SupportWidget
          appId={process.env.NEXT_PUBLIC_SUPPORTFLOW_APP_ID!}
          user={{
            id: user.id,
            email: user.email,
            name: user.name,
          }}
          token={user.supportToken}
        />
      )}
    </>
  )
}

2. Add to Root Layout

app/layout.tsxtsx
// app/layout.tsx
import { SupportProvider } from '@/components/SupportProvider'

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <SupportProvider>
          {children}
        </SupportProvider>
      </body>
    </html>
  )
}

3. Generate Token in API Route

app/api/support-token/route.tstsx
// app/api/support-token/route.ts
import { NextResponse } from 'next/server'
import jwt from 'jsonwebtoken'
import { getServerSession } from 'next-auth'

export async function GET() {
  const session = await getServerSession()

  if (!session?.user) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  const token = jwt.sign(
    {
      sub: session.user.id,
      email: session.user.email,
      name: session.user.name,
    },
    process.env.SUPPORT_JWT_SECRET!,
    { expiresIn: '24h' }
  )

  return NextResponse.json({ token })
}

React with REST API

Direct API integration without the widget.

Custom API Integrationtsx
// hooks/useSupportFlow.ts
import { useState, useEffect } from 'react'

const API_BASE = 'https://support.example.com/api/support/myapp'

export function useSupportFlow(token: string) {
  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`,
  }

  async function searchArticles(query: string) {
    const res = await fetch(
      `${API_BASE}/articles?search=${encodeURIComponent(query)}`,
      { headers }
    )
    return res.json()
  }

  async function createIssue(data: {
    title: string
    description: string
    type: 'bug' | 'feature' | 'billing' | 'other'
  }) {
    const res = await fetch(`${API_BASE}/issues`, {
      method: 'POST',
      headers,
      body: JSON.stringify(data),
    })
    return res.json()
  }

  async function sendChatMessage(message: string, sessionId?: string) {
    const res = await fetch(`${API_BASE}/chat`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ message, sessionId }),
    })
    return res.json()
  }

  return { searchArticles, createIssue, sendChatMessage }
}

// Usage in component
function HelpButton() {
  const { searchArticles, sendChatMessage } = useSupportFlow(userToken)
  const [answer, setAnswer] = useState('')

  async function handleSearch(query: string) {
    const { articles } = await searchArticles(query)
    // Display articles
  }

  async function handleChat(message: string) {
    const { message: response } = await sendChatMessage(message)
    setAnswer(response.content)
  }

  return (/* ... */)
}

Express.js Backend

Token generation endpoint for Express apps.

Express Token Routejavascript
// routes/support.js
import express from 'express'
import jwt from 'jsonwebtoken'
import { requireAuth } from '../middleware/auth'

const router = express.Router()

// Generate support token for authenticated users
router.get('/support-token', requireAuth, (req, res) => {
  const token = jwt.sign(
    {
      sub: req.user.id,
      email: req.user.email,
      name: req.user.name,
    },
    process.env.SUPPORT_JWT_SECRET,
    { expiresIn: '24h' }
  )

  res.json({ token })
})

export default router

Django Backend

Token generation for Django REST Framework.

Django Token Viewpython
# views.py
import jwt
import os
from datetime import datetime, timedelta
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class SupportTokenView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        payload = {
            'sub': str(request.user.id),
            'email': request.user.email,
            'name': request.user.get_full_name(),
            'iat': datetime.utcnow(),
            'exp': datetime.utcnow() + timedelta(hours=24)
        }

        token = jwt.encode(
            payload,
            os.environ['SUPPORT_JWT_SECRET'],
            algorithm='HS256'
        )

        return Response({'token': token})

# urls.py
from django.urls import path
from .views import SupportTokenView

urlpatterns = [
    path('api/support-token/', SupportTokenView.as_view()),
]

Bug Report with State Capture

Capture browser state and create detailed bug reports.

Bug Report with State Capturetsx
// components/BugReportButton.tsx
'use client'

import { useState } from 'react'
import { useSupportFlow } from '@supportflow/react'

export function BugReportButton() {
  const { createIssue } = useSupportFlow()
  const [isSubmitting, setIsSubmitting] = useState(false)

  async function handleBugReport() {
    setIsSubmitting(true)

    // Capture current state
    const metadata = {
      url: window.location.href,
      userAgent: navigator.userAgent,
      screenSize: `${window.innerWidth}x${window.innerHeight}`,
      timestamp: new Date().toISOString(),
      // Add custom app state
      localStorage: Object.keys(localStorage),
    }

    // Capture console errors (if tracked)
    const errors = window.__capturedErrors || []

    try {
      await createIssue({
        title: 'Bug Report from App',
        description: 'User-submitted bug report',
        type: 'bug',
        metadata,
        attachments: errors.length > 0 ? [{
          name: 'console-errors.json',
          content: JSON.stringify(errors),
          type: 'application/json'
        }] : undefined
      })

      alert('Bug report submitted!')
    } catch (error) {
      console.error('Failed to submit bug report:', error)
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <button
      onClick={handleBugReport}
      disabled={isSubmitting}
      className="fixed bottom-4 left-4 bg-red-500 text-white px-4 py-2 rounded"
    >
      {isSubmitting ? 'Submitting...' : 'Report Bug'}
    </button>
  )
}