Setup Macbook M1 for Web and React Native development

Published on May 23, 2023

12 min read

TOOLS

🕑 This article was originally written on March 14, 2021. Since then, it has been updated many times to reflect my setup process. In 2023, I decided to re-write this article from scratch.

cover_image

It's 2023, and I am still coming back to this article. I wrote this originally in 2021 to keep track of what I need to start when setting up a new laptop. Since then, I have had two Macbook Pros using an Apple Silicon processor (M1). I try to keep this article up to date.

I believe small optimizations help you go faster in the long run. Also, a flavor of personalization makes my developer experience more enjoyable. I like to keep two separate setups, one for work and the other for personal use and fun. However, often I end up switching between both. Having the same set of tools and configurations helps me just be me. It also helps me keep my setup portable and up-to-date (have had those days where I lost everything).

1: Install Xcode and Command Line Tools

🔗

To get started, open the App Store on the Mac and install Xcode. It's a large download, so it might take a while.

Once installed, open the Terminal app on the Mac and run:

xcode-select --install && sudo xcodebuild -license

1.1: Verify Command Line Tools installation

🔗

After installing Xcode and command line tools, open the app. Then, from the menu bar, open Xcode > Preferences > Locations and make sure that Command Line Tools point towards the current Xcode app.

ss3

2: Install Warp terminal

🔗

Previously, I've used iTerm2 as y default terminal app over the years. Find more info about iterm2 in the Alternate tools section at the end of this post.

I recently started using Warp as my first choice for a terminal app on Mac. After downloading the app, start the app:

  • Go to Appearance
  • Set theme to Dracula
  • Window Opacity: 95
  • Window Blur Radius: 17

2.1: Install Oh My Zsh

🔗

ZSH is the default shell in macOS. However, I like to use Oh My Zsh to manage the ZSH configuration, plugins, and a theme to prettify the terminal (especially when using iterm2 previously).

To install, run the command below:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

After installation, make sure that the file .zshrc is exporting the below path at the top:

# Path to your oh-my-zsh installation
export ZSH="$HOME/.oh-my-zsh"

The $HOME should be /Users/<your-macos-username>. You can verify this by running:

echo $HOME

2.2: Install syntax highlighting plugin

🔗

The first I like to do after setting up the bare minimum ZSH configuration is to install a plugin called zsh-syntax-highlighting. It provides syntax highlighting for the ZSH shell. Execute the series below commands in the terminal window:

# depending on the /plugins folder in your local setup
cd $HOME/.oh-my-zsh/plugins
# then clone the git repository
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git
echo "source ${(q-)PWD}/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc

On iterm2, after installing the syntax highlight plugin, it starts to recognize the commands:

ss4

Only for iterm2: Install a theme

🔗

The next step is to install spaceship-prompt theme. Follow the steps described in oh-my-sh section.

Final ZSH configuration

🔗

This is my final ZSH configuration in the file ~/.zshrc file:

# Path to your oh-my-zsh installation
export ZSH="/Users/amanhimself/.oh-my-zsh"
export PATH=/opt/homebrew/bin:$PATH
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
# ZSH_THEME="spaceship"
# Uncomment the following line to disable bi-weekly auto-update checks.
DISABLE_AUTO_UPDATE="true"
plugins=(
git
node
vscode
zsh-syntax-highlighting
)
source $ZSH/oh-my-zsh.sh
source /Users/amanhimself/.oh-my-zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

3: Change system settings

🔗

System preferences and settings that I prefer. These settings are available in the Systems Settings:

  • Siri:
    • Disable Ask Siri
  • Desktop & Dock:
    • Enable "Automatically hide and show the Dock"
    • Set "Automatically hide and show the menu bar in full screen" to "In Full Screen Only"
    • Set Recent documents, applications and servers to "None"
    • Size: 30%
    • Magnification: 45%-50%
  • Trackpad:
    • Point & click
      • Enable secondary click with the bottom right corner
      • Enable Tap to click with one finger
      • Tracking speed: 90%
      • Click: Medium
      • Force click and haptic feedback: Disable
      • Look up & data detectors: Disable
    • Scroll & zoom
      • Natural scrolling: Disable
    • More Gestures
      • Swipe between pages: Off
  • Spotlight:
    • Disable search except for Applications, Calculator, Conversion, Developer, Definition, and System Settings.
  • Finder settings:
    • Advanced > Show filename extensions
    • Enable showing hidden files (hold Cmd + Shift dot(.) in a Finder window)
    • Enable: View -> Show Path Bar, Show Status Bar
  • Lock Screen:
    • Start screen saver when inactive: 1 hour
    • Turn display off on battery when inactive: For 3 hours
    • Turn display off on power adapter when inactive: For 3 hours

