Collecting and showing testimonials: a form that takes text or video, a library of what came in, and embeddable walls and widgets for your site.
Build me a testimonial system that replaces Senja: collect what customers say, keep the proof, and put it on my site without a third-party script. STACK - Node 20+ with Fastify, server-rendered HTML - SQLite through better-sqlite3, WAL mode - ffmpeg on the box for video, or nothing at all if you only take text - Caddy in front, serving media directly from disk THE DATA MODEL - spaces: id, slug, name, brand_json, collect_page_json - testimonials: id, space_id, kind, author_name, author_title, author_company, author_avatar_path, body, rating, video_path, poster_path, duration_ms, source, source_url, status, consent_text, consent_at, created_at - imports: id, space_id, platform, external_id, raw_json, imported_at — the original of anything pulled in from elsewhere - walls: id, space_id, slug, layout, filter_json, theme_json - wall_views: id, wall_id, created_at, referrer_host, ip_hash — because a wall that nobody sees is worth knowing about - Kinds: text, video, imported. Status: pending, approved, hidden - consent_text is the exact sentence the person agreed to, stored with the row. A testimonial without recorded consent is a legal problem waiting COLLECTING - A public collect page per space: a question, a text box or a record button, and the fields you actually need - Video recorded in the browser with MediaRecorder, uploaded in chunks, transcoded to H.264 and a poster frame taken at two seconds - A hard limit on length — 120 seconds — enforced in the browser and again on the server - The consent checkbox is not pre-ticked, and its exact wording is stored with the testimonial - A thank-you screen with an optional offer, because the moment somebody has just praised you is the moment to ask for one more thing - Works on a phone, in one hand, without an account IMPORTING WHAT ALREADY EXISTS - Paste a URL from a review site, a social post or a support ticket and store it with a screenshot of the source - The screenshot is the proof: a deleted tweet still needs evidence that it was said - Imported testimonials are marked as such and carry a link to the source. Never present an import as if it were collected APPROVAL - Nothing is public until somebody approves it - Edit for length and typos, never for meaning, and keep the original body alongside the edited one so the change is visible - Tag by product, by theme, by customer size - A rejected testimonial is hidden, not deleted PUTTING IT ON A SITE - A wall: a public page and an embeddable version, both server-rendered - Layouts: grid, masonry, single quote, carousel that is a scroller and not a timer - The embed is an iframe with a fixed set of layouts, or a script that injects plain HTML. Both take a height message so the host page can size the frame - No web fonts, no framework, under 15KB - Every wall filters by tag, rating or kind, and the filter is in the wall's definition rather than in the embed code - Structured data for reviews on the wall page, so a search engine can read it — and only where the testimonials are genuine and consented, which they are, because that is how they were collected MEDIA HANDLING - Store original and transcoded, serve the transcoded one - Avatars resized to two sizes at upload - Everything on your own disk with hashed filenames; nothing on a CDN you do not control THE INTERFACE - One screen: the queue on the left, the testimonial being read on the right, approve and tag from the keyboard - Dark and light, one accent OPERATIONS - .env: DATABASE_PATH, MEDIA_PATH, BASE_URL, SMTP_URL, ADMIN_PASSWORD_HASH - Migrations on boot, each once - Backup covers the database and the media directory, and the restore script proves both - Health endpoint that checks disk space, because video fills a disk quietly WHAT MATTERS MOST Collection and consent are the product. Build the collect page, the consent record and the approval queue first, and record a real video on a real phone before writing a line of the wall. A testimonial you cannot prove was given freely is one you cannot use. Give me the repository, migrations, .env.example, a seed space with six testimonials, and a README with deploy steps behind Caddy including ffmpeg.
What you lose
- In-browser video recording with transcoding and captions, which is the part that would take the longest
- Import of reviews from other platforms
- A dozen embeddable layouts already designed and responsive
If you would rather not build
- A form plus a static grid, which is most of the product
- Testimonial.to, for the hosted version
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $29/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Formbricks
$0Self-hosted forms with file upload for the collection half.
formbricks/formbricksfree · open source
Uppy
$0Handles the video upload, including resumable transfers to S3.
transloadit/uppyfree · open source
Why this verdict
our own opinion · changed only by a person
87/100
Verdict yes at 87. Text testimonials are a form and a grid. Storing the consent wording with the row is the detail that matters legally.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Senja
answered from the record above
Is Senja free?
No — the plan we track is $29 a month. Starter at around $29/month billed monthly, cheaper annually.
Can you replace Senja by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 87 out of 100, build time one session. Read what you lose before you decide.
How much does Senja cost?
$29 a month on Starter — $348 a year. Recorded 10 Aug 2026.
What do you lose by replacing Senja?
In-browser video recording with transcoding and captions, which is the part that would take the longest; Import of reviews from other platforms; A dozen embeddable layouts already designed and responsive. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Senja?
Yes: Formbricks, Uppy. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

