// Lifestyle app UI

Dog Care App UI Design in Expo

Dog Assistant is a bright, neo-brutalist pet app UI for owners who want to track their dog and meet other owners at local events.

Screens
3
Built with
Expo SDK 58
Fonts
Outfit
License
Free (MIT)
Dog events screen with event cards and dog photos

Dog Assistant app screens

Dog app welcome screen with a pug in a sweater on coral shapes

Welcome

A cut-out pug on coral blobs, a big title, a loose hand-drawn squiggle with sparkles and a Let's go button.

Dog events screen with event cards and dog photos

Events

An outdoor events card with a jumping dog, a photo card with a sticker badge and Join action, and an outlined tab bar.

Dog tracking screen with an aerial map, route and transport options

Dog tracking

An aerial map with a live route and pins, zoom controls, distance to the dog and transport times.

Copy the Dog Assistant 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

# Dog Assistant: design artifact

Dog Assistant is a bright, neo-brutalist pet app UI for owners who want to track their dog and meet other owners at local events.

- Type: Lifestyle 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/dog-assistant-app-ui-design

## Design direction

Playful neo-brutalism with thick black outlines, hard shadows, lime and coral colour blocking and cut-out dog photography.

- Neo-brutalist outlines and hard shadows
- Map tracking with a live route and pins
- Event cards with cut-out photography
- Transport options with travel times

## Foundations

### Colour

| Token | Hex |
| --- | --- |
| Pale lime | `#EEF7BC` |
| Neon lime | `#C8F25A` |
| Coral | `#F26B5B` |
| Pine | `#1F4A35` |
| Outline | `#141413` |
| Sky | `#9FC7E6` |

### Typography

- Typefaces: Outfit
- Common sizes (px): 13, 15, 16, 17, 24, 26, 30, 48

### Shape and depth

- Common corner radii (px): 3, 22, 24, 26, 28, 32
- Shadows: `0 4px 0 #141413`, `0 3px 0 #141413`

## Screens

### 1. Welcome

A cut-out pug on coral blobs, a big title, a loose hand-drawn squiggle with sparkles and a Let's go button.

Preview: https://developermill.com/app-designs/dog-assistant-app-ui-design/welcome.webp

Copy on this screen:

- Dog
- Assistant
- Helping owners track their dogs and organise events to meet up for networking
- Let’s go

### 2. Events

An outdoor events card with a jumping dog, a photo card with a sticker badge and Join action, and an outlined tab bar.

Preview: https://developermill.com/app-designs/dog-assistant-app-ui-design/events.webp

Copy on this screen:

- Events
- What is new?
- Outdoor
- events
- Perfect chance to enrich your social circle
- How does
- your dog
- feel?
- New
- event!
- Join

### 3. Dog tracking

An aerial map with a live route and pins, zoom controls, distance to the dog and transport times.

Preview: https://developermill.com/app-designs/dog-assistant-app-ui-design/tracking.webp

Copy on this screen:

- Dog tracking
- Spike
- Downing St, 794
- 3.7 km
- Transports
- Wrap
- Find others
- Create event

