Testimonial Section
The TestimonialSection and Testimonial components create beautiful customer testimonial displays with avatars, ratings, and quotes. Perfect for landing pages, marketing sites, and social proof sections.
Goal
By the end of this guide, you'll be able to create professional testimonial sections that build trust and credibility instantly.
Quick Start
Here's the simplest way to create a testimonial.
John Doe
CEO, Acme Corp"This product changed my life! Highly recommended."
Visual Examples & Use Cases
1. Complete Testimonial Section
Full section with multiple testimonials.
TestimonialSection(
Testimonial(
quote="FastStrap made building our app incredibly fast. We launched in weeks, not months!",
author="Sarah Johnson",
role="CTO, TechStart",
avatar="/static/avatars/sarah.jpg",
rating=5
),
Testimonial(
quote="The zero-JS philosophy is brilliant. Our pages load instantly and SEO is perfect.",
author="Mike Chen",
role="Lead Developer, WebCo",
avatar="/static/avatars/mike.jpg",
rating=5
),
Testimonial(
quote="Best FastHTML framework out there. Clean API, great docs, active community.",
author="Emma Davis",
role="Freelance Developer",
avatar="/static/avatars/emma.jpg",
rating=5
),
title="What Our Customers Say",
subtitle="Join thousands of developers building with FastStrap",
columns=3
)
2. Without Avatars
Simple text-only testimonials.
Testimonial(
quote="Simple, powerful, and exactly what I needed.",
author="Alex Thompson",
role="Indie Hacker"
)
3. Without Ratings
Testimonials without star ratings.
Testimonial(
quote="The documentation is outstanding. I was productive in minutes.",
author="Lisa Park",
role="Software Engineer"
)
Practical Functionality
Dynamic Testimonials
Load testimonials from database.
def TestimonialsPage():
# Get testimonials from database
testimonials = db.query(Testimonial).filter(
Testimonial.approved == True
).order_by(Testimonial.created_at.desc()).limit(6).all()
return TestimonialSection(
*[
Testimonial(
quote=t.quote,
author=t.author_name,
role=t.author_role,
avatar=t.avatar_url,
rating=t.rating
)
for t in testimonials
],
title="Customer Reviews",
subtitle=f"Rated {get_average_rating()}/5 by {len(testimonials)} customers"
)
With Carousel
Rotating testimonials.
from faststrap.components.display import Carousel
Carousel(
*[
Testimonial(
quote=t.quote,
author=t.author,
role=t.role,
rating=t.rating
)
for t in featured_testimonials
],
indicators=True,
controls=True,
auto_play=True,
interval=5000
)
Video Testimonials
Embed video testimonials.
Card(
Div(
Video(
src="/static/testimonials/john-doe.mp4",
controls=True,
cls="w-100"
),
cls="ratio ratio-16x9"
),
CardBody(
H6("John Doe"),
P("CEO, Acme Corp", cls="text-muted small"),
P('"This product transformed our business."')
)
)
Integration Patterns
In Landing Page
def LandingPage():
return Container(
# Hero section
Hero(...),
# Features
FeatureGrid(...),
# Testimonials
TestimonialSection(
*get_testimonials(),
title="Loved by Developers",
subtitle="See what our community is saying",
cls="my-5 py-5 bg-light"
),
# Pricing
PricingGroup(...),
# CTA
CallToAction(...)
)
With Trust Badges
Combine with company logos.
Section(
Container(
H2("Trusted by Industry Leaders", cls="text-center mb-4"),
# Company logos
Row(
*[
Col(
Img(src=f"/static/logos/{company}.png", cls="img-fluid"),
md=2
)
for company in ["google", "microsoft", "amazon", "apple", "meta", "netflix"]
],
cls="justify-content-center align-items-center mb-5"
),
# Testimonials
TestimonialSection(
*testimonials,
title="What They're Saying"
)
),
cls="py-5"
)
Filterable Testimonials
Filter by category or rating.
def TestimonialsWithFilter():
return Div(
H2("Customer Stories"),
# Filter buttons
ButtonGroup(
Button("All", hx_get="/testimonials?filter=all", hx_target="#testimonials"),
Button("5 Stars", hx_get="/testimonials?filter=5", hx_target="#testimonials"),
Button("Developers", hx_get="/testimonials?filter=dev", hx_target="#testimonials"),
cls="mb-4"
),
# Testimonials container
Div(id="testimonials")
)
@app.get("/testimonials")
def get_testimonials(filter: str = "all"):
query = db.query(Testimonial)
if filter == "5":
query = query.filter(Testimonial.rating == 5)
elif filter == "dev":
query = query.filter(Testimonial.category == "developer")
testimonials = query.all()
return TestimonialSection(*[
Testimonial(
quote=t.quote,
author=t.author,
role=t.role,
rating=t.rating
)
for t in testimonials
])
Parameter Reference
Testimonial
| Parameter | Type | Default | Description |
|---|---|---|---|
quote |
str |
Required | Testimonial quote text |
author |
str |
Required | Author name |
role |
str \| None |
None |
Author role/title |
avatar |
str \| None |
None |
Avatar image URL |
rating |
int \| None |
None |
Star rating (1-5) |
**kwargs |
Any |
- | Additional HTML attributes |
TestimonialSection
| Parameter | Type | Default | Description |
|---|---|---|---|
*testimonials |
Any |
Required | Testimonial components |
title |
str \| None |
None |
Section title |
subtitle |
str \| None |
None |
Section subtitle |
columns |
int |
3 | Number of columns (1-4) |
**kwargs |
Any |
- | Additional HTML attributes |
Best Practices
✅ Do This
# Use real customer quotes
Testimonial(
quote="Specific, authentic feedback from real users",
author="Real Name",
role="Actual Title, Company"
)
# Include avatars for credibility
Testimonial(
quote="...",
author="...",
avatar="/path/to/real/photo.jpg" # Real photo
)
# Show ratings
Testimonial(
quote="...",
author="...",
rating=5 # Helps build trust
)
# Organize in sections
TestimonialSection(
*testimonials,
title="What Our Customers Say",
subtitle="Real feedback from real users"
)
❌ Don't Do This
# Don't use fake testimonials
Testimonial(
quote="This is the best product ever!", # Too generic
author="Anonymous" # Not credible
)
# Don't use stock photos
avatar="https://thispersondoesnotexist.com/..." # Fake!
# Don't show only 5-star reviews
# Include variety for authenticity
# Don't overcrowd
TestimonialSection(*50_testimonials) # Too many!
Complete Example
Full testimonials page with filtering.
from fasthtml.common import *
from faststrap import TestimonialSection, Testimonial, Container
@app.get("/testimonials")
def testimonials_page(category: str = "all"):
# Get testimonials
query = db.query(TestimonialModel)
if category != "all":
query = query.filter(TestimonialModel.category == category)
testimonials = query.order_by(
TestimonialModel.rating.desc()
).limit(12).all()
# Calculate stats
total = db.query(TestimonialModel).count()
avg_rating = db.query(func.avg(TestimonialModel.rating)).scalar()
return Container(
# Header
Div(
H1("Customer Stories", cls="text-center"),
P(
f"{total} reviews • {avg_rating:.1f}/5 average rating",
cls="text-center text-muted"
),
cls="my-5"
),
# Filter
ButtonGroup(
Button(
"All",
variant="primary" if category == "all" else "outline-primary",
hx_get="/testimonials?category=all",
hx_target="#testimonials-content"
),
Button(
"Developers",
variant="primary" if category == "developer" else "outline-primary",
hx_get="/testimonials?category=developer",
hx_target="#testimonials-content"
),
Button(
"Businesses",
variant="primary" if category == "business" else "outline-primary",
hx_get="/testimonials?category=business",
hx_target="#testimonials-content"
),
cls="mb-4 d-flex justify-content-center"
),
# Testimonials
Div(
TestimonialSection(
*[
Testimonial(
quote=t.quote,
author=t.author_name,
role=t.author_role,
avatar=t.avatar_url,
rating=t.rating
)
for t in testimonials
],
columns=3
),
id="testimonials-content"
)
)
faststrap.components.patterns.testimonial
Testimonial Pattern Components.
Customer testimonial cards and sections for social proof.
Testimonial(quote, author, role=None, avatar=None, rating=None, **kwargs)
Single testimonial card with quote, author, and optional avatar/rating.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
quote
|
str
|
Testimonial quote text |
required |
author
|
str
|
Author name |
required |
role
|
str | None
|
Author's role/title (optional) |
None
|
avatar
|
str | None
|
URL to author's avatar image (optional) |
None
|
rating
|
int | None
|
Star rating out of 5 (optional) |
None
|
**kwargs
|
Any
|
Additional HTML attributes |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Card component with testimonial content |
Example
Basic testimonial:
Testimonial( ... quote="This product changed my life!", ... author="John Doe", ... role="CEO, Acme Corp" ... )
With avatar and rating:
Testimonial( ... quote="Absolutely amazing experience.", ... author="Jane Smith", ... role="Designer", ... avatar="/static/avatars/jane.jpg", ... rating=5 ... )
Note
Marked as @beta - API may change in future releases.
Source code in src/faststrap/components/patterns/testimonial.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
TestimonialSection(*testimonials, title='What Our Customers Say', subtitle=None, columns=3, **kwargs)
Section displaying multiple testimonials in a grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*testimonials
|
Any
|
Testimonial components to display |
()
|
title
|
str
|
Section title |
'What Our Customers Say'
|
subtitle
|
str | None
|
Optional subtitle |
None
|
columns
|
int
|
Number of columns in grid (default: 3) |
3
|
**kwargs
|
Any
|
Additional HTML attributes |
{}
|
Returns:
| Type | Description |
|---|---|
Div
|
Div with testimonials in responsive grid |
Example
Basic testimonial section:
TestimonialSection( ... Testimonial( ... quote="Great product!", ... author="Alice", ... role="Developer" ... ), ... Testimonial( ... quote="Highly recommend!", ... author="Bob", ... role="Designer" ... ), ... Testimonial( ... quote="Best decision ever!", ... author="Carol", ... role="Manager" ... ) ... )
Custom title and 2 columns:
TestimonialSection( ... *testimonials, ... title="Success Stories", ... subtitle="Hear from our happy customers", ... columns=2 ... )
Note
Marked as @beta - API may change in future releases.
Source code in src/faststrap/components/patterns/testimonial.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |