// Education app UI

Quiz App UI Design in Expo

This quiz app UI stands out with a printed, zine-like feel: heavy Anton headlines, warm paper and halftone collage art drawn entirely in SVG.

Screens
3
Built with
Expo SDK 58
Fonts
Anton, Barlow Condensed
License
Free (MIT)
Quiz app leaderboard screen with a podium and ranked players

Quiz Game app screens

Quiz app onboarding screen with a collage illustration and confetti

Onboarding

A big Quiz wordmark and trophy, a collage of friends celebrating with confetti, a short pitch and a Get started button.

Quiz game home screen with a technology category card and recent games

Game home

Diamond balance, an upgrade row, a peeking category carousel with a Technology card and recently played games.

Quiz app leaderboard screen with a podium and ranked players

Leaderboard

A three-person podium with medals above a ranked list, a highlighted Me row and score badges.

Copy the Quiz Game kit

Use the artifact as a design brief, the skill to generate the UI with an AI agent, or the code to run it right away.

Design artifact

The full design: tokens, screens and source

# Quiz Game: design artifact

This quiz app UI stands out with a printed, zine-like feel: heavy Anton headlines, warm paper and halftone collage art drawn entirely in SVG.

- Type: Education mobile app UI
- Screens: 3
- Artboard: 390 × 844
- Target: Expo SDK 58, Expo Router, TypeScript, react-native-svg
- Live page: https://developermill.com/app-designs/quiz-app-ui-design

## Design direction

Warm paper, condensed poster type and halftone collage illustrations with confetti, closer to a printed zine than a typical app.

- Halftone collage art drawn in SVG, with no image files
- Peeking game category carousel
- Podium leaderboard with ranked rows
- Floating pill navigation

## Foundations

### Colour

| Token | Hex |
| --- | --- |
| Paper | `#EFE9E0` |
| Vermilion | `#E8513A` |
| Trophy gold | `#F5B82E` |
| Ink | `#111111` |
| Forest | `#2F5B48` |
| Umber | `#5E5850` |

### Typography

- Typefaces: Anton, Barlow Condensed
- Common sizes (px): 14, 15, 16, 17, 18, 19, 26, 100

### Shape and depth

- Common corner radii (px): 18, 22, 23, 28, 30, 32
- Shadows: `0 14px 28px rgba(0,0,0,0.22)`, `0 12px 30px rgba(0,0,0,0.14)`, `0 10px 24px rgba(0,0,0,0.10)`, `0 6px 20px rgba(0,0,0,0.05)`

## Screens

### 1. Onboarding

A big Quiz wordmark and trophy, a collage of friends celebrating with confetti, a short pitch and a Get started button.

Preview: https://developermill.com/app-designs/quiz-app-ui-design/onboarding.webp

Copy on this screen:

- Quiz
- Play To Gain Your Knowledge
- Answer quick rounds, challenge your friends and climb the ranks as you learn something new every day.
- Get started

### 2. Game home

Diamond balance, an upgrade row, a peeking category carousel with a Technology card and recently played games.

Preview: https://developermill.com/app-designs/quiz-app-ui-design/home.webp

Copy on this screen:

- Quiz
- 20
- Challenge your friends and family with our Quiz app. See who comes out on top as the ultimate quiz champion and earn the bragging rights!
- Upgrade pro
- Remove ads, unlock unlimited play and every game
- Upgrade
- Popular Game
- Science
- Tech
- Technology
- Explore the world of technology and see if you have what it takes to go from a novice to a tech master!
- Recent Played
- Play again
- Home
- R

### 3. Leaderboard

A three-person podium with medals above a ranked list, a highlighted Me row and score badges.

Preview: https://developermill.com/app-designs/quiz-app-ui-design/leaderboard.webp

Copy on this screen:

- Leaderboard
- 20
- Me
- Ranking
- R

## Full source

The complete design source for each screen. Images point at hosted demo files.

### Main

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Quiz — Onboarding</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Anton&family=Barlow+Condensed:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#111}a:hover{color:#000}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EFE9E0; font-family: 'Barlow Condensed', sans-serif; color: #111111; display: flex; flex-direction: column; align-items: center; padding: 104px 32px 64px; position: relative; overflow: hidden">