4: Install homebrew

🔗

On December 1, 2020, the Homebrew team announced on their website about the version release 2.6.0. The most significant changes they listed were:

  • The support for macOS Big Sur.
  • Using brew commands instead of brew cask.
  • Beginning to support macOS M1 and Apple Silicon or ARM-based chips.

Using the terminal, you can install the Homebrew by executing the default command:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

5: Install Git

🔗

To install Git, run the command:

brew install git

To authenticate GitHub to be used from the terminal environment, I recommend you check out the official document on creating and accessing personal tokens.

🔥 Tip: As of Git version 2.28, there is a new config option to set the default branch to main. Set it globally and forget about it.

git config --global init.defaultBranch main

To enable colors in the output, run the command:

git config --global color.ui auto

6: Install homebrew packages

🔗

Run the following script to install other packages from homebrew:

brew install yarn
brew install scrcpy
brew install watchman
brew install exa
brew install imageoptim

Some highlights from the above script:

7: After installing Node.js

🔗

Node.js comes with the default package manager npm. Set defaults for it:

npm config set init-author-name "your name"
npm config set init-author-url "example.com"
npm config set init-license MIT

8: Install global npm packages

🔗
npm i -g eas-cli

Also, I use the following command to update global packages:

npx npm-check -gu

9: VS Code

🔗

VS Code and VS Code Insiders are currently supported on ARM chips (March 13, 2021). Download the installer for Insiders edition from here and for VS Code here.

ss5

I am using the following VS Code configuration:

1{
2 "workbench.startupEditor": "welcomePage",
3 "workbench.iconTheme": "material-icon-theme",
4 "workbench.editor.tabSizing": "shrink",
5 "security.workspace.trust.untrustedFiles": "open",
6 "explorer.confirmDelete": false,
7 "explorer.confirmDragAndDrop": false,
8 "workbench.editor.enablePreview": false,
9 "window.restoreFullscreen": true,
10 "editor.tabSize": 2,
11 "editor.fontSize": 13.5,
12 "editor.minimap.enabled": false,
13 "editor.cursorBlinking": "phase",
14 "editor.fontLigatures": false,
15 "editor.wordWrap": "on",
16 "editor.cursorSmoothCaretAnimation": "on",
17 "editor.tabCompletion": "on",
18 "editor.formatOnPaste": true,
19 "editor.formatOnSave": true,
20 "editor.semanticHighlighting.enabled": true,
21 "editor.guides.bracketPairs": true,
22 "explorer.openEditors.visible": 0,
23 "files.trimTrailingWhitespace": true,
24 "search.exclude": {
25 "**/node_modules": true,
26 "**/*.code-search": true,
27 "dist/": true,
28 "yarn.lock": true,
29 "package-lock.json": true,
30 ".gitignore": true,
31 ".expo": true,
32 ".vscode": true
33 },
34 "extensions.autoUpdate": false,
35 // --------------------------------------
36 // --------------------------------------
37 // CODE::STATS EXTENSION
38 // --------------------------------------
39 // READ TIME EXTENSION
40 "readTime.enabled": true,
41 // --------------------------------------
42 // HIGHLIGHT MATCHING TAG EXTENSION
43 "highlight-matching-tag.styles": {
44 "opening": {
45 "name": {
46 // surround is border
47 "surround": "yellow"
48 }
49 }
50 },
51 // --------------------------------------
52 // INTEGRATED TERMINAL
53 "terminal.external.osxExec": "iTerm.app",
54 // "terminal.external.osxExec": "warp.app",
55 "terminal.integrated.fontSize": 12,
56 // --------------------------------------
57 // NPM
58 "npm-intellisense.importES6": true,
59 // --------------------------------------
60 // TS IMPORT SUGGESTION
61 "typescript.suggest.paths": false,
62 // --------------------------------------
63 // NATIVE BRACKET PAIR COLOR SETTINGS
64 "editor.bracketPairColorization.enabled": true,
65 "workbench.colorCustomizations": {
66 "editorBracketHighlight.foreground1": "#ffb86c",
67 "editorBracketHighlight.unexpectedBracket.foreground": "#ff5555",
68 "[morgan.codes]": {
69 "gitDecoration.ignoredResourceForeground": "#434343"
70 },
71 "[Expo Dark]": {
72 // "activityBar.background": "#635985",
73 "activityBarBadge.background": "#fc4384",
74 "activityBarBadge.foreground": "#ffffff",
75 // "activityBar.activeBackground": "#bd93f9",
76 "activityBar.activeBorder": "#fc4384",
77 "gitDecoration.ignoredResourceForeground": "#434343",
78 "statusBar.background": "#fc4384",
79 "statusBar.noFolderBackground": "#fc4384",
80 // Gutter
81 "editorGutter.deletedBackground": "#ff0055",
82 "editorGutter.addedBackground": "#fc4384",
83 "editorGutter.modifiedBackground": "#9765c9",
84
85 // Selection and matches
86 "editor.selectionHighlightBorder": "#e18cc9",
87 "editor.selectionHighlightBackground": "#635985",
88 "editor.selectionForeground": "#eff8ff",
89 "editor.findMatchHighlightBackground": "#ff2b7c8e",
90 "editor.hoverHighlightBackground": "#ff000013",
91 "editor.lineHighlightBackground": "#2b2b2b50",
92 "editor.lineHighlightBorder": "#00000000",
93 "editorOverviewRuler.bracketMatchForeground": "#635985"
94 }
95 },
96 // --------------------------------------
97 "editor.defaultFormatter": "esbenp.prettier-vscode",
98 // Markdown
99 "[markdown]": {
100 "editor.quickSuggestions": {
101 "comments": "on",
102 "strings": "on",
103 "other": "on"
104 }
105 },
106 // JSON
107 "[json]": {
108 "editor.defaultFormatter": "esbenp.prettier-vscode"
109 },
110 // JavaScript
111 "[javascript]": {
112 "editor.defaultFormatter": "esbenp.prettier-vscode"
113 },
114 // JavaScript + React
115 "[javascriptreact]": {
116 "editor.defaultFormatter": "esbenp.prettier-vscode"
117 },
118 // TypeScript
119 "[typescript]": {
120 "editor.defaultFormatter": "esbenp.prettier-vscode"
121 },
122 // TypeScript + React
123 "[typescriptreact]": {
124 "editor.defaultFormatter": "esbenp.prettier-vscode"
125 },
126 // JSON with Comments
127 "[jsonc]": {
128 "editor.defaultFormatter": "esbenp.prettier-vscode"
129 },
130 // HTML
131 "[html]": {
132 "editor.defaultFormatter": "esbenp.prettier-vscode"
133 },
134 // ----------------------------------
135 // ESLINT
136 "eslint.validate": [
137 "javascript",
138 "javascriptreact",
139 "typescript",
140 "typescriptreact"
141 ],
142 // --------------------------------------
143 // ERROR LENS
144 // "errorLens.fontSize": "11",
145 // "errorLens.onSave": true,
146 // "errorLens.enabledDiagnosticLevels": ["error", "warning", "hint"],
147 // "workbench.colorCustomizations": {
148 // "errorLens.hintForeground": "#ffc600A1",
149 // "errorLens.hintBackground": "#ff00dd2f",
150 // "errorLens.errorBackground": "#ff000005",
151 // "editor.selectionBackground": "#ff1493",
152 // "editor.selectionHighlightBackground": "#ff1493",
153 // "editor.findMatchBackground": "#ff1493",
154 // "editor.findMatchHighlightBackground": "#3cb371"
155 // },
156 // "errorLens.exclude": ["never (read|used)"],
157 // --------------------------------------
158 // LANGUAGES SPECIFIC
159 "javascript.updateImportsOnFileMove.enabled": "always",
160 "security.workspace.trust.banner": "never",
161 "emmet.includeLanguages": {
162 "typescript": "typescriptreact",
163 "javascript": "javascriptreact"
164 },
165 "cSpell.userWords": [
166 "Appbar",
167 "asyncstorage",
168 "backgrounded",
169 "backoff",
170 "Cacheable",
171 "cancelation",
172 "Chakra",
173 "concurrencies",
174 "Contentful",
175 "Ecommerce",
176 "Entypo",
177 "Firestore",
178 "Grammarly",
179 "Ionicons",
180 "launchable",
181 "nocheck",
182 "Parens",
183 "Podfile",
184 "prefetch",
185 "Pressable",
186 "Transifex",
187 "Turborepo",
188 "undeployed",
189 "Vercel",
190 "vercelians",
191 "yantramanav",
192 "zustand"
193 ],
194 "git.autofetch": true,
195 "cSpell.language": "en,en-US",
196 "cSpell.enableFiletypes": ["markdown", "mdx"],
197 "editor.inlineSuggest.enabled": true,
198 "github.copilot.enable": {
199 "*": true,
200 "yaml": true,
201 "plaintext": true,
202 "markdown": true
203 },
204 "workbench.colorTheme": "Expo Light",
205 "window.commandCenter": true,
206 "customizeUI.fontSizeMap": {
207 "13px": "12px",
208 "12px": "11px",
209 "window-title": "12px", // Window title font when using custom titlebar
210 "tab-title": "12px", // Used for editor tab titles
211 "monospace": "11px" // Used for monospace fonts in user interface
212 },
213 "react-native-tools.showUserTips": false,
214 "errorLens.fontSize": "12",
215 "grammarly.files.include": [
216 "**/README.md",
217 "**/readme.md",
218 "**/*.txt",
219 "**/*.md",
220 "**/*.mdx"
221 ],
222 "css.lint.unknownAtRules": "ignore",
223 "workbench.editorAssociations": {
224 "*.js": "default"
225 },
226 "githubPullRequests.pullBranch": "never"

VS Code themes

🔗

I usually like to switch between a dark and a light theme.

For a light theme, I prefer:

For the dark theme where I spent most of my time with fairyFloss.

For file icons, I love Material-Icon-Theme.

VS Code extensions

🔗

Apps

🔗

10: Download browsers

🔗

Use Safari for personal email.

Other apps on my macOS

🔗
  • Android Studio
  • Insomnia as a REST API client
  • Slack and Discord (for work and community)
  • There (to track team mate's timezones)
  • Zoom (for work)
  • GitHub Desktop App
  • Cleanshot (for screenshots and recording videos)
  • Spotify
  • Bandwidth +
  • Linear (for work)
  • Skype
  • Discord
  • The Unarchiver
  • HiddenMe
  • Numbers
  • Telegram
  • Android file transfer

Chrome settings

🔗

ImageOptim settings

🔗

The custom config I use for ImageOptim app:

General settings in ImageOptim

Quality settings in ImageOptim

Optimization settings in ImageOptim

For React Native Development

🔗

Follow React Native documentation for info on how to install open JDK and Android Studio.

Alternate tools

🔗

Tools and apps that I've used in the past that I may come back to one day.

iterm2

🔗

My favorite terminal app that I have been using for years is iTerm2.

  • Enable Working Directory for New Split Panes: General -> Advanced Configuration

iterm1

  • Text:

iterm2

iterm3

  • Window:
    • Transparency: 5
    • Blur: 20

Rosetta 2

🔗

Update: I am not using the Rosetta environment to install anything on the secondary machine since August 2021. That is why I've mentioned it at the end of the post.

Rosetta 2 is the lifeline that allows you to run apps designed for Intel-based chips that use x86 architecture on ARM-based chips (in this case M1). This solution is provided by Apple as an emulator and doesn't come pre-installed. You have to install it manually. Fire up the Terminal application that comes pre-installed on the macOS and execute the following command:

/usr/sbin/softwareupdate --install-rosetta --agree-to-license

If you decide not to put the flag --agree-to-license, you will be prompted by Apple's interactive install, and you will have to agree to their terms and license conditions to use it.

Conclusion

🔗

That’s the setup I now use for my JavaScript, Node.js, React, React Native and documentation work. I think it's a great machine. Hopefully, M1 is just the beginning of a new era of powerful computers for daily work use.

🤔 The only thing left for me is to find a way to transfer all laptop swag/stickers from my Macbook Air 2017 to Pro. I miss having them on this one.

isapplesiliconready.com is another helpful link I found to check what is compatible to work on Apple Silicon chips natively or using Rosetta or not optimized at all.


More Posts

Browse all posts

Aman Mittal author

I'm a software developer and a technical writer. On this blog, I write about my learnings in software development and technical writing.

Currently, working maintaining docs at 𝝠 Expo. Read more about me on the About page.


Copyright ©  2019-2024 Aman Mittal · All Rights Reserved.