// 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 Game app screens

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

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

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 }} />;
}src/app/home.tsx
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Defs, Path, Pattern, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
const accent = '#E8513A';
const recent = [
{ name: 'Social sciences', meta: '12 questions · 80% correct', tint: '#F6C9D0' },
{ name: 'World geography', meta: '15 questions · 66% correct', tint: '#CFE5D5' },
];
export default function HomeScreen() {
return (
<Screen background="#EFE9E0" statusBar="dark">
<View style={{ paddingTop: 64, paddingBottom: 0, paddingHorizontal: 0, flex: 1 }}>
<View
style={{
paddingVertical: 0,
paddingHorizontal: 22,
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<View style={{ alignItems: 'flex-end', gap: 8, flexShrink: 1, flexDirection: 'row' }}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Anton_400Regular',
fontSize: 54,
color: '#111111',
letterSpacing: 0.5,
lineHeight: 51.3,
}}>
Quiz
</Text>
<Svg width="34" height="38" viewBox="0 0 56 64" style={{ marginBottom: 4 }}>
<Path d="M14 4h28v18c0 9-6 16-14 16S14 31 14 22z" fill="#F5B82E" />
<Path
d="M14 10H5v6c0 7 5 11 10 11M42 10h9v6c0 7-5 11-10 11"
fill="none"
stroke="#E39A12"
strokeWidth="4"
strokeLinecap="round"
/>
<Path d="M24 38h8v10h-8z" fill="#E39A12" />
<Path d="M16 50h24v8H16z" fill="#B5651D" />
</Svg>
</View>
<View
style={{
height: 36,
paddingVertical: 0,
paddingHorizontal: 14,
borderRadius: 18,
backgroundColor: '#FFFFFF',
alignItems: 'center',
gap: 6,
flexShrink: 1,
flexDirection: 'row',
}}>
<Svg width="18" height="18" viewBox="0 0 24 24">
<Path d="M6 3h12l4 6-10 12L2 9z" fill="#4FA8F0" />
<Path
d="M2 9h20M9 3l3 18M15 3l-3 18"
stroke="#2B7FCC"
strokeWidth="1.2"
fill="none"
/>
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 18,
color: '#111111',
}}>
20
</Text>
</View>
</View>
<Text
style={{
marginTop: 12,
marginBottom: 0,
marginHorizontal: 22,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 16,
color: '#5E5850',
lineHeight: 22.4,
}}>
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!
</Text>
<View
style={{
marginTop: 16,
marginBottom: 0,
marginHorizontal: 22,
alignItems: 'center',
gap: 12,
flexDirection: 'row',
}}>
<Svg width="34" height="28" viewBox="0 0 34 28">
<Path d="M3 8l7 6 7-11 7 11 7-6-3 16H6z" fill="#F5B82E" />
<Path d="M6 24h22v3H6z" fill="#E39A12" />
</Svg>
<View style={{ flex: 1, minWidth: 0 }}>
<Text
style={{
margin: 0,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 19,
color: '#111111',
}}>
Upgrade pro
</Text>
<Text
style={{
marginTop: 2,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 14,
color: '#5E5850',
}}>
Remove ads, unlock unlimited play and every game
</Text>
</View>
<Pressable
accessibilityRole="button"
style={{
height: 44,
paddingVertical: 0,
paddingHorizontal: 20,
borderWidth: 0,
borderRadius: 22,
backgroundColor: '#111111',
flexShrink: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 17,
color: '#FFFFFF',
textAlign: 'center',
}}>
Upgrade
</Text>
</Pressable>
</View>
<View
style={{
marginTop: 22,
marginBottom: 0,
marginHorizontal: 22,
alignItems: 'center',
gap: 6,
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 26,
color: '#111111',
}}>
Popular Game
</Text>
<Svg width="20" height="24" viewBox="0 0 20 24">
<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 d="M10 12c1 3 4 4 4 7a4 4 0 0 1-8 0c0-2 2-4 4-7z" fill="#F5B82E" />
</Svg>
</View>
<View style={{ marginTop: 14, height: 296 }}>
<View
style={{
position: 'absolute',
left: -200,
top: 20,
width: 222,
height: 256,
borderRadius: 28,
backgroundColor: '#F5B82E',
}}
/>
<View
style={{
position: 'absolute',
right: -200,
top: 20,
width: 222,
height: 256,
borderRadius: 28,
backgroundColor: '#2F5B48',
padding: 22,
}}>
<Text
style={{
marginTop: 50,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'Anton_400Regular',
fontSize: 28,
color: '#FFFFFF',
}}>
Science
</Text>
</View>
<View
style={{
position: 'absolute',
left: 36,
top: 0,
width: 318,
height: 296,
borderRadius: 32,
backgroundColor: accent,
paddingVertical: 20,
paddingHorizontal: 22,
overflow: 'hidden',
}}>
<View
style={{
justifyContent: 'space-between',
alignItems: 'flex-start',
flexDirection: 'row',
}}>
<View
style={{
height: 40,
paddingVertical: 0,
paddingHorizontal: 22,
borderRadius: 20,
backgroundColor: '#111111',
alignItems: 'center',
flexShrink: 1,
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_600SemiBold',
fontSize: 17,
color: '#FFFFFF',
flexShrink: 1,
}}>
Tech
</Text>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Add Technology to favorites"
style={{
width: 44,
height: 44,
borderWidth: 0,
borderRadius: '50%',
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="20" height="20" viewBox="0 0 24 24">
<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}
/>
</Svg>
</Pressable>
</View>
<Text
style={{
marginTop: 14,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'Anton_400Regular',
fontSize: 32,
color: '#FFFFFF',
letterSpacing: 0.3,
}}>
Technology
</Text>
<Text
style={{
marginTop: 6,
marginBottom: 0,
marginHorizontal: 0,
maxWidth: 250,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 15,
color: '#FFFFFF',
lineHeight: 20.25,
}}>
Explore the world of technology and see if you have what it takes to go from a novice
to a tech master!
</Text>
<View
accessibilityRole="image"
accessibilityLabel="Collage illustration of a woman working at a retro computer"
style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 120 }}>
<Svg width="318" height="120" viewBox="0 0 318 120">
<Defs>
<Pattern id="htHm" width="4" height="4" patternUnits="userSpaceOnUse">
<Circle cx="2" cy="2" r="1.25" fill="#000000" fillOpacity="0.4" />
</Pattern>
</Defs>
<Rect x="22" y="100" width="170" height="20" fill="#F2853A" />
<Rect x="196" y="96" width="110" height="24" fill="#6A4BD8" />
<Rect x="30" y="52" width="74" height="54" rx="6" fill="#EDEDED" />
<Rect x="30" y="52" width="74" height="54" rx="6" fill="url(#htHm)" />
<Rect x="40" y="60" width="54" height="34" rx="3" fill="#2A2A2A" />
<Path
d="M46 70h26M46 78h36M46 86h18"
stroke="#9AD18B"
strokeWidth="2"
strokeLinecap="round"
/>
<Rect x="22" y="106" width="96" height="6" fill="#E3DED6" />
<Path d="M120 120c0-34 12-52 32-52s30 18 30 52z" fill="#4A4A4A" />
<Path d="M120 120c0-34 12-52 32-52s30 18 30 52z" fill="url(#htHm)" />
<Path d="M132 88l-22 14" stroke="#4A4A4A" strokeWidth="10" strokeLinecap="round" />
<Path
d="M136 52c-2-18 6-28 16-28s18 10 16 28l2 22h-8l-2-18h-16l-2 18h-8z"
fill="#1A1A1A"
/>
<Circle cx="152" cy="48" r="14" fill="#D9D9D9" />
<Circle cx="152" cy="48" r="14" fill="url(#htHm)" fillOpacity="0.6" />
<Path
d="M138 46c1-10 7-15 14-15s13 5 14 15c-4-5-9-7-14-7s-10 2-14 7z"
fill="#1A1A1A"
/>
<Rect
x="214"
y="40"
width="8"
height="24"
rx="2"
fill="#F5B82E"
transform="rotate(28 218 52)"
/>
<Rect
x="244"
y="18"
width="7"
height="22"
rx="2"
fill="#111111"
transform="rotate(-34 247 29)"
/>
<Rect
x="268"
y="50"
width="7"
height="20"
rx="2"
fill="#3B6CE0"
transform="rotate(14 271 60)"
/>
<Rect
x="232"
y="64"
width="6"
height="18"
rx="2"
fill="#FFFFFF"
transform="rotate(-50 235 73)"
/>
<Rect
x="286"
y="20"
width="6"
height="18"
rx="2"
fill="#F5B82E"
transform="rotate(40 289 29)"
/>
<Rect
x="196"
y="10"
width="6"
height="18"
rx="2"
fill="#FFFFFF"
transform="rotate(-18 199 19)"
/>
</Svg>
</View>
</View>
</View>
<View
style={{
marginTop: 22,
marginBottom: 0,
marginHorizontal: 22,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 24,
color: '#111111',
}}>
Recent Played
</Text>
</View>
<View style={{ marginTop: 10, marginBottom: 0, marginHorizontal: 22, gap: 12 }}>
{recent.map((item, index) => (
<View key={index} style={{ alignItems: 'center', gap: 12, flexDirection: 'row' }}>
<View
style={{
width: 44,
height: 44,
borderRadius: 14,
backgroundColor: item.tint,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="24" height="24" viewBox="0 0 24 24">
<Circle cx="12" cy="12" r="8" fill="none" stroke="#111111" strokeWidth="2" />
<Path
d="M12 8v4l3 2"
stroke="#111111"
strokeWidth="2"
fill="none"
strokeLinecap="round"
/>
</Svg>
</View>
<View style={{ flex: 1, minWidth: 0 }}>
<Text
style={{
margin: 0,
fontFamily: 'BarlowCondensed_600SemiBold',
fontSize: 18,
color: '#111111',
}}>
{item.name}
</Text>
<Text
style={{
marginTop: 1,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 14,
color: '#5E5850',
}}>
{item.meta}
</Text>
</View>
<Pressable
accessibilityRole="button"
style={{
height: 36,
paddingVertical: 0,
paddingHorizontal: 16,
borderWidth: 0,
borderRadius: 18,
backgroundColor: '#F0705B',
flexShrink: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 15,
color: '#FFFFFF',
textAlign: 'center',
}}>
Play again
</Text>
</Pressable>
</View>
))}
</View>
<View
style={{
position: 'absolute',
left: '50%',
bottom: 30,
transform: [{ translateX: '-50%' }],
height: 64,
paddingVertical: 0,
paddingHorizontal: 10,
borderRadius: 32,
backgroundColor: '#FFFFFF',
boxShadow: '0 12px 30px rgba(0,0,0,0.14)',
alignItems: 'center',
gap: 8,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/home')}
style={{
height: 46,
paddingVertical: 0,
paddingHorizontal: 20,
borderRadius: 23,
backgroundColor: '#111111',
alignItems: 'center',
gap: 8,
flexShrink: 1,
flexDirection: 'row',
}}>
<Svg width="18" height="18" viewBox="0 0 24 24">
<Path d="M3 11l9-8 9 8v10h-6v-6H9v6H3z" fill="#FFFFFF" />
</Svg>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 16,
color: '#FFFFFF',
flexShrink: 1,
}}>
Home
</Text>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Games"
onPress={() => router.navigate('/home')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="22" height="22" viewBox="0 0 24 24">
<Rect
x="4"
y="3"
width="16"
height="18"
rx="3"
fill="none"
stroke="#6E6E6E"
strokeWidth="2"
/>
<Path
d="M8 13h8M8 17h5M8 8h8"
stroke="#6E6E6E"
strokeWidth="2"
strokeLinecap="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Ranking"
onPress={() => router.navigate('/leaderboard')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="22" height="22" viewBox="0 0 24 24">
<Path
d="M9 21V9h6v12M3 21v-7h6M15 21v-9h6v9"
fill="none"
stroke="#6E6E6E"
strokeWidth="2"
strokeLinejoin="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Profile"
onPress={() => router.navigate('/home')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<View
style={{
width: 34,
height: 34,
borderRadius: '50%',
backgroundColor: '#C9A27E',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 14,
color: '#111111',
flexShrink: 1,
}}>
R
</Text>
</View>
</Pressable>
</View>
</View>
</Screen>
);
}src/app/index.tsx
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Defs, Ellipse, G, Path, Pattern, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
const accent = '#E8513A';
export default function MainScreen() {
return (
<Screen background="#EFE9E0" statusBar="dark">
<View
style={{
alignItems: 'center',
paddingTop: 104,
paddingBottom: 64,
paddingHorizontal: 32,
flex: 1,
}}>
<View style={{ alignItems: 'flex-end', gap: 10, flexDirection: 'row' }}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'Anton_400Regular',
fontSize: 100,
color: '#111111',
letterSpacing: 1,
lineHeight: 90,
}}>
Quiz
</Text>
<Svg width="54" height="62" viewBox="0 0 56 64" style={{ marginBottom: 6 }}>
<Path d="M14 4h28v18c0 9-6 16-14 16S14 31 14 22z" fill="#F5B82E" />
<Path
d="M14 10H5v6c0 7 5 11 10 11M42 10h9v6c0 7-5 11-10 11"
fill="none"
stroke="#E39A12"
strokeWidth="4"
strokeLinecap="round"
/>
<Path d="M24 38h8v10h-8z" fill="#E39A12" />
<Path d="M16 50h24v8H16z" fill="#B5651D" />
<Path d="M20 8h4v14c0 4 2 7 4 8-5 0-8-4-8-8z" fill="#FFE08A" />
</Svg>
</View>
<View
accessibilityRole="image"
accessibilityLabel="Collage illustration of three friends celebrating at a desk with confetti"
style={{ marginTop: 34, width: 326, height: 300 }}>
<Svg width="326" height="300" viewBox="0 0 326 300">
<Defs>
<Pattern id="htOn" width="4" height="4" patternUnits="userSpaceOnUse">
<Circle cx="2" cy="2" r="1.25" fill="#000000" fillOpacity="0.38" />
</Pattern>
<Pattern id="htOnL" width="4" height="4" patternUnits="userSpaceOnUse">
<Circle cx="2" cy="2" r="0.9" fill="#000000" fillOpacity="0.25" />
</Pattern>
</Defs>
<G>
<Rect
x="24"
y="30"
width="8"
height="26"
rx="2"
fill="#E8513A"
transform="rotate(-24 28 43)"
/>
<Rect
x="62"
y="10"
width="8"
height="30"
rx="2"
fill={accent}
transform="rotate(18 66 25)"
/>
<Rect
x="104"
y="40"
width="7"
height="22"
rx="2"
fill="#F5B82E"
transform="rotate(-40 107 51)"
/>
<Rect
x="148"
y="6"
width="8"
height="28"
rx="2"
fill="#3B6CE0"
transform="rotate(30 152 20)"
/>
<Rect
x="184"
y="34"
width="7"
height="24"
rx="2"
fill="#2F6B4F"
transform="rotate(-12 187 46)"
/>
<Rect
x="276"
y="18"
width="8"
height="30"
rx="2"
fill="#F5B82E"
transform="rotate(42 280 33)"
/>
<Rect
x="300"
y="70"
width="7"
height="22"
rx="2"
fill="#E8513A"
transform="rotate(-30 303 81)"
/>
<Rect
x="8"
y="96"
width="7"
height="22"
rx="2"
fill="#2F6B4F"
transform="rotate(50 11 107)"
/>
<Rect
x="290"
y="120"
width="7"
height="20"
rx="2"
fill="#3B6CE0"
transform="rotate(-56 293 130)"
/>
<Rect
x="250"
y="8"
width="6"
height="18"
rx="2"
fill="#111111"
transform="rotate(-20 253 17)"
/>
<Rect
x="306"
y="160"
width="6"
height="18"
rx="2"
fill="#F5B82E"
transform="rotate(22 309 169)"
/>
<Rect
x="132"
y="70"
width="6"
height="18"
rx="2"
fill="#E8513A"
transform="rotate(60 135 79)"
/>
</G>
<Rect x="30" y="238" width="154" height="46" fill="#6A4BD8" />
<Rect x="160" y="256" width="120" height="30" fill="#F2853A" />
<G>
<Path d="M36 240c0-48 18-74 46-74s44 26 44 74z" fill="#5C5C5C" />
<Path d="M36 240c0-48 18-74 46-74s44 26 44 74z" fill="url(#htOn)" />
<Path d="M70 168l12 30 12-30z" fill="#EDEDED" />
<Circle cx="82" cy="140" r="21" fill="#CFCFCF" />
<Circle cx="82" cy="140" r="21" fill="url(#htOnL)" />
<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
d="M74 150q8 6 16 0"
stroke="#3A3A3A"
strokeWidth="2"
fill="none"
strokeLinecap="round"
/>
</G>
<G>
<Path d="M108 242c0-40 14-60 36-60s34 20 34 60z" fill="#8E8E8E" />
<Path d="M108 242c0-40 14-60 36-60s34 20 34 60z" fill="url(#htOn)" />
<Path
d="M120 170c-2-24 8-36 24-36s26 12 24 36l4 30h-12l-2-26h-28l-2 26h-12z"
fill="#1E1E1E"
/>
<Circle cx="144" cy="160" r="17" fill="#D6D6D6" />
<Circle cx="144" cy="160" r="17" fill="url(#htOnL)" />
<Path
d="M127 156c2-12 9-17 17-17s15 5 17 17c-6-6-11-8-17-8s-11 2-17 8z"
fill="#1E1E1E"
/>
<Ellipse cx="144" cy="168" rx="4" ry="3" fill="#3A3A3A" />
</G>
<Rect x="40" y="226" width="160" height="12" fill="#E3DED6" />
<Rect x="92" y="204" width="50" height="24" rx="3" fill="#2A2A2A" />
<Rect x="88" y="226" width="58" height="4" fill="#4A4A4A" />
<G>
<Path d="M196 168l-24-68" stroke="#3A3A3A" strokeWidth="17" strokeLinecap="round" />
<Path
d="M196 168l-24-68"
stroke="url(#htOn)"
strokeWidth="17"
strokeLinecap="round"
/>
<Path d="M256 168l22-66" stroke="#3A3A3A" strokeWidth="17" strokeLinecap="round" />
<Path d="M256 168l22-66" stroke="url(#htOn)" strokeWidth="17" strokeLinecap="round" />
<Circle cx="171" cy="94" r="9" fill="#D6D6D6" />
<Circle cx="279" cy="96" r="9" fill="#D6D6D6" />
<Path d="M180 290c-2-80 16-128 46-128s46 48 44 128z" fill="#3A3A3A" />
<Path d="M180 290c-2-80 16-128 46-128s46 48 44 128z" fill="url(#htOn)" />
<Path d="M214 164l12 26 12-26z" fill="#F4F4F4" />
<Path
d="M198 136c-4-30 10-46 28-46s32 16 28 46l2 22h-10l-2-20h-36l-2 20h-10z"
fill="#1A1A1A"
/>
<Circle cx="226" cy="128" r="22" fill="#D9D9D9" />
<Circle cx="226" cy="128" r="22" fill="url(#htOnL)" />
<Path
d="M203 124c2-16 12-24 23-24s21 8 23 24c-7-9-14-12-23-12s-16 3-23 12z"
fill="#1A1A1A"
/>
<Ellipse cx="226" cy="138" rx="7" ry="6" fill="#2A2A2A" />
<Path
d="M216 122h5M231 122h5"
stroke="#2A2A2A"
strokeWidth="2"
strokeLinecap="round"
/>
</G>
<Rect x="226" y="242" width="50" height="46" rx="8" fill="#2B2B2B" />
<Path
d="M240 254l22 22M262 254l-22 22"
stroke="#F4EFE7"
strokeWidth="4"
strokeLinecap="round"
/>
</Svg>
</View>
<Text
style={{
marginTop: 40,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 26,
color: '#111111',
letterSpacing: 0.3,
textAlign: 'center',
}}>
Play To Gain Your Knowledge
</Text>
<Text
style={{
marginTop: 12,
marginBottom: 0,
marginHorizontal: 0,
maxWidth: 290,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 19,
color: '#5E5850',
lineHeight: 27.55,
textAlign: 'center',
}}>
Answer quick rounds, challenge your friends and climb the ranks as you learn something new
every day.
</Text>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/home')}
style={{
marginTop: 'auto',
width: 226,
height: 60,
borderRadius: 30,
backgroundColor: '#111111',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 14px 28px rgba(0,0,0,0.22)',
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 22,
color: '#FFFFFF',
letterSpacing: 0.4,
flexShrink: 1,
}}>
Get started
</Text>
</Pressable>
</View>
</Screen>
);
}src/app/leaderboard.tsx
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Defs, Path, Pattern, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
const podium = [
{
name: 'Sophia Cba',
initials: 'SC',
diamonds: 880,
rank: 2,
bg: '#F08A7A',
medal: '#D6DCE4',
size: '84px',
font: '24px',
hair: 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z',
},
{
name: 'Emma Ema',
initials: 'EE',
diamonds: 888,
rank: 1,
bg: '#BFD2E6',
medal: '#F5B82E',
size: '108px',
font: '32px',
hair: 'M13 17c0-6 4-9 8-9s8 3 8 9c-2-3-5-4-8-4s-6 1-8 4z',
},
{
name: 'Andrew W',
initials: 'AW',
diamonds: 808,
rank: 3,
bg: '#9CCBB0',
medal: '#E3A16B',
size: '84px',
font: '24px',
hair: 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z',
},
];
const rows = [
{
name: 'Bayu Aji Sadewa',
initials: 'BA',
points: 20,
score: 99,
bg: '#D8CFC2',
badge: '#C73A25',
me: true,
hair: 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z',
},
{
name: 'Olivia Ava',
initials: 'OA',
points: 80,
score: 50,
bg: '#F6C9D0',
badge: '#2F6F9E',
me: false,
hair: 'M13 17c0-6 4-9 8-9s8 3 8 9c-2-3-5-4-8-4s-6 1-8 4z',
},
{
name: 'David Joshua',
initials: 'DJ',
points: 88,
score: 52,
bg: '#F7DC8A',
badge: '#2E7A44',
me: false,
hair: 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z',
},
{
name: 'Charlotte Harper',
initials: 'CH',
points: 22,
score: 97,
bg: '#E4E0DA',
badge: '#9A6A00',
me: false,
hair: 'M13 17c0-6 4-9 8-9s8 3 8 9c-2-3-5-4-8-4s-6 1-8 4z',
},
{
name: 'Mia Evelyn',
initials: 'ME',
points: 11,
score: 120,
bg: '#BFD2E6',
badge: '#6A45C9',
me: false,
hair: 'M12 19c0-7 4-11 9-11s9 4 9 11v9h-3v-10c-2-2-4-3-6-3s-4 1-6 3v10h-3z',
},
{
name: 'Liam Noah',
initials: 'LN',
points: 9,
score: 60,
bg: '#CFE5D5',
badge: '#2F6F9E',
me: false,
hair: 'M13 17c0-6 4-9 8-9s8 3 8 9c-2-3-5-4-8-4s-6 1-8 4z',
},
];
export default function LeaderboardScreen() {
return (
<Screen background="#EFE9E0" statusBar="dark">
<View style={{ paddingTop: 64, paddingBottom: 0, paddingHorizontal: 0, flex: 1 }}>
<View
style={{
paddingVertical: 0,
paddingHorizontal: 22,
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<View style={{ width: 72 }} />
<View style={{ alignItems: 'center', gap: 4, flexShrink: 1, flexDirection: 'row' }}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 26,
color: '#111111',
}}>
Leaderboard
</Text>
<Svg width="18" height="22" viewBox="0 0 20 24">
<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 d="M10 12c1 3 4 4 4 7a4 4 0 0 1-8 0c0-2 2-4 4-7z" fill="#F5B82E" />
</Svg>
</View>
<View
style={{
width: 72,
height: 36,
borderRadius: 18,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
gap: 6,
flexDirection: 'row',
}}>
<Svg width="18" height="18" viewBox="0 0 24 24">
<Path d="M6 3h12l4 6-10 12L2 9z" fill="#4FA8F0" />
<Path
d="M2 9h20M9 3l3 18M15 3l-3 18"
stroke="#2B7FCC"
strokeWidth="1.2"
fill="none"
/>
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 18,
color: '#111111',
}}>
20
</Text>
</View>
</View>
<View
style={{
marginTop: 30,
paddingVertical: 0,
paddingHorizontal: 18,
justifyContent: 'space-between',
alignItems: 'flex-end',
flexDirection: 'row',
}}>
{podium.map((p, index) => (
<View key={index} style={{ width: 110, alignItems: 'center' }}>
<View
style={{
width: parseFloat(p.size),
height: parseFloat(p.size),
borderRadius: '50%',
backgroundColor: '#FFFFFF',
padding: 5,
boxShadow: '0 10px 24px rgba(0,0,0,0.10)',
}}>
<View
style={{
width: '100%',
height: '100%',
borderRadius: '50%',
backgroundColor: p.bg,
overflow: 'hidden',
}}>
<Svg width="100%" height="100%" viewBox="0 0 42 42">
<Defs>
<Pattern id="htLb" width="3" height="3" patternUnits="userSpaceOnUse">
<Circle cx="1.5" cy="1.5" r="0.9" fill="#000000" fillOpacity="0.4" />
</Pattern>
</Defs>
<Path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="#4A4A4A" />
<Path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="url(#htLb)" />
<Circle cx="21" cy="18" r="8" fill="#D6D6D6" />
<Path d={p.hair} fill="#1E1E1E" />
</Svg>
</View>
</View>
<View
style={{
marginTop: -14,
width: 30,
height: 30,
borderRadius: '50%',
backgroundColor: p.medal,
borderWidth: 3,
borderColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 14,
color: '#111111',
flexShrink: 1,
}}>
{p.rank}
</Text>
</View>
<Text
style={{
marginTop: 8,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_600SemiBold',
fontSize: 18,
color: '#111111',
}}>
{p.name}
</Text>
<Text
style={{
marginTop: 1,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 14,
color: '#5E5850',
}}>
{p.diamonds}
{' Diamonds'}
</Text>
</View>
))}
</View>
<View
style={{
marginTop: 24,
marginBottom: 0,
marginHorizontal: 14,
backgroundColor: '#FFFFFF',
borderRadius: 28,
paddingTop: 6,
paddingBottom: 90,
paddingHorizontal: 14,
boxShadow: '0 6px 20px rgba(0,0,0,0.05)',
}}>
{rows.map((r, index) => (
<View
key={index}
style={{
height: 61,
alignItems: 'center',
gap: 12,
borderBottomWidth: 1,
borderBottomColor: '#F0ECE6',
flexDirection: 'row',
}}>
<View
style={{
width: 42,
height: 42,
borderRadius: '50%',
backgroundColor: r.bg,
overflow: 'hidden',
flexShrink: 0,
}}>
<Svg width="42" height="42" viewBox="0 0 42 42">
<Defs>
<Pattern id="htLb" width="3" height="3" patternUnits="userSpaceOnUse">
<Circle cx="1.5" cy="1.5" r="0.9" fill="#000000" fillOpacity="0.4" />
</Pattern>
</Defs>
<Path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="#4A4A4A" />
<Path d="M6 44c0-10 7-16 15-16s15 6 15 16z" fill="url(#htLb)" />
<Circle cx="21" cy="18" r="8" fill="#D6D6D6" />
<Path d={r.hair} fill="#1E1E1E" />
</Svg>
</View>
<View style={{ flex: 1, minWidth: 0 }}>
<Text
style={{
margin: 0,
fontFamily: 'BarlowCondensed_600SemiBold',
fontSize: 18,
color: '#111111',
}}>
{r.name}
</Text>
<Text
style={{
marginTop: 1,
marginBottom: 0,
marginHorizontal: 0,
fontFamily: 'BarlowCondensed_400Regular',
fontSize: 13,
color: '#5E5850',
}}>
{r.points}
{' Point'}
</Text>
</View>
{r.me && (
<View
style={{
height: 34,
paddingVertical: 0,
paddingHorizontal: 20,
borderRadius: 17,
backgroundColor: '#111111',
alignItems: 'center',
flexShrink: 1,
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 15,
color: '#FFFFFF',
flexShrink: 1,
}}>
Me
</Text>
</View>
)}
<View
style={{
width: 38,
height: 38,
borderRadius: '50%',
backgroundColor: r.badge,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 15,
color: '#FFFFFF',
flexShrink: 1,
}}>
{r.score}
</Text>
</View>
</View>
))}
</View>
<View
style={{
position: 'absolute',
left: '50%',
bottom: 30,
transform: [{ translateX: '-50%' }],
height: 64,
paddingVertical: 0,
paddingHorizontal: 10,
borderRadius: 32,
backgroundColor: '#FFFFFF',
boxShadow: '0 12px 30px rgba(0,0,0,0.16)',
alignItems: 'center',
gap: 8,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Home"
onPress={() => router.navigate('/home')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="22" height="22" viewBox="0 0 24 24">
<Path
d="M3 11l9-8 9 8v10h-6v-6H9v6H3z"
fill="none"
stroke="#6E6E6E"
strokeWidth="2"
strokeLinejoin="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Games"
onPress={() => router.navigate('/home')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg width="22" height="22" viewBox="0 0 24 24">
<Rect
x="4"
y="3"
width="16"
height="18"
rx="3"
fill="none"
stroke="#6E6E6E"
strokeWidth="2"
/>
<Path
d="M8 13h8M8 17h5M8 8h8"
stroke="#6E6E6E"
strokeWidth="2"
strokeLinecap="round"
/>
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/leaderboard')}
style={{
height: 46,
paddingVertical: 0,
paddingHorizontal: 20,
borderRadius: 23,
backgroundColor: '#111111',
alignItems: 'center',
gap: 8,
flexShrink: 1,
flexDirection: 'row',
}}>
<Svg width="18" height="18" viewBox="0 0 24 24">
<Path d="M9 21V9h6v12zM3 21v-7h6v7zM15 21v-9h6v9z" fill="#FFFFFF" />
</Svg>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 16,
color: '#FFFFFF',
flexShrink: 1,
}}>
Ranking
</Text>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Profile"
onPress={() => router.navigate('/home')}
style={{
width: 46,
height: 46,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<View
style={{
width: 34,
height: 34,
borderRadius: '50%',
backgroundColor: '#C9A27E',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'BarlowCondensed_700Bold',
fontSize: 14,
color: '#111111',
flexShrink: 1,
}}>
R
</Text>
</View>
</Pressable>
</View>
</View>
</Screen>
);
}src/components/screen.tsx
import { StatusBar } from 'expo-status-bar';
import type { ReactNode } from 'react';
import { ScrollView, useWindowDimensions, View } from 'react-native';
// Every screen is drawn on a 390 x 844 artboard, then scaled to the device width.
const ARTBOARD_WIDTH = 390;
const ARTBOARD_HEIGHT = 844;
type Props = {
background: string;
statusBar: 'light' | 'dark';
children: ReactNode;
};
export function Screen({ background, statusBar, children }: Props) {
const { width, height } = useWindowDimensions();
const scale = width / ARTBOARD_WIDTH;
return (
<ScrollView
bounces={false}
showsVerticalScrollIndicator={false}
style={{ flex: 1, backgroundColor: background }}
contentContainerStyle={{ height: Math.max(ARTBOARD_HEIGHT * scale, height) }}>
<StatusBar style={statusBar} />
<View
style={{
width: ARTBOARD_WIDTH,
height: ARTBOARD_HEIGHT,
overflow: 'hidden',
transformOrigin: 'left top',
transform: [{ scale }],
}}>
{children}
</View>
</ScrollView>
);
}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
- 01
Pick what to copy
Copy the Quiz Game artifact, skill or code from this page.
- 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.
- 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.