<div style="display: flex; align-items: flex-end; gap: 10px">
<h1 style="margin: 0; font-family: Anton, sans-serif; font-weight: 400; font-size: 100px; line-height: 0.9; letter-spacing: 1px">Quiz</h1>
<svg width="54" height="62" viewBox="0 0 56 64" aria-hidden="true" style="margin-bottom: 6px"><path d="M14 4h28v18c0 9-6 16-14 16S14 31 14 22z" fill="#F5B82E"></path><path d="M14 10H5v6c0 7 5 11 10 11M42 10h9v6c0 7-5 11-10 11" fill="none" stroke="#E39A12" stroke-width="4" stroke-linecap="round"></path><path d="M24 38h8v10h-8z" fill="#E39A12"></path><path d="M16 50h24v8H16z" fill="#B5651D"></path><path d="M20 8h4v14c0 4 2 7 4 8-5 0-8-4-8-8z" fill="#FFE08A"></path></svg>
</div>

<div role="img" aria-label="Collage illustration of three friends celebrating at a desk with confetti" style="margin-top: 34px; width: 326px; height: 300px">
<svg width="326" height="300" viewBox="0 0 326 300" aria-hidden="true">
<defs>
<pattern id="htOn" width="4" height="4" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.25" fill="#000000" fill-opacity="0.38"></circle></pattern>
<pattern id="htOnL" width="4" height="4" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="0.9" fill="#000000" fill-opacity="0.25"></circle></pattern>
</defs>
<g>
<rect x="24" y="30" width="8" height="26" rx="2" fill="#E8513A" transform="rotate(-24 28 43)"></rect>
<rect x="62" y="10" width="8" height="30" rx="2" fill="{{accent}}" transform="rotate(18 66 25)"></rect>
<rect x="104" y="40" width="7" height="22" rx="2" fill="#F5B82E" transform="rotate(-40 107 51)"></rect>
<rect x="148" y="6" width="8" height="28" rx="2" fill="#3B6CE0" transform="rotate(30 152 20)"></rect>
<rect x="184" y="34" width="7" height="24" rx="2" fill="#2F6B4F" transform="rotate(-12 187 46)"></rect>
<rect x="276" y="18" width="8" height="30" rx="2" fill="#F5B82E" transform="rotate(42 280 33)"></rect>
<rect x="300" y="70" width="7" height="22" rx="2" fill="#E8513A" transform="rotate(-30 303 81)"></rect>
<rect x="8" y="96" width="7" height="22" rx="2" fill="#2F6B4F" transform="rotate(50 11 107)"></rect>
<rect x="290" y="120" width="7" height="20" rx="2" fill="#3B6CE0" transform="rotate(-56 293 130)"></rect>
<rect x="250" y="8" width="6" height="18" rx="2" fill="#111111" transform="rotate(-20 253 17)"></rect>
<rect x="306" y="160" width="6" height="18" rx="2" fill="#F5B82E" transform="rotate(22 309 169)"></rect>
<rect x="132" y="70" width="6" height="18" rx="2" fill="#E8513A" transform="rotate(60 135 79)"></rect>
</g>
<rect x="30" y="238" width="154" height="46" fill="#6A4BD8"></rect>
<rect x="160" y="256" width="120" height="30" fill="#F2853A"></rect>
<g>
<path d="M36 240c0-48 18-74 46-74s44 26 44 74z" fill="#5C5C5C"></path>
<path d="M36 240c0-48 18-74 46-74s44 26 44 74z" fill="url(#htOn)"></path>
<path d="M70 168l12 30 12-30z" fill="#EDEDED"></path>
<circle cx="82" cy="140" r="21" fill="#CFCFCF"></circle>
<circle cx="82" cy="140" r="21" fill="url(#htOnL)"></circle>
<path d="M60 138c0-16 10-24 22-24s22 8 22 22c-6-6-13-8-22-8-10 0-16 4-22 10z" fill="#1E1E1E"></path>
<path d="M74 150q8 6 16 0" stroke="#3A3A3A" stroke-width="2" fill="none" stroke-linecap="round"></path>
</g>
<g>
<path d="M108 242c0-40 14-60 36-60s34 20 34 60z" fill="#8E8E8E"></path>
<path d="M108 242c0-40 14-60 36-60s34 20 34 60z" fill="url(#htOn)"></path>
<path d="M120 170c-2-24 8-36 24-36s26 12 24 36l4 30h-12l-2-26h-28l-2 26h-12z" fill="#1E1E1E"></path>
<circle cx="144" cy="160" r="17" fill="#D6D6D6"></circle>
<circle cx="144" cy="160" r="17" fill="url(#htOnL)"></circle>
<path d="M127 156c2-12 9-17 17-17s15 5 17 17c-6-6-11-8-17-8s-11 2-17 8z" fill="#1E1E1E"></path>
<ellipse cx="144" cy="168" rx="4" ry="3" fill="#3A3A3A"></ellipse>
</g>
<rect x="40" y="226" width="160" height="12" fill="#E3DED6"></rect>
<rect x="92" y="204" width="50" height="24" rx="3" fill="#2A2A2A"></rect>
<rect x="88" y="226" width="58" height="4" fill="#4A4A4A"></rect>
<g>
<path d="M196 168l-24-68" stroke="#3A3A3A" stroke-width="17" stroke-linecap="round"></path>
<path d="M196 168l-24-68" stroke="url(#htOn)" stroke-width="17" stroke-linecap="round"></path>
<path d="M256 168l22-66" stroke="#3A3A3A" stroke-width="17" stroke-linecap="round"></path>
<path d="M256 168l22-66" stroke="url(#htOn)" stroke-width="17" stroke-linecap="round"></path>
<circle cx="171" cy="94" r="9" fill="#D6D6D6"></circle>
<circle cx="279" cy="96" r="9" fill="#D6D6D6"></circle>
<path d="M180 290c-2-80 16-128 46-128s46 48 44 128z" fill="#3A3A3A"></path>
<path d="M180 290c-2-80 16-128 46-128s46 48 44 128z" fill="url(#htOn)"></path>
<path d="M214 164l12 26 12-26z" fill="#F4F4F4"></path>
<path d="M198 136c-4-30 10-46 28-46s32 16 28 46l2 22h-10l-2-20h-36l-2 20h-10z" fill="#1A1A1A"></path>
<circle cx="226" cy="128" r="22" fill="#D9D9D9"></circle>
<circle cx="226" cy="128" r="22" fill="url(#htOnL)"></circle>
<path d="M203 124c2-16 12-24 23-24s21 8 23 24c-7-9-14-12-23-12s-16 3-23 12z" fill="#1A1A1A"></path>
<ellipse cx="226" cy="138" rx="7" ry="6" fill="#2A2A2A"></ellipse>
<path d="M216 122h5M231 122h5" stroke="#2A2A2A" stroke-width="2" stroke-linecap="round"></path>
</g>
<rect x="226" y="242" width="50" height="46" rx="8" fill="#2B2B2B"></rect>
<path d="M240 254l22 22M262 254l-22 22" stroke="#F4EFE7" stroke-width="4" stroke-linecap="round"></path>
</svg>
</div>

