TicketWave for React & Next.js
Type-safe ticket widget for modern React applications.
Installation
No npm package needed. The widget script is loaded at runtime by the component. Just copy the component into your project.
# No package needed — just use our script loader component
# Copy the component below into your projectTicketWaveWidget Component
TypeScriptSave this as components/TicketWaveWidget.tsx in your project:
"use client";
import { useEffect, useRef } from "react";
interface TicketWaveProps {
client: string;
event: string;
apiUrl?: string;
theme?: "light" | "dark";
accentColor?: string;
buttonText?: string;
locale?: string;
className?: string;
}
export function TicketWaveWidget({
client,
event,
apiUrl = "https://www.ticketwavehq.com/api",
theme = "light",
accentColor,
buttonText,
locale,
className,
}: TicketWaveProps) {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Load script once
if (!document.querySelector('script[src*="ticketwave.js"]')) {
const script = document.createElement("script");
script.src = "https://www.ticketwavehq.com/widget/ticketwave.js";
script.async = true;
document.body.appendChild(script);
}
}, []);
return (
<div
ref={containerRef}
id={`ticketwave-${client}-${event}`}
data-client={client}
data-event={event}
data-api-url={apiUrl}
data-theme={theme}
{...(accentColor && { "data-accent-color": accentColor })}
{...(buttonText && { "data-button-text": buttonText })}
{...(locale && { "data-locale": locale })}
className={className}
/>
);
}Usage Examples
Basic Usage
import { TicketWaveWidget } from "@/components/TicketWaveWidget";
// Basic usage
<TicketWaveWidget client="oceanbeat" event="sunset-cruise-july" />Customised
// Customised
<TicketWaveWidget
client="oceanbeat"
event="sunset-cruise-july"
theme="dark"
accentColor="#7c3aed"
buttonText="Get Tickets"
locale="es"
/>Next.js App Router Page
// Next.js App Router page — app/tickets/page.tsx
import { TicketWaveWidget } from "@/components/TicketWaveWidget";
export default function TicketsPage() {
return (
<main className="max-w-xl mx-auto py-12">
<h1 className="text-3xl font-bold mb-8">Buy Tickets</h1>
<TicketWaveWidget client="oceanbeat" event="sunset-cruise-july" />
</main>
);
}Dynamic Event from URL Params
// Dynamic event from URL params — app/events/[slug]/page.tsx
import { TicketWaveWidget } from "@/components/TicketWaveWidget";
interface Props {
params: { slug: string };
}
export default function EventPage({ params }: Props) {
return (
<main className="max-w-xl mx-auto py-12">
<TicketWaveWidget
client="oceanbeat"
event={params.slug}
theme="light"
/>
</main>
);
}Props Reference
All available props for the TicketWaveWidget component.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
client | string | Required | — | Your venue slug from the TicketWave dashboard |
event | string | Required | — | Event slug from the event detail page |
apiUrl | string | Optional | "https://www.ticketwavehq.com/api" | API endpoint (rarely needs changing) |
theme | "light" | "dark" | Optional | "light" | Widget colour scheme |
accentColor | string (hex) | Optional | "#000000" | Primary accent colour for buttons |
buttonText | string | Optional | "Buy Tickets" | CTA button label |
locale | string | Optional | "en" | Language (en, es, pt, el, fr, de, it) |
className | string | Optional | — | Additional CSS classes for the container |
Troubleshooting
Widget not rendering in Next.js App Router
- Make sure the component has the "use client" directive at the top of the file. The widget uses useEffect and useRef, which require a client component.
- If using Server Components, import the TicketWaveWidget in a client component boundary.
- The widget renders client-side only. It will not appear during SSR — this is expected behaviour.
Script loading multiple times
- The component checks for an existing script element before creating a new one. If you see duplicate scripts, ensure you are not conditionally mounting/unmounting the component rapidly.
- In React Strict Mode (development), effects run twice. This is normal — the duplicate check prevents double loading.
TypeScript type errors
- Copy the full component code including the TicketWaveProps interface. All props are typed.
- The spread operator for optional data attributes uses conditional spreading, which TypeScript handles natively.
Widget not updating when props change
- The widget initialises once when the script loads. If you need to change the event dynamically, remount the component by changing its key prop.
- Example: <TicketWaveWidget key={eventSlug} client="venue" event={eventSlug} />
Frequently Asked Questions
Do I need to install an npm package?
No. The TicketWave widget is loaded via a script tag at runtime. The React component simply manages the script loading and renders the container div with the correct data attributes. No npm install required.
Does this work with Next.js Pages Router?
Yes. The component works with both the App Router and Pages Router. For Pages Router, remove the "use client" directive (it is not needed) and use the component as-is.
Can I use this with Vite, Remix, or other React frameworks?
Yes. The component is framework-agnostic React code. Remove the "use client" directive if your framework does not use it, and import the component normally.
Is the widget SSR-compatible?
The container div renders during SSR, but the widget script only executes client-side. This means search engines see the container element, and the interactive widget loads after hydration.
Can I style the widget with Tailwind CSS?
You can style the container div using the className prop. The widget itself renders in a shadow DOM, so Tailwind classes will not affect the widget's internal styles. Use the theme, accentColor, and buttonText props for visual customisation.
How do I show multiple events on one page?
Render multiple TicketWaveWidget components, each with a different event prop. The component generates a unique ID for each instance (ticketwave-{client}-{event}), and the script initialises all containers automatically.
Ready to add tickets to your React app?
Create your free account, copy the component, and start selling tickets in minutes.