Examples
Overview

Examples

Real-world examples of Produck SDK integration.

Quick Links

Browse complete examples for different use cases:

Common Patterns

Opening Modals

import { useProduckAction } from '@produck/sdk/react';
 
function App() {
  const [showContact, setShowContact] = useState(false);
  const [showLogin, setShowLogin] = useState(false);
 
  useProduckAction('open-contact', () => setShowContact(true));
  useProduckAction('open-login', () => setShowLogin(true));
 
  return (
    <>
      <YourContent />
      {showContact && <ContactModal onClose={() => setShowContact(false)} />}
      {showLogin && <LoginModal onClose={() => setShowLogin(false)} />}
    </>
  );
}

Navigation

import { useProduckAction } from '@produck/sdk/react';
import { useRouter } from 'next/router';
 
function Navigation() {
  const router = useRouter();
 
  useProduckAction('go-to-pricing', () => {
    router.push('/pricing');
  });
 
  useProduckAction('go-to-docs', () => {
    router.push('/docs');
  });
 
  useProduckAction('go-to-dashboard', () => {
    router.push('/dashboard');
  });
 
  return <nav>{/* Your nav items */}</nav>;
}

Scrolling & Highlighting

import { ProduckTarget } from '@produck/sdk/react';
 
function LandingPage() {
  return (
    <div>
      <ProduckTarget actionKey="show-features">
        <section id="features">
          <h2>Features</h2>
          {/* Features content */}
        </section>
      </ProduckTarget>
 
      <ProduckTarget actionKey="show-pricing">
        <section id="pricing">
          <h2>Pricing</h2>
          {/* Pricing content */}
        </section>
      </ProduckTarget>
 
      <ProduckTarget actionKey="show-testimonials">
        <section id="testimonials">
          <h2>What Our Customers Say</h2>
          {/* Testimonials content */}
        </section>
      </ProduckTarget>
    </div>
  );
}

Form Filling

function ContactForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: '',
  });
 
  useProduckAction('fill-contact-form', (payload) => {
    setFormData({
      name: payload.actionConfig.name || '',
      email: payload.actionConfig.email || '',
      message: payload.actionConfig.message || '',
    });
  });
 
  return (
    <form>
      <input
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Name"
      />
      <input
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Email"
      />
      <textarea
        value={formData.message}
        onChange={(e) => setFormData({ ...formData, message: e.target.value })}
        placeholder="Message"
      />
      <button type="submit">Send</button>
    </form>
  );
}

Multi-Step Wizards

function OnboardingWizard() {
  const [step, setStep] = useState(1);
  const [data, setData] = useState({});
 
  useProduckAction('start-onboarding', () => setStep(1));
  useProduckAction('next-step', () => setStep(s => Math.min(s + 1, 4)));
  useProduckAction('previous-step', () => setStep(s => Math.max(s - 1, 1)));
  useProduckAction('skip-onboarding', () => setStep(5));
 
  return (
    <div>
      {step === 1 && <Step1 onNext={() => setStep(2)} />}
      {step === 2 && <Step2 onNext={() => setStep(3)} />}
      {step === 3 && <Step3 onNext={() => setStep(4)} />}
      {step === 4 && <Step4 onComplete={() => setStep(5)} />}
      {step === 5 && <CompletionScreen />}
    </div>
  );
}

State Management

// With Zustand
import { create } from 'zustand';
import { useProduckAction } from '@produck/sdk/react';
 
const useStore = create((set) => ({
  cart: [],
  addItem: (item) => set((state) => ({ cart: [...state.cart, item] })),
  removeItem: (id) => set((state) => ({
    cart: state.cart.filter(item => item.id !== id)
  })),
  clearCart: () => set({ cart: [] }),
}));
 
function ShoppingCart() {
  const { cart, addItem, clearCart } = useStore();
 
  useProduckAction('add-to-cart', (payload) => {
    const productId = payload.actionConfig.productId;
    addItem({ id: productId, name: 'Product', price: 99 });
  });
 
  useProduckAction('clear-cart', () => {
    clearCart();
  });
 
  return (
    <div>
      <h2>Cart ({cart.length})</h2>
      {cart.map(item => (
        <div key={item.id}>{item.name} - ${item.price}</div>
      ))}
    </div>
  );
}

Filtering & Search