<h2 style="margin: 40px 0 0; font-size: 26px; font-weight: 700; letter-spacing: 0.3px; text-align: center">Play To Gain Your Knowledge</h2>
<p style="margin: 12px 0 0; font-size: 19px; line-height: 1.45; color: #5E5850; text-align: center; max-width: 290px">Answer quick rounds, challenge your friends and climb the ranks as you learn something new every day.</p>

<a href="Home.dc.html" style="margin-top: auto; width: 226px; height: 60px; border-radius: 30px; background: #111111; color: #FFFFFF; display: flex; align-items: center; justify-content: center; font-size: 22px; font-weight: 700; letter-spacing: 0.4px; text-decoration: none; box-shadow: 0 14px 28px rgba(0,0,0,0.22)">Get started</a>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#E8513A","options":["#E8513A","#3B6CE0","#2F6B4F","#F5B82E"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#E8513A' };
}
}
</script>
</body>
</html>
```

### Home

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Quiz — Home</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Anton&family=Barlow+Condensed:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#111}a:hover{color:#000}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EFE9E0; font-family: 'Barlow Condensed', sans-serif; color: #111111; position: relative; overflow: hidden; padding: 64px 0 0">

<div style="padding: 0 22px; display: flex; align-items: center; justify-content: space-between">
<div style="display: flex; align-items: flex-end; gap: 8px">
<h1 style="margin: 0; font-family: Anton, sans-serif; font-weight: 400; font-size: 54px; line-height: 0.95; letter-spacing: 0.5px">Quiz</h1>
<svg width="34" height="38" viewBox="0 0 56 64" aria-hidden="true" style="margin-bottom: 4px"><path d="M14 4h28v18c0 9-6 16-14 16S14 31 14 22z" fill="#F5B82E"></path><path d="M14 10H5v6c0 7 5 11 10 11M42 10h9v6c0 7-5 11-10 11" fill="none" stroke="#E39A12" stroke-width="4" stroke-linecap="round"></path><path d="M24 38h8v10h-8z" fill="#E39A12"></path><path d="M16 50h24v8H16z" fill="#B5651D"></path></svg>
</div>
<div aria-label="20 diamonds" style="height: 36px; padding: 0 14px; border-radius: 18px; background: #FFFFFF; display: flex; align-items: center; gap: 6px; font-size: 18px; font-weight: 700">
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h12l4 6-10 12L2 9z" fill="#4FA8F0"></path><path d="M2 9h20M9 3l3 18M15 3l-3 18" stroke="#2B7FCC" stroke-width="1.2" fill="none"></path></svg>
<span>20</span>
</div>
</div>

<p style="margin: 12px 22px 0; font-size: 16px; line-height: 1.4; color: #5E5850">Challenge your friends and family with our Quiz app. See who comes out on top as the ultimate quiz champion and earn the bragging rights!</p>

<div style="margin: 16px 22px 0; display: flex; align-items: center; gap: 12px">
<svg width="34" height="28" viewBox="0 0 34 28" aria-hidden="true"><path d="M3 8l7 6 7-11 7 11 7-6-3 16H6z" fill="#F5B82E"></path><path d="M6 24h22v3H6z" fill="#E39A12"></path></svg>
<div style="flex: 1; min-width: 0">
<p style="margin: 0; font-size: 19px; font-weight: 700">Upgrade pro</p>
<p style="margin: 2px 0 0; font-size: 14px; color: #5E5850">Remove ads, unlock unlimited play and every game</p>
</div>
<button type="button" style="height: 44px; padding: 0 20px; border: 0; border-radius: 22px; background: #111111; color: #FFFFFF; font-family: inherit; font-size: 17px; font-weight: 700; cursor: pointer">Upgrade</button>
</div>

<div style="margin: 22px 22px 0; display: flex; align-items: center; gap: 6px">
<h2 style="margin: 0; font-size: 26px; font-weight: 700">Popular Game</h2>
<svg width="20" height="24" viewBox="0 0 20 24" aria-hidden="true"><path d="M10 1c1 5 8 8 8 15a8 8 0 0 1-16 0c0-4 2-6 4-8 0 3 1 4 3 5-1-4 0-8 1-12z" fill="#F2853A"></path><path d="M10 12c1 3 4 4 4 7a4 4 0 0 1-8 0c0-2 2-4 4-7z" fill="#F5B82E"></path></svg>
</div>

<div style="margin-top: 14px; height: 296px; position: relative">
<div style="position: absolute; left: -200px; top: 20px; width: 222px; height: 256px; border-radius: 28px; background: #F5B82E"></div>
<div style="position: absolute; right: -200px; top: 20px; width: 222px; height: 256px; border-radius: 28px; background: #2F5B48; padding: 22px; box-sizing: border-box">
<p style="margin: 50px 0 0; font-family: Anton, sans-serif; font-size: 28px; color: #FFFFFF">Science</p>
</div>
<div style="position: absolute; left: 36px; top: 0; width: 318px; height: 296px; border-radius: 32px; background: {{accent}}; padding: 20px 22px; box-sizing: border-box; overflow: hidden; color: #FFFFFF">
<div style="display: flex; justify-content: space-between; align-items: flex-start">
<span style="height: 40px; padding: 0 22px; border-radius: 20px; background: #111111; display: flex; align-items: center; font-size: 17px; font-weight: 600">Tech</span>
<button type="button" aria-label="Add Technology to favorites" style="width: 44px; height: 44px; border: 0; border-radius: 50%; background: #FFFFFF; display: flex; align-items: center; justify-content: center; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21s-8-5.2-8-11a4.5 4.5 0 0 1 8-2.8A4.5 4.5 0 0 1 20 10c0 5.8-8 11-8 11z" fill="{{accent}}"></path></svg>
</button>
</div>
<h3 style="margin: 14px 0 0; font-family: Anton, sans-serif; font-weight: 400; font-size: 32px; letter-spacing: 0.3px">Technology</h3>
<p style="margin: 6px 0 0; font-size: 15px; line-height: 1.35; max-width: 250px">Explore the world of technology and see if you have what it takes to go from a novice to a tech master!</p>
<div role="img" aria-label="Collage illustration of a woman working at a retro computer" style="position: absolute; left: 0; right: 0; bottom: 0; height: 120px">
<svg width="318" height="120" viewBox="0 0 318 120" aria-hidden="true">
<defs>
<pattern id="htHm" width="4" height="4" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.25" fill="#000000" fill-opacity="0.4"></circle></pattern>
</defs>
<rect x="22" y="100" width="170" height="20" fill="#F2853A"></rect>
<rect x="196" y="96" width="110" height="24" fill="#6A4BD8"></rect>
<rect x="30" y="52" width="74" height="54" rx="6" fill="#EDEDED"></rect>
<rect x="30" y="52" width="74" height="54" rx="6" fill="url(#htHm)"></rect>
<rect x="40" y="60" width="54" height="34" rx="3" fill="#2A2A2A"></rect>
<path d="M46 70h26M46 78h36M46 86h18" stroke="#9AD18B" stroke-width="2" stroke-linecap="round"></path>
<rect x="22" y="106" width="96" height="6" fill="#E3DED6"></rect>
<path d="M120 120c0-34 12-52 32-52s30 18 30 52z" fill="#4A4A4A"></path>
<path d="M120 120c0-34 12-52 32-52s30 18 30 52z" fill="url(#htHm)"></path>
<path d="M132 88l-22 14" stroke="#4A4A4A" stroke-width="10" stroke-linecap="round"></path>
<path d="M136 52c-2-18 6-28 16-28s18 10 16 28l2 22h-8l-2-18h-16l-2 18h-8z" fill="#1A1A1A"></path>
<circle cx="152" cy="48" r="14" fill="#D9D9D9"></circle>
<circle cx="152" cy="48" r="14" fill="url(#htHm)" fill-opacity="0.6"></circle>
<path d="M138 46c1-10 7-15 14-15s13 5 14 15c-4-5-9-7-14-7s-10 2-14 7z" fill="#1A1A1A"></path>
<rect x="214" y="40" width="8" height="24" rx="2" fill="#F5B82E" transform="rotate(28 218 52)"></rect>
<rect x="244" y="18" width="7" height="22" rx="2" fill="#111111" transform="rotate(-34 247 29)"></rect>
<rect x="268" y="50" width="7" height="20" rx="2" fill="#3B6CE0" transform="rotate(14 271 60)"></rect>
<rect x="232" y="64" width="6" height="18" rx="2" fill="#FFFFFF" transform="rotate(-50 235 73)"></rect>
<rect x="286" y="20" width="6" height="18" rx="2" fill="#F5B82E" transform="rotate(40 289 29)"></rect>
<rect x="196" y="10" width="6" height="18" rx="2" fill="#FFFFFF" transform="rotate(-18 199 19)"></rect>
</svg>
</div>
</div>
</div>

<div style="margin: 22px 22px 0; display: flex; justify-content: space-between; align-items: center">
<h2 style="margin: 0; font-size: 24px; font-weight: 700">Recent Played</h2>
</div>

<div style="margin: 10px 22px 0; display: flex; flex-direction: column; gap: 12px">
<sc-for list="{{recent}}" as="item" hint-placeholder-count="2">
<div style="display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 14px; background: {{item.tint}}; display: flex; align-items: center; justify-content: center">
<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8" fill="none" stroke="#111111" stroke-width="2"></circle><path d="M12 8v4l3 2" stroke="#111111" stroke-width="2" fill="none" stroke-linecap="round"></path></svg>
</div>
<div style="flex: 1; min-width: 0">
<p style="margin: 0; font-size: 18px; font-weight: 600">{{item.name}}</p>
<p style="margin: 1px 0 0; font-size: 14px; color: #5E5850">{{item.meta}}</p>
</div>
<button type="button" style="height: 36px; padding: 0 16px; border: 0; border-radius: 18px; background: #F0705B; color: #FFFFFF; font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer">Play again</button>
</div>
</sc-for>
</div>

<nav aria-label="Main" style="position: absolute; left: 50%; bottom: 30px; transform: translateX(-50%); height: 64px; padding: 0 10px; border-radius: 32px; background: #FFFFFF; box-shadow: 0 12px 30px rgba(0,0,0,0.14); display: flex; align-items: center; gap: 8px">
<a href="Home.dc.html" aria-current="page" style="height: 46px; padding: 0 20px; border-radius: 23px; background: #111111; color: #FFFFFF; display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 700; text-decoration: none">
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 11l9-8 9 8v10h-6v-6H9v6H3z" fill="#FFFFFF"></path></svg>Home</a>
<a href="Home.dc.html" aria-label="Games" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="3" fill="none" stroke="#6E6E6E" stroke-width="2"></rect><path d="M8 13h8M8 17h5M8 8h8" stroke="#6E6E6E" stroke-width="2" stroke-linecap="round"></path></svg></a>
<a href="Leaderboard.dc.html" aria-label="Ranking" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 21V9h6v12M3 21v-7h6M15 21v-9h6v9" fill="none" stroke="#6E6E6E" stroke-width="2" stroke-linejoin="round"></path></svg></a>
<a href="Home.dc.html" aria-label="Profile" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<span style="width: 34px; height: 34px; border-radius: 50%; background: #C9A27E; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: #111111">R</span></a>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#E8513A","options":["#E8513A","#3B6CE0","#2F6B4F","#6A4BD8"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return {
accent: this.props.accent ?? '#E8513A',
recent: [
{ name: 'Social sciences', meta: '12 questions · 80% correct', tint: '#F6C9D0' },
{ name: 'World geography', meta: '15 questions · 66% correct', tint: '#CFE5D5' }
]
};
}
}
</script>
</body>
</html>
```

