evidence-based
Duolingo
Overview
Duolingo's marketing surface is playful, energetic, and deliberately un-intimidating — a mass-market education product that wears its game-like personality on its sleeve. The visual system is built on a single rounded workhorse typeface (Duolingo Sans), crisp white surfaces, dark charcoal text, and one hero accent: the signature bright feather green. Depth is created almost entirely through layered mascot and character illustration rather than shadow, so the UI reads as flat, honest, and bright.
Density is generous on the marketing pages — big hero headlines set in the Feather display face, tall vertical rhythm ({spacing.section} = 96px between sections), and alternating two-column feature blocks that flip left-to-right down the page. The courses pages break this rhythm into a dense uniform 4-column grid of thin-bordered tiles for fast scanning. Hierarchy is made three ways: by type scale (48px display down to 15px labels), by the reserved use of feather green for primary action, and by chunky 4px-bordered pill buttons that dominate every call to action.
The most distinctive move is confidence through weight and shape: buttons use uppercase, letter-spaced bold labels ({typography.button} with 0.8px tracking), borders are unusually thick (4px is the most common border width across all 8 pages), and the footer is a full-bleed green panel rather than a quiet legal strip.
Key Characteristics:
- One hero accent — feather green (
{colors.primary}— #58CC02) reserved for primary action and the footer panel - Two typefaces only: Feather for display, Duolingo Sans for everything else
- Only two font weights exist: 500 (medium) and 700 (bold) — no light, no black
- Chunky rounded geometry: 12px/16px radii, pill buttons, 4px borders
- Flat by strategy — depth comes from illustration, not shadow
- Uppercase, letter-spaced CTA labels for a confident, tappable feel
- Crisp white surfaces with dark charcoal ink (
{colors.ink}— #3C3C3C)
Colors
The palette is tight and cheerful: one saturated hero green, a supporting sky blue, near-neutral charcoals for text, and a single hairline gray. There are no gradients anywhere in the system — color is applied flat, in solid fills and thick solid borders.
Brand & Accent
- Feather Green (
{colors.primary}— #58CC02): the hero accent. Fills primary buttons and the full-bleed footer panel; appears as surface and text across 5 pages. - Feather Green on Dark (
{colors.primary-on-dark}— #A5ED6E): the lighter green used for footer link text against the green panel — the highest-weight accent role in the evidence. - Green Tint (
{colors.primary-tint}— #D7FFB8): a pale wash for subtle green text/highlights on light surfaces. - Sky Blue (
{colors.secondary}— #1CB0F6): secondary action color for buttons and interactive accents. - Sky Blue Border (
{colors.secondary-border}— #1B99D6): the darker 4px border under secondary blue buttons, giving the pressed, tactile look. - Teal (
{colors.tertiary}— #00CD9C): a rare tertiary accent (one page only). - Deep Navy (
{colors.accent-deep}— #0B3E71): a very rare deep accent for occasional dark text.
Surface
- White (
{colors.surface}— #FFFFFF): the universal page and card background. Everything sits on white.
Text
- Charcoal Ink (
{colors.ink}— #3C3C3C): the primary body and heading color — by far the heaviest-weight color in the system. - Ink Strong (
{colors.ink-strong}— #4B4B4B): a slightly darker charcoal for emphasis. - Muted Gray (
{colors.muted}— #777777): secondary and supporting copy. - Muted Light (
{colors.muted-light}— #AFAFAF): the lightest text tier, for hints and disabled states. - Classic Link Blue (
{colors.link}— #0000EE): the raw browser-blue used for header nav links — a deliberately utilitarian, unbranded link color.
Hairlines & Borders
- Border Gray (
{colors.border}— #E5E5E5): the only hairline color, used for 2px card/tile borders and outline-button edges across all 8 pages.
On Gradients & Dark Mode
No gradients are used — all fills are solid. There is no dark-mode token block; the system is designed light-only, with the green footer panel acting as the sole large dark-on-color surface. Do not synthesize a dark theme.
Typography
Two typefaces, two weights, a bold-forward ladder. Nearly all UI text is Duolingo Sans; the oversized display headline is the only place the Feather face appears.
Font Family
- Feather — display only. Used for the 48px hero headline (
{typography.display}), appearing as<h2>across 5 pages. A rounded, chunky brand face. - Duolingo Sans — everything else: titles, leads, body, nav, footer, buttons, and labels. The dominant family by a wide margin (3579 vs 21 weight).
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
{typography.display} | 48px | 700 | 1.5 | normal | Hero headline (Feather) |
{typography.title-lg} | 28px | 700 | 1.15 | normal | Large section titles |
{typography.title-md} | 24px | 700 | 1.15 | normal | Section titles |
{typography.title-sm} | 20px | 700 | 1.2 | normal | Sub-titles / card headings |
{typography.lead} | 20px | 500 | 1.4 | normal | Lead / intro paragraphs |
{typography.body} | 17px | 500 | 1.4 | normal | Body copy |
{typography.nav-link} | 17px | 500 | 1.2 | normal | Header nav links |
{typography.footer-link} | 15px | 700 | 1.45 | normal | Footer links |
{typography.button} | 15px | 700 | 1.5 | 0.8px | Button labels (uppercase) |
{typography.button-lg} | 16px | 700 | 2.65 | 0.64px | Large button labels |
{typography.label-caps} | 15px | 700 | 1.15 | 0.8px | Caps labels / eyebrows |
Principles
- Only two weights exist: 500 (medium) for reading text and 700 (bold) for every heading, button, and label. Weight 400 and anything heavier are deliberately absent — do not add them.
- Letter-spacing is reserved for uppercase labels. Body, titles, and leads all run at normal tracking; only button and caps labels carry the 0.8px / 0.64px spacing that gives CTAs their confident feel.
- Line-height splits by role: tight (1.15–1.2) for headings so they stack punchily, relaxed (1.4–1.45) for reading text. The button-lg token's 2.65 line-height is a vertical-centering trick inside tall pill buttons, not a reading measure.
Note on Font Substitutes
Both Feather and Duolingo Sans are proprietary rounded faces. For rebuilds, substitute a friendly rounded geometric sans such as Nunito or Baloo 2 for Duolingo Sans, and a heavier rounded display cut (Baloo 2 700 or Fredoka) for Feather. Keep weights to 500/700, preserve the 0.8px tracking on caps labels, and round terminals to match the toy-like character.
Layout
Spacing System
The spacing scale is roughly 2px-derived with a friendly mid-range: {spacing.xs} 6px, {spacing.sm} 10px, {spacing.md} 12px, {spacing.lg} 16px, {spacing.xl} 24px, {spacing.2xl} 32px, {spacing.3xl} 40px, {spacing.4xl} 48px, then a big jump to {spacing.section} 96px for between-section rhythm and {spacing.gutter} 101px for the wide horizontal gutter. The 12px ({spacing.md}) and 16px ({spacing.lg}) steps are the most-used across all 8 pages — they carry component-internal padding and small gaps.
Grid & Container
The marketing pages are single-column and centered: a stacked hero (headline + two vertically stacked CTAs) followed by alternating two-column feature blocks that flip illustration/text left-to-right down the page. The wide 101px gutter ({spacing.gutter}) frames content on desktop. The courses pages switch to a dense, uniform 4-column grid of thin-bordered tiles with consistent gutters — optimized for scanning many languages at once. Cards carry 24px internal padding ({spacing.xl}).
Whitespace Philosophy
Whitespace is generous and rhythmic. The 96px section spacing ({spacing.section}) gives each marketing block room to breathe and lets illustrations dominate. Mobile collapses everything to a single centered column — illustration stacked above text — preserving section order and rhythm at tighter margins. The philosophy: big air between ideas on marketing surfaces, tight uniform gutters on utility grids.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Base | Flat white surface, no shadow | Page background, hero, feature sections |
| Hairline | 2px {colors.border} (#E5E5E5) outline | Course/flag tiles, cards, outline buttons |
| Tactile border | 4px solid darker-tone border | Buttons — the thick under-edge gives a pressable, chunky feel |
| Overlay | Flat white bar with hard divider | Cookie banner (no floating shadow) |
Shadow philosophy. Elevation comes from surface change and illustration layering, not shadows. The single shadow found in evidence (rgba(0,205,156,0.1) 0 0 0 1440px) is a full-screen tint overlay, not a card shadow. Separation between content is achieved with thin 2px borders and, on buttons, a distinctive 4px solid border that mimics a physical edge rather than a drop shadow. Depth on the marketing pages is purely illustrative — foreground characters overlap background shapes. Treat the system as flat by design.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
{rounded.md} | 12px | Smaller elements, tile icons — appears on all 8 pages |
{rounded.lg} | 16px | Buttons and cards — the dominant radius |
The geometry is soft, rounded, and toy-like throughout. Corner radii stay in a narrow soft-medium band (12–16px), reinforcing the friendly, non-sharp character. Buttons read as pills because their 16px radius ({rounded.lg}) combines with tall vertical padding; the outline and primary buttons all share this rounded rectangle language. Illustrations push it further — bouncy curved mascot shapes and a blob-shaped green curve closing the homepage hero. There is no sharp-cornered element in the system; do not introduce 0px or small (2–8px) radii, and don't add new large values beyond 16px.
Components
Navigation
navbar — A 70px-tall ({components.navbar.height}) static (non-sticky, non-fixed) bar on a white surface ({colors.surface}) with no border (borderWidth: 0px) and no backdrop blur. It carries a single nav link in the captured evidence, styled in classic Link Blue ({colors.link} — #0000EE) at 17px/500 ({typography.nav-link}). The header carries no CTA button (hasCtaButton: false) — the primary action lives in the hero, not the bar.
Buttons
All buttons share the uppercase, letter-spaced label ({typography.button} — 15px/700, 0.8px tracking), 16px radius ({rounded.lg}), and 11px 24px padding, giving the signature chunky pill.
button-primary— Feather green fill ({colors.primary}) with white text ({colors.surface}) and a 4px border in the same green. The main call to action (GET STARTED).button-secondary— Sky blue fill ({colors.secondary}) with white text and a 4px darker-blue border ({colors.secondary-border}) that reads as a physical under-edge.button-outline— White fill ({colors.surface}), blue text ({colors.secondary}), and a thinner 2px border in hairline gray ({colors.border}). Used for lower-priority actions like "I ALREADY HAVE AN ACCOUNT".
Cards & Containers
card — White surface ({colors.surface}), charcoal text ({colors.ink}), 16px radius ({rounded.lg}), 2px hairline border ({colors.border}), and 24px padding ({spacing.xl}). Used for course/flag tiles arranged in the 4-column courses grid; separation is by border, never shadow.
Links
link — Classic browser Link Blue ({colors.link} — #0000EE) at body scale ({typography.body}). Deliberately unbranded, utilitarian.
Footer
footer — A tall (827px) full-bleed panel filled with Feather green ({components.footer.backgroundColor} = {colors.primary}), static positioned, no border, no blur. Content is organized into 5 columns (columnCount: 5) holding 66 links total. footer-link items are set in the lighter Feather Green on Dark ({colors.primary-on-dark} — #A5ED6E) at 15px/700 with 1.45 line-height ({typography.footer-link}) — bold, light-green links on the green panel. This is the system's boldest color statement: the footer is a brand moment, not a quiet legal strip.
Do's and Don'ts
Do
- Reserve Feather green (
{colors.primary}) for primary action and the footer panel; let blue ({colors.secondary}) carry secondary CTAs. - Stick to the observed corner radii — 12px (
{rounded.md}) and 16px ({rounded.lg}); don't introduce new radius values. - Keep the two-typeface split: Feather for the 48px display headline (
{typography.display}), Duolingo Sans everywhere else. - Use only weights 500 and 700 across the type ladder — no lighter or heavier cuts.
- Give buttons their thick 4px border (
{components.button-primary.borderWidth}) with a darker-tone edge color for the tactile, pressable look. - Set every button label in uppercase with 0.8px tracking (
{typography.button}) for the confident CTA voice. - Separate cards and tiles with the 2px hairline border (
{colors.border}), not shadows.
Don't
- Don't add drop shadows for elevation — depth comes from illustration layering and borders, and the system is flat by strategy.
- Don't introduce gradients; all fills are solid.
- Don't recolor footer links away from Feather Green on Dark (
{colors.primary-on-dark}) — light-green on green is the intended contrast. - Don't make the header sticky or add a header CTA button; it is static (
{components.navbar.position}) and CTA-free. - Don't add letter-spacing to body, lead, or title text — tracking is reserved for caps labels only.
- Don't add a third typeface or a black/light weight beyond 500/700.
- Don't use branded blue for inline text links — those use raw Link Blue (
{colors.link}— #0000EE).
Responsive Behavior
This is a two-viewport analysis (desktop and mobile); no intermediate breakpoint pixel values were captured, so treat exact thresholds as unknown.
On desktop the layout uses single-column centered heroes plus alternating two-column feature blocks (illustration on one side, headline + copy on the other), framed by the wide 101px gutter ({spacing.gutter}). The courses pages render a 4-column bordered-tile grid.
On mobile everything collapses to a single centered column: illustration stacks above text, the two-column feature blocks unstack, and the multi-column grid reduces to a stacked list. Section order and the vertical rhythm ({spacing.section} = 96px) are preserved at tighter horizontal margins. The green footer's 5 columns ({components.footer.columns}) reflow into stacked groups.
Touch targets are comfortable: primary buttons carry 11px 24px padding plus a 4px border ({components.button-primary}), and the 70px header ({components.navbar.height}) leaves ample tap room. Exact mobile breakpoint values and reflow rules beyond these two captured viewports are not verifiable.
Iteration Guide
- Change accents via tokens, not hex. Swap
{colors.primary}or{colors.secondary}to retheme; never hardcode #58CC02 or #1CB0F6 into components. - Button variants live in three tokens —
{components.button-primary},{components.button-secondary},{components.button-outline}. Add a new CTA style there, keeping the 16px radius ({rounded.lg}), 4px border, and uppercase{typography.button}label. - Respect the two-weight rule. All type edits must resolve to weight 500 or 700; introducing 400/600/800 breaks the system's voice.
- Keep the radius scale closed. Use only
{rounded.md}(12px) and{rounded.lg}(16px) — no new corner values. - Never add shadows for depth. Elevation is flat; separate content with the 2px
{colors.border}hairline or illustration layering. - The footer is a brand surface. Preserve the green panel (
{components.footer.backgroundColor}) with light-green{colors.primary-on-dark}links; don't demote it to a neutral strip. - Header stays static and CTA-free. Don't add sticky positioning, backdrop blur, or a header button — the design intentionally omits them.
Known Gaps
- No hover/focus/active states were captured. Button and link interaction styling (press animation, hover fills) is inferred from static tokens only.
- No dark-mode tokens exist. The system was captured light-only; any dark theme would be invention.
- Header nav is thin evidence. Only one nav link was detected (
linkCount: 1), likely because the marketing header is minimal or menus are collapsed — full navigation structure is unverified. - Animation and motion are unknown. The mascot-driven brand almost certainly animates, but no motion data was captured.
- Breakpoints unverified. Only two viewports (desktop/mobile) were captured; intermediate/tablet reflow and exact breakpoint pixels are unknown.
- Auth-walled surfaces (the actual learning app) were not reached — all 8 captured pages are marketing/course-landing pages, so in-product component patterns (lesson UI, progress, streaks) are out of scope.
- No values were dropped during grounding, so the token set fully reflects the measured evidence for these pages.