UNPKG

react-waitlist

Version:

A customizable waitlist form component for React applications

478 lines (374 loc) 13.2 kB
# React Waitlist A customizable, self-contained waitlist component for React that integrates with Resend audiences. This package provides everything you need to create beautiful, secure waitlist forms without external dependencies. ## Features - Secure integration with [Resend audiences](https://resend.com/blog/manage-subscribers-using-resend-audiences) - Fully customizable UI with theming support - Bot and spam protection with reCAPTCHA v3 - Accessibility built-in - Analytics tracking - Easy to integrate with any React application - Event system for client-side integrations - Webhook support for integration with external systems - Multiple security options built into the package - SSR Support for Next.js and other frameworks ## Installation ### Frontend (React application) ```bash npm install react-waitlist # or yarn add react-waitlist # or pnpm add react-waitlist ``` ### Backend (Optional but recommended for security) ```bash npm install react-waitlist/server # or yarn add react-waitlist/server ``` ## Integration Options React Waitlist is designed to be flexible and secure, offering multiple integration options depending on your application architecture: ### 1. Server-Side Integration (Most Secure) For frameworks with server-side rendering support (Next.js App Router, Remix, etc.), use the `ServerWaitlist` and `ClientWaitlist` components to keep API keys secure on the server: ```jsx // app/page.js (Next.js App Router) import { ServerWaitlist, ClientWaitlist } from 'react-waitlist/server'; export default function Home() { return ( <main> <h1>My Awesome Product</h1> {/* Server Component - Renders a placeholder */} <ServerWaitlist apiKey={process.env.RESEND_API_KEY} // Securely used on the server resendAudienceId="your_audience_id" title="Join Our Waitlist" /> {/* Client Component - Hydrates the placeholder */} <ClientWaitlist /> </main> ); } ``` ### 2. Client-Side with Security Utilities (Recommended for most applications) For client-side React applications, use the included security utilities to create proxy endpoints that protect your API keys: ```jsx // Frontend component import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm resendAudienceId="your_audience_id" resendProxyEndpoint="/api/resend-proxy" /> ); } // Backend proxy (part of this package) // api/resend-proxy.js import { createResendProxy } from 'react-waitlist/server'; export default createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], }); ``` ### 3. Custom Integration with Your Own Backend Use event callbacks to integrate with your existing backend systems: ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm onSuccess={({ formData }) => { // Handle successful submission with your own backend fetch('https://your-api.com/waitlist', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }); }} /> ); } ``` ## Basic Usage ### Frontend (React) React Waitlist can be integrated with various systems through different methods: #### Simple Usage with Custom Handlers ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm onSuccess={({ formData }) => { // Handle successful submission console.log('Form submitted successfully:', formData); // You could save to your database here saveToDatabase(formData); // Or integrate with your CRM sendToCRM(formData); // Or add to your marketing tool addToMailingList(formData); }} onError={({ error }) => { console.error('Error submitting form:', error); }} /> ); } ``` #### With Resend Integration ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm resendAudienceId="your_audience_id" resendProxyEndpoint="https://your-api.com/api/resend-proxy" /> ); } ``` #### With Webhooks for External Systems ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm webhooks={[ { url: "https://your-api.com/webhook", events: ["success"], includeAllFields: true } ]} webhookProxyEndpoint="https://your-api.com/api/webhook-proxy" /> ); } ``` #### Combining Multiple Integration Methods ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm // Resend integration resendAudienceId="your_audience_id" resendProxyEndpoint="https://your-api.com/api/resend-proxy" // Event callbacks onSuccess={({ formData, response }) => { // Custom logic after successful submission trackConversion(formData); }} // Webhooks for external systems webhooks={[ { url: "https://your-crm.com/api/leads", events: ["success"] } ]} webhookProxyEndpoint="https://your-api.com/api/webhook-proxy" /> ); } ``` ## Server-Side Rendering (SSR) Architecture When using the `ServerWaitlist` and `ClientWaitlist` components with frameworks like Next.js App Router, the following architecture is used: 1. **ServerWaitlist (Server Component)**: - Runs on the server only - Securely handles API keys and sensitive configuration - Renders a placeholder with serialized props - No React hooks or client-side code 2. **ClientWaitlist (Client Component)**: - Has the `'use client'` directive - Hydrates the placeholder rendered by ServerWaitlist - Handles all client-side interactivity - Uses React hooks for state management This architecture ensures that sensitive information like API keys stays on the server while providing a seamless user experience with client-side interactivity. ## Backend Setup (Optional but Recommended) For security reasons, it's recommended to use proxy endpoints to protect your API keys and credentials. ### Express.js Backend ```javascript // server.js const express = require('express'); const cors = require('cors'); const { createResendProxy } = require('react-waitlist/server'); const app = express(); app.use(express.json()); app.use(cors()); app.post('/api/resend-proxy', createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], })); app.listen(3001, () => { console.log('Server running on port 3001'); }); ``` ### AWS Lambda Function ```javascript // lambda-function.js const { createResendProxy } = require('react-waitlist/server'); const proxyHandler = createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], }); exports.handler = async (event) => { const req = { body: JSON.parse(event.body), headers: event.headers, }; let statusCode = 200; let responseBody = {}; const res = { status: (code) => { statusCode = code; return { json: (data) => { responseBody = data; } }; } }; await proxyHandler(req, res); return { statusCode, body: JSON.stringify(responseBody), headers: { 'Content-Type': 'application/json' } }; }; ``` ### Firebase Cloud Function ```javascript // functions/index.js const functions = require('firebase-functions'); const { createResendProxy } = require('react-waitlist/server'); exports.resendProxy = functions.https.onRequest(async (req, res) => { const proxyHandler = createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], }); await proxyHandler(req, res); }); ``` ## Next.js Integration For Next.js applications, you can use the same component with API routes: ```jsx // pages/api/resend-proxy.js (Next.js Pages Router) import { createResendProxy } from 'react-waitlist/server'; export default createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], }); ``` ```jsx // app/api/resend-proxy/route.js (Next.js App Router) import { NextResponse } from 'next/server'; import { createResendProxy } from 'react-waitlist/server'; const proxyHandler = createResendProxy({ apiKey: process.env.RESEND_API_KEY, allowedAudiences: ['your_audience_id'], }); export async function POST(req) { const res = { status: (code) => ({ json: (data) => NextResponse.json(data, { status: code }), }), }; return await proxyHandler(req, res); } ``` ## Customization The component is designed to be highly customizable to match your application's design system. ```jsx import { WaitlistForm } from 'react-waitlist'; function App() { return ( <WaitlistForm // Theme customization theme={{ colors: { primary: '#6366F1', secondary: '#8B5CF6', background: '#FFFFFF', text: '#1F2937', error: '#EF4444', success: '#10B981', } }} // Apply custom CSS class className="my-custom-waitlist" // Content customization title="Join our waitlist" description="Be the first to know when we launch" submitText="Join Now" successTitle="You're on the list!" successDescription="Thank you for joining our waitlist." // Field customization fields={[ { name: 'email', type: 'email', required: true, label: 'Email' }, { name: 'firstName', type: 'text', required: false, label: 'First Name' }, { name: 'role', type: 'select', options: ['Developer', 'Designer', 'Other'], required: false } ]} /> ); } ``` The component supports multiple customization approaches: - **Theme Configuration**: Customize colors, typography, spacing, and more via the `theme` prop - **CSS Classes**: Apply custom styles with the `className` prop - **External CSS**: Use CSS variables and advanced styling techniques - **Design System Integration**: Seamlessly integrate with your existing design system For detailed customization options and examples, see the [Customization Guide](docs/customization.md). ## Architecture React Waitlist is designed with a modular architecture that separates concerns and promotes maintainability: ### Core Modules The library is built around a set of core modules that handle specific functionality: - **core/types**: Type definitions for the entire library - **core/events**: Event system for tracking user interactions - **core/validation**: Form validation logic - **core/security**: Security features like honeypot fields and bot detection - **core/analytics**: Analytics tracking integrations - **core/webhook**: Webhook handling for external integrations ### Component Architecture The component architecture follows a modular approach: ```mermaid graph TD A[Application] --> B{Integration Method} B -->|Client-Side| C[WaitlistForm] C --> D[Core Modules] B -->|Server-Side| E[ServerWaitlist] E --> F[ClientWaitlist] F --> C D --> G[events] D --> H[validation] D --> I[security] D --> J[analytics] D --> K[webhook] ``` ### Package Structure The package is organized into several subpackages: - **react-waitlist**: Main package with client-side components - **react-waitlist/server**: Server-side components and utilities - **react-waitlist/client**: Client components for hydration in SSR This modular approach allows for: 1. **Tree-shaking**: Only import what you need 2. **Separation of concerns**: Each module has a specific responsibility 3. **Testability**: Modules can be tested in isolation 4. **Maintainability**: Changes to one module don't affect others For more detailed information about the architecture, see the [Architecture Guide](docs/architecture.md). ## Documentation For full documentation and examples, visit our [Storybook documentation](https://pmatheusvinhas.github.io/react-waitlist/). Additional documentation: - [Getting Started](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/getting-started.md) - [API Reference](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/api-reference.md) - [Customization](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/customization.md) - [Webhooks](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/webhooks.md) - [Events](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/events.md) - [reCAPTCHA](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/recaptcha.md) - [Accessibility](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/accessibility.md) - [Security](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/security.md) - [Testing](https://github.com/pmatheusvinhas/react-waitlist/blob/main/docs/testing.md) - [Changelog](https://github.com/pmatheusvinhas/react-waitlist/blob/main/CHANGELOG.md) ## License MIT