### Leaderboard

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Quiz — Leaderboard</title>
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Anton&family=Barlow+Condensed:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#111}a:hover{color:#000}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EFE9E0; font-family: 'Barlow Condensed', sans-serif; color: #111111; position: relative; overflow: hidden; padding: 64px 0 0">

<svg width="0" height="0" style="position: absolute" aria-hidden="true"><defs><pattern id="htLb" width="3" height="3" patternUnits="userSpaceOnUse"><circle cx="1.5" cy="1.5" r="0.9" fill="#000000" fill-opacity="0.4"></circle></pattern></defs></svg>
<div style="padding: 0 22px; display: flex; align-items: center; justify-content: space-between">
<span style="width: 72px"></span>
<div style="display: flex; align-items: center; gap: 4px">
<h1 style="margin: 0; font-size: 26px; font-weight: 700">Leaderboard</h1>
<svg width="18" height="22" viewBox="0 0 20 24" aria-hidden="true"><path d="M10 1c1 5 8 8 8 15a8 8 0 0 1-16 0c0-4 2-6 4-8 0 3 1 4 3 5-1-4 0-8 1-12z" fill="#F2853A"></path><path d="M10 12c1 3 4 4 4 7a4 4 0 0 1-8 0c0-2 2-4 4-7z" fill="#F5B82E"></path></svg>
</div>
<div aria-label="20 diamonds" style="width: 72px; height: 36px; box-sizing: border-box; border-radius: 18px; background: #FFFFFF; display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 18px; font-weight: 700">
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h12l4 6-10 12L2 9z" fill="#4FA8F0"></path><path d="M2 9h20M9 3l3 18M15 3l-3 18" stroke="#2B7FCC" stroke-width="1.2" fill="none"></path></svg>
<span>20</span>
</div>
</div>

