Skip to main content

React Quickstart

Build a cStar integration with React in under 5 minutes. This guide covers installation, seeding sample data, provider setup, knowledge base browsing, customer chat, and article search.

1. Install

npm install @cstar.help/react

2. Seed Sample Data

If you haven't already, populate your team with sample help center content so you have data to work with:

cstar seed

This creates 5 categories, 12 articles, 3 customers, and 5 tickets. See the quickstart for details.

3. Set Up Providers

providers.tsx
// app/providers.tsx
// Two providers: Chat (authenticated) and Library (public)
import { CStarChatProvider, CStarLibraryProvider } from '@cstar.help/react';

export default function Providers({ children }) {
  return (
    <CStarLibraryProvider teamSlug="acme">
      <CStarChatProvider
        teamSlug="acme"
        supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL}
        supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY}
      >
        {children}
      </CStarChatProvider>
    </CStarLibraryProvider>
  );
}

4. Browse the Knowledge Base

List categories and articles from your public help center.

HelpCenter.tsx
// components/HelpCenter.tsx
import { useCategories, useArticles } from '@cstar.help/react';

export function HelpCenter() {
  const { categories, isLoading } = useCategories();
  const { articles } = useArticles({ limit: 5 });

  if (isLoading) return <p>Loading...</p>;

  return (
    <div>
      <h2>Help Center</h2>
      {categories.map(cat => (
        <div key={cat.id}>
          <h3>{cat.name} ({cat.article_count})</h3>
        </div>
      ))}
      <h2>Latest Articles</h2>
      {articles.map(a => (
        <a key={a.id} href={`/help/${a.slug}`}>{a.title}</a>
      ))}
    </div>
  );
}

5. Add Customer Chat

Let customers start conversations and send messages in real-time.

ChatWidget.tsx
// components/ChatWidget.tsx
import { useChat, useConversations, useMessages } from '@cstar.help/react';
import { useState } from 'react';

export function ChatWidget() {
  const { identify, isIdentified } = useChat();
  const { conversations, create } = useConversations();
  const [activeId, setActiveId] = useState(null);
  const { messages, send } = useMessages(activeId);
  const [draft, setDraft] = useState('');

  async function startChat() {
    // Get HMAC signature from your server
    const res = await fetch('/api/cstar-auth');
    const { signature, customer } = await res.json();
    await identify(customer, signature);

    const convo = await create({ subject: 'Help needed' });
    setActiveId(convo.id);
  }

  if (!isIdentified) {
    return <button onClick={startChat}>Chat with us</button>;
  }

  return (
    <div>
      {messages.map(m => (
        <p key={m.id}><b>{m.sender_name}</b>: {m.content}</p>
      ))}
      <input value={draft} onChange={e => setDraft(e.target.value)} />
      <button onClick={() => { send(draft); setDraft(''); }}>Send</button>
    </div>
  );
}

Full-text article search with built-in debounce.

SearchBar.tsx
// components/SearchBar.tsx
import { useArticleSearch } from '@cstar.help/react';
import { useState } from 'react';

export function SearchBar() {
  const [query, setQuery] = useState('');
  const { results, totalCount, isLoading } = useArticleSearch(query);

  return (
    <div>
      <input
        value={query}
        onChange={e => setQuery(e.target.value)}
        placeholder="Search help articles..."
      />
      {isLoading ? <p>Searching...</p> : <p>{totalCount} results</p>}
      {results.map(a => (
        <a key={a.id} href={`/help/${a.slug}`}>{a.title}</a>
      ))}
    </div>
  );
}

What's Next?