Setting up a Mac for development
Tags: node, php, setup, mac
Published: 2020-04-13 21:04:41

I'm no stranger to setting up a new machine for development. My love for shiny new equipment and almost bi-yearly machine wipes have got my process fairly tuned. Part 1 of this series is going to cover the initial steps of setting of a new Mac with a simple dev environment along with all the applications and settings I've come to enjoy.

1.  Homebrew
2.  Runtime management with asdf
3.  PHP & Laravel Valet
4.  System settings and the dock
5.  Bonus

## Homebrew

The benefits of using [Homebrew](https://brew.sh/) are two-fold. We often get access to all the packages and libraries we may need on our development journey, but also get a simple interface for installing applications without needing to navigate away from our terminal window. I like to install Homebrew right off the bat so that I can also sit back while brew cask installs the majority of my most critical applications.

### Installing Homebrew

First thing's first. We need to make sure we have the Command Line Tools installed before we can utilize Homebrew. Luckily, we're just a couple of copy/pastes away.

Install the Xcode Command Line Tools and Homebrew:

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

This will prompt you to agree to some terms and then it'll be off and running. On fairly quick internet it should only take about 5-10 minutes.

Once Homebrew has been installed we need to make it available by adding it to our `$PATH`. As of Catalina, Mac now uses Zsh by default so we'll echo the path into our `.zshrc` instead of a `.bash_profile`.

    $ echo 'PATH="/usr/local/bin:$PATH"' >> ~/.zshrc

As with any changes to our `.zshrc` we'll need to restart our terminal window to load the latest settings. Once we do that we can run verify that Homebrew has installed successfully with a simple command.

    $ brew doctor

Hopefully, everything goes off without a hitch and you're ready to brew.

## Installing Apps with Brew Cask

[Brew Cask](https://github.com/Homebrew/homebrew-cask) is a major productivity boost when handling the initial setup of our Mac. In addition to the normal brew install command we get another command called brew cask install that will download and install applications for us. This is just a starter list of apps I use and definitely suggest you customize it based on your needs.

    $ brew cask install 1password discord figma firefox google-chrome imageoptim iterm2 moom sketch slack spotify visual-studio-code

This list includes some core utilities like 1password, Image Optim, iTerm 2 and Moom as well as various browsers and design/development tools.

Going forward we can see if an app we want to install is available by using the default search command. If a Cask is available it will show up under a "Casks" section in the output.

    $ brew search moom
    $ ==> Casks
    $ moom

## Runtime management with asdf

No matter your preferred language you'll probably need to manage various versions of it as projects age. [asdf is version management](https://asdf-vm.com/) with community plugins for many (if not all) of the runtimes you'll come across.

### Installing asdf

Since we already set up Homebrew we can use that to install asdf. Open up Terminal (or iTerm if you've opted to install that in the last step) and install asdf:

    brew install asdf

asdf recommends adding a couple of lines to your `.zshrc` but since we installed it via Homebrew the autocompletion settings will automatically be configured for us. We still need to make asdf available though:

    $ echo 'export PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"' >> ~/.zshrc
    $ echo '. $(brew --prefix asdf)/asdf.sh' >> ~/.zshrc

At this point asdf would be good to go, but I like to add an optional configuration setting. By default asdf uses `~/.tool-versions` to automatically switch between versions. Some languages have their own way of managing versions. For example, Node will try to use a version specified in `.nvmrc` or `.node-version`.

To pick those language-specific version files we need to configure asdf to recognize them.

    $ touch ~/.asdfrc
    $ echo 'legacyversionfile = yes' >> ~/.asdfrc

Restart your terminal again and give it a test:

    $ asdf -v

### Preemptively Installing Packages

This step is also optional, but since I do a lot of exploring around various languages I always install the [common packages asdf suggests](https://asdf-vm.com/#/core-manage-asdf-vm?id=plugin-dependencies).

    $ brew install coreutils automake autoconf openssl libyaml readline libxslt libtool unixodbc unzip curl gpg

## Installing Node

asdf makes the installation of a runtime very simple. The Node installation is actually an example of one of the more complicated runtimes to install that I've encountered, but isn't at all intimidating.

First, add the asdf Node plugin:

    $ asdf plugin-add nodejs

Then we need to add the Node release team's OpenPGP keys. If you didn't install the the other packages you'll need to install `gpg`:

    $ brew install gpg
    $ bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring

We can now use the nodejs plugin to install a specific version of Node. To list all available versions we can use the `asdf list all <plugin>` command.

    $ asdf list all nodejs

I current have a project that I know uses `12.13.0` so I'll go ahead and install that.

    $ asdf install nodejs 12.13.0
    $ touch .tool-versions
    $ echo 'nodejs 12.13.0' >> ~/.tool-versions

Perfect. Node is installed and ready for us when we move onto building our site.

A quick tip: If you are going to install multiple runtimes you can populate your `~/.tool-versions` and run `asdf install` once. It will grab any runtime version listed in that file and install it.

## PHP with Laravel Valet

I know, I know.. we went through all the trouble of installing asdf and we aren't even using it to manage PHP. The way [Valet](https://laravel.com/docs/7.x/valet) handles PHP versions is already very elegant so fix it if it's not broken.

### Installing PHP, Composer & Valet

We'll kick off this step by installing the latest version of PHP with Homebrew. By default Valet will use Homebrew if you decide to use it to install additional versions.

    $ brew install php composer
    $ composer global require laravel/valet

These lines installs both PHP and Composer, PHP's package manager. With PHP and composer installed we can install the Valet package globally. In order to make sure we can call the Valet command we'll need to add it to our path.

    $ echo 'PATH="$HOME/.composer/vendor/bin:$PATH"' >> ~/.zshrc

Just like the other times we've edited `~/.zshrc` we can go ahead and fire up a new window so we have the latest config. Once we do that we can run Valet's install command:

    $ valet install

After installation we will be setup to use Nginx as our default web server. Dnsmasq is also installed to provide us with nice local urls. The default local tld is `.test`, but you can [customize](https://laravel.com/docs/7.x/valet#installation) this to whatever you'd like.

### Using Valet

Valet provides a simple interface for linking projects to use the Valet environment. Let's take a quick look at how we can use it.

    $ cd ~/projects/project-name
    $ valet link

After linking the directory our local site is now setup to run at `http://project-name.test`. Of course if you changed that tld you will need to adjust the url.

Valet also comes with the option to "park" itself in a specific directory where it will serve all of the child directories. Checkout the [documentation for using Valet](https://laravel.com/docs/7.x/valet#serving-sites) for more information.

## Tune system settings and the dock.

I'm not too hardcore when it comes to modifying system settings. I do have a couple of must have settings in relation to development.

### Hide/show speed of the dock

I like setting it up so the dock is hidden and appears when you hover near it. The only problem is the delay before the dock starts to appear and the duration in which it takes to transition is way too slow for my taste. These settings make it appear almost instantly with a slight animation.

    $ defaults write com.apple.dock autohide-time-modifier -float 0.25;
    $ defaults write com.apple.dock autohide-delay -float 0;
    $ killall Dock

### Organize the dock with blank spaces

Absolute necessity here. This snippet will add a blank space to your dock that you can use to organize your app icons into sections. Nothing triggers me quite like some messy icons.

    $ defaults write com.apple.dock persistent-apps -array-add '{"tile-type"="spacer-tile";}'; $ killall Dock

### Key repeat

Confession: I stink at Vim. I've tried. I've failed. I've tried again. I'm all thumbs. To do my best at keeping my hands on the keyboard I use my arrows, but have to crank up the key repeat speeds while dropping the delay before key repeating starts.

    $ defaults write -g InitialKeyRepeat -int 10
    $ defaults write -g KeyRepeat -int 1

These changes will take affect after a logout.

### Remove screenshot shadow

Sharing screenshots has long been apart of my day to day communication flow. I use it to share snippets, work in progress dev work and communicate with my team/clients. To save a couple KBs I remove the shadow, plus I think it looks better.

    $ defaults write com.apple.screencapture disable-shadow -bool true;
    $ killall SystemUIServer

## Bonus

Here are some additional "nice to haves" that I setup on all of my machines. These aren't required in any way, but may be a good resource for you.

### Alias `rm` to `trash`

We've all done it. You get a little fast and loose with the `rm -rf` and completely wipe out a directory on accident. By installing `trash` and aliasing `rm` to it we can prevent a complete delete and instead just move our files to the Trash where we can recover them if needed.

    $ npm i -g trash-cli
    $ echo 'alias rm="trash"' >> ~/.zshrc

Now you can `rm` to your hearts content without worry.

### Updating Git

Apple ships with it's own version of git. It's not that it's bad or anything, it's just that updating can be tricky and since we're already using Homebrew to manage everything else, why not keep our git up-to-date using it.

    $ brew install git

### VS Code Plugins

The VS Code ecosystem runs deep. There is no lack of themes and plugins. Here are a few of my suggested plugins.

#### Dark Theme: Ayu Mirage PowerUp Theme

There are plenty of forks for the [original Ayu themes](https://marketplace.visualstudio.com/items?itemName=teabyii.ayu) and this mirage variant hits all the right buttons for me. Building on top of the original it adds bold & italic fonts as well as more distinguishable colors and contrast. It's just a joy to work in.

    $ code --install-extension geisslerh.ayu-mirage-bold-italic

#### Light Theme: Night Owl Light Bold (More Contrast)

I may be in the minority here but I actually enjoy working in light themes at times. Specifically day time. After only using a dark theme 24/7 for quite some time I've noticed my eyes not straining as much after making this switch. The [original Night Owl theme](https://marketplace.visualstudio.com/items?itemName=sdras.night-owl) was made by the mighty [Sarah Drasner](https://twitter.com/sarah_edo). As with most themes people take it and tweak it to their needs. The "Bold (More Contrast)" portion of this fork is what really got my attention

    $ code --install-extension feego.night-owl-light-bold-more-contrast

#### Relative Path Extension

It's always hard setting up relative paths. This extension makes it easier by automatically inserting the relative path of a file you specify. Using the hotkeys `cmd + h` to bring up the prompt, you then search for the file and hit enter to insert the path. It's a real life saver in those deeply nested directories.

    $ code --install-extension jakob101.relativepath

#### Settings Sync Extension

I jump between a Mac Mini and a Macbook Pro. To keep my VS Code settings in sync there is a great plugin aptly named "Settings Sync." Connecting this plugin to Github will give you the ability to sync your settings by storing them in a gist and automatically updating it whenever your settings change.

    $ code --install-extension shan.code-settings-sync

Let me know how you like to setup your machine on [Twitter](https://twitter.com/kidqueb). I'll do my best to help you debug any issues you run into during this process too.