<div style="margin-top: 30px; padding: 0 18px; display: flex; justify-content: space-between; align-items: flex-end">
<sc-for list="{{podium}}" as="p" hint-placeholder-count="3">
<div style="width: 110px; display: flex; flex-direction: column; align-items: center">
<div style="width: {{p.size}}; height: {{p.size}}; border-radius: 50%; background: #FFFFFF; padding: 5px; box-sizing: border-box; box-shadow: 0 10px 24px rgba(0,0,0,0.10)">
<div style="width: 100%; height: 100%; border-radius: 50%; background: {{p.bg}}; overflow: hidden">
<svg width="100%" height="100%" viewBox="0 0 42 42" aria-hidden="true"><path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="#4A4A4A"></path><path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="url(#htLb)"></path><circle cx="21" cy="18" r="8" fill="#D6D6D6"></circle><path d="{{p.hair}}" fill="#1E1E1E"></path></svg>
</div>
</div>
<div style="margin-top: -14px; width: 30px; height: 30px; border-radius: 50%; background: {{p.medal}}; border: 3px solid #FFFFFF; box-sizing: border-box; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: #111111">{{p.rank}}</div>
<p style="margin: 8px 0 0; font-size: 18px; font-weight: 600">{{p.name}}</p>
<p style="margin: 1px 0 0; font-size: 14px; color: #5E5850">{{p.diamonds}} Diamonds</p>
</div>
</sc-for>
</div>