function ProductList() {
  const [products, setProducts] = useState(allProducts);
  const [filters, setFilters] = useState({
    category: null,
    priceRange: null,
    color: null,
  });
 
  useProduckAction('filter-by-category', (payload) => {
    const category = payload.actionConfig.category;
    setFilters({ ...filters, category });
    setProducts(allProducts.filter(p => p.category === category));
  });
 
  useProduckAction('filter-by-price', (payload) => {
    const { min, max } = payload.actionConfig;
    setProducts(allProducts.filter(p => p.price >= min && p.price <= max));
  });
 
  useProduckAction('clear-filters', () => {
    setFilters({ category: null, priceRange: null, color: null });
    setProducts(allProducts);
  });
 
  return (
    <div>
      <FilterBar filters={filters} />
      <div className="products-grid">
        {products.map(product => (
          <ProductCard key={product.id} product={product} />
        ))}
      </div>
    </div>
  );
}

API Integration

function DataFetching() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
 
  useProduckAction('fetch-user-data', async (payload) => {
    setLoading(true);
    try {
      const userId = payload.actionConfig.userId;
      const response = await fetch(`/api/users/${userId}`);
      const userData = await response.json();
      setData(userData);
    } catch (error) {
      console.error('Failed to fetch:', error);
    } finally {
      setLoading(false);
    }
  });
 
  useProduckAction('refresh-data', async () => {
    setLoading(true);
    try {
      const response = await fetch('/api/data');
      const newData = await response.json();
      setData(newData);
    } finally {
      setLoading(false);
    }
  });
 
  if (loading) return <Spinner />;
  if (!data) return <EmptyState />;
  
  return <DataDisplay data={data} />;
}

Theme Switching

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
 
  useProduckAction('toggle-dark-mode', () => {
    setTheme(t => t === 'light' ? 'dark' : 'light');
  });
 
  useProduckAction('set-light-mode', () => setTheme('light'));
  useProduckAction('set-dark-mode', () => setTheme('dark'));
 
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);
 
  return <div className={theme}>{children}</div>;
}

Analytics Tracking

function AnalyticsIntegration() {
  useProduckAction('track-conversion', (payload) => {
    analytics.track('Conversion', {
      source: 'ai-assistant',
      action: payload.actionKey,
      value: payload.actionConfig.value,
    });
  });
 
  useProduckAction('track-engagement', (payload) => {
    analytics.track('Engagement', {
      feature: payload.actionConfig.feature,
      timestamp: Date.now(),
    });
  });
 
  return <YourContent />;
}

Custom Chat UI

function CustomChatInterface() {
  const { messages, isLoading, sendMessage } = useProduckMessages();
  const [input, setInput] = useState('');
 
  const handleSend = async () => {
    if (!input.trim()) return;
    await sendMessage(input);
    setInput('');
  };
 
  return (
    <div className="chat-interface">
      <div className="messages-container">
        {messages.map((msg, i) => (
          <div key={i} className={`message message-${msg.role}`}>
            <div className="message-content">{msg.content}</div>
            {msg.action && (
              <div className="action-badge">
                Action triggered: {msg.action.name}
              </div>
            )}
          </div>
        ))}
        {isLoading && (
          <div className="message message-loading">
            <div className="typing-indicator">
              <span></span><span></span><span></span>
            </div>
          </div>
        )}
      </div>
      
      <div className="input-container">
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && handleSend()}
          placeholder="Type a message..."
        />
        <button onClick={handleSend} disabled={!input.trim() || isLoading}>
          Send
        </button>
      </div>
    </div>
  );
}

Complete Applications

For full application examples, check out:

Code Snippets

Vanilla JavaScript Setup

<!DOCTYPE html>
<html>
<head>
  <title>Produck SDK Example</title>
</head>
<body>
  <div id="app"></div>
 
  <script type="module">
    import { createProduck } from 'https://cdn.skypack.dev/@produck/sdk';
 
    const produck = createProduck({
      sdkKey: 'your-sdk-key'
    });
 
    await produck.init();
 
    produck.register('my-action', (payload) => {
      console.log('Action triggered!', payload);
      // Your custom logic here
    });
  </script>
</body>
</html>

Next.js Setup

// app/layout.tsx
import { ProduckProvider, ProduckChat } from '@produck/sdk/react';
 
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ProduckProvider config={{ sdkKey: process.env.NEXT_PUBLIC_SDK_KEY }}>
          {children}
          <ProduckChat position="bottom-right" />
        </ProduckProvider>
      </body>
    </html>
  );
}
 
// app/page.tsx
'use client';
 
import { useProduckAction } from '@produck/sdk/react';
import { useState } from 'react';
 
export default function Home() {
  const [modal, setModal] = useState(false);
 
  useProduckAction('open-modal', () => {
    setModal(true);
  });
 
  return (
    <div>
      <h1>Welcome</h1>
      {modal && <Modal onClose={() => setModal(false)} />}
    </div>
  );
}

Need More Help?