Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fanfare.io/llms.txt

Use this file to discover all available pages before exploring further.

Deployment

This guide covers everything you need to deploy your Fanfare integration to production, including environment configuration, security considerations, and monitoring.

Pre-Deployment Checklist

Before deploying to production, verify the following:

1. Use Production Credentials

Ensure you are using production API keys, not test keys:
// Production
<FanfareProvider
  organizationId={process.env.NEXT_PUBLIC_FANFARE_ORG_ID}
  publishableKey={process.env.NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY} // pk_live_...
  environment="production"
>
Production keys:
  • Start with pk_live_
  • Connect to https://api.fanfare.io
  • Use your production organization data

2. Remove Debug Mode

Disable debug logging in production:
<FanfareProvider
  organizationId={process.env.NEXT_PUBLIC_FANFARE_ORG_ID}
  publishableKey={process.env.NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY}
  debug={false}  // Always false in production
  logging={{ level: "error" }}  // Only log errors
>

3. Verify Environment Variables

Ensure all required environment variables are set in your production environment:
# Required
NEXT_PUBLIC_FANFARE_ORG_ID=org_your_production_id
NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY=pk_live_your_production_key

# Optional
NEXT_PUBLIC_FANFARE_ENVIRONMENT=production

4. Test Production Configuration Locally

Before deploying, test with production credentials locally:
# Create a .env.production.local file (gitignored)
NEXT_PUBLIC_FANFARE_ORG_ID=org_production_123
NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY=pk_live_xyz789

# Run with production config
npm run build && npm run start

Backend Integration

Validating Admission Tokens

When customers are admitted, they receive an admission token. Your backend must validate this token before completing the transaction.
// Your backend API
import { createHmac } from "crypto";

interface AdmissionValidation {
  valid: boolean;
  experienceId?: string;
  consumerId?: string;
  admittedAt?: string;
  expiresAt?: string;
}

async function validateAdmissionToken(token: string): Promise<AdmissionValidation> {
  const response = await fetch("https://api.fanfare.io/v1/admissions/validate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.FANFARE_SECRET_KEY}`,
      "X-Organization-Id": process.env.FANFARE_ORG_ID!,
    },
    body: JSON.stringify({ token }),
  });

  if (!response.ok) {
    return { valid: false };
  }

  return response.json();
}
Security Note: Never expose your secret API key (sk_live_...) in client-side code. Only use it in your backend.

Webhook Integration

Set up webhooks to receive real-time notifications about experience events: Common webhook events:
EventDescription
queue.admittedConsumer was admitted from queue
draw.completedDraw finished, winners selected
auction.endedAuction ended
admission.expiredAdmission token expired
Example webhook handler:
// pages/api/webhooks/fanfare.ts (Next.js)
import { NextApiRequest, NextApiResponse } from "next";
import { createHmac } from "crypto";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== "POST") {
    return res.status(405).end();
  }

  // Verify webhook signature
  const signature = req.headers["x-fanfare-signature"] as string;
  const payload = JSON.stringify(req.body);
  const expectedSignature = createHmac("sha256", process.env.FANFARE_WEBHOOK_SECRET!).update(payload).digest("hex");

  if (signature !== expectedSignature) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  // Handle the event
  const event = req.body;

  switch (event.type) {
    case "queue.admitted":
      // Handle queue admission
      await handleQueueAdmission(event.data);
      break;
    case "draw.completed":
      // Handle draw completion
      await handleDrawCompletion(event.data);
      break;
    default:
      console.log("Unhandled event type:", event.type);
  }

  res.status(200).json({ received: true });
}

Security Considerations

Content Security Policy (CSP)

Allow connections to Fanfare APIs in your CSP:
// next.config.js
const securityHeaders = [
  {
    key: "Content-Security-Policy",
    value: `
      default-src 'self';
      connect-src 'self' https://api.fanfare.io https://beacon.fanfare.io;
      script-src 'self' 'unsafe-inline' 'unsafe-eval';
      style-src 'self' 'unsafe-inline';
    `.replace(/\n/g, ""),
  },
];

module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: securityHeaders,
      },
    ];
  },
};

CORS Configuration

The Fanfare API handles CORS automatically. Ensure your domain is registered in your Fanfare dashboard.

Rate Limiting

The Fanfare API has rate limits to protect against abuse:
EndpointLimit
Queue entry100 requests/minute per IP
Draw entry100 requests/minute per IP
Auction bidding60 requests/minute per consumer
Status polling120 requests/minute per consumer
The SDK handles rate limit errors gracefully with exponential backoff.

Performance Optimization

Bundle Size

Verify your bundle size includes only what you need:
# Analyze bundle
npm run build -- --analyze
The SDK supports tree-shaking. If you only use queues, draw/auction code is not included.

