<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/dressed-to-ship-92hm4j7cw" -->

---
title: Dressed to Ship | daily.dev
description: Step 02 of a 'Zero to Shipped' series focused on building a fully themed React Native/Expo app shell with no features — just a consistent design system. The...
canonical: https://daily.dev/posts/dressed-to-ship-92hm4j7cw
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Dressed to Ship | daily.dev
og:description: Step 02 of a 'Zero to Shipped' series focused on building a fully themed React Native/Expo app shell with no features — just a consistent design system. The...
og:url: https://daily.dev/posts/dressed-to-ship-92hm4j7cw
og:image: https://api.daily.dev/og/posts/92HM4j7cw.png
og:image:alt: Dressed to Ship
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Dressed to Ship

**[Medium](https://daily.dev/sources/medium_js)** · 7 min read · 0 upvotes · 0 comments

## Summary

Step 02 of a 'Zero to Shipped' series focused on building a fully themed React Native/Expo app shell with no features — just a consistent design system. The post covers design tokens (colors, typography, shadows, radii), a data-driven tab bar config, shared chrome components (floating header, glass pill tab bar), and an audit gate that enforces no dead code. Key lessons include keeping tokens minimal and adding them only when needed, avoiding speculative code, and structuring the app so renaming or restructuring requires editing only config files. Practical gotchas around Metro port conflicts, Watchman, Expo SDK pinning, and physical device networking are also covered.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@srivardhanjalan/dressed-to-ship-1e2591179d8a>

## Questions this post answers

### How do I stop a Watchman daemon from hanging Metro bundler at 'Waiting for Watchman'?

Disable Watchman entirely and let Metro use Node's built-in file watcher instead by setting useWatchman: false in metro.config.js. On small to medium projects, Watchman adds no meaningful speed benefit, but a stale Watchman daemon can hang Metro indefinitely at the 'Waiting for Watchman' step, so removing the dependency eliminates that failure mode with a single config line.

_daily.dev surfaces practical Metro and Expo fixes for developers hardening their React Native build setup._

### Why does React Navigation v7 require an explicit id prop on the navigator even when I don't need one?

React Navigation v7's TypeScript types require an explicit id even when there's no functional need for one, so passing id={undefined} on the navigator is the correct, deliberate workaround rather than an error to fix. Developers upgrading to v7 should expect this typing requirement and leave the undefined value in place.

_developers migrating to react navigation v7 track typing quirks like this one on daily.dev._

## Similar posts on daily.dev

- [Building balanced mobile layouts: nesting tabs and drawers with Expo Router](https://daily.dev/posts/building-balanced-mobile-layouts-nesting-tabs-and-drawers-with-expo-router-rtwziriwn) · Expo Blog · 8 upvotes · 1 comments
- [Working With the React Native Super App Showcase Repository](https://daily.dev/posts/working-with-the-react-native-super-app-showcase-repository-5ciobo8b6) · Callstack Blog · 0 upvotes · 0 comments
- [Making React Native actually native](https://daily.dev/posts/making-react-native-actually-native-bdan1xdzt) · Bytes by ui.dev · 2 upvotes · 0 comments

---

Tags: [#mobile](https://daily.dev/tags/mobile), [#typescript](https://daily.dev/tags/typescript), [#ui-design](https://daily.dev/tags/ui-design), [#react-native](https://daily.dev/tags/react-native)

[View this post on daily.dev](https://daily.dev/posts/dressed-to-ship-92hm4j7cw)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Dressed to Ship","url":"https://daily.dev/posts/dressed-to-ship-92hm4j7cw","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/dressed-to-ship-92hm4j7cw"},"datePublished":"2026-07-19T04:37:08.567Z","dateModified":"2026-09-14T08:56:50.981Z","description":"Step 02 of a 'Zero to Shipped' series focused on building a fully themed React Native/Expo app shell with no features — just a consistent design system. The...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/34c671a21b60f2d8bf3e0c27e40d1030?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/34c671a21b60f2d8bf3e0c27e40d1030?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/dressed-to-ship-92hm4j7cw","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"mobile,typescript,ui-design,react-native","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"Dressed to Ship"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/dressed-to-ship-92hm4j7cw#faq","mainEntity":[{"@type":"Question","name":"How do I stop a Watchman daemon from hanging Metro bundler at 'Waiting for Watchman'?","acceptedAnswer":{"@type":"Answer","text":"Disable Watchman entirely and let Metro use Node's built-in file watcher instead by setting useWatchman: false in metro.config.js. On small to medium projects, Watchman adds no meaningful speed benefit, but a stale Watchman daemon can hang Metro indefinitely at the 'Waiting for Watchman' step, so removing the dependency eliminates that failure mode with a single config line. daily.dev surfaces practical Metro and Expo fixes for developers hardening their React Native build setup."}},{"@type":"Question","name":"Why does React Navigation v7 require an explicit id prop on the navigator even when I don't need one?","acceptedAnswer":{"@type":"Answer","text":"React Navigation v7's TypeScript types require an explicit id even when there's no functional need for one, so passing id={undefined} on the navigator is the correct, deliberate workaround rather than an error to fix. Developers upgrading to v7 should expect this typing requirement and leave the undefined value in place. developers migrating to react navigation v7 track typing quirks like this one on daily.dev."}}]}
```

