npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marvalt/tadapter

v1.0.12

Published

Testimonials integration package for React applications with passwordless authentication

Readme

@marvalt/tadapter

Testimonials integration package for React applications with passwordless authentication.

Overview

@marvalt/tadapter provides a complete solution for implementing testimonial submission workflows in React applications. It integrates with the Vibrant Testimonials WordPress plugin to enable passwordless authentication and testimonial submission.

Features

  • Passwordless Authentication: Token-based authentication system
  • Session Management: Secure session handling with configurable expiration
  • React Hooks: Easy-to-use hooks for authentication and submission
  • React Components: Pre-built form components with validation
  • Cloudflare Pages Functions: Server-side proxy for secure API calls
  • TypeScript: Full TypeScript support with comprehensive types

Installation

npm install @marvalt/tadapter

Prerequisites

  • React 16.8+ (for hooks)
  • @tanstack/react-query 4.0+
  • Vibrant Testimonials WordPress plugin (v3.0.0+)

Setup

1. Install the Package

npm install @marvalt/tadapter

2. Create Pages Function

Create functions/api/testimonials.ts in your Cloudflare Pages project:

import { handleTestimonialsProxy } from '@marvalt/tadapter/server';

export const onRequest = handleTestimonialsProxy;

3. Configure Environment Variables

Set these in your Cloudflare Pages dashboard (or .env.local for local development):

VITE_WORDPRESS_API_URL=https://your-wordpress-site.com
VITE_CF_ACCESS_CLIENT_ID=your-cf-access-client-id
VITE_CF_ACCESS_CLIENT_SECRET=your-cf-access-client-secret
ALLOWED_ORIGINS=https://your-frontend.com,https://www.your-frontend.com
TURNSTILE_SECRET_KEY=your-turnstile-secret-key  # Optional

Usage

Basic Example

import { useTestimonialAuth, TestimonialForm } from '@marvalt/tadapter';

function TestimonialPage() {
  const { searchParams } = useSearchParams();
  const token = searchParams.get('token');
  const { sessionId, isLoading, validateToken } = useTestimonialAuth();

  useEffect(() => {
    if (token) {
      validateToken(token);
    }
  }, [token]);

  if (!sessionId) {
    return <div>Loading...</div>;
  }

  return (
    <TestimonialForm
      sessionId={sessionId}
      memberId={123} // Optional
      onSubmitSuccess={() => console.log('Success!')}
    />
  );
}

Using Hooks

import { 
  useTestimonialAuth, 
  useTestimonialSubmission, 
  useKudosOptions 
} from '@marvalt/tadapter';

function MyComponent() {
  const { sessionId, email, metadata, validateToken } = useTestimonialAuth();
  const { submit, isLoading } = useTestimonialSubmission();
  const { kudos } = useKudosOptions();

  // Use the hooks...
}

Custom Form

import { useTestimonialSubmission, useKudosOptions } from '@marvalt/tadapter';
import { KudosSelector } from '@marvalt/tadapter';

function CustomTestimonialForm({ sessionId }) {
  const { submit, isLoading } = useTestimonialSubmission();
  const { kudos } = useKudosOptions();

  const handleSubmit = async (data) => {
    await submit({
      ...data,
      session_id: sessionId,
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Your custom form fields */}
      <KudosSelector
        selected={selectedKudos}
        onChange={setSelectedKudos}
        required
      />
    </form>
  );
}

API Reference

Hooks

useTestimonialAuth(token?: string)

Manages authentication state and token validation.

Returns:

  • sessionId: string | null - Current session ID
  • email: string | null - Authenticated user's email
  • metadata: Record<string, any> | null - Session metadata
  • isLoading: boolean - Loading state
  • error: Error | null - Error state
  • validateToken: (token: string) => Promise<void> - Validate a token
  • checkSession: () => Promise<void> - Check session validity
  • logout: () => Promise<void> - Logout and destroy session
  • isAuthenticated: boolean - Whether user is authenticated

useTestimonialSubmission()

Handles testimonial submission.

Returns:

  • submit: (data: TestimonialSubmission) => Promise<TestimonialSubmissionResponse> - Submit testimonial
  • isLoading: boolean - Loading state
  • error: Error | null - Error state
  • isSuccess: boolean - Success state
  • data: TestimonialSubmissionResponse | undefined - Response data

useKudosOptions()

Fetches available kudos options.

Returns:

  • kudos: KudoOption[] - Array of kudos options
  • isLoading: boolean - Loading state
  • error: Error | null - Error state
  • refetch: () => void - Refetch kudos options

Components

<TestimonialForm />

Main testimonial form component.

Props:

  • sessionId: string (required) - Session ID from authentication
  • memberId?: number - Optional member ID to submit testimonial for
  • onSubmitSuccess?: (response: any) => void - Success callback
  • onSubmitError?: (error: Error) => void - Error callback
  • className?: string - Additional CSS classes
  • showTurnstile?: boolean - Enable Turnstile CAPTCHA
  • turnstileSiteKey?: string - Turnstile site key

<KudosSelector />

Component for selecting kudos (praise emojis).

Props:

  • selected: string[] (required) - Selected kudos values
  • onChange: (selected: string[]) => void (required) - Change handler
  • className?: string - Additional CSS classes
  • label?: string - Label text
  • required?: boolean - Whether selection is required

Client

TestimonialClient

Low-level API client (usually accessed via hooks).

import { TestimonialClient } from '@marvalt/tadapter';

const client = new TestimonialClient({
  proxyEndpoint: '/api/testimonials', // Default
});

// Methods:
await client.validateToken(token);
await client.checkSession(sessionId);
await client.logout(sessionId);
await client.submitTestimonial(data);
await client.getKudosOptions();
await client.getNonce();

Types

interface TestimonialSubmission {
  submitter_name: string;
  submitter_email?: string;
  submitter_role?: string;
  submitter_business_name?: string;
  submitter_company?: string;
  testimonial: string;
  kudos?: string[];
  testimonial_for?: number;
  category_id?: number;
  session_id: string;
  nonce?: string;
  'cf-turnstile-response'?: string;
  website_url?: string; // Honeypot
}

interface TokenValidationResponse {
  success: boolean;
  session_id: string;
  email: string;
  metadata: {
    name?: string;
    role?: string;
    business_name?: string;
    [key: string]: any;
  };
}

interface KudoOption {
  value: string;
  label: string;
}

Workflow

  1. Request Testimonial: Visitor clicks "Leave a testimonial" button
  2. Gravity Form: Visitor fills out form (firstname, business, email)
  3. Token Generation: WordPress plugin generates token and sends email
  4. Email Link: Visitor receives email with link: /testimonial?token=xxx&member_id=123
  5. Token Validation: Frontend validates token and creates session
  6. Form Display: Testimonial form is displayed with pre-filled metadata
  7. Submission: Visitor submits testimonial with session ID
  8. Moderation: Testimonial awaits admin approval

Security

  • Single-use tokens: Tokens are marked as used after validation
  • Session expiration: Configurable session duration (minimum 10 minutes)
  • Origin validation: CORS protection via Pages Function
  • Endpoint whitelisting: Only allowed endpoints are accessible
  • Turnstile CAPTCHA: Optional bot protection
  • Honeypot fields: Spam protection

License

GPL-3.0-or-later

Support

For issues and questions, please visit: https://github.com/MarVAlt/marvalt-tadapter/issues