<div style="margin: 24px 14px 0; background: #FFFFFF; border-radius: 28px; padding: 6px 14px 90px; box-shadow: 0 6px 20px rgba(0,0,0,0.05)">
<sc-for list="{{rows}}" as="r" hint-placeholder-count="6">
<div style="height: 60px; display: flex; align-items: center; gap: 12px; border-bottom: 1px solid #F0ECE6">
<div style="width: 42px; height: 42px; border-radius: 50%; background: {{r.bg}}; overflow: hidden; flex-shrink: 0">
<svg width="42" height="42" viewBox="0 0 42 42" aria-hidden="true"><path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="#4A4A4A"></path><path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="url(#htLb)"></path><circle cx="21" cy="18" r="8" fill="#D6D6D6"></circle><path d="{{r.hair}}" fill="#1E1E1E"></path></svg>
</div>
<div style="flex: 1; min-width: 0">
<p style="margin: 0; font-size: 18px; font-weight: 600">{{r.name}}</p>
<p style="margin: 1px 0 0; font-size: 13px; color: #5E5850">{{r.points}} Point</p>
</div>
<sc-if value="{{r.me}}" hint-placeholder-val="{{false}}">
<span style="height: 34px; padding: 0 20px; border-radius: 17px; background: #111111; color: #FFFFFF; display: flex; align-items: center; font-size: 15px; font-weight: 700">Me</span>
</sc-if>
<div style="width: 38px; height: 38px; border-radius: 50%; background: {{r.badge}}; color: #FFFFFF; display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 700">{{r.score}}</div>
</div>
</sc-for>
</div>

