react-native-template-santis-world
v1.0.4
Published
Quick starter template
Maintainers
Readme
React Native Template
A React Native CLI starter with theming, navigation, and a design system baked in — structured so you can build on it immediately or strip out what you don't need.
Usage
npx @react-native-community/cli@latest init MyNewApp --template react-native-template-santis-worldGetting Started
yarn install
yarn ios
yarn androidpod installation:
yarn podStack
- Navigation:
@react-navigation/native-stack— native-backed transitions viareact-native-screens - Screen transitions:
react-native-screen-transitionsfor source-to-destination zoom transitions (e.g. list → detail) - Data fetching: TanStack Query, with query cache persistence to disk (see Data Fetching)
- Lists:
@shopify/flash-listin place ofFlatListfor large/virtualized lists - Local persistence:
react-native-mmkv - Icons:
lucide-react-native— SVG-based, no font linking required - Animation:
react-native-reanimated
design-system/
Everything visual and theme-related lives here, kept isolated so it can be lifted into another project as a single unit if needed:
design-system/
components/ Button, Text, ScreenWrapper, Shimmer, ThemeToggle, and other themed primitives
hooks/ useThemeMode, useColorScheme
interfaces/ ColorScheme and other theming types
theme/ Theme definitions (light/dark)Theming
Theme preference (light / dark / system) is stored via react-native-mmkv and resolved against the device's color scheme using useThemeMode(). There's no separate state library involved — MMKV's reactive hooks (useMMKVString) handle both persistence and re-rendering on change.
const { theme, statusBarStyle, setThemePreference } = useThemeMode()theme— the resolved theme object (light/dark colors)statusBarStyle—'light-content' | 'dark-content', derived from the resolved themesetThemePreference('light' | 'dark' | 'system')— override the user's preference
StatusBar is set once at the root of the navigation tree, not per-screen, so it stays consistent across auth and app flows without flicker. On Android, remember backgroundColor and translucent are separate props from barStyle — both need to be set explicitly to match your theme.
Splash Screen
The splash screen (logo + footer wordmark) is fully rebrandable without touching native code directly.
Replace the placeholder images (keep the exact filenames — the sync script looks for these names specifically) in
splash-templates/:splash_logo.png— your square center logo (ideal: 350×350px)splash_footer.png— your horizontal bottom wordmark (ideal: 400×300px)
Run the sync script from your project root:
yarn splash:syncThis copies your images into the correct Android
drawable-nodpifolder and iOSImages.xcassetsimagesets automatically, regenerating the iOSContents.jsonmanifests for you.Rebuild the app so the native bundle picks up the new assets:
yarn ios yarn androidA Metro/JS reload alone won't show the change — splash assets are compiled into the native build.
Data Fetching
TanStack Query handles fetching and caching. The query cache is persisted to MMKV via experimental_createQueryPersister, so cached data survives app restarts instead of refetching from scratch every cold start.
const { data, isLoading, isError, error, refetch, isRefetching } = useComments()Loading states use design-system/components/Shimmer for skeleton placeholders shaped to match the real content layout, rather than a generic spinner.
Examples
The examples/ folder is a self-contained demonstration of the stack: fetching data with TanStack Query from a free dummy API, rendering it in a FlashList with skeleton loading states, animated list-to-detail zoom transitions, and pull-to-refresh — all using the design system's components.
It's built to be removed in three steps:
- Delete the
src/examples/folder. - Remove its import and route from
navigation/RootStackScreen.tsx. - Done — nothing else in the app depends on it.
examples/ is a one-way dependency: it imports from design-system/, hooks/, and services/, but nothing outside examples/ imports from it. That's what makes deleting it safe.
Navigation Transitions
Beyond native-stack's default transitions, react-native-screen-transitions provides a navigation.zoom() helper for a source-to-destination zoom effect (see examples/ for a working list → detail implementation). This is a separate concern from Reanimated's own experimental shared-element transitions, which are not used here due to stability issues on the current Reanimated version.
Safe Areas
SafeAreaProvider wraps the app once at the root. Individual screens use the ScreenWrapper component (design-system/components/ScreenWrapper) rather than wrapping the whole navigator in a single SafeAreaView — this avoids double-applying insets, since native-stack already handles header insets natively per screen.
Image Assets
Bundled local images should be resized to roughly the largest size they'll actually render at before adding them to assets/ — an oversized source image (e.g. a multi-thousand-pixel photo) forces a larger decode at render time, which can cause visible stutter during animated transitions. mogrify (ImageMagick) or a sharp script are both reasonable ways to batch-resize before committing images to the repo.
💡 Contributing
Feel free to open issues and pull requests! Contributions are welcome.
📜 License
This project is licensed under the MIT License.
(iOS tooling in the React Native ecosystem is actively changing — check the React Native docs for the current recommended command for your version.)