## 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>Dog Assistant — Welcome</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=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1F4A35}a:hover{color:#14301f}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: {{ground}}; font-family: 'Outfit', system-ui, sans-serif; color: #141413; position: relative; overflow: hidden; display: flex; flex-direction: column; padding: 64px 24px 36px">
<div style="position: relative; height: 330px; margin: 0 -8px">
<svg viewBox="0 0 360 330" width="360" height="330" aria-hidden="true" style="position: absolute; left: 0; top: 0">
<g transform="rotate(-8 180 165)">
<ellipse cx="185" cy="98" rx="150" ry="62" fill="{{accent}}" stroke="#141413" stroke-width="3"></ellipse>
<ellipse cx="175" cy="170" rx="160" ry="66" fill="{{accent}}" stroke="#141413" stroke-width="3"></ellipse>
<ellipse cx="185" cy="242" rx="150" ry="62" fill="{{accent}}" stroke="#141413" stroke-width="3"></ellipse>
</g>
</svg>
<img src="https://developermill.com/app-designs/dog-assistant-app-ui-design/assets/53dc736f77.webp" alt="Black pug in a grey knitted sweater" style="position: absolute; left: 50px; top: 0px; width: 262px; height: 312px; object-fit: contain; filter: grayscale(1) contrast(1.08)"></div>
<div style="display: flex; flex-direction: column; gap: 14px; margin-top: 18px">
<h1 style="margin: 0; font-size: 48px; line-height: 1.02; font-weight: 700; letter-spacing: -1.5px">Dog<br>Assistant</h1>
<p style="margin: 0; font-size: 15px; line-height: 1.4; color: #2E3A22; max-width: 260px">Helping owners track their dogs and organise events to meet up for networking</p>
</div>
<div style="flex: 1; position: relative">
<svg viewBox="0 0 340 150" width="340" height="150" aria-hidden="true" style="position: absolute; left: 0; top: 4px">
<path d="M40 10 c-30 30 30 50 0 80 c-20 20 -10 35 10 45" fill="none" stroke="#141413" stroke-width="2.5" stroke-linecap="round"></path>
<path d="M44 128 l8 9 l-12 2" fill="none" stroke="#141413" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M215 70 l5 13 l13 5 l-13 5 l-5 13 l-5 -13 l-13 -5 l13 -5 Z" fill="#1F4A35"></path>
<path d="M300 40 l7 18 l18 7 l-18 7 l-7 18 l-7 -18 l-18 -7 l18 -7 Z" fill="{{accent}}"></path>
<path d="M260 20 l3 8 l8 3 l-8 3 l-3 8 l-3 -8 l-8 -3 l8 -3 Z" fill="#B7D94A"></path>
<path d="M190 112 l2 6 l6 2 l-6 2 l-2 6 l-2 -6 l-6 -2 l6 -2 Z" fill="{{accent}}"></path>
<path d="M250 118 l2 5 l5 2 l-5 2 l-2 5 l-2 -5 l-5 -2 l5 -2 Z" fill="#1F4A35"></path>
</svg>
</div>
<a href="Events.dc.html" style="display: flex; align-items: center; justify-content: center; height: 56px; border-radius: 28px; background: #1F4A35; color: #F4FBD8; font-size: 17px; font-weight: 500; text-decoration: none; border: 2.5px solid #141413; box-shadow: 0 4px 0 #141413">Let’s go</a>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F26B5B","options":["#F26B5B","#FF9F43","#7C6CF2","#3BA7F2"]},"ground":{"editor":"color","default":"#EEF7BC","options":["#EEF7BC","#FFF4E0","#E8F0FF"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
  renderVals() {
    return { accent: this.props.accent ?? '#F26B5B', ground: this.props.ground ?? '#EEF7BC' };
  }
}
</script>
</body>
</html>
```

### Events

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dog Assistant — 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=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1F4A35}a:hover{color:#14301f}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EEF7BC; font-family: 'Outfit', system-ui, sans-serif; color: #141413; position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 16px; padding: 60px 20px 28px">
<div style="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: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; box-sizing: border-box">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"></path></svg>
</a>
<div style="font-size: 17px; font-weight: 600">Events</div>
<button type="button" aria-label="Settings" style="width: 44px; height: 44px; border-radius: 22px; background: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"></path></svg>
</button>
</div>

<div style="display: flex; align-items: center; justify-content: space-between; margin-top: 6px">
<h1 style="margin: 0; font-size: 30px; font-weight: 600; letter-spacing: -0.5px">What is new?</h1>
<svg width="40" height="40" viewBox="0 0 40 40" aria-hidden="true"><path d="M8 32 c10 -2 4 -16 14 -20 c6 -2 10 4 10 -6" fill="none" stroke="#F26B5B" stroke-width="2.5" stroke-linecap="round"></path></svg>
</div>

<div style="position: relative; height: 196px; border-radius: 26px; background: #1F4A35; border: 2.5px solid #141413; box-shadow: 0 4px 0 #141413; padding: 20px; box-sizing: border-box; color: #F4FBD8; overflow: visible">
<div style="font-size: 24px; font-weight: 500; line-height: 1.1">Outdoor<br>events</div>
<p style="margin: 10px 0 0; font-size: 13px; line-height: 1.35; color: #C9DDB5; max-width: 150px">Perfect chance to enrich your social circle</p>
<div style="position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); display: flex; gap: 6px">
<span style="width: 18px; height: 6px; border-radius: 3px; background: #F26B5B"></span>
<span style="width: 6px; height: 6px; border-radius: 3px; background: #F4FBD8"></span>
<span style="width: 6px; height: 6px; border-radius: 3px; background: #F4FBD8"></span>
<span style="width: 6px; height: 6px; border-radius: 3px; background: #F4FBD8"></span>
</div>
<svg viewBox="0 0 80 40" width="80" height="40" aria-hidden="true" style="position: absolute; right: 96px; top: -14px"><ellipse cx="40" cy="20" rx="30" ry="11" fill="#F26B5B" stroke="#141413" stroke-width="2.5" transform="rotate(-14 40 20)"></ellipse></svg>
<img src="https://developermill.com/app-designs/dog-assistant-app-ui-design/assets/05d181ed31.webp" alt="Happy terrier leaping through the air" style="position: absolute; right: -22px; top: 6px; width: 200px; height: 152px; object-fit: contain; transform: rotate(-12deg)"><svg viewBox="0 0 20 20" width="20" height="20" aria-hidden="true" style="position: absolute; right: 18px; top: 8px"><path d="M10 0 l3 7 l7 3 l-7 3 l-3 7 l-3 -7 l-7 -3 l7 -3 Z" fill="#C8F25A"></path></svg>
</div>

<div style="position: relative; flex: 1; border-radius: 26px; background: #9FC7E6; border: 2.5px solid #141413; box-shadow: 0 4px 0 #141413; overflow: hidden; padding: 20px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between">
<img src="https://developermill.com/app-designs/dog-assistant-app-ui-design/assets/217fada78a.webp" alt="Cocker spaniel with ears flying, head out of a car window" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; object-position: 70% 30%"><div style="position: relative; font-size: 24px; font-weight: 500; line-height: 1.1; color: #141413">How does<br>your dog<br>feel?</div>
<div style="position: absolute; right: 18px; top: 16px; width: 70px; height: 70px">
<svg viewBox="0 0 70 70" width="70" height="70" aria-hidden="true" style="position: absolute; left: 0; top: 0"><path d="M35 2 l7 10 l12 -4 l1 12 l12 3 l-6 11 l8 9 l-11 5 l1 12 l-12 -1 l-5 11 l-9 -8 l-9 8 l-5 -11 l-12 1 l1 -12 l-11 -5 l8 -9 l-6 -11 l12 -3 l1 -12 l12 4 Z" fill="#F26B5B" stroke="#141413" stroke-width="2"></path></svg>
<div style="position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 11px; font-weight: 600; line-height: 1.1; transform: rotate(-12deg); color: #141413">New<br>event!</div>
</div>
<div style="position: relative; display: flex; align-items: center; justify-content: space-between">
<button type="button" style="width: 140px; height: 48px; border-radius: 24px; background: #C8F25A; border: 2.5px solid #141413; font-family: inherit; font-size: 16px; font-weight: 500; color: #141413; cursor: pointer">Join</button>
<button type="button" aria-label="Open event" style="width: 44px; height: 44px; border-radius: 22px; background: #1F4A35; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#F4FBD8" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17L17 7M8 7h9v9"></path></svg>
</button>
</div>
</div>

<nav aria-label="Main" style="height: 64px; border-radius: 32px; background: #F26B5B; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: space-around; box-sizing: border-box">
<a href="Events.dc.html" aria-label="Home" style="width: 44px; height: 44px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="#141413" aria-hidden="true"><path d="M3 11l9-7 9 7v9a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"></path></svg></a>
<a href="Events.dc.html" aria-label="Weather" style="width: 44px; height: 44px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M7 18h10a4 4 0 0 0 0-8 6 6 0 0 0-11.5 1.5A3.3 3.3 0 0 0 7 18z"></path></svg></a>
<a href="Tracking.dc.html" aria-label="Tracking" style="width: 44px; height: 44px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21s7-6.2 7-12a7 7 0 0 0-14 0c0 5.8 7 12 7 12z"></path><circle cx="12" cy="9" r="2.5"></circle></svg></a>
<a href="Main.dc.html" aria-label="Profile" style="width: 44px; height: 44px; display: flex; align-items: center; justify-content: center"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="8" r="4"></circle><path d="M4 21c1.5-4 4.5-6 8-6s6.5 2 8 6"></path></svg></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() { return {}; }
}
</script>
</body>
</html>
```