<nav aria-label="Main" style="position: absolute; left: 50%; bottom: 30px; transform: translateX(-50%); height: 64px; padding: 0 10px; border-radius: 32px; background: #FFFFFF; box-shadow: 0 12px 30px rgba(0,0,0,0.16); display: flex; align-items: center; gap: 8px">
<a href="Home.dc.html" aria-label="Home" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 11l9-8 9 8v10h-6v-6H9v6H3z" fill="none" stroke="#6E6E6E" stroke-width="2" stroke-linejoin="round"></path></svg></a>
<a href="Home.dc.html" aria-label="Games" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="3" width="16" height="18" rx="3" fill="none" stroke="#6E6E6E" stroke-width="2"></rect><path d="M8 13h8M8 17h5M8 8h8" stroke="#6E6E6E" stroke-width="2" stroke-linecap="round"></path></svg></a>
<a href="Leaderboard.dc.html" aria-current="page" style="height: 46px; padding: 0 20px; border-radius: 23px; background: #111111; color: #FFFFFF; display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 700; text-decoration: none">
<svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 21V9h6v12zM3 21v-7h6v7zM15 21v-9h6v9z" fill="#FFFFFF"></path></svg>Ranking</a>
<a href="Home.dc.html" aria-label="Profile" style="width: 46px; height: 46px; display: flex; align-items: center; justify-content: center">
<span style="width: 34px; height: 34px; border-radius: 50%; background: #C9A27E; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: #111111">R</span></a>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
const S = 'M13 17c0-6 4-9 8-9s8 3 8 9c-2-3-5-4-8-4s-6 1-8 4z';
const L = 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z';
const withHair = (a) => a.map((x, i) => ({ ...x, hair: i % 2 === 0 ? L : S }));
return {
podium: withHair([
{ name: 'Sophia Cba', initials: 'SC', diamonds: 880, rank: 2, bg: '#F08A7A', medal: '#D6DCE4', size: '84px', font: '24px' },
{ name: 'Emma Ema', initials: 'EE', diamonds: 888, rank: 1, bg: '#BFD2E6', medal: '#F5B82E', size: '108px', font: '32px' },
{ name: 'Andrew W', initials: 'AW', diamonds: 808, rank: 3, bg: '#9CCBB0', medal: '#E3A16B', size: '84px', font: '24px' }
]),
rows: withHair([
{ name: 'Bayu Aji Sadewa', initials: 'BA', points: 20, score: 99, bg: '#D8CFC2', badge: '#C73A25', me: true },
{ name: 'Olivia Ava', initials: 'OA', points: 80, score: 50, bg: '#F6C9D0', badge: '#2F6F9E', me: false },
{ name: 'David Joshua', initials: 'DJ', points: 88, score: 52, bg: '#F7DC8A', badge: '#2E7A44', me: false },
{ name: 'Charlotte Harper', initials: 'CH', points: 22, score: 97, bg: '#E4E0DA', badge: '#9A6A00', me: false },
{ name: 'Mia Evelyn', initials: 'ME', points: 11, score: 120, bg: '#BFD2E6', badge: '#6A45C9', me: false },
{ name: 'Liam Noah', initials: 'LN', points: 9, score: 60, bg: '#CFE5D5', badge: '#2F6F9E', me: false }
])
};
}
}
</script>
</body>
</html>
```

SKILL.md

Save as .claude/skills/quiz-app-ui/SKILL.md

---
name: quiz-app-ui
description: Build the Quiz Game mobile app UI in Expo React Native. Use when asked to create a quiz app UI or a new screen in this visual style.
---

# Quiz Game app UI

Build this UI in an Expo SDK 58 app with Expo Router and strict TypeScript. Match the spec below rather than inventing a new look. The finished reference lives at https://developermill.com/app-designs/quiz-app-ui-design

## Visual direction

Warm paper, condensed poster type and halftone collage illustrations with confetti, closer to a printed zine than a typical app.

Keep these signature details:

- Halftone collage art drawn in SVG, with no image files
- Peeking game category carousel
- Podium leaderboard with ranked rows
- Floating pill navigation

## Set up

```bash
npx expo install react-native-svg @expo-google-fonts/anton @expo-google-fonts/barlow-condensed expo-font
```

## Tokens

| Token | Hex |
| --- | --- |
| Paper | `#EFE9E0` |
| Vermilion | `#E8513A` |
| Trophy gold | `#F5B82E` |
| Ink | `#111111` |
| Forest | `#2F5B48` |
| Umber | `#5E5850` |

