Skip to content
ExamsLibraryFor agentsConnect your agent
metaMeta: working with agents·13/26

Point of View

Installer's opinions and taste calls. This install is forked to Duolingo's design language — physical buttons, meaning-bearing color, rounded lowercase type, celebration on the reward beat — plus HKTITAN's launch-film calls (Skale's UI-motion register, sound derived from motion) and diagram calls (diagram-design's own skin, ask then figure, static unless order is the point).

Raw markdown On GitHub

This file is meant to be edited by you. The rest of the skill is mostly canonical — Emil, Benji, Jakub, guidelines.sh — and this file is the override layer.

This install is forked to Duolingo's design language. Sources are design.duolingo.com (identity, writing, illustration) plus token values read directly off the shipped product. Where a section below contradicts a canonical node, this file wins. Where it is silent, canon holds.

How to use this file

Two kinds of entry are useful:

  1. Hard overrides — "I never use X." or "I always prefer Y over Z."
  2. Taste calls — "When in doubt, lean toward A because B."

Be specific. "I like clean UI" changes nothing. "1px borders in all cases; if a border needs more weight, raise contrast not width" changes output.

A taste call should orient a decision, not amputate a possibility.

The stance, in one line

Duolingo's UI is physical, loud, and kind. Surfaces look pressable, color carries meaning instead of decoration, type is rounded and lowercase, and the product celebrates the user out loud. Restraint is not the goal here — legibility of intent is.

1. Buttons are physical objects, not rectangles

Every pressable surface has a 4px solid lip in a darker shade of its own fill. The host element reserves that lip with a transparent bottom border, so pressing moves the fill into space that already exists — no reflow, no layout shift.

.btn {
  position: relative;
  height: 50px;
  padding: 0 16px;
  border-radius: 12px;
  border-bottom: 4px solid transparent; /* reserves the lip */
  font: 700 15px/1 "DIN Next Rounded", Nunito, system-ui, sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #fff;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 12px;
  background: #58CC02;            /* fill */
  box-shadow: 0 4px 0 0 #58A700;  /* lip — same hue, ~15% darker */
}
.btn:active::before {
  transform: translateY(4px);
  box-shadow: 0 0 0 0 #58A700;    /* the button compresses into its own lip */
}

Rules that come with it:

  • Every fill has a paired lip color. Feather Green #58CC02 → Tree Frog #58A700. Macaw #1CB0F6 → #0096DD. Fox #FF9600 → Guinea Pig #CD7900. Cardinal #FF4B4B → Fire Ant #EA2B2B. Bee #FFC800 → Lion #FFB100.
  • Secondary buttons keep the geometry, drop the fill: 2px border plus 2px lip in Swan #E5E5E5, label in Wolf #777777 or Macaw.
  • Labels are ALL CAPS, 700, 15px, letter-spacing: 0.04em, no punctuation. NO THANKS, never NO, THANKS.
  • One button shape for the whole product. One radius, one lip depth. If you are adding a fourth variant, you are solving a hierarchy problem with a shape.
  • Cards, list rows, and pickable answer tiles use the same construction at 2px — pickable things look pickable.

Overrides shadows-whisper: here the shadow is structural and opaque, not atmospheric. Whisper shadows still own floating layers (menus, sheets, modals) — anything that leaves the page plane. Anything you press gets a lip.

2. Color carries meaning. When in doubt, go green

RoleTokenHex
Primary / correct / progressFeather Green#58CC02
Primary lip, green text on whiteTree Frog#58A700
Body text, headingsEel#4B4B4B
Page backgroundSnow#FFFFFF
Secondary textWolf#777777
Disabled text, placeholdersHare#AFAFAF
Borders, dividers, lipsSwan#E5E5E5
Inset surfaces, tracksPolar#F7F7F7

Secondary colors are a vocabulary, not a palette. Each owns exactly one meaning and is never used decoratively:

  • Macaw #1CB0F6 — information, secondary action, links
  • Cardinal #FF4B4B — wrong, destructive, hearts lost
  • Fox #FF9600 — streaks, urgency, time
  • Bee #FFC800 — earned currency, XP, rewards
  • Beetle #CE82FF — premium / upgrade
  • Humpback #2B70C9 — chrome, headers, calm depth

Overrides color-monochromatic. Mono-plus-one-accent is the wrong default for this language — but its discipline survives intact: a color that means nothing gets deleted. Six meaningful hues is a system; six pretty hues is noise.

Never set text in Feather Green on Snow — it computes to ≈2.1:1. Green is a fill. If you need green type, use Tree Frog (≈4.2:1 on Snow).

Dark mode is a remap, not a second palette. Token names stay, values flip: Polar is #F7F7F7 in light and #202F36 in dark; the dark ground is #131F24 and dark text #F1F7FB, never #000/#FFF. A token that must not flip carries an explicit -always-light / -always-dark suffix. Adopt that suffix convention — it kills the whole class of "this looked fine until dark mode" bugs. Agrees with dark-mode and contrast-and-color-scheme.

3. Type: rounded, lowercase, two faces with a hard role split

Display face (Feather Bold's role — substitute any bold rounded display sans):

  • Short headlines only, 10 words maximum. Longer than that is a body-face job.
  • Always lowercase. Capitals only for proper nouns. Never Title Case, never all caps.
  • Leading 100–110%. Tracking -0.02em. Never below 30px.
  • Left-aligned. Never justified, never hyphenated.
  • Never set it in a neutral like Eel, and never in two secondary colors at once.

Body face (DIN Next Rounded's role; Nunito is the sanctioned free substitute):

  • Everything else — long headlines, subheads, body, UI. Leading 140%, tracking 0, never below 14px.
  • Roughly 1.5× smaller than the display face when the two share a block, with equal leading.
  • Never mix the two faces inside one sentence.

Overrides typography-humanity on two points: rounded-and-friendly is the brief, not a default to escape, so Nunito is a correct answer here rather than a tell; and the single-weight rule does not apply — this language needs two faces precisely because the role split does the hierarchy work.

4. Nothing is pointy

Duolingo's illustration guidelines put it flatly: "Pointy shapes are off-brand."

  • Everything is built from rounded rectangles, circles, and rounded triangles.
  • Radius scale: 12px buttons and tiles, 16px cards and modals, full for pills, progress bars, and avatars. Keep the nested-radius math from border-radius.
  • Progress bars are full-radius with a full-radius fill and an inset highlight. They are the most-looked-at element in the product; give them the care.
  • Character eyes are pills, never ovals. Ground shadows are pills, never ovals — an oval implies a perspective the flat style doesn't have.

5. Motion: feedback always, celebration on the reward beat

Canon's default is don't animate. This POV raises the floor by one notch and leaves the ceiling where Benji put it.

FrequencyCanonical allowanceThis POV
Every keystroke / scrollNoneNone. Unchanged.
Every tapSubtle, ~100–160msAlways. The lip compress, ~100ms, plus sound where the platform has it. A tap with no physical response is a bug.
Daily reward beat (lesson done, streak day, XP earned)Small — a tickMedium. Scale-in, stagger, a number that counts up. The reward loop is the product.
Rare milestoneBigBig. Unchanged — confetti belongs here and only here.

Character motion is small and expressive: a wave, a wing flap, a fist pump. Never sudden, never fast. A mascot that lurches reads as broken rather than alive.

Extends delight-impact-curve and animation-decision-framework: the decision tree is unchanged, but "feedback" and "reward" are load-bearing purposes in a habit product, not decoration.

6. Copy: expressive, playful, embracing, worldly

  • Brief, active, direct, excited. "You did it!" beats "Congratulations." "Check your answer" beats "You can see how you did by checking your answer."
  • Errors support, never blame. "Not quite correct. Try again!" — never "Incorrect."
  • Contractions always. Gender-neutral always (they/them).
  • Numerals for every number, even under 10 — unless one starts a sentence. Comma above 999, but never in an XP or currency total.
  • Capitalization is minimized: sentence case for headings, subheads, and page titles; ALL CAPS for buttons; capitalize product-specific proper nouns (feature names, purchasable items) and nothing else.
  • Punctuation: none in buttons; none in headlines except !. Serial comma. Avoid em dashes and semicolons — write two sentences instead. Write "and", not "&".
  • Emoji are allowed in notifications, subject lines, and social — one, roughly half the time, so it keeps its impact. Never as list bullets and never as UI iconography; that stays an ai-default-tells offense.
  • Tone reads the room. Wins get exclamation points. Serious human subject matter gets them stripped out entirely, along with the exuberance. Voice is fixed; tone is not.

Overrides copy-voice on three specifics: Title Case buttons (→ ALL CAPS), Title Case headings (→ sentence case), and "&" over "and" (→ reversed). Its other rules — active voice, second person, specificity, errors that name the exit — hold.

7. Illustration over stock, characters over icons

  • Reach for an illustrated character before a photograph and before a generic glyph. Characters are posed and expressive; a static, expressionless character reads as dead.
  • Keep each illustration to roughly 15 shapes. Six is too abstract; thirty muddies at small sizes.
  • Flat perspective, one line of sight, minimal color count per object.
  • No gray inside illustrations — it reads lifeless against the rest of the palette. Because backgrounds are white, use light pastels where you would reach for white.
  • Mascot characters communicate in text, never narrate the product, and never carry anything aggressive.

Extends content-authenticity: an original character beats a stock photo beats a Lucide glyph, in that order.

8. What the brand does not override

Two things outrank every taste call above.

  1. accessibility-baseline. White on Feather Green computes to ≈2.1:1, white on Tree Frog to ≈3.0:1 — neither clears WCAG AA for normal text. Duolingo ships it; you should not, unless you have checked it. Either darken the fill for text-bearing surfaces (≈#367F00 clears 4.5:1 against white) or accept it only for large bold labels with a non-color affordance carrying the same meaning. Never let green-vs-red be the only signal for right-vs-wrong.
  2. prefers-reduced-motion. Celebration is the first thing to drop, not the last. Kill the confetti, the count-up, and the mascot loop; keep opacity fades and keep the button's state change legible.

Where this overrides the canonical graph

Canonical nodeIts defaultThis POV
shadows-whisperLayered shadows at 4–6%, #111 baseOpaque 4px lip on anything pressable; whisper shadows only for floating layers
color-monochromaticOne hue plus one accentSix named hues, one meaning each; green leads
typography-humanityAvoid Google-default faces; one weightRounded is the brief; Nunito sanctioned; two faces, hard role split
copy-voiceTitle Case buttons/headings, "&" over "and"ALL CAPS buttons, sentence case headings, "and" over "&"
delight-impact-curveDaily moments get a tickDaily reward beat gets medium-tier celebration
hover-states-subtle1px shifts, no liftPress compresses 4px; hover lightens the fill
visual-imperfectionImperfection lives on marketing surfacesWarmth comes from rounded geometry and characters, not from texture or wobble
launch-video-registersPick the register from the product and the briefUnspecified launch films default to Skale's UI-motion register; bounce only on request
diagram-decisionPick the surface by who touches it nextAsk who edits it next; with no answer, a finished diagram-design figure
diagram-design-reconciliationContract, then profile, then diagram-designWith no contract, diagram-design's shipped skin, not the Duolingo language; static, with step only when the order is the point

Everything not listed is unchanged. states-are-the-work, data-is-content, dependency-discipline, transform-opacity-only, never-scale-from-zero, and feeling-right apply exactly as written.

Reviewing under this POV

When reviewing UI in a product built on this language, the review-format table judges against the values above — a flat button with no lip, a Title Case CTA, or a silent correct-answer state are findings, not preferences. When reviewing a product that is not on this language, fall back to canon and say so.

Your POV (add yours below)

The narrow calls the sections above deliberately leave open. Examples:

  • I always prefer ____ over ____.
  • In my products, ____ is non-negotiable.
  • Skip ____, even if the rest of the skill recommends it. The reason is ____.

Launch films (HKTITAN)

The Duolingo sections above govern product UI. A rendered launch film follows these calls instead:

  • Default register. An unspecified "make a launch video" gets Skale's UI-motion register (launch-video-registers): rebuilt UI on a light ground with one accent, type as the script, the newest word in the accent before it settles, holds that creep on their entry vector (still share near 10 %), and hard cuts hidden on a cause, a constant ground or inside a fill (launch-video-cuts). HeyGen's bouncy sting (zeta 1/3) only when someone asks for bounce.
  • "Lively" and "crazy" mean density and causality, not bounce. Camera creep under every hold, rhythm that accelerates into a snap, a click that starts its consequence on the same frame, a glyph the camera dives through (launch-video-motion, launch-video-seams).
  • Sound is OpenAI's register B, derived from the motion: a bed in one key, clicks on the stamps, thuds on the landings, something taken away just before the name (launch-video-sound, sound-from-motion). A licensed beat track only when its drop and breakdowns can be placed on picture events (launch-video-music). Never library blips dropped on frames.
  • Every film ships with its numbers (cuts a minute, still share, loudness), measured on the render before it goes out (launch-video-review).

Diagrams (HKTITAN)

The Duolingo sections above govern product UI. A diagram follows these calls instead. A project's .design or DESIGN.md still outranks all three (diagram-design-reconciliation).

  • The default skin is diagram-design's. With no contract, a figure keeps diagram-design's shipped editorial skin: off-white paper, ink strokes, one tangerine accent, Instrument Serif titles, Geist names and Geist Mono labels. The Duolingo hues, rounded lowercase display type and button lips never reach a figure. Answer diagram-design's first-run gate with "keep default", and offer the profile: default marker, writing it only with consent.
  • Ask who edits it next; with no answer, make a figure. "Make a diagram" that names no reader or editor gets one question (diagram-decision). If nobody can answer it, as in a run with no one to reply, draw a finished diagram-design figure and note the assumption beside it. Open a tldraw board only when someone names one or says the team will keep editing it (tldraw-canvas).
  • Static by default; step when the order is the point. A flow, a lifecycle or a policy trace whose meaning is the sequence gets diagram-design's step mode, where the reader clicks through. Everything else is static. No reveal, no loop and no autoplay unless someone asks. The launch-film "lively" taste does not carry over, because a figure is read, not watched (animation-decision-framework).

Gotcha

Do not confuse POV with gotchas:

  • gotchas = "the agent did this wrong, here's the right answer." Negative examples, append-only.
  • pov = "I prefer this default over the canonical default." Taste overrides.

Both grow over time. Both outrank canonical content. The framing is different.

When the agent should consult this file

Always. Before producing UI code or a review, load this file alongside gotchas.

If the user explicitly says "ignore my pov" or "use canonical defaults," skip this file for that response only.

Sources

  • design.duolingo.com — identity (logos, color, typography, imagery, brand family), writing (brand narrative, voice, tone, Duo, style), illustration (shape language, characters, Duo), marketing.
  • Token values, the button construction, and the light/dark remap read off the shipped Duolingo product (--color-* and --text-* custom properties).
  • Contrast ratios computed from the published hex values, not quoted from the guidelines.
  • Perplexity Agent Skills team — the "inject your opinion" principle. Henry Modisett (Perplexity head of design) — design Skills written for personal taste.

povopinioncustomizableduolingolaunch-videodiagram