Note: A new version of this post was written in 2024. See My 2024 Macbook setup for more information.
🕑 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.
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.
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:
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
- Point & click
- 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 ofbrew 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 tomain
. 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
- Node.js and npm via Node Version Manager (NVM). Read the entire blog post on how to install Node.js using NVM.
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:
- Watchman to watch changes in the filesystem.
- scrcpy (control Android devices connect via USB on Mac)
- exa a modern replacement for
ls
. - imageoptim for compressing image files. See ImageOptim Settings for how to set it up.
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
- eas-cli For work and personal use:
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.
I am using the following VS Code configuration:
{
"workbench.startupEditor": "welcomePage",
"workbench.iconTheme": "material-icon-theme",
"workbench.editor.tabSizing": "shrink",
"security.workspace.trust.untrustedFiles": "open",
"explorer.confirmDelete": false,
"explorer.confirmDragAndDrop": false,
"workbench.editor.enablePreview": false,
"window.restoreFullscreen": true,
"editor.tabSize": 2,
"editor.fontSize": 13.5,
"editor.minimap.enabled": false,
"editor.cursorBlinking": "phase",
"editor.fontLigatures": false,
"editor.wordWrap": "on",
"editor.cursorSmoothCaretAnimation": "on",
"editor.tabCompletion": "on",
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.semanticHighlighting.enabled": true,
"editor.guides.bracketPairs": true,
"explorer.openEditors.visible": 0,
"files.trimTrailingWhitespace": true,
"search.exclude": {
"**/node_modules": true,
"**/*.code-search": true,
"dist/": true,
"yarn.lock": true,
"package-lock.json": true,
".gitignore": true,
".expo": true,
".vscode": true
},
"extensions.autoUpdate": false,
// --------------------------------------
// --------------------------------------
// CODE::STATS EXTENSION
// --------------------------------------
// READ TIME EXTENSION
"readTime.enabled": true,
// --------------------------------------
// HIGHLIGHT MATCHING TAG EXTENSION
"highlight-matching-tag.styles": {
"opening": {
"name": {
// surround is border
"surround": "yellow"
}
}
},
// --------------------------------------
// INTEGRATED TERMINAL
"terminal.external.osxExec": "iTerm.app",
// "terminal.external.osxExec": "warp.app",
"terminal.integrated.fontSize": 12,
// --------------------------------------
// NPM
"npm-intellisense.importES6": true,
// --------------------------------------
// TS IMPORT SUGGESTION
"typescript.suggest.paths": false,
// --------------------------------------
// NATIVE BRACKET PAIR COLOR SETTINGS
"editor.bracketPairColorization.enabled": true,
"workbench.colorCustomizations": {
"editorBracketHighlight.foreground1": "#ffb86c",
"editorBracketHighlight.unexpectedBracket.foreground": "#ff5555",
"[morgan.codes]": {
"gitDecoration.ignoredResourceForeground": "#434343"
},
"[Expo Dark]": {
// "activityBar.background": "#635985",
"activityBarBadge.background": "#fc4384",
"activityBarBadge.foreground": "#ffffff",
// "activityBar.activeBackground": "#bd93f9",
"activityBar.activeBorder": "#fc4384",
"gitDecoration.ignoredResourceForeground": "#434343",
"statusBar.background": "#fc4384",
"statusBar.noFolderBackground": "#fc4384",
// Gutter
"editorGutter.deletedBackground": "#ff0055",
"editorGutter.addedBackground": "#fc4384",
"editorGutter.modifiedBackground": "#9765c9",
// Selection and matches
"editor.selectionHighlightBorder": "#e18cc9",
"editor.selectionHighlightBackground": "#635985",
"editor.selectionForeground": "#eff8ff",
"editor.findMatchHighlightBackground": "#ff2b7c8e",
"editor.hoverHighlightBackground": "#ff000013",
"editor.lineHighlightBackground": "#2b2b2b50",
"editor.lineHighlightBorder": "#00000000",
"editorOverviewRuler.bracketMatchForeground": "#635985"
}
},
// --------------------------------------
"editor.defaultFormatter": "esbenp.prettier-vscode",
// Markdown
"[markdown]": {
"editor.quickSuggestions": {
"comments": "on",
"strings": "on",
"other": "on"
}
},
// JSON
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// JavaScript
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// JavaScript + React
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// TypeScript
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// TypeScript + React
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// JSON with Comments
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// HTML
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
// ----------------------------------
// ESLINT
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
// --------------------------------------
// ERROR LENS
// "errorLens.fontSize": "11",
// "errorLens.onSave": true,
// "errorLens.enabledDiagnosticLevels": ["error", "warning", "hint"],
// "workbench.colorCustomizations": {
// "errorLens.hintForeground": "#ffc600A1",
// "errorLens.hintBackground": "#ff00dd2f",
// "errorLens.errorBackground": "#ff000005",
// "editor.selectionBackground": "#ff1493",
// "editor.selectionHighlightBackground": "#ff1493",
// "editor.findMatchBackground": "#ff1493",
// "editor.findMatchHighlightBackground": "#3cb371"
// },
// "errorLens.exclude": ["never (read|used)"],
// --------------------------------------
// LANGUAGES SPECIFIC
"javascript.updateImportsOnFileMove.enabled": "always",
"security.workspace.trust.banner": "never",
"emmet.includeLanguages": {
"typescript": "typescriptreact",
"javascript": "javascriptreact"
},
"cSpell.userWords": [
"Appbar",
"asyncstorage",
"backgrounded",
"backoff",
"Cacheable",
"cancelation",
"Chakra",
"concurrencies",
"Contentful",
"Ecommerce",
"Entypo",
"Firestore",
"Grammarly",
"Ionicons",
"launchable",
"nocheck",
"Parens",
"Podfile",
"prefetch",
"Pressable",
"Transifex",
"Turborepo",
"undeployed",
"Vercel",
"vercelians",
"yantramanav",
"zustand"
],
"git.autofetch": true,
"cSpell.language": "en,en-US",
"cSpell.enableFiletypes": ["markdown", "mdx"],
"editor.inlineSuggest.enabled": true,
"github.copilot.enable": {
"*": true,
"yaml": true,
"plaintext": true,
"markdown": true
},
"workbench.colorTheme": "Expo Light",
"window.commandCenter": true,
"customizeUI.fontSizeMap": {
"13px": "12px",
"12px": "11px",
"window-title": "12px", // Window title font when using custom titlebar
"tab-title": "12px", // Used for editor tab titles
"monospace": "11px" // Used for monospace fonts in user interface
},
"react-native-tools.showUserTips": false,
"errorLens.fontSize": "12",
"grammarly.files.include": [
"**/README.md",
"**/readme.md",
"**/*.txt",
"**/*.md",
"**/*.mdx"
],
"css.lint.unknownAtRules": "ignore",
"workbench.editorAssociations": {
"*.js": "default"
},
"githubPullRequests.pullBranch": "never"
VS Code themes
I usually like to switch between a dark and a light theme.
For a light theme, I prefer:
- Quiet Light (built-in)
- Expo Light (based on Expo Docs)
For the dark theme where I spent most of my time with fairyFloss.
- fairyFloss
- Expo Dark theme (based on Expo Docs)
For file icons, I love Material-Icon-Theme.
VS Code extensions
- Auto Close tag
- Auto Complete Tag
- Auto Rename Tag
- Babel JavaScript
Bracket Pair Colorizer 2- VSCode now supports this natively. See How to configure VSCode Bracket Pair Colors Natively- Code Spell Checker
- Code::Stats
- Color Highlight
- Customize UI
- DotENV
- Error Lens
- ESLint
- Expo Tools
- GitHub Copilot
- GitHub Pull Requests and Issues
- Grammarly
- Highlight Matching Tag
- Indent rainbow
- iOS common files
- Material Icon Theme
- MDX - For syntax highlighting of
.mdx
files - npm intellisense
- Prettier
- Paste JSON as code
- React Native Tools
- Read Time
- TODO Highlight
- Version Lens
- WakaTime
- Word Count
Apps
10: Download browsers
- Arc Browser
- Google Chrome Login to work and personal Gmail.
- Brave Browser.
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
- Sync settings and switch “Developer Mode” on.
- Extensions that I use:
ImageOptim settings
The custom config I use for ImageOptim app:
Copy dotfiles
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
- Text:
- Colors: For the overall looks and appearance, I use Dracula Pro Color Presets created by Zen Rocha.
- 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.