### Tracking

```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dog Assistant — Tracking</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=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet">
<style>
body{margin:0}
a{color:#1F4A35}a:hover{color:#14301f}
</style>
</helmet>
<div style="width: 390px; height: 844px; box-sizing: border-box; background: #EEF7BC; font-family: 'Outfit', system-ui, sans-serif; color: #141413; position: relative; overflow: hidden">

<div style="position: absolute; left: 0; top: 0; width: 390px; height: 470px; background: #6E7F5C">
<img src="https://developermill.com/app-designs/dog-assistant-app-ui-design/assets/5306f632e1.webp" alt="Aerial map of the neighbourhood around Spike" style="position: absolute; left: 0; top: -40px; width: 390px; height: 585px; object-fit: cover"><div style="position: absolute; left: 0; top: 0; width: 390px; height: 130px; background: linear-gradient(rgba(0,0,0,0.35), rgba(0,0,0,0))"></div>
<svg viewBox="0 0 390 470" width="390" height="470" aria-hidden="true" style="position: absolute; left: 0; top: 0">
<path d="M58 290 C110 270 130 230 170 236 C210 242 220 200 250 166" fill="none" stroke="#141413" stroke-width="7" stroke-linecap="round" opacity="0.5"></path>
<path d="M58 290 C110 270 130 230 170 236 C210 242 220 200 250 166" fill="none" stroke="#C8F25A" stroke-width="4" stroke-linecap="round"></path>
</svg>

<div style="position: absolute; left: 30px; top: 252px; width: 54px; height: 66px">
<svg viewBox="0 0 54 66" width="54" height="66" aria-hidden="true"><ellipse cx="27" cy="60" rx="14" ry="5" fill="#141413" opacity="0.35"></ellipse><path d="M27 58 L18 44 A20 20 0 1 1 36 44 Z" fill="#F4FBD8" stroke="#141413" stroke-width="2.5"></path><circle cx="27" cy="27" r="14" fill="#D9934D"></circle><circle cx="22" cy="25" r="2" fill="#141413"></circle><circle cx="32" cy="25" r="2" fill="#141413"></circle><ellipse cx="27" cy="31" rx="3" ry="2" fill="#141413"></ellipse></svg>
</div>
<div style="position: absolute; left: 224px; top: 120px; width: 54px; height: 66px">
<svg viewBox="0 0 54 66" width="54" height="66" aria-hidden="true"><ellipse cx="27" cy="60" rx="14" ry="5" fill="#141413" opacity="0.35"></ellipse><path d="M27 58 L18 44 A20 20 0 1 1 36 44 Z" fill="#F26B5B" stroke="#141413" stroke-width="2.5"></path><circle cx="27" cy="27" r="14" fill="#F4FBD8"></circle><circle cx="27" cy="23" r="5" fill="#1F4A35"></circle><path d="M18 36 a9 7 0 0 1 18 0" fill="#1F4A35"></path></svg>
</div>
</div>

<div style="position: absolute; left: 20px; right: 20px; top: 60px; display: flex; align-items: center; justify-content: space-between">
<a href="Events.dc.html" aria-label="Back" style="width: 44px; height: 44px; border-radius: 22px; background: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; box-sizing: border-box">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"></path></svg>
</a>
<div style="font-size: 17px; font-weight: 600; color: #FFFFFF; text-shadow: 0 1px 4px rgba(0,0,0,0.5)">Dog tracking</div>
<button type="button" aria-label="Settings" style="width: 44px; height: 44px; border-radius: 22px; background: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="3"></circle><path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M4.9 19.1L7 17M17 7l2.1-2.1"></path></svg>
</button>
</div>

<div style="position: absolute; right: 20px; top: 270px; display: flex; flex-direction: column; gap: 10px">
<button type="button" aria-label="Zoom in" style="width: 44px; height: 44px; border-radius: 22px; background: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.6" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"></path></svg></button>
<button type="button" aria-label="Zoom out" style="width: 44px; height: 44px; border-radius: 22px; background: #C8F25A; border: 2.5px solid #141413; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2.6" stroke-linecap="round" aria-hidden="true"><path d="M5 12h14"></path></svg></button>
</div>

<div style="position: absolute; left: 12px; right: 12px; top: 438px; bottom: 24px; display: flex; flex-direction: column; gap: 0">
<div style="background: #EEF7BC; border: 2.5px solid #141413; border-radius: 26px 26px 0 0; border-bottom: none; padding: 16px 18px; display: flex; align-items: center; gap: 12px">
<div style="width: 44px; height: 44px; border-radius: 22px; background: #F26B5B; border: 2px solid #141413; display: flex; align-items: center; justify-content: center; box-sizing: border-box">
<svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><circle cx="15" cy="16" r="10" fill="#D9934D"></circle><path d="M6 10 C2 12 3 20 7 22 L9 14 Z M24 10 C28 12 27 20 23 22 L21 14 Z" fill="#A9652A"></path><circle cx="12" cy="15" r="1.6" fill="#141413"></circle><circle cx="18" cy="15" r="1.6" fill="#141413"></circle><ellipse cx="15" cy="19" rx="2.2" ry="1.6" fill="#141413"></ellipse></svg>
</div>
<div style="flex: 1; display: flex; flex-direction: column; gap: 2px">
<div style="font-size: 16px; font-weight: 600">Spike</div>
<div style="font-size: 13px; color: #4A5638">Downing St, 794</div>
</div>
<div style="font-size: 26px; font-weight: 600; letter-spacing: -0.5px">3.7 km</div>
</div>

<div style="flex: 1; background: {{accent}}; border: 2.5px solid #141413; border-radius: 26px; padding: 18px; display: flex; flex-direction: column; gap: 18px; box-shadow: 0 4px 0 #141413; margin-top: -10px">
<div style="display: flex; align-items: center; justify-content: space-between">
<h2 style="margin: 0; font-size: 26px; font-weight: 500; color: #FFFFFF">Transports</h2>
<button type="button" style="background: none; border: none; font-family: inherit; font-size: 13px; color: #FFFFFF; cursor: pointer; min-height: 44px; padding: 0 4px">Wrap</button>
</div>
<div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px">
<sc-for list="{{modes}}" as="m" hint-placeholder-count="4">
<button type="button" aria-label="{{m.label}}" style="background: none; border: none; padding: 0; font-family: inherit; display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer">
<span style="width: 58px; height: 58px; border-radius: 29px; background: #FFFFFF; border: 2.5px solid #141413; box-shadow: 0 3px 0 #141413; display: flex; align-items: center; justify-content: center">
<sc-if value="{{m.car}}" hint-placeholder-val="{{ false }}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 16V11l2-5h10l2 5v5"></path><rect x="3" y="11" width="18" height="6" rx="2"></rect><circle cx="7.5" cy="14" r="1"></circle><circle cx="16.5" cy="14" r="1"></circle><path d="M6 17v2M18 17v2"></path></svg></sc-if>
<sc-if value="{{m.bus}}" hint-placeholder-val="{{ false }}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="3" width="14" height="15" rx="3"></rect><path d="M5 11h14M8 18v2M16 18v2"></path><circle cx="8.5" cy="14.5" r="1"></circle><circle cx="15.5" cy="14.5" r="1"></circle></svg></sc-if>
<sc-if value="{{m.bike}}" hint-placeholder-val="{{ false }}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="6" cy="16" r="3.5"></circle><circle cx="18" cy="16" r="3.5"></circle><path d="M6 16l4-8h5l3 8M10 8l3 8h-7M14 5h2"></path></svg></sc-if>
<sc-if value="{{m.walk}}" hint-placeholder-val="{{ false }}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#141413" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="13" cy="4" r="2"></circle><path d="M9 21l2-6 3 3v3M11 15l1-6 3 3 3 1M12 9l-4 2-1 4"></path></svg></sc-if>
</span>
<span style="font-size: 12px; color: #FFFFFF">{{m.time}}</span>
</button>
</sc-for>
</div>
<div style="flex: 1"></div>
<div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px">
<button type="button" style="height: 52px; border-radius: 26px; background: #C8F25A; border: 2.5px solid #141413; font-family: inherit; font-size: 16px; font-weight: 500; color: #141413; cursor: pointer">Find others</button>
<button type="button" style="height: 52px; border-radius: 26px; background: #1F4A35; border: 2.5px solid #141413; font-family: inherit; font-size: 16px; font-weight: 500; color: #F4FBD8; cursor: pointer">Create event</button>
</div>
</div>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#E85A4A","options":["#E85A4A","#FF9F43","#7C6CF2","#3BA7F2"]},"$preview":{"width":390,"height":844}}'>
class Component extends DCLogic {
  renderVals() {
    return {
      accent: this.props.accent ?? '#E85A4A',
      modes: [
        { label: 'Car', time: '15 min', car: true },
        { label: 'Bus', time: '25 min', bus: true },
        { label: 'Bike', time: '40 min', bike: true },
        { label: 'Walk', time: '1 h', walk: true }
      ]
    };
  }
}
</script>
</body>
</html>
```