Lazy Loading

Load Fanfare components lazily if they are not needed on initial page load:
import { lazy, Suspense } from "react";

const QueueWidget = lazy(() => import("@fanfare/react").then((m) => ({ default: m.QueueWidget })));

function ProductPage() {
  return (
    <div>
      <h1>Product Details</h1>
      {/* QueueWidget loads only when rendered */}
      <Suspense fallback={<div>Loading queue...</div>}>
        <QueueWidget experienceId="exp_123" />
      </Suspense>
    </div>
  );
}

Preconnect to API

Add preconnect hints to reduce connection latency:
<head>
  <link rel="preconnect" href="https://api.fanfare.io" />
  <link rel="preconnect" href="https://beacon.fanfare.io" />
</head>

Monitoring and Observability

Error Tracking

Integrate with your error tracking service:
import * as Sentry from "@sentry/react";
import { FanfareProvider } from "@fanfare/react";

function App() {
  return (
    <Sentry.ErrorBoundary fallback={<ErrorFallback />}>
      <FanfareProvider
        organizationId={process.env.NEXT_PUBLIC_FANFARE_ORG_ID!}
        publishableKey={process.env.NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY!}
      >
        <YourApp />
      </FanfareProvider>
    </Sentry.ErrorBoundary>
  );
}

Analytics Events

Track Fanfare events in your analytics:
import { useFanfare } from "@fanfare/react";
import { useEffect } from "react";

function AnalyticsTracker() {
  const fanfare = useFanfare();

  useEffect(() => {
    const unsubscribeAdmitted = fanfare.on("queue:admitted", (data) => {
      // Track in your analytics
      analytics.track("Queue Admitted", {
        queueId: data.queueId,
      });
    });

    const unsubscribeDrawWon = fanfare.on("draw:won", (data) => {
      analytics.track("Draw Won", {
        drawId: data.drawId,
      });
    });

    return () => {
      unsubscribeAdmitted();
      unsubscribeDrawWon();
    };
  }, [fanfare]);

  return null;
}

Health Checks

Monitor Fanfare API availability:
// health-check.ts
async function checkFanfareHealth(): Promise<boolean> {
  try {
    const response = await fetch("https://api.fanfare.io/health", {
      timeout: 5000,
    });
    return response.ok;
  } catch {
    return false;
  }
}

Deployment Platforms

Vercel

# Set environment variables in Vercel dashboard or CLI
vercel env add NEXT_PUBLIC_FANFARE_ORG_ID
vercel env add NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY

# Deploy
vercel --prod

Netlify

# netlify.toml
[build]
  command = "npm run build"
  publish = ".next"

[build.environment]
  NEXT_PUBLIC_FANFARE_ORG_ID = "org_your_id"
  NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY = "pk_live_your_key"

AWS Amplify

# amplify.yml
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: .next
    files:
      - "**/*"
  cache:
    paths:
      - node_modules/**/*
Set environment variables in the Amplify console.

Docker

# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ARG NEXT_PUBLIC_FANFARE_ORG_ID
ARG NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY
ENV NEXT_PUBLIC_FANFARE_ORG_ID=$NEXT_PUBLIC_FANFARE_ORG_ID
ENV NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY=$NEXT_PUBLIC_FANFARE_PUBLISHABLE_KEY
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

EXPOSE 3000
CMD ["npm", "start"]

Post-Deployment Verification

After deploying, verify your integration:

1. Test the Full Flow

  1. Visit your production site
  2. Join a queue/draw/auction
  3. Verify you are admitted (use a test experience if needed)
  4. Complete a test transaction
  5. Verify the admission token was validated

2. Check Logging

Monitor your application logs for any Fanfare-related errors:
# Vercel
vercel logs --follow

# Docker
docker logs -f your-container

3. Verify Webhooks

Trigger a test event and verify your webhook endpoint receives it:
  1. Go to Fanfare Dashboard > Webhooks
  2. Click “Send Test Event”
  3. Verify your endpoint returns 200 OK

4. Monitor Metrics

Check your Fanfare dashboard for:
  • Request volume
  • Error rates
  • Average queue times
  • Conversion rates

Rollback Plan

Have a rollback plan ready:
  1. Feature Flag: Use a feature flag to disable Fanfare integration quickly
  2. Fallback UI: Show a fallback message if Fanfare is unavailable
  3. Previous Version: Keep the previous deployment available for quick rollback
function ProductPage() {
  const fanfareEnabled = useFeatureFlag("fanfare_enabled");

  if (!fanfareEnabled) {
    return <FallbackProductPage />;
  }

  return (
    <FanfareProvider {...config}>
      <ProductWithQueue />
    </FanfareProvider>
  );
}

Next Steps