@marvalt/tadapter
v1.0.12
Published
Testimonials integration package for React applications with passwordless authentication
Maintainers
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/tadapterPrerequisites
- 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/tadapter2. 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 # OptionalUsage
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 IDemail: string | null- Authenticated user's emailmetadata: Record<string, any> | null- Session metadataisLoading: boolean- Loading stateerror: Error | null- Error statevalidateToken: (token: string) => Promise<void>- Validate a tokencheckSession: () => Promise<void>- Check session validitylogout: () => Promise<void>- Logout and destroy sessionisAuthenticated: boolean- Whether user is authenticated
useTestimonialSubmission()
Handles testimonial submission.
Returns:
submit: (data: TestimonialSubmission) => Promise<TestimonialSubmissionResponse>- Submit testimonialisLoading: boolean- Loading stateerror: Error | null- Error stateisSuccess: boolean- Success statedata: TestimonialSubmissionResponse | undefined- Response data
useKudosOptions()
Fetches available kudos options.
Returns:
kudos: KudoOption[]- Array of kudos optionsisLoading: boolean- Loading stateerror: Error | null- Error staterefetch: () => void- Refetch kudos options
Components
<TestimonialForm />
Main testimonial form component.
Props:
sessionId: string(required) - Session ID from authenticationmemberId?: number- Optional member ID to submit testimonial foronSubmitSuccess?: (response: any) => void- Success callbackonSubmitError?: (error: Error) => void- Error callbackclassName?: string- Additional CSS classesshowTurnstile?: boolean- Enable Turnstile CAPTCHAturnstileSiteKey?: string- Turnstile site key
<KudosSelector />
Component for selecting kudos (praise emojis).
Props:
selected: string[](required) - Selected kudos valuesonChange: (selected: string[]) => void(required) - Change handlerclassName?: string- Additional CSS classeslabel?: string- Label textrequired?: 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
- Request Testimonial: Visitor clicks "Leave a testimonial" button
- Gravity Form: Visitor fills out form (firstname, business, email)
- Token Generation: WordPress plugin generates token and sends email
- Email Link: Visitor receives email with link:
/testimonial?token=xxx&member_id=123 - Token Validation: Frontend validates token and creates session
- Form Display: Testimonial form is displayed with pre-filled metadata
- Submission: Visitor submits testimonial with session ID
- 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