SKILL.md

Save as .claude/skills/dog-assistant-app-ui/SKILL.md

---
name: dog-assistant-app-ui
description: Build the Dog Assistant mobile app UI in Expo React Native. Use when asked to create a dog app UI or a new screen in this visual style.
---

# Dog Assistant 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/dog-assistant-app-ui-design

## Visual direction

Playful neo-brutalism with thick black outlines, hard shadows, lime and coral colour blocking and cut-out dog photography.

Keep these signature details:

- Neo-brutalist outlines and hard shadows
- Map tracking with a live route and pins
- Event cards with cut-out photography
- Transport options with travel times

## Set up

```bash
npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/outfit expo-font
```

## Tokens

| Token | Hex |
| --- | --- |
| Pale lime | `#EEF7BC` |
| Neon lime | `#C8F25A` |
| Coral | `#F26B5B` |
| Pine | `#1F4A35` |
| Outline | `#141413` |
| Sky | `#9FC7E6` |

- Typefaces: Outfit
- Common sizes (px): 13, 15, 16, 17, 24, 26, 30, 48
- Common corner radii (px): 3, 22, 24, 26, 28, 32

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

## Screens

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

1. **Welcome**: A cut-out pug on coral blobs, a big title, a loose hand-drawn squiggle with sparkles and a Let's go button.
2. **Events**: An outdoor events card with a jumping dog, a photo card with a sticker badge and Join action, and an outlined tab bar.
3. **Dog tracking**: An aerial map with a live route and pins, zoom controls, distance to the dog and transport times.