- Typefaces: Anton, Barlow Condensed
- Common sizes (px): 14, 15, 16, 17, 18, 19, 26, 100
- Common corner radii (px): 18, 22, 23, 28, 30, 32

Define these once and reuse them. Do not add new colours.

## Screens

Build one Expo Router route per screen, in this order:

1. **Onboarding**: A big Quiz wordmark and trophy, a collage of friends celebrating with confetti, a short pitch and a Get started button.
2. **Game home**: Diamond balance, an upgrade row, a peeking category carousel with a Technology card and recently played games.
3. **Leaderboard**: A three-person podium with medals above a ranked list, a highlighted Me row and score badges.

## Build rules

- Design on a 390 × 844 artboard, then scale to the device width so layouts match on every phone.
- Load each custom font weight by its own family name with expo-font. Do not rely on `fontWeight` with custom fonts.
- Draw icons, charts and illustrations with react-native-svg rather than image files or chart libraries.
- Use `Pressable` with an `accessibilityLabel` for every icon-only control, and keep touch targets at 44 px or larger.
- Wire navigation with `router.navigate`, and keep sample data in constants at the top of each file so it is easy to replace.
- Use expo-image for photos, with `contentFit` set explicitly.

## Done when

- Every screen above exists as a route and they link together.
- Colours, type and radii match the tokens exactly.
- `npx tsc --noEmit` and `npx expo lint` both pass.
- Layouts hold up on small and large phones.

Set up the project

npx create-expo-app@latest quiz-app --template default
cd quiz-app
rm -rf src
npx expo install react-native-svg @expo-google-fonts/anton @expo-google-fonts/barlow-condensed expo-font

src/app/_layout.tsx

import { Anton_400Regular } from '@expo-google-fonts/anton';
import {
  BarlowCondensed_400Regular,
  BarlowCondensed_600SemiBold,
  BarlowCondensed_700Bold,
} from '@expo-google-fonts/barlow-condensed';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';

export default function RootLayout() {
  const [fontsLoaded] = useFonts({
    Anton_400Regular,
    BarlowCondensed_400Regular,
    BarlowCondensed_600SemiBold,
    BarlowCondensed_700Bold,
  });

  if (!fontsLoaded) return null;

  return <Stack screenOptions={{ headerShown: false }} />;
}

About this design

It covers onboarding, a game home with a peeking category carousel, and a podium leaderboard, which makes it a good base for trivia, learning and competitive games.

Warm paper, condensed poster type and halftone collage illustrations with confetti, closer to a printed zine than a typical app.

  • Halftone collage art drawn in SVG, with no image files
  • Peeking game category carousel
  • Podium leaderboard with ranked rows
  • Floating pill navigation

Colour palette

  • Paper

    #EFE9E0

  • Vermilion

    #E8513A

  • Trophy gold

    #F5B82E

  • Ink

    #111111

  • Forest

    #2F5B48

  • Umber

    #5E5850

How to use this design

  1. 01

    Pick what to copy

    Copy the Quiz Game artifact, skill or code from this page.

  2. 02

    Run it or generate it

    Paste the code into a new Expo app and start it, or give the skill to your AI coding agent.

  3. 03

    Make it yours

    Replace the demo images and sample content, then connect your own data.

Frequently asked questions

Are the illustrations image files?

No. The collage art is react-native-svg, including the halftone pattern, so it scales cleanly and you can recolour it in code.

Is the Quiz Game design free to use?

Yes. The design, skill and Expo code are free and MIT licensed, including for commercial apps. Replace the demo images and sample content with your own before you ship.

What is the difference between the artifact, skill and code?

The artifact is the full design: tokens, screens and source. The skill is a SKILL.md that teaches an AI coding agent to build the UI. The code is the finished Expo app you can paste in and run.

Which Expo version does the code use?

It targets Expo SDK 58 with Expo Router and TypeScript. It uses packages installed through npx expo install, with no custom native code.

More app UI designs