Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/dev-os/llms.txt

Use this file to discover all available pages before exploring further.

The Testimonials app borrows the visual language of e-commerce product reviews to present peer recommendations in a format visitors immediately recognise. A teal banner at the top mimics the aggregate-rating hero found on Amazon product pages, complete with gold stars and a global-ratings count. Below it, each testimonial appears as a review card with an avatar, role, star row, serif quote, date, and a thumbs-up “Helpful” button — all rendered from a single static data array. The header section is a full-width bg-os-teal text-white banner with p-6 padding. It contains:
  • Title"Developer Reviews & Ratings" in text-2xl font-bold
  • Star row — five Star icons from lucide-react, each size={20} with fill="currentColor" in text-yellow-400
  • Rating label"5.0 out of 5" in text-lg font-medium
  • Count badge"(3 global ratings)" in text-sm text-white/80; the number is derived from testimonials.length so it updates automatically as you add or remove entries

Sort Bar

A slim bg-white border-b border-gray-200 row below the header holds a label ("Top reviews from the internet") and a <select> dropdown on the right. The dropdown tracks selection in a sortBy state variable:
const [sortBy, setSortBy] = useState('flattering');
The three options are:
valueDisplay label
flatteringSort by: Most flattering
cringeySort by: Least cringey
recentSort by: Recent
sortBy state is tracked but no sort logic is applied to the testimonials array in the current implementation. The dropdown is decorative. To implement sorting, add a useMemo that returns a reordered copy of the array based on sortBy before mapping over it.

Testimonials Data

All reviews live in a static array at the top of TestimonialsApp.js:
const testimonials = [
  {
    id: 1,
    name: 'Former Manager',
    role: 'Engineering Director',
    text: 'Shipped features faster than I could write the Jira tickets. Highly recommended.',
    date: 'Oct 2023',
  },
  {
    id: 2,
    name: 'Designer Colleague',
    role: 'UX Lead',
    text: 'Actually cares about padding and typography. A rare breed of developer who doesn\'t make me cry during QA.',
    date: 'Aug 2023',
  },
  {
    id: 3,
    name: 'My Mom',
    role: 'Mom',
    text: "I don't know what a React is, but the colors on this website are very nice.",
    date: 'Yesterday',
  },
];
Each object requires five fields:
FieldTypeRendered as
idnumberReact list key
namestringReviewer name + avatar initial
rolestringSub-label beneath the name
textstringSerif block quote
datestring"Reviewed on [date]" footer label

Review Card Anatomy

Each entry in testimonials renders as a bg-white p-4 rounded-lg shadow-sm border border-gray-100 card:
┌──────────────────────────────────────────┐
│  [F]  Former Manager                     │
│       Engineering Director               │
│  ★★★★★                                  │
│                                          │
│  "Shipped features faster than I could   │
│   write the Jira tickets."               │
│                                          │
│  Reviewed on Oct 2023     👍 Helpful     │
└──────────────────────────────────────────┘
  • Avatar — an 8×8 circle (bg-gray-200 rounded-full) containing the first character of name (name.charAt(0)) in text-gray-500 font-bold. No image upload or external URL needed.
  • Star row — five Star icons (size={14}, fill="currentColor", text-yellow-400), identical in structure to the header stars but smaller.
  • Quotetext-sm text-gray-800 font-serif, wrapped with curly quotation marks in the JSX.
  • Footer — flexbox row with justify-between; left side shows the reviewed-on date, right side has a ThumbsUp icon button (hover:text-os-teal transition-colors). The Helpful button is currently stateless — no click handler is attached.

Customising the Testimonials App

Add a real testimonial — append a new object to the testimonials array. The rating count in the header updates automatically:
{
  id: 4,
  name: 'Open Source Collaborator',
  role: 'Staff Engineer',
  text: 'Merged a 400-file PR with zero merge conflicts. Witchcraft.',
  date: 'Mar 2024',
},
Remove a testimonial — delete its object from the array. No other changes required. Make the Helpful button interactive — add a helpfulCounts state object keyed by id and increment on click:
const [helpfulCounts, setHelpfulCounts] = useState({});

const handleHelpful = (id) => {
  setHelpfulCounts(prev => ({ ...prev, [id]: (prev[id] || 0) + 1 }));
};
The avatar is generated from the first letter of name — no image needed. To visually distinguish reviewers, replace the static bg-gray-200 class with a per-reviewer colour. You can derive one deterministically from the id using an array lookup:
const avatarColors = ['bg-teal-100', 'bg-purple-100', 'bg-amber-100', 'bg-rose-100'];
const colorClass = avatarColors[testimonial.id % avatarColors.length];

<div className={`w-8 h-8 ${colorClass} rounded-full ...`}>
  {testimonial.name.charAt(0)}
</div>

Build docs developers (and LLMs) love