## 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 dog-assistant-app --template default
cd dog-assistant-app
rm -rf src
npx expo install expo-image expo-linear-gradient react-native-svg @expo-google-fonts/outfit expo-font

src/app/_layout.tsx

import {
  Outfit_400Regular,
  Outfit_500Medium,
  Outfit_600SemiBold,
  Outfit_700Bold,
} from '@expo-google-fonts/outfit';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';

export default function RootLayout() {
  const [fontsLoaded] = useFonts({
    Outfit_400Regular,
    Outfit_500Medium,
    Outfit_600SemiBold,
    Outfit_700Bold,
  });

  if (!fontsLoaded) return null;

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

About this design

Thick outlines and hard shadows give it plenty of character, and the tracking screen pairs a live route on a map with arrival times for each way of getting there.

Playful neo-brutalism with thick black outlines, hard shadows, lime and coral colour blocking and cut-out dog photography.

  • Neo-brutalist outlines and hard shadows
  • Map tracking with a live route and pins
  • Event cards with cut-out photography
  • Transport options with travel times

Colour palette

  • Pale lime

    #EEF7BC

  • Neon lime

    #C8F25A

  • Coral

    #F26B5B

  • Pine

    #1F4A35

  • Outline

    #141413

  • Sky

    #9FC7E6

How to use this design

  1. 01

    Pick what to copy

    Copy the Dog Assistant artifact, skill or code from this page.

  2. 02

    Run it or generate it

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

  3. 03

    Make it yours

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

Frequently asked questions

Is the tracking map live?

The map is a static image with an SVG route, so the screen works without API keys. Swap it for react-native-maps when you connect real location data.

Is the Dog Assistant design free to use?

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

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

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

Which Expo version does the code use?

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

More app UI designs