# 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 