From 300188f135a598a4ae2a5bb6f119af1d13cae7eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?=
Date: Fri, 5 Jun 2026 14:37:49 +0200
Subject: [PATCH] feat(landing): real testimonials with gravatar/facehash
avatars (#493)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
- Replaces the placeholder landing testimonials with **11 real ones**
sourced from welcome-email replies and the Discord community.
- All testimonials shown in **English** with **Spanish translations**
added to `lang/es.json`.
- Adds a testimonial from Víctor Falcón (co-owner).
## Avatars
- Uses **Gravatar** with `d=404`; on miss, Radix `Avatar` falls back to
**``** (same config as `user-info.tsx`).
- Privacy: raw emails are **not** stored in the repo — only precomputed
MD5 hashes.
## Layout
- Testimonials render in **two marquee rows**, same direction but with
different speeds + a phase offset so cards don't line up into a grid.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
lang/es.json | 13 +-
resources/js/pages/welcome.tsx | 232 +++++++++++++++++++++------------
2 files changed, 164 insertions(+), 81 deletions(-)
diff --git a/lang/es.json b/lang/es.json
index 7f0e3b4a..ec4ee31b 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -1949,5 +1949,16 @@
"yellow": "amarillo",
"— $9/month": "— $9/mes",
"← Back to home": "← Volver al inicio",
- "🎉 Get a founder discount •": "🎉 Obtén un descuento de fundador •"
+ "🎉 Get a founder discount •": "🎉 Obtén un descuento de fundador •",
+ "I just started syncing my accounts and it already feels like a great app. The interface is lovely and it looks like a really solid tool. Great work!": "Acabo de empezar a sincronizar cuentas y ya me parece una gran app. La interfaz me encanta y parece una herramienta muy sólida. ¡Muy buen trabajo!",
+ "I have a lot of faith in this project — it's really well built and your MVP is fantastic. Thanks for everything!": "Confío mucho en este proyecto, está muy bien montado y vuestro MVP está de lujo. ¡Gracias por todo!",
+ "I'm exploring the web app and the design and UX are excellent. Thanks, team!": "Estoy descubriendo la aplicación web y, a nivel de diseño y UX, está excelente. ¡Gracias, chicos!",
+ "Thank you for developing Whisper Money. The focus on privacy and centralizing finances is an excellent proposition.": "Gracias por desarrollar Whisper Money. El enfoque en la privacidad y en centralizar las finanzas es una propuesta excelente.",
+ "I found Whisper Money and instantly knew I needed it. I was stuck doing everything in a spreadsheet — a chore I kept putting off. This makes it effortless.": "Descubrí Whisper Money y supe al instante que lo necesitaba. Estaba haciéndolo todo en una hoja de cálculo, una tarea que acababa posponiendo siempre. Esto lo hace facilísimo.",
+ "Thank you so much for creating such a clean, simple app.": "Muchísimas gracias por crear una app tan limpia y sencilla.",
+ "Great project!": "¡Gran proyecto!",
+ "I love this project!": "¡Me encanta este proyecto!",
+ "I'm genuinely happy using an open-source project with a real commitment to privacy — that's exactly what I want from a finance app.": "Estoy realmente contento usando un proyecto open-source con un compromiso real con la privacidad: es exactamente lo que quiero de una app de finanzas.",
+ "I can't wait to discover everything the app can do. Thank you — it must have taken a tremendous effort. Congratulations!": "Con muchas ganas de ir descubriendo todo lo que se puede hacer con la aplicación. ¡Gracias! Debe haber sido un esfuerzo tremendo. ¡Enhorabuena!",
+ "I built the app I needed to make better decisions. Understanding how I spend and where my income comes from has brought me real financial peace of mind.": "He construido la app que necesitaba para tomar mejores decisiones. Entender cómo gasto y de dónde vienen mis ingresos me ha dado una verdadera tranquilidad financiera."
}
diff --git a/resources/js/pages/welcome.tsx b/resources/js/pages/welcome.tsx
index 5c8103f9..0b663f69 100644
--- a/resources/js/pages/welcome.tsx
+++ b/resources/js/pages/welcome.tsx
@@ -3,9 +3,11 @@ import InputError from '@/components/input-error';
import AuthenticatedRedirectDialog from '@/components/landing/authenticated-redirect-dialog';
import InstallAppButton from '@/components/landing/install-app-button';
import Header from '@/components/partials/header';
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Spinner } from '@/components/ui/spinner';
+import { tailwindColorClasses } from '@/components/user-info';
import { usePwaInstall } from '@/hooks/use-pwa-install';
import { cn } from '@/lib/utils';
import { store as storeUserLead } from '@/routes/user-leads';
@@ -15,6 +17,7 @@ import { Plan } from '@/types/pricing';
import { formatCurrency } from '@/utils/currency';
import { __ } from '@/utils/i18n';
import { Form, Head, Link, router, usePage } from '@inertiajs/react';
+import { Facehash } from 'facehash';
import {
ArrowDownLeftIcon,
ArrowLeftRightIcon,
@@ -1913,6 +1916,87 @@ export default function Welcome({
const planEntries = Object.entries(pricing.plans);
const { isMobile } = usePwaInstall();
+ const testimonials = [
+ {
+ name: 'Brian Bansuela',
+ gravatar: '9314f776a17ae977871076ac71f2ff60',
+ text: __(
+ 'I just started syncing my accounts and it already feels like a great app. The interface is lovely and it looks like a really solid tool. Great work!',
+ ),
+ },
+ {
+ name: 'David Carrión',
+ gravatar: '2a0a1e872f2f883da214b65e1c2e2156',
+ text: __(
+ "I have a lot of faith in this project — it's really well built and your MVP is fantastic. Thanks for everything!",
+ ),
+ },
+ {
+ name: 'Jorge Navarrete',
+ gravatar: 'd20d4e05a100d5b20b45c84f3c566a25',
+ text: __(
+ "I'm exploring the web app and the design and UX are excellent. Thanks, team!",
+ ),
+ },
+ {
+ name: 'Marcus Oliveira',
+ gravatar: '3c4342baddf0beb8b0bd9fe89168e282',
+ text: __(
+ 'Thank you for developing Whisper Money. The focus on privacy and centralizing finances is an excellent proposition.',
+ ),
+ },
+ {
+ name: 'Carla Álvarez',
+ gravatar: '9901ee5e849cf9a0caea00e897cb8123',
+ text: __(
+ 'I found Whisper Money and instantly knew I needed it. I was stuck doing everything in a spreadsheet — a chore I kept putting off. This makes it effortless.',
+ ),
+ },
+ {
+ name: 'Yaritza Rey',
+ gravatar: 'a519f143865c358b013f3f6dcdbc387a',
+ text: __(
+ 'Thank you so much for creating such a clean, simple app.',
+ ),
+ },
+ {
+ name: 'Will Harris',
+ gravatar: 'c6fbc4911d6143fe723a42f46230275e',
+ text: __('Great project!'),
+ },
+ {
+ name: 'Haru',
+ gravatar: '3e52d6b2cbefb0fa2a572a588b3f7953',
+ text: __('I love this project!'),
+ },
+ {
+ name: 'Tom',
+ gravatar: 'd721bb1875ac11132d4d33295867cbd9',
+ text: __(
+ "I'm genuinely happy using an open-source project with a real commitment to privacy — that's exactly what I want from a finance app.",
+ ),
+ },
+ {
+ name: 'Elena',
+ gravatar: '9867fc6636afc02ae519820e657e4485',
+ text: __(
+ "I can't wait to discover everything the app can do. Thank you — it must have taken a tremendous effort. Congratulations!",
+ ),
+ },
+ {
+ name: 'Víctor Falcón (co-owner)',
+ gravatar: '50901af884c50a8f12804b0cf3aeb98a',
+ text: __(
+ 'I built the app I needed to make better decisions. Understanding how I spend and where my income comes from has brought me real financial peace of mind.',
+ ),
+ },
+ ];
+ const half = Math.ceil(testimonials.length / 2);
+ const testimonialRows = [
+ testimonials.slice(0, half),
+ testimonials.slice(half),
+ ];
+
const hasMonthlyAndYearly =
planEntries.some(([, p]) => p.billing_period === 'month') &&
planEntries.some(([, p]) => p.billing_period === 'year');
@@ -2431,88 +2515,76 @@ export default function Welcome({
-
-
- {[0, 1].map((copy) => (
-
- {[
- {
- name: __('Sarah M.'),
- handle: '@sarahm_finance',
- text: __(
- "Finally, a finance app that respects my privacy. Knowing my data isn't being shared gives me peace of mind.",
- ),
- },
- {
- name: __('Michael R.'),
- handle: '@mike_tech',
- text: __(
- "The budgeting features are intuitive and the dark mode is gorgeous. Best finance app I've used.",
- ),
- },
- {
- name: __('Emma L.'),
- handle: '@emmalou',
- text: __(
- 'Love that my financial data stays private. No more worrying about who has access to my spending habits!',
- ),
- },
- {
- name: __('David K.'),
- handle: '@davidk_dev',
- text: __(
- 'As a developer, I appreciate the security architecture. This is how finance apps should be built.',
- ),
- },
- {
- name: __('Jessica P.'),
- handle: '@jessicap',
- text: __(
- 'The automation rules save me so much time. And knowing my data is private? Priceless.',
- ),
- },
- {
- name: __('Alex T.'),
- handle: '@alext_money',
- text: __(
- 'Clean interface, powerful features, and zero compromise on privacy. What more could you want?',
- ),
- },
- ].map((testimonial) => (
-
-
-
- {testimonial.name.charAt(
- 0,
- )}
-
-
-
- {
- testimonial.name
- }
-
-
- {
- testimonial.handle
- }
-
+
+ {testimonialRows.map((row, rowIndex) => (
+
+ {[0, 1].map((copy) => (
+
+ {row.map((testimonial) => (
+
+
+
+
+
+
+
+
+
+
+ {
+ testimonial.name
+ }
+
+
+
+ {testimonial.text}
+
-
- {testimonial.text}
-
-
- ))}
-
- ))}
-
+ ))}
+
+ ))}
+
+ ))}