// Entertainment app UI
Event Booking App UI Design in Expo
This event booking app UI takes a fan from browsing to a ticket in three steps: an upcoming events feed, a concert detail page and a digital pass with a barcode.
- Screens
- 3
- Built with
- Expo SDK 58
- Fonts
- Source Sans 3
- License
- Free (MIT)

Cine Ring Events app screens

Upcoming events
Location, search and category chips above large event cards with date badges and prices.

Event detail
A full-bleed artist photo, price chip, date and time, a description and a Get a Ticket action.

Digital ticket
An illustrated ticket with event details, perforated notches, a barcode and image or QR code actions.
Copy the Cine Ring Events 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
# Cine Ring Events: design artifact
This event booking app UI takes a fan from browsing to a ticket in three steps: an upcoming events feed, a concert detail page and a digital pass with a barcode.
- Type: Entertainment mobile app UI
- Screens: 3
- Artboard: 390 × 844
- Target: Expo SDK 58, Expo Router, TypeScript, expo-image, expo-linear-gradient, react-native-svg
- Live page: https://developermill.com/app-designs/event-booking-app-ui-design
## Design direction
Deep wine pages with coral actions, full-width concert photos and a white perforated ticket as the final reward.
- Category filters for feed, food and concerts
- Event cards with a date badge and price
- Concert detail with a sticky ticket action
- Perforated digital ticket with barcode
## Foundations
### Colour
| Token | Hex |
| --- | --- |
| Wine | `#2A1010` |
| Plum brown | `#4A2323` |
| Coral | `#F2545B` |
| Tangerine | `#FF7A45` |
| Blush | `#FFD9D9` |
| Rose grey | `#E9D3D1` |
### Typography
- Typefaces: Source Sans 3
- Common sizes (px): 11, 12, 13, 14, 15, 16, 17, 18
### Shape and depth
- Common corner radii (px): 14, 16, 18, 22, 26, 28
## Screens
### 1. Upcoming events
Location, search and category chips above large event cards with date badges and prices.
Preview: https://developermill.com/app-designs/event-booking-app-ui-design/events.webp
Copy on this screen:
- Jakarta, Ina
- Search events
- Upcoming events
- See All
- My feed
- Food
- Concerts
- 29
- Dec
- Rowan Vale Concert
- Jakarta Indonesia · 10:00 PM
- $45.90
- 22
- Jan
### 2. Event detail
A full-bleed artist photo, price chip, date and time, a description and a Get a Ticket action.
Preview: https://developermill.com/app-designs/event-booking-app-ui-design/event.webp
Copy on this screen:
- Rowan Vale
- Concert: Jakarta, Indonesia
- $45.90
- 29
- December
- Tuesday
- 10:00 PM · End
- About this event:
- Rowan Vale takes the stage at 10:00 PM for a night of fan favourites and new songs from the latest album, live at Gelora Bung Karno.
- Description
- 4.8
- Rowan Vale live on stage, 29 Dec at 10:00 PM
- Meet and greet after the show
- Get a Ticket
### 3. Digital ticket
An illustrated ticket with event details, perforated notches, a barcode and image or QR code actions.
Preview: https://developermill.com/app-designs/event-booking-app-ui-design/ticket.webp
Copy on this screen:
- Tickets
- Rowan Vale Concert: Indonesia
- 29 December 2026
- Date
- Dec 29, 2026
- Time
- 10:00 PM
- Venue
- Gelora Bung Karno
- Seat
- No seat
- Image
- QR Code
## Full source
The original artboards as HTML. Image URLs point at the hosted demo assets.
### Upcoming events (Main)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home – upcoming events</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=Source+Sans+3:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#FFFFFF;text-decoration:none}a:hover{color:#FFD9D9}
button{font-family:inherit;cursor:pointer}
input::placeholder{color:#C7A6A3}
</style>
</helmet>
<div style="width: 390px; height: 844px; position: relative; overflow: hidden; box-sizing: border-box; background: #2A1010; font-family: 'Source Sans 3', system-ui, sans-serif; color: #FFFFFF">
<div style="display: flex; flex-direction: column; gap: 20px; padding: 56px 20px 0 20px">
<div style="display: flex; align-items: center; justify-content: space-between">
<button aria-label="Open menu" style="width: 44px; height: 44px; border-radius: 22px; border: none; background: #4A2323; display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="4" y1="7" x2="20" y2="7"></line><line x1="4" y1="12" x2="14" y2="12"></line><line x1="4" y1="17" x2="20" y2="17"></line></svg>
</button>
<div style="display: flex; align-items: center; gap: 6px; font-size: 15px; font-weight: 600">
<svg width="16" height="16" viewBox="0 0 24 24" fill="{{accent}}" aria-hidden="true"><path d="M12 2a7 7 0 0 0-7 7c0 5.2 7 13 7 13s7-7.8 7-13a7 7 0 0 0-7-7zm0 9.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5z"></path></svg>
<span>Jakarta, Ina</span>
</div>
<img src="https://developermill.com/app-designs/event-booking-app-ui-design/assets/f1133ae529.jpg" alt="Your profile" style="width: 44px; height: 44px; border-radius: 22px; object-fit: cover; object-position: 50% 30%; border: 2px solid #5A2C2C; box-sizing: border-box">
</div>
<label style="display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 8px 0 18px; border-radius: 26px; background: #4A2323">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"></circle><line x1="16.5" y1="16.5" x2="21" y2="21"></line></svg>
<span style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Search events</span>
<input type="search" placeholder="Search all events..." style="flex-grow: 1; min-width: 0; border: none; outline: none; background: transparent; color: #FFFFFF; font-family: inherit; font-size: 15px">
<button aria-label="Filters" style="width: 40px; height: 40px; border: none; border-radius: 20px; background: transparent; display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="4" y1="7" x2="13" y2="7"></line><circle cx="17" cy="7" r="3"></circle><line x1="20" y1="17" x2="11" y2="17"></line><circle cx="7" cy="17" r="3"></circle></svg>
</button>
</label>
<div style="display: flex; align-items: center; justify-content: space-between">
<h2 style="margin: 0; font-size: 16px; font-weight: 700">Upcoming events</h2>
<a href="#" style="font-size: 13px; font-weight: 600; color: #E9D3D1">See All</a>
</div>
<div style="display: flex; gap: 10px">
<button style="display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 16px 0 6px; border: none; border-radius: 22px; background: {{accent}}; color: #FFFFFF; font-size: 14px; font-weight: 600">
<span style="width: 32px; height: 32px; border-radius: 16px; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="{{accent}}" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3c1 3 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-7 1.5 1 3 2 3 4"></path></svg></span>
My feed
</button>
<button style="display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 16px 0 6px; border: none; border-radius: 22px; background: #4A2323; color: #FFFFFF; font-size: 14px; font-weight: 600">
<span style="width: 32px; height: 32px; border-radius: 16px; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A1010" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 3v8M5 3v5a2 2 0 0 0 4 0V3M7 11v10M17 3c-2 1-3 4-3 7h3v11"></path></svg></span>
Food
</button>
<button style="display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 16px 0 6px; border: none; border-radius: 22px; background: #4A2323; color: #FFFFFF; font-size: 14px; font-weight: 600">
<span style="width: 32px; height: 32px; border-radius: 16px; background: #FFFFFF; display: flex; align-items: center; justify-content: center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#2A1010" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18V5l11-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="17" cy="16" r="3"></circle></svg></span>
Concerts
</button>
</div>
<a href="EventDetail.dc.html" aria-label="Rowan Vale Concert, Jakarta Indonesia, 10:00 PM, $45.90" style="display: block; position: relative; height: 236px; border-radius: 26px; overflow: hidden">
<img src="https://developermill.com/app-designs/event-booking-app-ui-design/assets/4c18274a94.jpg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block">
<div style="position: absolute; top: 14px; right: 14px; width: 44px; height: 54px; border-radius: 22px; background: #5E3434; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.1">
<span style="font-size: 16px; font-weight: 700">29</span>
<span style="font-size: 11px; color: #F3E4E2">Dec</span>
</div>
<div style="position: absolute; left: 10px; right: 10px; bottom: 10px; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 14px 14px 16px; border-radius: 18px; background: #5A3030">
<div style="display: flex; flex-direction: column; gap: 4px; min-width: 0">
<span style="font-size: 18px; font-weight: 700">Rowan Vale Concert</span>
<span style="font-size: 13px; color: #F3E4E2">Jakarta Indonesia · 10:00 PM</span>
</div>
<span style="flex-shrink: 0; padding: 8px 14px; border-radius: 18px; background: #FFFFFF; color: #2A1010; font-size: 15px; font-weight: 700">$45.90</span>
</div>
</a>
<a href="#" aria-label="Neon Night Party, 22 January" style="display: block; position: relative; height: 236px; border-radius: 26px; overflow: hidden">
<img src="https://developermill.com/app-designs/event-booking-app-ui-design/assets/e4da41ebaf.jpg" alt="" style="width: 100%; height: 100%; object-fit: cover; display: block">
<div style="position: absolute; top: 14px; right: 14px; width: 44px; height: 54px; border-radius: 22px; background: #5E3434; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.1">
<span style="font-size: 16px; font-weight: 700">22</span>
<span style="font-size: 11px; color: #F3E4E2">Jan</span>
</div>
</a>
</div>
<nav aria-label="Main" style="position: absolute; left: 0; right: 0; bottom: 0; height: 92px; box-sizing: border-box; padding: 12px 28px 28px 28px; background: #1F0B0B; display: flex; align-items: center; justify-content: space-between">
<a href="Main.dc.html" aria-label="Home" aria-current="page" style="width: 48px; height: 48px; border-radius: 24px; background: {{accent}}; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z"></path></svg>
</a>
<a href="#" aria-label="Favourites" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.5-7 10-7 10z"></path></svg>
</a>
<a href="#" aria-label="Videos" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="6" width="13" height="12" rx="2"></rect><path d="M16 10l5-3v10l-5-3"></path></svg>
</a>
<a href="Ticket.dc.html" aria-label="My tickets" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="2"></rect><path d="M3 7l9 6 9-6"></path></svg>
</a>
<a href="#" aria-label="Profile" style="width: 48px; height: 48px; display: flex; align-items: center; justify-content: center">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#E9D3D1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="8" r="4"></circle><path d="M4 21c0-4 4-6 8-6s8 2 8 6"></path></svg>
</a>
</nav>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F2545B","options":["#F2545B","#FF7A45","#E8447A"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F2545B' };
}
}
</script>
</body>
</html>
```
### Event detail (EventDetail)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Event detail – Rowan Vale</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=Source+Sans+3:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#FFFFFF;text-decoration:none}a:hover{color:#FFD9D9}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; position: relative; overflow: hidden; box-sizing: border-box; background: #2A1010; font-family: 'Source Sans 3', system-ui, sans-serif; color: #FFFFFF">
<img src="https://developermill.com/app-designs/event-booking-app-ui-design/assets/8e9fb59704.jpg" alt="Rowan Vale singing on stage" style="position: absolute; top: -2px; left: 0px; width: 399px; height: 483px; object-fit: cover; object-position: 50% 20%; display: block">
<div style="position: absolute; top: 260px; left: 0; width: 390px; height: 222px; background: linear-gradient(180deg, rgba(42,16,16,0) 0%, #2A1010 100%)"></div>
<div style="position: absolute; top: 52px; left: 20px; right: 20px; display: flex; align-items: center; justify-content: space-between">
<a href="Main.dc.html" aria-label="Back" style="width: 44px; height: 44px; border-radius: 22px; background: rgba(42,16,16,0.55); display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"></path></svg>
</a>
<span style="font-size: 17px; font-weight: 700">Rowan Vale</span>
<button aria-label="Share" style="width: 44px; height: 44px; border: none; border-radius: 22px; background: rgba(42,16,16,0.55); display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="2.5"></circle><circle cx="6" cy="12" r="2.5"></circle><circle cx="18" cy="19" r="2.5"></circle><path d="M8.2 10.8l7.6-4.4M8.2 13.2l7.6 4.4"></path></svg>
</button>
</div>
<div style="position: absolute; top: 400px; left: 20px; right: 20px; display: flex; flex-direction: column; gap: 18px">
<div style="display: flex; align-items: flex-end; justify-content: space-between; gap: 12px">
<div style="display: flex; flex-direction: column; gap: 4px">
<h1 style="margin: 0; font-size: 30px; font-weight: 700; line-height: 1.1">Rowan Vale</h1>
<span style="font-size: 14px; color: #E9D3D1">Concert: Jakarta, Indonesia</span>
</div>
<span style="flex-shrink: 0; padding: 9px 16px; border-radius: 20px; background: #FFFFFF; color: #2A1010; font-size: 17px; font-weight: 700">$45.90</span>
</div>
<div style="display: flex; align-items: center; gap: 36px">
<div style="display: flex; flex-direction: column; gap: 2px">
<span style="font-size: 16px; font-weight: 700">29</span>
<span style="font-size: 13px; color: #E9D3D1">December</span>
</div>
<div style="display: flex; flex-direction: column; gap: 2px; flex-grow: 1">
<span style="font-size: 16px; font-weight: 700">Tuesday</span>
<span style="font-size: 13px; color: #E9D3D1">10:00 PM · End</span>
</div>
<button aria-label="Add to calendar" style="width: 44px; height: 44px; border: 1px solid #6A3B3B; border-radius: 22px; background: #4A2323; display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="16" rx="2"></rect><path d="M3 10h18M8 3v4M16 3v4"></path></svg>
</button>
</div>
<p style="margin: 0; font-size: 14px; line-height: 1.5; color: #E9D3D1"><span style="font-weight: 700; color: #FFFFFF">About this event: </span>Rowan Vale takes the stage at 10:00 PM for a night of fan favourites and new songs from the latest album, live at Gelora Bung Karno.</p>
<div style="display: flex; flex-direction: column; gap: 10px">
<div style="display: flex; align-items: center; justify-content: space-between">
<h2 style="margin: 0; font-size: 16px; font-weight: 700">Description</h2>
<span style="display: flex; align-items: center; gap: 4px; font-size: 14px; font-weight: 600">
<svg width="16" height="16" viewBox="0 0 24 24" fill="#F5B83D" aria-hidden="true"><path d="M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z"></path></svg>
4.8
</span>
</div>
<div style="display: flex; align-items: center; gap: 10px; font-size: 14px; color: #E9D3D1">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="12" cy="12" r="10" fill="#6A3B3B"></circle><path d="M7.5 12.5l3 3 6-6" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
Rowan Vale live on stage, 29 Dec at 10:00 PM
</div>
<div style="display: flex; align-items: center; gap: 10px; font-size: 14px; color: #E9D3D1">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="12" cy="12" r="10" fill="#6A3B3B"></circle><path d="M7.5 12.5l3 3 6-6" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>
Meet and greet after the show
</div>
</div>
</div>
<div style="position: absolute; left: 0; right: 0; bottom: 0; box-sizing: border-box; padding: 16px 20px 34px 20px; background: #2A1010; display: flex; align-items: center; gap: 14px">
<button aria-label="Save to favourites" style="width: 56px; height: 56px; flex-shrink: 0; border: none; border-radius: 28px; background: #FFFFFF; display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="22" height="22" viewBox="0 0 24 24" fill="#2A1010" aria-hidden="true"><path d="M12 20.5s-7.5-4.7-7.5-10.4A4.2 4.2 0 0 1 12 7.4a4.2 4.2 0 0 1 7.5 2.7c0 5.7-7.5 10.4-7.5 10.4z"></path></svg>
</button>
<a href="Ticket.dc.html" style="flex-grow: 1; height: 56px; border-radius: 28px; background: {{accent}}; display: flex; align-items: center; justify-content: center; font-size: 17px; font-weight: 700; color: #FFFFFF">Get a Ticket</a>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F2545B","options":["#F2545B","#FF7A45","#E8447A"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
return { accent: this.props.accent ?? '#F2545B' };
}
}
</script>
</body>
</html>
```
### Digital ticket (Ticket)
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ticket – Rowan Vale Concert</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=Source+Sans+3:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#FFFFFF;text-decoration:none}a:hover{color:#FFD9D9}
button{font-family:inherit;cursor:pointer}
</style>
</helmet>
<div style="width: 390px; height: 844px; position: relative; overflow: hidden; box-sizing: border-box; background: #2A1010; font-family: 'Source Sans 3', system-ui, sans-serif; color: #FFFFFF">
<div style="position: absolute; top: 52px; left: 20px; right: 20px; display: flex; align-items: center; justify-content: space-between">
<a href="EventDetail.dc.html" aria-label="Back" style="width: 44px; height: 44px; border-radius: 22px; background: #4A2323; display: flex; align-items: center; justify-content: center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 5l-7 7 7 7"></path></svg>
</a>
<h1 style="margin: 0; font-size: 18px; font-weight: 700">Tickets</h1>
<button aria-label="Share ticket" style="width: 44px; height: 44px; border: none; border-radius: 22px; background: #4A2323; display: flex; align-items: center; justify-content: center; padding: 0">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="5" r="2.5"></circle><circle cx="6" cy="12" r="2.5"></circle><circle cx="18" cy="19" r="2.5"></circle><path d="M8.2 10.8l7.6-4.4M8.2 13.2l7.6 4.4"></path></svg>
</button>
</div>
<div style="position: absolute; top: 118px; left: 20px; right: 20px; box-sizing: border-box; padding: 12px; border-radius: 30px; background: #4A2323; display: flex; flex-direction: column; gap: 12px">
<img src="https://developermill.com/app-designs/event-booking-app-ui-design/assets/f1133ae529.jpg" alt="Illustrated Rowan Vale artwork" style="width: 100%; height: 196px; border-radius: 22px; object-fit: cover; object-position: 50% 35%; display: block">
<div style="position: relative; border-radius: 22px; background: #FFFFFF; color: #2A1010; padding: 22px 22px 20px 22px; display: flex; flex-direction: column; gap: 16px">
<div style="display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center">
<span style="font-size: 17px; font-weight: 700">Rowan Vale Concert: Indonesia</span>
<span style="font-size: 17px; font-weight: 700">29 December 2026</span>
</div>
<div style="border-top: 2px dashed #D9C6C4"></div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 14px; column-gap: 12px">
<div style="display: flex; flex-direction: column; gap: 3px">
<span style="font-size: 12px; color: #6E5452">Date</span>
<span style="font-size: 14px; font-weight: 700">Dec 29, 2026</span>
</div>
<div style="display: flex; flex-direction: column; gap: 3px; align-items: flex-end">
<span style="font-size: 12px; color: #6E5452">Time</span>
<span style="font-size: 14px; font-weight: 700">10:00 PM</span>
</div>
<div style="display: flex; flex-direction: column; gap: 3px">
<span style="font-size: 12px; color: #6E5452">Venue</span>
<span style="font-size: 14px; font-weight: 700">Gelora Bung Karno</span>
</div>
<div style="display: flex; flex-direction: column; gap: 3px; align-items: flex-end">
<span style="font-size: 12px; color: #6E5452">Seat</span>
<span style="font-size: 14px; font-weight: 700">No seat</span>
</div>
</div>
<div style="position: relative; height: 0">
<div style="position: absolute; left: -36px; top: -14px; width: 28px; height: 28px; border-radius: 14px; background: #4A2323"></div>
<div style="position: absolute; right: -36px; top: -14px; width: 28px; height: 28px; border-radius: 14px; background: #4A2323"></div>
<div style="border-top: 2px dashed #D9C6C4"></div>
</div>
<div role="img" aria-label="Ticket barcode" style="display: flex; align-items: stretch; justify-content: center; gap: 2px; height: 54px">
<sc-for list="{{bars}}" as="bar" hint-placeholder-count="40">
<div style="width: {{bar.w}}; background: #1A0A0A"></div>
</sc-for>
</div>
</div>
</div>
<div style="position: absolute; left: 20px; right: 20px; bottom: 34px; display: flex; gap: 14px">
<button style="flex-grow: 1; flex-basis: 0; height: 56px; border: none; border-radius: 28px; background: {{accent}}; color: #FFFFFF; font-size: 16px; font-weight: 700; display: flex; align-items: center; justify-content: center; gap: 8px">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v8M8.5 11.5L12 15l3.5-3.5"></path></svg>
Image
</button>
<button style="flex-grow: 1; flex-basis: 0; height: 56px; border: none; border-radius: 28px; background: #FFFFFF; color: #2A1010; font-size: 16px; font-weight: 700; display: flex; align-items: center; justify-content: center; gap: 8px">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#2A1010" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1"></rect><rect x="14" y="3" width="7" height="7" rx="1"></rect><rect x="3" y="14" width="7" height="7" rx="1"></rect><path d="M14 14h3v3h-3zM20 14v.01M14 20h.01M17 20h4v-3"></path></svg>
QR Code
</button>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F2545B","options":["#F2545B","#FF7A45","#E8447A"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
renderVals() {
var pattern = [3,1,2,1,4,1,1,2,3,1,2,2,1,3,1,1,4,2,1,1,3,2,1,2,1,4,1,2,1,3,2,1,1,2,4,1,2,1,3,1,1,2,3,1,2,1,4,1];
return {
accent: this.props.accent ?? '#F2545B',
bars: pattern.map(function (w) { return { w: w + 'px' }; })
};
}
}
</script>
</body>
</html>
```SKILL.md
Save as .claude/skills/event-booking-app-ui/SKILL.md
--- name: event-booking-app-ui description: Build the Cine Ring Events mobile app UI in Expo React Native. Use when asked to create a event booking app UI or a new screen in this visual style. --- # Cine Ring Events app UI Build this entertainment app UI in an Expo Router project with TypeScript. Reference: https://developermill.com/app-designs/event-booking-app-ui-design ## Visual direction Deep wine pages with coral actions, full-width concert photos and a white perforated ticket as the final reward. Keep these signature details: - Category filters for feed, food and concerts - Event cards with a date badge and price - Concert detail with a sticky ticket action - Perforated digital ticket with barcode ## Set up ```bash npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/source-sans-3 expo-font ``` ## Tokens | Name | Hex | | --- | --- | | Wine | `#2A1010` | | Plum brown | `#4A2323` | | Coral | `#F2545B` | | Tangerine | `#FF7A45` | | Blush | `#FFD9D9` | | Rose grey | `#E9D3D1` | - Typefaces: Source Sans 3 - Text sizes (px): 11, 12, 13, 14, 15, 16, 17, 18 - Corner radii (px): 14, 16, 18, 22, 26, 28 Define these once and reuse them. Do not add new colours. ## Screens 1. **Upcoming events.** Location, search and category chips above large event cards with date badges and prices. 2. **Event detail.** A full-bleed artist photo, price chip, date and time, a description and a Get a Ticket action. 3. **Digital ticket.** An illustrated ticket with event details, perforated notches, a barcode and image or QR code actions. ## Build rules - Draw each screen on a 390 × 844 artboard and scale it to the device width. - Load each custom font weight by family name with expo-font. Do not set fontWeight with custom fonts. - Draw icons, charts and illustrations with react-native-svg. - Use Pressable with an accessibilityLabel for controls, with at least a 44px target. - Navigate with router.navigate and keep sample data as constants at the top of the file. - Use expo-image with contentFit for photos. ## Done when - All routes are linked and reachable. - Colours, type and radii match the tokens above. - `npx tsc --noEmit` and `npx expo lint` pass. - The layout holds up on small and large phones.
Set up the project
npx create-expo-app@latest event-booking-app --template default cd event-booking-app rm -rf src npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/source-sans-3 expo-font
src/app/_layout.tsx
import {
SourceSans3_400Regular,
SourceSans3_600SemiBold,
SourceSans3_700Bold,
} from '@expo-google-fonts/source-sans-3';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
export default function RootLayout() {
const [fontsLoaded] = useFonts({
SourceSans3_400Regular,
SourceSans3_600SemiBold,
SourceSans3_700Bold,
});
if (!fontsLoaded) return null;
return <Stack screenOptions={{ headerShown: false }} />;
}src/app/index.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, TextInput, View } from 'react-native';
import Svg, { Circle, Line, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
const accent = '#F2545B';
export default function MainScreen() {
return (
<Screen background="#2A1010" statusBar="light">
<View style={{ flex: 1 }}>
<View style={{ gap: 20, paddingTop: 56, paddingBottom: 0, paddingHorizontal: 20 }}>
<View
style={{ alignItems: 'center', justifyContent: 'space-between', flexDirection: 'row' }}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Open menu"
style={{
width: 44,
height: 44,
borderRadius: 22,
borderWidth: 0,
backgroundColor: '#4A2323',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round">
<Line x1="4" y1="7" x2="20" y2="7" />
<Line x1="4" y1="12" x2="14" y2="12" />
<Line x1="4" y1="17" x2="20" y2="17" />
</Svg>
</Pressable>
<View style={{ alignItems: 'center', gap: 6, flexShrink: 1, flexDirection: 'row' }}>
<Svg width="16" height="16" viewBox="0 0 24 24" fill={accent}>
<Path d="M12 2a7 7 0 0 0-7 7c0 5.2 7 13 7 13s7-7.8 7-13a7 7 0 0 0-7-7zm0 9.5a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5z" />
</Svg>
<Text
style={{
flexShrink: 1,
fontFamily: 'SourceSans3_600SemiBold',
fontSize: 15,
color: '#FFFFFF',
}}>
Jakarta, Ina
</Text>
</View>
<Image
source={{ uri: asset('f1133ae529.jpg') }}
contentFit="cover"
contentPosition={{ left: '50%', top: '30%' }}
accessibilityLabel="Your profile"
style={{
width: 44,
height: 44,
borderRadius: 22,
borderWidth: 2,
borderColor: '#5A2C2C',
}}
/>
</View>
<View
style={{
alignItems: 'center',
gap: 12,
height: 52,
paddingVertical: 0,
paddingLeft: 18,
paddingRight: 8,
borderRadius: 26,
backgroundColor: '#4A2323',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round">
<Circle cx="11" cy="11" r="7" />
<Line x1="16.5" y1="16.5" x2="21" y2="21" />
</Svg>
<TextInput
placeholder="Search all events..."
placeholderTextColor="#8A8A8A"
style={{
flexGrow: 1,
minWidth: 0,
borderWidth: 0,
flexShrink: 1,
fontFamily: 'SourceSans3_400Regular',
fontSize: 15,
color: '#FFFFFF',
}}
/>
<Pressable
accessibilityRole="button"
accessibilityLabel="Filters"
style={{
width: 40,
height: 40,
borderWidth: 0,
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round">
<Line x1="4" y1="7" x2="13" y2="7" />
<Circle cx="17" cy="7" r="3" />
<Line x1="20" y1="17" x2="11" y2="17" />
<Circle cx="7" cy="17" r="3" />
</Svg>
</Pressable>
</View>
<View
style={{ alignItems: 'center', justifyContent: 'space-between', flexDirection: 'row' }}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#FFFFFF',
}}>
Upcoming events
</Text>
<Pressable accessibilityRole="link" style={{ flexShrink: 1 }}>
<Text
style={{ fontFamily: 'SourceSans3_600SemiBold', fontSize: 13, color: '#E9D3D1' }}>
See All
</Text>
</Pressable>
</View>
<View style={{ gap: 10, flexDirection: 'row' }}>
<Pressable
accessibilityRole="button"
style={{
alignItems: 'center',
gap: 8,
height: 44,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderWidth: 0,
borderRadius: 22,
backgroundColor: accent,
flexShrink: 1,
flexDirection: 'row',
}}>
<View
style={{
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke={accent}
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M12 3c1 3 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-7 1.5 1 3 2 3 4" />
</Svg>
</View>
<Text
style={{
fontFamily: 'SourceSans3_600SemiBold',
fontSize: 14,
color: '#FFFFFF',
flexShrink: 1,
}}>
My feed
</Text>
</Pressable>
<Pressable
accessibilityRole="button"
style={{
alignItems: 'center',
gap: 8,
height: 44,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderWidth: 0,
borderRadius: 22,
backgroundColor: '#4A2323',
flexShrink: 1,
flexDirection: 'row',
}}>
<View
style={{
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#2A1010"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M7 3v8M5 3v5a2 2 0 0 0 4 0V3M7 11v10M17 3c-2 1-3 4-3 7h3v11" />
</Svg>
</View>
<Text
style={{
fontFamily: 'SourceSans3_600SemiBold',
fontSize: 14,
color: '#FFFFFF',
flexShrink: 1,
}}>
Food
</Text>
</Pressable>
<Pressable
accessibilityRole="button"
style={{
alignItems: 'center',
gap: 8,
height: 44,
paddingVertical: 0,
paddingLeft: 6,
paddingRight: 16,
borderWidth: 0,
borderRadius: 22,
backgroundColor: '#4A2323',
flexShrink: 1,
flexDirection: 'row',
}}>
<View
style={{
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#2A1010"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M9 18V5l11-2v13" />
<Circle cx="6" cy="18" r="3" />
<Circle cx="17" cy="16" r="3" />
</Svg>
</View>
<Text
style={{
fontFamily: 'SourceSans3_600SemiBold',
fontSize: 14,
color: '#FFFFFF',
flexShrink: 1,
}}>
Concerts
</Text>
</Pressable>
</View>
<Pressable
accessibilityRole="link"
accessibilityLabel="Rowan Vale Concert, Jakarta Indonesia, 10:00 PM, $45.90"
onPress={() => router.navigate('/eventdetail')}
style={{ height: 236, borderRadius: 26, overflow: 'hidden' }}>
<Image
source={{ uri: asset('4c18274a94.jpg') }}
contentFit="cover"
style={{ width: '100%', height: '100%' }}
/>
<View
style={{
position: 'absolute',
top: 14,
right: 14,
width: 44,
height: 54,
borderRadius: 22,
backgroundColor: '#5E3434',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#FFFFFF',
lineHeight: 17.6,
}}>
29
</Text>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 11,
color: '#F3E4E2',
lineHeight: 12.1,
}}>
Dec
</Text>
</View>
<View
style={{
position: 'absolute',
left: 10,
right: 10,
bottom: 10,
alignItems: 'center',
justifyContent: 'space-between',
gap: 12,
paddingVertical: 14,
paddingLeft: 16,
paddingRight: 14,
borderRadius: 18,
backgroundColor: '#5A3030',
flexDirection: 'row',
}}>
<View style={{ gap: 4, minWidth: 0, flexShrink: 1 }}>
<Text style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 18, color: '#FFFFFF' }}>
Rowan Vale Concert
</Text>
<Text
style={{ fontFamily: 'SourceSans3_400Regular', fontSize: 13, color: '#F3E4E2' }}>
Jakarta Indonesia · 10:00 PM
</Text>
</View>
<Text
style={{
flexShrink: 0,
paddingVertical: 8,
paddingHorizontal: 14,
borderRadius: 18,
backgroundColor: '#FFFFFF',
fontFamily: 'SourceSans3_700Bold',
fontSize: 15,
color: '#2A1010',
}}>
$45.90
</Text>
</View>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Neon Night Party, 22 January"
style={{ height: 236, borderRadius: 26, overflow: 'hidden' }}>
<Image
source={{ uri: asset('e4da41ebaf.jpg') }}
contentFit="cover"
style={{ width: '100%', height: '100%' }}
/>
<View
style={{
position: 'absolute',
top: 14,
right: 14,
width: 44,
height: 54,
borderRadius: 22,
backgroundColor: '#5E3434',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#FFFFFF',
lineHeight: 17.6,
}}>
22
</Text>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 11,
color: '#F3E4E2',
lineHeight: 12.1,
}}>
Jan
</Text>
</View>
</Pressable>
</View>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 92,
paddingTop: 12,
paddingBottom: 28,
paddingHorizontal: 28,
backgroundColor: '#1F0B0B',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Home"
onPress={() => router.navigate('/')}
style={{
width: 48,
height: 48,
borderRadius: 24,
backgroundColor: accent,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6h-6v6H4a1 1 0 0 1-1-1z" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Favourites"
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M12 20s-7-4.5-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.5-7 10-7 10z" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Videos"
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Rect x="3" y="6" width="13" height="12" rx="2" />
<Path d="M16 10l5-3v10l-5-3" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="My tickets"
onPress={() => router.navigate('/ticket')}
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Rect x="3" y="5" width="18" height="14" rx="2" />
<Path d="M3 7l9 6 9-6" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
accessibilityLabel="Profile"
style={{
width: 48,
height: 48,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="#E9D3D1"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Circle cx="12" cy="8" r="4" />
<Path d="M4 21c0-4 4-6 8-6s8 2 8 6" />
</Svg>
</Pressable>
</View>
</View>
</Screen>
);
}src/app/eventdetail.tsx
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { router } from 'expo-router';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import Svg, { Circle, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
const accent = '#F2545B';
export default function EventDetailScreen() {
return (
<Screen background="#2A1010" statusBar="light">
<View style={{ flex: 1 }}>
<Image
source={{ uri: asset('8e9fb59704.jpg') }}
contentFit="cover"
contentPosition={{ left: '50%', top: '20%' }}
accessibilityLabel="Rowan Vale singing on stage"
style={{ position: 'absolute', top: -2, left: 0, width: 399, height: 483 }}
/>
<View style={{ position: 'absolute', top: 260, left: 0, width: 390, height: 222 }}>
<LinearGradient
colors={['rgba(42,16,16,0)', '#2A1010']}
locations={[0, 1]}
start={{ x: 0.5, y: 0 }}
end={{ x: 0.5, y: 1 }}
style={StyleSheet.absoluteFill}
/>
</View>
<View
style={{
position: 'absolute',
top: 52,
left: 20,
right: 20,
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Back"
onPress={() => router.navigate('/')}
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: 'rgba(42,16,16,0.55)',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M15 5l-7 7 7 7" />
</Svg>
</Pressable>
<Text
style={{
flexShrink: 1,
fontFamily: 'SourceSans3_700Bold',
fontSize: 17,
color: '#FFFFFF',
}}>
Rowan Vale
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="Share"
style={{
width: 44,
height: 44,
borderWidth: 0,
borderRadius: 22,
backgroundColor: 'rgba(42,16,16,0.55)',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Circle cx="18" cy="5" r="2.5" />
<Circle cx="6" cy="12" r="2.5" />
<Circle cx="18" cy="19" r="2.5" />
<Path d="M8.2 10.8l7.6-4.4M8.2 13.2l7.6 4.4" />
</Svg>
</Pressable>
</View>
<View style={{ position: 'absolute', top: 400, left: 20, right: 20, gap: 18 }}>
<View
style={{
alignItems: 'flex-end',
justifyContent: 'space-between',
gap: 12,
flexDirection: 'row',
}}>
<View style={{ gap: 4, flexShrink: 1 }}>
<Text
style={{
margin: 0,
fontFamily: 'SourceSans3_700Bold',
fontSize: 30,
color: '#FFFFFF',
lineHeight: 33,
}}>
Rowan Vale
</Text>
<Text
style={{ fontFamily: 'SourceSans3_400Regular', fontSize: 14, color: '#E9D3D1' }}>
Concert: Jakarta, Indonesia
</Text>
</View>
<Text
style={{
flexShrink: 0,
paddingVertical: 9,
paddingHorizontal: 16,
borderRadius: 20,
backgroundColor: '#FFFFFF',
fontFamily: 'SourceSans3_700Bold',
fontSize: 17,
color: '#2A1010',
}}>
$45.90
</Text>
</View>
<View style={{ alignItems: 'center', gap: 36, flexDirection: 'row' }}>
<View style={{ gap: 2, flexShrink: 1 }}>
<Text style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 16, color: '#FFFFFF' }}>
29
</Text>
<Text
style={{ fontFamily: 'SourceSans3_400Regular', fontSize: 13, color: '#E9D3D1' }}>
December
</Text>
</View>
<View style={{ gap: 2, flexGrow: 1, flexShrink: 1 }}>
<Text style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 16, color: '#FFFFFF' }}>
Tuesday
</Text>
<Text
style={{ fontFamily: 'SourceSans3_400Regular', fontSize: 13, color: '#E9D3D1' }}>
10:00 PM · End
</Text>
</View>
<Pressable
accessibilityRole="button"
accessibilityLabel="Add to calendar"
style={{
width: 44,
height: 44,
borderWidth: 1,
borderColor: '#6A3B3B',
borderRadius: 22,
backgroundColor: '#4A2323',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Rect x="3" y="5" width="18" height="16" rx="2" />
<Path d="M3 10h18M8 3v4M16 3v4" />
</Svg>
</Pressable>
</View>
<Text
style={{
margin: 0,
fontFamily: 'SourceSans3_400Regular',
fontSize: 14,
color: '#E9D3D1',
lineHeight: 21,
}}>
<Text style={{ fontFamily: 'SourceSans3_700Bold', color: '#FFFFFF' }}>
{'About this event: '}
</Text>
Rowan Vale takes the stage at 10:00 PM for a night of fan favourites and new songs from
the latest album, live at Gelora Bung Karno.
</Text>
<View style={{ gap: 10 }}>
<View
style={{
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#FFFFFF',
}}>
Description
</Text>
<View style={{ alignItems: 'center', gap: 4, flexShrink: 1, flexDirection: 'row' }}>
<Svg width="16" height="16" viewBox="0 0 24 24" fill="#F5B83D">
<Path d="M12 2.5l2.9 6.1 6.6.8-4.9 4.6 1.3 6.6L12 17.3l-5.9 3.3 1.3-6.6-4.9-4.6 6.6-.8z" />
</Svg>
<Text
style={{
fontFamily: 'SourceSans3_600SemiBold',
fontSize: 14,
color: '#FFFFFF',
flexShrink: 1,
}}>
4.8
</Text>
</View>
</View>
<View style={{ alignItems: 'center', gap: 10, flexDirection: 'row' }}>
<Svg width="18" height="18" viewBox="0 0 24 24" fill="none">
<Circle cx="12" cy="12" r="10" fill="#6A3B3B" />
<Path
d="M7.5 12.5l3 3 6-6"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 14,
color: '#E9D3D1',
flexShrink: 1,
}}>
Rowan Vale live on stage, 29 Dec at 10:00 PM
</Text>
</View>
<View style={{ alignItems: 'center', gap: 10, flexDirection: 'row' }}>
<Svg width="18" height="18" viewBox="0 0 24 24" fill="none">
<Circle cx="12" cy="12" r="10" fill="#6A3B3B" />
<Path
d="M7.5 12.5l3 3 6-6"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</Svg>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 14,
color: '#E9D3D1',
flexShrink: 1,
}}>
Meet and greet after the show
</Text>
</View>
</View>
</View>
<View
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
paddingTop: 16,
paddingBottom: 34,
paddingHorizontal: 20,
backgroundColor: '#2A1010',
alignItems: 'center',
gap: 14,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="button"
accessibilityLabel="Save to favourites"
style={{
width: 56,
height: 56,
flexShrink: 0,
borderWidth: 0,
borderRadius: 28,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg width="22" height="22" viewBox="0 0 24 24" fill="#2A1010">
<Path d="M12 20.5s-7.5-4.7-7.5-10.4A4.2 4.2 0 0 1 12 7.4a4.2 4.2 0 0 1 7.5 2.7c0 5.7-7.5 10.4-7.5 10.4z" />
</Svg>
</Pressable>
<Pressable
accessibilityRole="link"
onPress={() => router.navigate('/ticket')}
style={{
flexGrow: 1,
height: 56,
borderRadius: 28,
backgroundColor: accent,
alignItems: 'center',
justifyContent: 'center',
flexShrink: 1,
flexDirection: 'row',
}}>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 17,
color: '#FFFFFF',
flexShrink: 1,
}}>
Get a Ticket
</Text>
</Pressable>
</View>
</View>
</Screen>
);
}src/app/ticket.tsx
import { Image } from 'expo-image';
import { router } from 'expo-router';
import { Pressable, Text, View } from 'react-native';
import Svg, { Circle, Path, Rect } from 'react-native-svg';
import { Screen } from '@/components/screen';
import { asset } from '@/lib/assets';
const accent = '#F2545B';
const bars = [
{ w: 3 },
{ w: 1 },
{ w: 2 },
{ w: 1 },
{ w: 4 },
{ w: 1 },
{ w: 1 },
{ w: 2 },
{ w: 3 },
{ w: 1 },
{ w: 2 },
{ w: 2 },
{ w: 1 },
{ w: 3 },
{ w: 1 },
{ w: 1 },
{ w: 4 },
{ w: 2 },
{ w: 1 },
{ w: 1 },
{ w: 3 },
{ w: 2 },
{ w: 1 },
{ w: 2 },
{ w: 1 },
{ w: 4 },
{ w: 1 },
{ w: 2 },
{ w: 1 },
{ w: 3 },
{ w: 2 },
{ w: 1 },
{ w: 1 },
{ w: 2 },
{ w: 4 },
{ w: 1 },
{ w: 2 },
{ w: 1 },
{ w: 3 },
{ w: 1 },
{ w: 1 },
{ w: 2 },
{ w: 3 },
{ w: 1 },
{ w: 2 },
{ w: 1 },
{ w: 4 },
{ w: 1 },
];
export default function TicketScreen() {
return (
<Screen background="#2A1010" statusBar="light">
<View style={{ flex: 1 }}>
<View
style={{
position: 'absolute',
top: 52,
left: 20,
right: 20,
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="link"
accessibilityLabel="Back"
onPress={() => router.navigate('/eventdetail')}
style={{
width: 44,
height: 44,
borderRadius: 22,
backgroundColor: '#4A2323',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2.2"
strokeLinecap="round"
strokeLinejoin="round">
<Path d="M15 5l-7 7 7 7" />
</Svg>
</Pressable>
<Text
style={{
margin: 0,
flexShrink: 1,
fontFamily: 'SourceSans3_700Bold',
fontSize: 18,
color: '#FFFFFF',
}}>
Tickets
</Text>
<Pressable
accessibilityRole="button"
accessibilityLabel="Share ticket"
style={{
width: 44,
height: 44,
borderWidth: 0,
borderRadius: 22,
backgroundColor: '#4A2323',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
flexDirection: 'row',
}}>
<Svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Circle cx="18" cy="5" r="2.5" />
<Circle cx="6" cy="12" r="2.5" />
<Circle cx="18" cy="19" r="2.5" />
<Path d="M8.2 10.8l7.6-4.4M8.2 13.2l7.6 4.4" />
</Svg>
</Pressable>
</View>
<View
style={{
position: 'absolute',
top: 118,
left: 20,
right: 20,
padding: 12,
borderRadius: 30,
backgroundColor: '#4A2323',
gap: 12,
}}>
<Image
source={{ uri: asset('f1133ae529.jpg') }}
contentFit="cover"
contentPosition={{ left: '50%', top: '35%' }}
accessibilityLabel="Illustrated Rowan Vale artwork"
style={{ width: '100%', height: 196, borderRadius: 22 }}
/>
<View
style={{
borderRadius: 22,
backgroundColor: '#FFFFFF',
paddingTop: 22,
paddingBottom: 20,
paddingHorizontal: 22,
gap: 16,
}}>
<View style={{ alignItems: 'center', gap: 4 }}>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 17,
color: '#2A1010',
textAlign: 'center',
}}>
Rowan Vale Concert: Indonesia
</Text>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 17,
color: '#2A1010',
textAlign: 'center',
}}>
29 December 2026
</Text>
</View>
<View style={{ borderTopWidth: 2, borderTopColor: '#D9C6C4', borderStyle: 'dashed' }} />
<View style={{ gap: 14 }}>
<View style={{ flexDirection: 'row', gap: 12 }}>
<View style={{ gap: 3, flex: 1 }}>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 12,
color: '#6E5452',
}}>
Date
</Text>
<Text
style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 14, color: '#2A1010' }}>
Dec 29, 2026
</Text>
</View>
<View style={{ gap: 3, alignItems: 'flex-end', flex: 1 }}>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 12,
color: '#6E5452',
}}>
Time
</Text>
<Text
style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 14, color: '#2A1010' }}>
10:00 PM
</Text>
</View>
</View>
<View style={{ flexDirection: 'row', gap: 12 }}>
<View style={{ gap: 3, flex: 1 }}>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 12,
color: '#6E5452',
}}>
Venue
</Text>
<Text
style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 14, color: '#2A1010' }}>
Gelora Bung Karno
</Text>
</View>
<View style={{ gap: 3, alignItems: 'flex-end', flex: 1 }}>
<Text
style={{
fontFamily: 'SourceSans3_400Regular',
fontSize: 12,
color: '#6E5452',
}}>
Seat
</Text>
<Text
style={{ fontFamily: 'SourceSans3_700Bold', fontSize: 14, color: '#2A1010' }}>
No seat
</Text>
</View>
</View>
</View>
<View style={{ height: 0 }}>
<View
style={{
position: 'absolute',
left: -36,
top: -14,
width: 28,
height: 28,
borderRadius: 14,
backgroundColor: '#4A2323',
zIndex: 1,
}}
/>
<View
style={{
position: 'absolute',
right: -36,
top: -14,
width: 28,
height: 28,
borderRadius: 14,
backgroundColor: '#4A2323',
zIndex: 1,
}}
/>
<View
style={{ borderTopWidth: 2, borderTopColor: '#D9C6C4', borderStyle: 'dashed' }}
/>
</View>
<View
accessibilityRole="image"
accessibilityLabel="Ticket barcode"
style={{
alignItems: 'stretch',
justifyContent: 'center',
gap: 2,
height: 54,
flexDirection: 'row',
}}>
{bars.map((bar, index) => (
<View key={index} style={{ width: bar.w, backgroundColor: '#1A0A0A' }} />
))}
</View>
</View>
</View>
<View
style={{
position: 'absolute',
left: 20,
right: 20,
bottom: 34,
gap: 14,
flexDirection: 'row',
}}>
<Pressable
accessibilityRole="button"
style={{
flexGrow: 1,
flexBasis: 0,
height: 56,
borderWidth: 0,
borderRadius: 28,
backgroundColor: accent,
alignItems: 'center',
justifyContent: 'center',
gap: 8,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#FFFFFF"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Circle cx="12" cy="12" r="9" />
<Path d="M12 7v8M8.5 11.5L12 15l3.5-3.5" />
</Svg>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#FFFFFF',
flexShrink: 1,
}}>
Image
</Text>
</Pressable>
<Pressable
accessibilityRole="button"
style={{
flexGrow: 1,
flexBasis: 0,
height: 56,
borderWidth: 0,
borderRadius: 28,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
gap: 8,
flexDirection: 'row',
}}>
<Svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#2A1010"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round">
<Rect x="3" y="3" width="7" height="7" rx="1" />
<Rect x="14" y="3" width="7" height="7" rx="1" />
<Rect x="3" y="14" width="7" height="7" rx="1" />
<Path d="M14 14h3v3h-3zM20 14v.01M14 20h.01M17 20h4v-3" />
</Svg>
<Text
style={{
fontFamily: 'SourceSans3_700Bold',
fontSize: 16,
color: '#2A1010',
flexShrink: 1,
}}>
QR Code
</Text>
</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 wide artboard, then scaled to the device width.
const ARTBOARD_WIDTH = 390;
type Props = {
background: string;
statusBar: 'light' | 'dark';
height?: number;
children: ReactNode;
};
export function Screen({ background, statusBar, height: artboardHeight = 844, 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(artboardHeight * scale, height) }}>
<StatusBar style={statusBar} />
<View
style={{
width: ARTBOARD_WIDTH,
height: artboardHeight,
overflow: 'hidden',
transformOrigin: 'left top',
transform: [{ scale }],
}}>
{children}
</View>
</ScrollView>
);
}src/lib/assets.ts
// Demo images are hosted by DeveloperMill. Point this at your own CDN, or swap to require().
const ASSET_BASE = 'https://developermill.com/app-designs/event-booking-app-ui-design/assets';
export const asset = (name: string) => `${ASSET_BASE}/${name}`;About this design
The perforated ticket card is the most reusable part. It gives any booking flow a tangible finish, and the dark wine theme keeps the attention on the event photography, for concerts, conferences or festivals.
Deep wine pages with coral actions, full-width concert photos and a white perforated ticket as the final reward.
- Category filters for feed, food and concerts
- Event cards with a date badge and price
- Concert detail with a sticky ticket action
- Perforated digital ticket with barcode
Colour palette
Wine
#2A1010
Plum brown
#4A2323
Coral
#F2545B
Tangerine
#FF7A45
Blush
#FFD9D9
Rose grey
#E9D3D1
How to use this design
- 01
Pick what to copy
Copy the Cine Ring Events 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
Is the barcode real?
It is a drawn placeholder. Replace it with a barcode or QR library and pass in the booking code from your backend.
How are the ticket notches made?
They are small circles in the page colour placed on the card edges, so the ticket looks punched out without any masking.
Can it handle conferences or sports events?
Yes. The screens use a title, date, venue, price and image, which cover most event types.
Is the Cine Ring Events 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.



