File: README.md
TheCodingMachine React Native boilerplate
This project is a React Native boilerplate that can be used to kickstart a mobile application.
The boilerplate provides an optimized architecture for building solid cross-platform mobile applications through separation of concerns between the UI and business logic. It is fully documented so that each piece of code that lands in your application can be understood and used.
If you love this boilerplate, give us a star, you will be a ray of sunshine in our lives :)Requirements
Node 18 or greater is required. Development for iOS requires a Mac and Xcode 10 or up, and will target iOS 11 and up.
You also need to install the dependencies required by React Native.
Go to the React Native environment setup, then select React Native CLI Quickstart tab.
Follow instructions for your given development OS and target OS.
Quick start
To create a new project using the boilerplate simply run :
npx @react-native-community/cli@latest init MyApp --template @thecodingmachine/react-native-boilerplateAssuming you have all the requirements installed, you can run the project by running:
yarn startto start the metro bundler, in a dedicated terminalyarnto run the platform application (remember to start a simulator or connect a device)
Digging Deeper
To learn more about this boilerplate, go to full documentation
License
This project is released under the MIT License.
About us
TheCodingMachine is a web and mobile agency based in Paris and Lyon, France. We are constantly looking for new developers and team leaders and we love working with freelancers. You'll find an overview of all our open source projects on our website and on Github.
File: documentation/blog/2020-04-19-React-Native-Boilerplate-3.0.0.md
title: React Native Boilerplate 3.0.0 authors: jed hide_table_of_contents: false tags: [boilerplate, starter-kit, starter, kit, react, native, react-native, javascript, typescript]
Welcome aboard! ๐ฅ๏ธ
As we have active users that uses this boilerplate, we will try to improve communication about updates
we're releasing. It's important for us to give you new reasons to try this boilerplate out!
We would love to have new ideas to make it even more convenient!
To do so, we will post a changelog every major updates. Unlike the changelog in the releases tab, we
will here provide more details and maybe some examples.
In this first post, we will present the current state of this boilerplate.
Light ๐ชถ Simple ๐ and Scalable ๐
This boilerplate is the core of every react-native applications we develop at TheCodingMachine.
This means that we are the first users! If an issue appear we are the first affected ๐ฅบ, that's why this project is actively maintained!
The main idea behind this boilerplate is to have just the necessary and well-known stuff to have a very
"easy to use" boilerplate for little and big real world apps.
We don't include components libraries, we don't depend on third-party libraries (like Firebase for example).
It's just a good template project that is build on top of all the accumulated experience of our mobile teams.
It also provides a solid architecture that facilitates separation of concerns between the UI, the state management
and the business logic.
Like that, everyone can add its own touch! ๐๏ธ
๐จ Every decision about the technical stack are made regarding our preferences (every library has his
pros and cons).
Easy to install ๐
Installation has been facilitated since the v2.0.0, thanks to the use of the react-native-cli and
custom template.
To run this boilerplate, the only commands you need are
npx react-native init --template @thecodingmachine/react-native-boilerplate
yarn start
yarn ios
yarn androidThat's this simple! ๐
Typescript support ๐
Since the v3.0.0, during the installation, you can choose to use typescript for your new app.
All the boilerplate will then be translated in typescript.
That's this simple! ๐
Solid libraries ๐จ
As I said before, main concerns are simplicity and scalability.
Each of the used libraries are well-known, tried and tested.
Well-know libraries
For the state management we use Redux (redux + redux toolkit + redux persist).
Some people like it, some people don't.
We are really comfortable with this library, it's not so difficult to learn, and the implementation is well-known,
recognized as a good choice and easy to debug!
Thanks to this boilerplate and redux-toolkit, the state management is ready out of the box.
A complete example is even included. This way, you can easier understand how it works.
To deal with the navigation, React Navigation is THE reference for screen navigation.
For the internationalization we use I18next. Well-know library, really easy to use and
providing nice hooks.
redux-toolkit-wrapper
This project is a Redux-toolkit wrapper (yes... it's obvious ๐
) used to write less code regarding classic CRUD operations.
Redux-toolkit provide a lot of abstraction for async operations, but we always have to create a loading and error
state and associated reducers.
Redux-toolkit-wrapper abstract these async operations. For a classic "fetch one user" operation all you need is adding these files :
import {
buildAsyncState, buildAsyncReducers, buildAsyncActions,
} from '@thecodingmachine/redux-toolkit-wrapper'
import fetchOneUserService from '@/Services/User/FetchOne'
export default {
initialState: buildAsyncState('fetchOne'),
action: buildAsyncActions('user/fetchOne', fetchOneUserService),
reducers: buildAsyncReducers({
errorKey: 'fetchOne.error',
loadingKey: 'fetchOne.loading',
}),
}const sliceInitialState = {
item: {},
}
export default buildSlice('user', [FetchOne], sliceInitialState).reducerNext, you can use your state in your container like this:
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { View, ActivityIndicator, Text } from 'react-native'
import FetchOne from '@/Store/User/FetchOne'
const ExampleContainer = () => {
const dispatch = useDispatch()
const user = useSelector(state => state.user.item)
const fetchOneUserLoading = useSelector(state => state.user.fetchOne.loading)
const fetchOneUserError = useSelector(state => state.user.fetchOne.error)
useEffect(() => {
dispatch(FetchOne.action(id))
}, [dispatch])
return (
<View>
{fetchOneUserLoading && <ActivityIndicator />}
{fetchOneUserError ? (
<Text style={Fonts.textRegular}>{fetchOneUserError.message}</Text>
) : (
<Text style={Fonts.textRegular}>
{t('example.helloUser', { name: user.name })}
</Text>
)}
</View>
)
}
export default ExampleContainerThat's this simple! ๐
What's in the box? ๐ฆ
Still hesitating ? Let's make a recap and see what this beautiful boilerplate can provide you:
- No headaches! ๐ค Thanks to the quick and easy install, the
documentation and of course the included example! (if you have all the installed
requirements
of course) - Typescript ๐ / Javascript ๐ ? Your project, your choice!
- Never again sailing on troubled waters with React Navigation: THE powerful library to handle navigation ๐ฑ
- Redux (with redux-toolkit and redux-toolkit-wrapper ๐) : handling
redux store has never been as easy as this!! โก - DarkMode or colorful app? Give your users the power to choose!
Multi-theming and darkMode support ๐ - French kisses aren't translatable, but you can translate your app! i18n friendly ๐
- You don't like bug hunt? Use Flipper debugging ๐
- Maintained by passionate developers โ๏ธ
Just Test It ๐งช !!
Installation plugins โ๏ธ
Freshly in the v3.0.0 we created an installation plugin system. Of course, the first plugin added is the typescript one. ๐
We are now able to add local or npm plugins to our boilerplate in order to apply them during the installation.
This way, we get the app template with the features we asked for.
In other words, no unwelcome pieces of code will lay in your app architecture anymore.
You got it, it's only the beginning thinking about the many plugins we could create for this project. ๐คฉ
So wait and see what could be the next plugins...๐๐ค
Why this boilerplate? ๐
Before starting this project, we looked for already existing boilerplates.
We've found some, but while many were (and are always) awesome, we did not find what we were
looking for: a light, scalable, and flexible boilerplate with a great separation of concerns.
One of the most popular was
Matt Mcnamee's React Native Starter Kit,
which unfortunately missed Redux middleware and React Navigation.
Digging deeper in the react-native boilerplates (ignoring unmaintained projects),
many popular boilerplates were too opinionated: they
included 3rd party services or very strong architecture choices
that we were not comfortable with.
To name a few:
- Snowflake ran with a Hapi Server running on Redhat OpenShift,
- Apollo's StarterKit is based on GraphQL using Apollo,
- Meteor Boilerplate is based on Meteor.
Finally, some did not contain the architecture we were looking for (the separation of concerns),
for example re-start.
One interesting exception was
Ignite IR Boilerplate "Andross", but after
consideration we decided not to use it because of the large amount of
unnecessary code/components it provided out of the box.
In 2021, some react-native boilerplates have changed. Let's see what are
the differences:
| Boilerplate | Difference from our |
|---|---|
| mcnamee/react-native-starter-kit | No React Navigation (react-native-router-flux instead), |
No Typescript support,
Don't use the react-native-cli to init || bartonhammond/snowflake | Seems not maintained anymore (last release was in 2017) ๐ค |
| sysgears/apollo-universal-starter-kit | Is based on GraphQL using Apollo,
Don't use the react-native-cli to init |
| spencercarli/react-native-meteor-boilerplate | Seems not maintained (no release, last commit was in 2018) ๐ค |
| react-everywhere/re-start | Seems not maintained (last release was in 2017) ๐ค |
| infinitered/ignite | Specific folders for ignite-cli and boilerplate items,
MobX instead of Redux,
Expo ready,
Reactotron (ignite product) ready,
Typescript only |
So there is no reason to hesitate : come ๐งฒ, test ๐งช and leave a star โญ
Thanks for reading, See you for the next release. ๐ท๏ธ
File: documentation/blog/2023-11-30-React-Native-Boilerplate-4.0.0.md
title: React Native Boilerplate 4.0.0 authors: jed hide_table_of_contents: false tags: [v4, boilerplate react, react-native, kickstart]
After using the boilerplate on several projects,
we decided to revisit some important aspects while still adhering to the core principles of the boilerplate:
separation of concerns, ease of setup, and maintainability.
We made several enhancements, which we'll detail here.
Improved Theming
Theming is a crucial aspect of any application.
Previously, we had designed a layered theming system where all variables could be customized for each theme,
including base colors and spacing.
Upon reflection, we found that this system, while effective, wasn't the most straightforward to use,
especially with the layered naming convention.
Additionally, being able to modify spacing between themes didn't make sense.
Furthermore, the variable names we used weren't always intuitive.
For instance, terms like 'medium' or 'large' didn't allow for easy interpolation between them.
It was even harder to find an intermediate value between 'medium' and 'regular,' for example.
As a result, we decided to simplify and improve the theming process, making it more efficient and comprehensive.
Configuration
Everything now revolves around a configuration file named _config.ts.
This file serves as a central configuration point where you can define the base theme values and declare theme variants.
We've moved away from the complex layering system in favor of a more reflective system with main themes and variants.
Theme Provider
To boost performance, we introduced a ThemeProvider component. This component provides the theme to the application,
preventing the need to regenerate the theme with every useTheme call.
Type Inference
We've also improved the type inference of the theme. Now each generated style is typed according to the theme configuration even if there are variants.
For example, let's imagine a configuration like this:
export const config = {
//...
fonts: {
//...
colors: {
primary: 'blue',
},
},
//...
variants: {
dark: {
fonts: {
colors: {
primary: 'darkblue',
},
},
},
premium: {
fonts: {
colors: {
primary: 'gold',
},
},
}
}
}The generated type will be inferred at the perfect level:
Goodbye Redux ๐คง
Redux is a fantastic library, but it's not always the best solution for every project.
When we started the boilerplate, our goal was to provide a comprehensive solution for state management. In our initial version, we integrated Redux, Redux Persist, and Redux Saga, to name a few. These libraries were essential for managing the application's state, handling asynchronous requests, and persisting data.
However, over time, alternative solutions emerged,
particularly in the realm of data fetching.
It was with Redux Toolkit Query that we began version 3.
Nonetheless, we decided to part ways with it for version 4.
Our aim has always been to offer a lightweight yet comprehensive solution
without being too opinionated. Thus, we chose to remove Redux from the boilerplate
in favor of lighter and more straightforward alternatives.
It's important to note that global state management remains crucial in an application,
and several options are available:
- Redux
- Mobx
- Zustand
- Jotai
- React Context
- And more...
Now, in this version, for data fetching, we now use React Query,
an excellent library that's straightforward to use.
As for data storage, we rely on React Native MMKV, a native library known for its high performance and secure,
synchronous data storage capabilities.
Enhanced Documentation ๐
We also took the opportunity to enhance the documentation.
It's now clearer and more comprehensive.
We've made an effort to make the documentation more accessible and easier to understand.
At times, we've added 'playgrounds' in the section related to theme generation,
allowing you to directly test the values you want and see the results for yourself
File: documentation/docs/04-Guides/04-Theming/03-Generated styles/01-Gutters.mdx
slug: /theming/generated-styles/gutters sidebar_label: Gutters title: Gutters id: theming-generated-styles_gutters keywords: [padding, margin, paddings, margins, gutters, spacings, gap]
import Gutters from "../../../../src/components/Gutters";
How to use ?
Generated styles provided by the gutters section of the theme configuration assist in applying margin and padding to your components.
You can access these styles using the following code:
const { gutters } = useTheme()For more details, refer to the gutters section of the theme configuration.
Generated gutters
Here's the representation of the generated styles for a given GuttersConfig like the one below:
export const config = {
// ...
gutters: [...value],
// ...
}Where value is an array of numbers, the generated keys available through the gutters key will be the concatenation of the gutter name and the value, including:
margin_${value},marginBottom_${value},marginTop_${value},marginRight_${value},marginLeft_${value},marginVertical_${value},marginHorizontal_${value},padding_${value},paddingBottom_${value},paddingTop_${value},paddingRight_${value},paddingLeft_${value},paddingVertical_${value},paddingHorizontal_${value},gap_${value},
The corresponding values behind these keys will be:
{
[gutter_name]: value
}This structure simplifies the process of accessing and applying margin and padding styles with various gutter values.
Static gutter styles
Some gutter styles, don't require dynamic generation.
To accommodate this, we offer the staticGuttersStyles object that houses static styles for gutters.
You can use this file as-is or customize it to your preferences.
These styles will be seamlessly merged with the generated ones,
making them accessible through the gutters object of the useTheme hook.
Playground
Here's a simple playground that provides a visual representation of the objects generated from a given gutters configuration:
File: documentation/docs/04-Guides/04-Theming/03-Generated styles/02-Fonts.mdx
slug: /theming/generated-styles/fonts
sidebar_label: Fonts
title: Fonts
id: theming-generated-styles_fonts
keywords: [fonts, fontsize, fontcolor, textcolor, textsize, text]
import Fonts from "../../../../src/components/Fonts";
How to use ?
Generated styles provided by the fonts section of the theme configuration assist in applying font sizes and text colors to your components.
You can access these styles using the following code:
const { fonts } = useTheme()For more details, refer to the fonts section of the theme configuration.
Generated fonts
Here is the representation of the generated styles for a givenFontsConfig like the one below:
export const config = {
//...
fonts: {
sizes: sizesValues,
colors: colorsValues,
},
//...
}Where sizesValues is an array of numbers, sizeValue is an item of sizeValues, and colorsValues is an object withcolorsKey keys and colorsValue values, the generated styles are as follows:
| font name | Generated style |
|---|---|
| fonts.size__sizesValue_ | { fontSize: sizeValue } |
| fonts.colorsKey | { color: colorsValue } |
Static fonts
Some fonts styles, such as the fontWeight property of a text style, don't require dynamic generation.
To accommodate this, we offer the staticFontStyles object that houses static styles for fonts.
You can use this file as-is or customize it to your preferences.
These styles will be seamlessly merged with the generated ones,
making them accessible through the fonts object of the useTheme hook.
Playground
Here's a simple playground that provides a visual representation of the objects generated from a given fonts configuration:
File: documentation/docs/04-Guides/04-Theming/03-Generated styles/03-Backgrounds.mdx
slug: /theming/generated-styles/backgrounds sidebar_label: Backgrounds title: Backgrounds id: theming-generated-styles_backgrounds keywords: [background, backgrounds, colors, color]
import Backgrounds from "../../../../src/components/Backgrounds";
How to use ?
The styles generated by the backgrounds section of the theme configuration are designed to apply background colors to your components.
To access these styles, you can use the following code:
const { backgrounds } = useTheme()Generated backgrounds
Here is the representation of the generated styles for a givenBackgroundConfig like the one below:
export const config = {
//...
backgrounds: {
[colorName]: colorValue,
//...
},
//...
}The generated styles take the following form:
| background name | Generated style |
|---|---|
| backgrounds.colorName | { backgroundColor: colorValue } |
These styles enable you to easily apply background colors to your components as needed.
Static backgrounds styles
Some background styles, don't require dynamic generation.
To accommodate this, we offer the staticBackgroundStyles object that houses static styles for background.
You can use this file as-is or customize it to your preferences.
These styles will be seamlessly merged with the generated ones,
making them accessible through the backgrounds object of the useTheme hook.
Playground
Here's a simple playground that provides a visual representation of the objects generated from a given backgrounds configuration:
File: documentation/docs/04-Guides/04-Theming/03-Generated styles/04-Borders.mdx
slug: /theming/generated-styles/borders sidebar_label: Borders title: Borders id: theming-generated-styles_borders keywords: [border, borders, radius, width, color, colors]
import Borders from "../../../../src/components/Borders";
How to use ?
Generated styles provided by the borders section of the theme configuration assist in applying border radius, width and color to your components.
You can access these styles using the following code:
const { borders } = useTheme()For more details, refer to the borders section of the theme configuration.
Generated borders
Here is the representation of the generated styles for a givenBordersConfig like the one below:
export const config = {
//...
borders: {
widths: widthsValues,
radius: radiusValues,
colors: colorsValues,
},
//...
}Where widthsValues and radiusValues are arrays of numbers, widthValue is an item of widthsValues, radiusValue is an item of radiusValues, and colorsValues is an object withcolorsKey keys and colorsValue values, the generated styles are as follows:
| border name | Generated style |
|---|---|
| borders.w__widthValue_ | { borderWidth: widthValue } |
| borders.wTop__widthValue_ | { borderWidth: widthValue } |
| borders.wBottom__widthValue_ | { borderWidth: widthValue } |
| borders.wLeft__widthValue_ | { borderWidth: widthValue } |
| borders.wRight__widthValue_ | { borderWidth: widthValue } |
| borders.rounded__radiusValue_ | { borderRadius: radiusValue } |
| borders.roundedTop__radiusValue_ | { borderRadius: radiusValue } |
| borders.roundedBottom__radiusValue_ | { borderRadius: radiusValue } |
| borders.colorsKey | { borderColor: colorsValue } |
Static borders styles
Some border styles, don't require dynamic generation.
To accommodate this, we offer the staticBorderStyles object that houses static styles for border.
You can use this file as-is or customize it to your preferences.
These styles will be seamlessly merged with the generated ones,
making them accessible through the borders object of the useTheme hook.
Playground
Here's a simple playground that provides a visual representation of the objects generated from a given borders configuration:
File: documentation/docs/04-Guides/04-Theming/03-Generated styles/05-Layout.mdx
slug: /theming/generated-styles/layout sidebar_label: Layout title: Layout id: theming-generated-styles_layout keywords: [layout, flex, row, col, column, center, align, justify]
import Layout from '../../../../../template/src/theme/layout'
How to use ?
Static styles provided by the static/layout.ts file assist in applying layout styles to your components.
You can access these styles using the following code:
const { layout } = useTheme()Default generated layout
| Key | Value |
|---|---|
| {key} | {JSON.stringify(value)} |
:::info
These styles are generated using the static/layout.ts file. You can modify the file to change the default styles.
:::
File: documentation/docs/04-Guides/04-Theming/01-Using.md
slug: /theming/how-to-use sidebar_label: How to use it? title: How to use it? id: theming-how-to-use keywords: [theme, theming, useTheme, hooks, themeProvider]
The boilerplate provides a pre-configured theme ready for use.
To make use of it, simply follow this section's instructions.
If you'd like to gain a deeper understanding of the theme configuration, please refer to
the configuration section for more details.
`useTheme` hook
If you need to access the style classes, you can use the useTheme hook in the following manner:
import { useTheme } from '@/theme';
const Example = () => {
const {
//highlight-start
colors,
variant,
layout,
gutters,
fonts,
backgrounds,
borders,
navigationTheme,
components,
//highlight-end
} = useTheme();
return (
<View
style={[
//highlight-start
layout.itemsCenter,
layout.justifyCenter,
//highlight-end
]}
>
{isError && (
<Text style={[
//highlight-start
gutters.marginTop_30,
fonts.font_16,
fonts.text_red_500
//highlight-end
]}>
An error occured
</Text>
)}
</View>
)
}Change theme
As mentioned in the configuration section, you have the flexibility to add new themes
(variants) and switch between them directly within the app. For example, if you have a default theme configured with adark variant, you can switch the current theme to dark at any point.
To achieve this, you can employ the useTheme hook as follows:
import { useTheme } from '@/theme';
const Example = () => {
const { changeTheme } = useTheme();
return (
changeTheme('dark')}
/>
)
}:::tip
If you require assistance in defining a new theme variant, kindly consult the configuration section for guidance.
:::
Theme Provider
The magic of useTheme is made possible by our ThemeProvider component.
This main component handles the generation of all the styles in your application.
As we've emphasized, a clean separation of concerns is paramount to us.
That's why we've designed a single, transparent component, using the adapted context pattern
that takes care of generating all your styles, storing the theme variant,
and even offers you the flexibility to switch the theme for your entire app.
No black box magic here โ you have full visibility into the code and the
freedom to enhance it as needed to meet your unique requirements.
File: documentation/docs/04-Guides/04-Theming/02-Configuration.md
slug: /theming/configuration sidebar_label: Configuration title: Configuration id: theme-configuration keywords: [theme, theming, configuration, config, colors, fonts, gutters, spacings, borders, navigation, variants]
Structure
The idea behind the theme configuration is to have a single source of truth for all the theme related values.
This is why the theme configuration is a simple object with the following structure:
| Key | Type | Description |
|---|---|---|
colors |
colorConfig |
Define global colors |
fonts |
FontConfig |
Define colors and sizes to generate associated styles (color and fontSize) |
gutters |
GuttersConfig |
Define sizes to generate associated styles (padding and margin) |
backgrounds |
Record<string, string> |
Define colors generate associated styles (backgroundColor) |
borders |
BordersConfig |
Define colors, sizes and radius to generate associated styles (borderColor, borderRadius, borderWidth) |
navigationColors |
NavigationColorsConfig |
Define colors override ReactNavigation theme colors |
variants |
VariantsConfig |
Define a new theme based on the previous values |
Variants
A variant is a new theme based on the previous values.
It means that the default theme is based on the previous keys (fonts, gutters, backgrounds, borders, navigationColors)
to be generated and variant are just a way to create a new theme based on the previous values.
For example, if you want to create a dark theme, you can create a new variant based on the default theme and override the colors you want to change.
export const config = {
//...
// highlight-start
backgrounds: {
gray_200: '#DFDFDF',
},
// highlight-end
//...
variants: {
dark: {
// highlight-start
backgrounds: {
gray_200: '#000000',
},
// highlight-end
},
},
};So here the theme dark will have the same values as the default theme except for the backgrounds.gray_200 value.
Statically generated styles
Some styles, including Backgrounds, Borders, Fonts and Gutters need to be dynamically generated depending on the actual theme.
But, in some cases, the configuration is not sufficient to generate all the styles you need. So, in this case, you will need to add some static styles.
In each style files you will find a static function to include non-config-based styles:
staticBackgroundStylesto generate static background stylesstaticBorderStylesto generate static border stylesstaticFontStylesto generate static font stylesstaticGutterStylesto generate static gutter styles
into these files, you will be able to add any style you want.
All of these will be available
Components styling
Sometimes, you will want to create some style object for a specific component.
As we want to keep the theme configuration as the single source of truth, we don't want to have some style object in the component itself.
Plus, we want to be able to use the theme configuration variables to generate these styles for example if we want to style a button based on the theme colors.
This is why we introduce the components file in the theme directory.
The benefit of this is that you will be able to create a style object for a specific component and use the theme styles to generate these styles.
For example, if you want to style a circle Button component, you will create a circleButton entry in the components file.
export default ({ layout, backgrounds, fonts }: ComponentTheme) => {
return {
buttonCircle: {
...layout.justifyCenter,
...layout.itemsCenter,
...backgrounds.purple100,
...fonts.gray400,
height: 70,
width: 70,
borderRadius: 35,
},
} as const satisfies Record<string, ImageStyle | TextStyle | ViewStyle>;
};