Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/anisur2805/proofpulse/archive/refs/heads/master.zipA modern, developer-first WordPress testimonial plugin. It ships — for free — the layout, collection, and styling features that competing plugins typically gate behind a pro license (Strong Testimonials, Real Testimonials, Testimonial Widgets, Testimonial Free).
Topics: wordpress · testimonials · reviews · gutenberg · block-editor · star-ratings · slider · carousel · masonry · rtl · wpml · polylang · rest-api · media-uploads · video-recording · storybook · typescript · lit-element · dark-mode · responsive · form-builder · schema-org
Quick facts:
- Testimonials render through Lit 2 web components (Shadow DOM) hydrated from a REST API
- Authored with a Gutenberg block or shortcodes
- Server-rendered markup fallback when JavaScript is disabled
- 5 responsive layouts: slider, carousel, grid, masonry, list
- 10+ layout-style variants (card, gradient, glass, minimal, border-left, outline, classic, modern, rounded, bordered)
- Advanced features: filtering, search, sorting, pagination, lazy-load images, read-more truncation, half-star ratings
- Slider/carousel UX: pause-on-hover, drag + touch swipe, adaptive height, transition speed, top-right nav
- RTL support, per-display color theming, avatar size + initials fallback, responsive columns/gap, section title
- Video testimonials: embeds or in-browser recording (MediaRecorder → validated upload); inline or lightbox
- Frontend submission form with honeypot + reCAPTCHA v3, multiple form presets, optional popup/lightbox
- Email: admin notification, submitter auto-responder, publish-approval notice; optional auto-publish by rating
- JSON-LD Review schema (toggle) + AggregateRating SEO markup
- Admin: Google Fonts, custom CSS/JS, JSON and CSV import/export, shortcode generator
- Integrations: Elementor widget, Polylang/WPML multilingual
Tech stack & tools used
| Concern | Choice |
|---|---|
| Frontend rendering | Lit 2 custom elements, Shadow DOM-encapsulated styles |
| Build | Vite 4 (single self-contained block.js bundle + a CSS-only frontend entry) |
| Styles | SCSS compiled by Vite; design tokens as CSS custom properties |
| Editor | Gutenberg block (@wordpress/* packages via lightweight React shims) |
| Server templating | Timber/Twig (optional, for theme overrides) |
| Data | Custom Post Type + taxonomies + post meta |
| Transport | WordPress REST API (proofpulse/v1) |
| Language | PHP 7.4+ / TypeScript |
| Component catalog | Storybook 8 (@storybook/web-components-vite) — isolated visual dev for the Lit layouts |
Build & develop
npm install
npm run build # production build → assets/js, assets/css
npm run dev # Vite dev server (HMR for component work)
Build outputs (committed):
assets/js/block.js— Gutenberg block registration + all Lit display components + API client. Loaded in both the editor and the frontend.assets/js/frontend.js— standalone JavaScript for frontend (lazy-loaded separately).assets/css/frontend.css— global design tokens (CSS custom properties) + light-DOM fallback layout styles + component styles.src/styles/frontend.ts— TypeScript styles file (imported in components).
Storybook
The Lit layout components render in isolation in Storybook — no WordPress install or live REST API needed. Stories set testimonials directly from mock fixtures (src/stories/fixtures.ts), so all 10 layout styles can be previewed and tweaked with hot reload.
npm run storybook # dev server at http://localhost:6006
npm run build-storybook # static build → storybook-static/ (git-ignored)
Stories live in src/stories/. Layouts.stories.ts covers every layout (card, minimal, modern, outline, classic, border-left, gradient, glass, bordered, rounded) plus single-item, video, hidden-rating, and empty states. The Gutenberg block editor (React/@wordpress/*) is intentionally out of scope — only the framework-agnostic Lit display layer is storied.
Features implemented
Core data model
- Testimonial CPT (
proofpulse_tstml) with category & tag taxonomies - Manual moderation via
pendingstatus - Meta: rating (half-star, 0.5–5), video URL, author website URL, photo (featured image)
- Extended identity fields: company, job title, location, country, reviewer avatar, company logo, social profiles (Facebook, X/Twitter, LinkedIn, Instagram, YouTube, GitHub)
- Unlimited custom fields (admin visual repeater builder + per-testimonial values)
- Admin list columns (photo, rating, category, tags, video) with sortable rating
Frontend display
- Layouts: slider, carousel, grid, masonry, list
- Layout styles: card, minimal, border-left, outline, gradient, glass, classic, modern, rounded, bordered
- Element ordering: drag-to-sort content, rating, author, video, custom fields, and category (global default + per-block override)
- Slider / carousel UX: pause-on-hover, mouse drag + touch swipe, slider adaptive height, configurable transition speed, arrows/dots toggles, top-right nav option
- RTL (right-to-left) across every layout
- Per-display colors: card background, text, accent, star (CSS custom properties that pierce the Shadow DOM)
- Avatar: size control + initials fallback when no photo
- Responsive: per-device columns (tablet/mobile) + gap (grid); optional section title heading
- Video: YouTube/Vimeo embeds or direct
<video>files; inline or lightbox playback - Pagination, lazy-loaded images & video, half-star ratings (including 0.5-star increments)
- Read-more / content truncation (character or word limit with expand button)
- Controls bar: instant search, category filter chips, rating filter, multi-field sorting (grid / masonry / list)
- Category/tag filtering, multiple instances per page, sidebar widgets (display + average rating)
- Server-rendered fallback inside every custom element (works when JS is disabled)
- RatingSummary element: average rating, total reviews, 1–5 star breakdown
Authoring
- Gutenberg block with inspector controls (layout, style picker, columns, slider/carousel options, element order)
- Shortcodes (see below)
Submission & collection
- Frontend submission form (Lit) via REST
POST - Fields: name, email, content, rating, video URL, website, category, tags, custom fields
- In-browser video recording (MediaRecorder) →
POST /upload-video(strict type/size validation, stored as attachment) - Multiple form presets — each with its own name, button text, and custom-field subset (
[proofpulse_form id="..."]) - Optional popup / lightbox form (trigger button + native
<dialog>) - Drag-sortable custom-field builder (admin)
- Honeypot + reCAPTCHA v3, admin notification + submitter auto-responder
- Publish-approval email to the reviewer (on pending → publish); optional auto-publish by star-rating threshold (gated on a passed reCAPTCHA)
Settings (admin)
- Spam protection (reCAPTCHA v3 keys)
- Custom form fields (drag-sortable visual builder) + global field order
- Forms tab (multiple form presets)
- Display & Code: schema on/off, auto-publish threshold, Google Font, custom CSS + custom JS
- Shortcode generator with live output + copy button
- Import / Export: JSON and CSV (CSV-safe export, auto-detected import)
Rating aggregation
- Average rating, total reviews, 1–5 star breakdown
- Custom
<proofpulse-rating-summary>element,ratingblock layout, and[proofpulse_rating]shortcode - AggregateRating JSON-LD schema emitted alongside the summary
SEO / data
- JSON-LD Review schema output (toggleable) + AggregateRating
- REST listing + filtering; JSON and CSV import/export
Integrations
- Elementor: a ProofPulse Testimonials widget (registered only when Elementor is active) reusing the shared renderer
- Polylang / WPML: translatable CPT + taxonomies, registered strings, and a shipped
wpml-config.xml
Shortcodes
All tags are namespaced with proofpulse_ to avoid collisions with other
testimonial plugins.
| Shortcode | Result |
|---|---|
[proofpulse] |
Generic display; set everything via attributes |
[proofpulse_testimonials] |
Slider (default) |
[proofpulse_slider] |
Slider |
[proofpulse_carousel] |
Carousel |
[proofpulse_grid] |
Grid |
[proofpulse_masonry] |
Masonry |
[proofpulse_list] |
List |
[proofpulse_form] |
Frontend submission form (add id="..." for a preset, popup="true" for a modal) |
[proofpulse_rating] |
Aggregate rating summary (average + breakdown) |
Back-compat: the old un-namespaced tags (
[testimonials],[testimonials_grid],[testimonial_form],[testimonial_rating], …) still work, but only when no other active plugin has claimed the same tag. Prefer theproofpulse_*tags.
Common attributes (kebab-case, mirror the block attributes):
[proofpulse_grid category="clients" tags="vip,2024" limit="6" columns="3"
style="gradient" show-rating="true" paginate="true" class="my-wrap"]
| Attribute | Default | Notes |
|---|---|---|
layout |
slider |
only on [proofpulse] |
category |
— | category slug |
tags |
— | comma-separated slugs |
limit / per-page |
3 |
number of testimonials |
columns |
3 |
grid / masonry |
style / inner-layout |
card |
layout-style variant |
show-rating |
true |
|
paginate |
false |
grid / masonry / list |
read-more |
false |
collapse long content behind a toggle |
read-more-type |
char |
char or word |
read-more-limit |
200 |
characters (or words) before truncating |
controls |
false |
show the filter/search/sort bar (grid / masonry / list) |
slides-to-show / slides-to-scroll |
3 / 1 |
carousel |
autoplay / autoplay-interval |
true / 5000 |
slider / carousel |
transition-speed |
500 |
track animation duration, ms (slider / carousel) |
pause-on-hover |
true |
slider / carousel |
enable-drag |
true |
mouse drag + touch swipe (slider / carousel) |
adaptive-height |
false |
slider matches the current slide height |
nav-position |
sides |
sides or top-right (slider / carousel) |
loop, show-arrows, show-dots |
true |
slider / carousel |
rtl |
false |
right-to-left text direction |
section-title |
— | heading rendered above the display |
gap |
0 |
grid/masonry gap in px (0 = default) |
columns-tablet / columns-mobile |
0 |
responsive grid columns (0 = same as desktop) |
image-size |
0 |
avatar size in px (0 = default) |
video-lightbox |
false |
open videos in a modal instead of inline |
bg-color / text-color / accent-color / star-color |
— | per-display colors (hex/rgb/hsl/named) |
field-order |
global default | comma-separated field keys |
class |
— | extra CSS classes on the wrapper |
Shortcodes share the exact same renderer as the Gutenberg block, so output, defaults, and sanitization stay identical.
REST API
Namespace proofpulse/v1:
GET /testimonials—category,tag,tags,per_page,page,search,orderby(newest/oldest/highest/lowest/random),min_rating; returns items +X-WP-Total/X-WP-TotalPagesheadersPOST /testimonials— public submission (honeypot + optional reCAPTCHA), saved aspending(orpublishwhen auto-publish + reCAPTCHA pass)POST /upload-video— public recorded-video upload; strict type (webm/mp4/mov) + 25 MB cap, stored as an attachment, returns{ id, url }GET /categories— non-empty testimonial categories (slug,name,count) for the filter chipsGET /rating-summary—category,tags; returnsaverage,total,count, and a 1–5breakdownGET /settings— public config for the submission form;formparam scopes to a preset (reCAPTCHA site key, custom-field definitions, button + success text)
Architecture & conventions (followed strictly)
These rules are intentional and must be kept when extending the plugin:
-
Prefixing. Everything is namespaced/prefixed
proofpulse/ProofPulse\— post type, taxonomies, meta keys, option names, REST namespace, CSS classes, custom-element tags, script/style handles. -
Class loading. PSR-style namespace
ProofPulse\…resolved by a flat autoloader againstsrc/php/<ShortClassName>.php. One class per file; init via a staticinit()called fromproofpulse.php. -
Rendering pipeline. The browser upgrades a server-printed custom element (e.g.
<proofpulse-grid>) that fetches via REST and renders into Shadow DOM. The server also prints a styled light-DOM fallback inside the element for the no-JS case. Never duplicate display logic — block and shortcodes both call the single sharedrender_testimonial_block(). -
Single bundle, no un-versioned sub-imports.
block.jsinlines the components; it must not split into relative ES imports (those aren't cache-busted and serve stale code). Assets are cache-busted withfilemtime()as the version. -
Shadow-DOM styling + design tokens. Component styles live in the component (
static styles), reusing sharedcssfragments (layout-styles,stars,pagination). Visual values come from--proofpulse-*custom properties (defined infrontend.css, they pierce the shadow boundary) with literal fallbacks so components survive even if the global sheet is missing. The card-variant styles consume:--proofpulse-bg-card— card background (minimal, outline, glass, classic)--proofpulse-color-primary— accent border (border-left, modern)--proofpulse-text-color— card text (gradient)--proofpulse-spacing-sm,--proofpulse-font-size-sm,--proofpulse-bg-muted— shared spacing/typography
The PHP renderer also emits
--proofpulse-text-color(and--proofpulse-grid-gap) inline on the wrapper so per-display color controls propagate into Shadow DOM without an extra stylesheet. -
BEM-ish class names.
proofpulse-{component}__{element}--{modifier}; layout-style modifier is alwaysproofpulse-card--{style}. -
Security. Escape on output (
esc_*), sanitize on input (sanitize_*,wp_kses_post), nonce + capability checks on admin writes,permission_callbackon every REST route, honeypot + reCAPTCHA on public submission. -
i18n. All user-facing strings wrapped with the
proofpulsetext domain. -
Field-order contract. Order flows: global Settings default → per-instance override → applied identically across every layout and the server fallback.
Project layout
proofpulse.php Bootstrap: constants, autoloader, hooks, block + shortcode render,
custom CSS/JS + Google Font output, color sanitizer
wpml-config.xml WPML translatable types/taxonomies + admin strings
src/php/ CPT, REST_API, Settings, CustomFields, Forms, ImportExport, Schema,
Shortcodes, TestimonialWidget, RatingSummaryWidget, Compat,
ElementorIntegration, ElementorTestimonialWidget, Timber
src/components/ Lit display components (Slider, Grid, Masonry, Carousel, List,
SubmissionForm, RatingSummary) + shared helpers (author,
controls, read-more, video) + css/render utilities
src/layouts/ Layout-style definitions (card, gradient, glass, …)
src/block/ Gutenberg block (edit/save/index, block.json, editor.scss, templates)
src/styles/ Design tokens (frontend.ts), layout styles, component styles
src/api/ REST client and service layer
src/stories/ Storybook stories + mock fixtures
src/templates/ Twig templates (Timber)
admin/ Settings page assets (admin.php, admin.js, admin.css)
Roadmap
See IMPLEMENTATION-TRACKER.md (status against the codebase), IMPLEMENTATION-TRACKER-2.md (full feature spec), and FEATURE-GAP-VS-REAL-TESTIMONIALS.md (parity vs. the Real Testimonials plugin — now complete except retina images, which needs an attachment-ID media rework).
Done: shortcodes · read-more · AJAX filter/search/sort · rating summary · extended data fields · pre-designed templates · slider UX (hover/drag/swipe/adaptive/speed/nav) · RTL · per-display colors · Google Fonts · avatar size + fallback · responsive columns/gap · section title · video lightbox + in-browser recording · multiple forms + popup · auto-publish + approval email · CSV import/export · schema toggle · custom CSS/JS · shortcode generator · standalone rating widget · Elementor · Polylang/WPML.
License
GPL-2.0+