React Native — Typescript Boilerplate 2023 | Useful git tools — Husky with Commitlint & OhMyZsh

Balamurugan V
9 min readJun 10, 2023

--

Hello folks! Hope you’re all doing great. Welcome to yet another quick and useful article that would aid you to bootstrap a react native project swiftly and smoothly. We shall see how to quickly bootstrap a react native project with Typescript and basic setup.

This project has only eslint enabled, initialised and rules are re-written as per the latest standards, husky — commitlint and commitizen enabled.

OK, time to see some inits and configs…

From the official link : https://reactnative.dev/docs/environment-setup

Step 1: Create a new react native project with latest version. By default, the latest version of react native comes with typescript!

npx react-native@latest init AwesomeProject

Step 2: Uninstall all linting configs to avoid conflicts from template project bootstrapped.

yarn add @react-native-community/eslint-config eslint

Step 3: Nowadays, linting your project is essential irrespective of whichever programming language you code with. Hence we should init, config and apply linting. This command adds eslint as a dev dependency and initializes it.

yarn add eslint -D && npx  eslint --init

Step 4: Initialize eslint

@eslint/create-config@0.4.1  Ok to proceed? (y)  -> Y

? How would you like to use ESLint? …
To check syntax only
To check syntax and find problems
❯ To check syntax, find problems, and enforce code style

? What type of modules does your project use? …
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these

? Which framework does your project use? …
❯ React
Vue.js
None of these

? Does your project use TypeScript? › No / Yes -> Yes

? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node

? How would you like to define a style for your project? …
❯ Use a popular style guide
Answer questions about your style

Which style guide do you want to follow? …
❯ Standard:https://github.com/standard/eslint-config-standard-with-typescript
XO: https://github.com/xojs/eslint-config-xo-typescript



? What format do you want your config file to be in? …
❯ JavaScript
YAML
JSON

Checking peerDependencies of eslint-config-airbnb@latest
The config that you've selected requires the following dependencies:

eslint-plugin-react@^7.28.0 eslint-config-airbnb@latest eslint@^7.32.0 || ^8.2.0 eslint-plugin-import@^2.25.3 eslint-plugin-jsx-a11y@^6.5.1 eslint-plugin-react-hooks@^4.3.0
? Would you like to install them now? › No / Yes -> Yes

? Which package manager do you want to use? …
npm
❯ yarn
Pnpm

Step 5: Install prettier, parser, lint-staged.

yarn add -D prettier eslint-config-prettier @babel/eslint-parser lint-staged @babel/core eslint-plugin-react-native

Step 6: Install TS — related plugins to eslint

yarn add -D  @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb eslint-config-airbnb-typescript eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-n eslint-plugin-promise eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-native eslint-import-resolver-typescript  @typescript-eslint/eslint-plugin eslint-plugin-import eslint-plugin-prettier prettier

Step 7: Install Commitment, Commitizen, Husky. It’s recommended to use husky with commitlint, a handy git hook helper, to check your commit message before making any git commit.

yarn add -D @commitlint/{config-conventional,cli} commitizen cz-conventional-changelog husky @commitlint/config-conventional

Step 8:

Create commitlint.config.js with the following content:

This will show the options during the commit (type of commit).

module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'build',
'chore',
'ci',
'docs',
'improvement',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
],
],
},
};

Add this line in your package.json > scripts

"prepare" : "husky install"

If you are using nvm, you might want to create a file called .huskyrc in your home directory and add the following lines of code to it:

touch .huskyrc

This command opens the newly created file above:

nano .huskyrc

Copy paste the following lines onto the above file:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

Change permissions for that file:

chmod +x .huskyrc

Make sure you have the following:-

// .husky folder at root > commit-msg file contents:-

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no -- commitlint --edit ${1}



// .husky folder at root > pre-commit file contents:-

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"


npm run lint &&
git add . &&
npx lint-staged



// .husky folder at root > prepare-commit-msg file contents:-

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec < /dev/tty && npx cz --hook || true

Issue the following command to trigger husky pre-commit hook:

yarn prepare
npx husky add .husky/pre-commit
npx husky add .husky/prepare-commit-msg 'exec < /dev/tty && npx cz --hook || true'
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'

Step 9: Update .eslintrc.js file. Delete the existing contents and copy paste the following lines entirely. Here we’ve customized the listing rules, setup and configs for TS and linting files:

module.exports = {
env: {
browser: true,
es2021: true,
node: true,
'react-native/react-native': true,
jest: true,
},
settings: {
react: { version: 'detect' },
'import/resolver': {
typescript: {},
},
},


extends: [
'standard-with-typescript',
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'airbnb',
'airbnb-typescript',
'airbnb/hooks',
],
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
parserOptions: {
project: './tsconfig.json',
},
},
],
parserOptions: {
ecmafeatures: { jsx: true },
ecmaVersion: 'latest',
project: ['./tsconfig.json', './packages/*/tsconfig.json'],
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint', 'react-native'],
rules: {
'react/jsx-filename-extension': [
'error',
{ extensions: ['.js', '.jsx', '.ts', '.tsx'] },
],
'no-use-before-define': [
'error',
{ functions: true, classes: true, variables: true },
],
'react-native/no-unused-styles': 'error',
'react-native/split-platform-components': 'error',
'react-native/no-inline-styles': 'error',
'react-native/no-color-literals': 'error',
'react-native/no-raw-text': 'error',
'react-native/no-single-element-style-arrays': 'error',
},
};

Step 10: Re-configure .prettierrc.js file with customizations:

module.exports = {
arrowParens: 'avoid',
bracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
bracketSpacing: true,
singleQuote: true,
tabWidth: 4,
semi: true,
};

Step 11: Update package.json scripts for linting and commit hook:

{
…………
"scripts": {
"lint": "eslint .",
"prepare": "husky install"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"prettier --write",
"eslint --fix"
]
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
…………
}

Step 12: Create .eslintignore file at root of the project and add below lines:

.eslintrc.js
ios/
android/
*.config.js

Step 13: Update .gitignore file:

# vs code
.vscode
.vs

# OSX
.DS_Store

# Xcode
!**/*.xcodeproj
!**/*.pbxproj
!**/*.xcworkspacedata
!**/*.xcsettings
!**/*.xcscheme
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
**/.xcode.env.local
build/

# Android/IntelliJ
build/
.idea
.gradle
local.properties
/packages/react-native/android/*
!/packages/react-native/android/README.md
*.iml
*.bundle
*.bin
*.apk
*.jprof
*.prof
*.lock
*.hprof
.cxx/
*.keystore
!debug.keystore


/android/app/src/main/res/drawable-hdpi
/android/app/src/main/res/drawable-mdpi
/android/app/src/main/res/drawable-xhdpi
/android/app/src/main/res/drawable-xxhdpi
/android/app/src/main/res/drawable-xxxhdpi
/android/app/src/main/res/raw


/packages/react-native-gradle-plugin/build/
/packages/rn-tester/build
/packages/rn-tester/android/app/.cxx/
/packages/rn-tester/android/app/build/
/packages/rn-tester/android/app/gradle/
/packages/rn-tester/android/app/gradlew
/packages/rn-tester/android/app/gradlew.bat
/packages/react-native/ReactAndroid/build/
/packages/react-native/ReactAndroid/.cxx/
/packages/react-native/ReactAndroid/gradle/
/packages/react-native/ReactAndroid/gradlew
/packages/react-native/ReactAndroid/gradlew.bat
/packages/react-native/ReactAndroid/external-artifacts/build/
/packages/react-native/ReactAndroid/external-artifacts/artifacts/
/packages/react-native/ReactAndroid/hermes-engine/build/
/packages/react-native/ReactAndroid/hermes-engine/.cxx/
/packages/react-native/template/android/app/build/
/packages/react-native/template/android/build/

# Android Studio
.project
.settings
.classpath

# node.js
yarn.lock
node_modules
*.log
.nvm
package-lock.json

# BUCK
*.keystore
.buckd
buck-out
/.lsp.buckd
/.lsp-buck-out
/packages/react-native/ReactAndroid/src/main/jni/prebuilt/lib/
/packages/react-native/ReactAndroid/src/main/gen

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/
*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots
*/fastlane/test_output

# Bundle artifact
*.jsbundle

# CocoaPods
/ios/Pods/
/ios/Podfile.lock
ios/Podfile.lock
ios/assets
/ios/assets
/vendor/bundle/

# Watchman
.watchmanconfig

# Test generated files
/packages/react-native/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
*.js.meta

/coverage
/third-party

# Test Reports
/reports

# Stack Dumps generated when programs crash (Ex. bash.exe.stackdump on Win)
*.stackdump

# Root dir shouldn't have Xcode project
/*.xcodeproj

# ReactCommon subdir shouldn't have Xcode project
/packages/react-native/ReactCommon/**/*.xcodeproj

# Libs that shouldn't have Xcode project
/packages/react-native/Libraries/FBLazyVector/**/*.xcodeproj
/packages/react-native/Libraries/RCTRequired/**/*.xcodeproj
/packages/react-native/React/CoreModules/**/*.xcodeproj
/packages/react-native/React/FBReactNativeSpec/**/*.xcodeproj
/packages/react-native-codegen/**/*.xcodeproj

# Ruby Gems (Bundler)
/packages/react-native/vendor
/packages/react-native/template/vendor
.ruby-version
/**/.ruby-version

# iOS / CocoaPods
/packages/react-native/template/ios/build/
/packages/react-native/template/ios/Pods/
/packages/react-native/template/ios/Podfile.lock
/packages/rn-tester/Gemfile.lock

# Ignore RNTester specific Pods, but keep the __offline_mirrors__ here.
/packages/rn-tester/Pods/*
!/packages/rn-tester/Pods/__offline_mirrors_hermes__
!/packages/rn-tester/Pods/__offline_mirrors_jsc__

# @react-native/codegen
/packages/react-native/React/FBReactNativeSpec/FBReactNativeSpec
/packages/react-native-codegen/lib
/packages/react-native-codegen/tmp/
/packages/react-native/ReactCommon/react/renderer/components/rncore/
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
/**/RCTThirdPartyFabricComponentsProvider.*

# Additional SDKs
/packages/react-native/sdks/download
/packages/react-native/sdks/hermes
/packages/react-native/sdks/hermesc

# Android memory profiler files
*.hprof

# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*

Step 14: Now you’re all set to run your linter with auto-fix option:

yarn lint --fix

Step 15: You’re all set to run your metro server and your brand new react native project in your device:

yarn start
yarn android

Congratulations! You’ve set up your new React native project with all recommended linting rules and husky git commit hook.

Now you can use this command to do all the tasks automated: apply linting, apply auto fixes for linting, add all files to git staging area, and then trigger git commit hook from commitizen:

git add .
git commit

...
... // You will be taken thru the steps for husky - to get the type of commit, description, affected files, etc
...


git push origin <branch-name>

The same is available in the Github repo: https://github.com/svbala99/RN2023Boilerplate

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Bonus:
If you’re on MacBook, try using Oh My Zsh, a delightful, open source, community-driven framework for managing your Zsh configuration. It comes bundled with thousands of helpful functions, helpers, plugins, themes, and a few things that make you shout…

It can be downloaded from: https://ohmyz.sh/

Just issue this command to get it done:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Now you can see your Mac terminal turned colourful which is very useful and eye-friendly for people who stare monitors for long long time…!

It also has some useful shortcuts which you can try out:

 ga .   // git add .
gcam "My commit msg". // git commit -m "my msg"
ggpush // git push origin <branch-name>
gm <branch-name> // git merge
grb <branch-name>. // git rebase
gco -b <new branch name> // create a new branch
gco <existing branch name> // git checkout
gb // git branch - show list of branches
gb -D <branch name> // delete remote git branch - git branch -D
ggpush --tags // push git tags to remote repo

You can also customize your command shortcuts open the file .zshrc and add custom commands:

nano ~/.zshrc

alias fp='gf && ggpull'
alias dev='gco development && fp'
alias p='ggpush'
alias abc='gco my-branch-name && fp'

Now if you simply issue these commands, that’d do wonders for you, which saves a lot of time for you during your tiresome coding phase:

fp      // git fetch && git pull origin <branch-name>
p // git push origin <branch-name>
dev // git checkout dev && git fetch && git pull
abc // git checkout <my-branch> && git fetch && git pull

Kindly spend some time to understand the difference between fetch and pull, as many of the developers even with plenty of experience don’t bother to bay an eye on this:

Courtesy: https://www.geeksforgeeks.org/git-difference-between-git-fetch-and-git-pull/

See you next time, until then, Happy RN coding!!!

--

--

Balamurugan V

Javascript enthusiast | Front end Engineer | Proud Tamilian