
Development · · 6 min read
My MacBook Air M4 Developer Setup
- Productivity
- Next.js
- Django
- Flutter
I run Next.js, Django, PostgreSQL, Flutter, Figma and a couple of coding agents on a fanless laptop, and it handles it. Here's how my MacBook Air M4 is set up, what I install first, and what I deliberately leave off.
People are often surprised that I don't use a Pro. For the work I do, mostly web apps with a Django backend and the occasional Flutter build, the Air has been more than enough. It's silent, the battery gets me through a full day of work away from a desk, and it's light enough that I actually carry it. When power cuts were a regular part of life here, battery life would have been the top spec. It still matters to me more than raw cores.
This isn't a list of every app I have. It's the setup I'd recreate from scratch if I got a new machine tomorrow.
The order I set things up
On a fresh Mac I go in roughly this order, so each step has what it needs:
- System settings and security
- Command Line Tools and Homebrew
- Terminal and shell
- Git and SSH keys
- Language runtimes: Node, Python, Flutter
- Databases
- Editor and AI tools
- Design and everyday apps
System settings first
A few changes I make before installing anything:
- FileVault on. Client code and credentials live on this machine.
- Key repeat fast, delay short. Holding a key to move through code should feel instant.
- Show file extensions and hidden files in Finder.
- Dock on auto-hide, small. Screen space on a 13-inch display is precious.
- Hot corner for lock screen. I lock the laptop every time I step away from it.
Homebrew and the terminal
Everything that can come from Homebrew does. I keep a Brewfile in a private dotfiles repo, so a new machine is mostly one command:
xcode-select --install
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew bundle --file ~/dotfiles/BrewfileThe core of that Brewfile looks like this:
brew "git"
brew "gh"
brew "fnm"
brew "uv"
brew "postgresql@17"
brew "ripgrep"
brew "fd"
brew "jq"
brew "bat"
cask "visual-studio-code"
cask "figma"
cask "raycast"
cask "rectangle"I stick with zsh, which is the macOS default, and keep the config short. A small prompt that shows the git branch, a few aliases, and that's it. I've wasted enough evenings tuning shell themes to know it doesn't make me faster.
# ~/.zshrc (the parts that matter)
eval "$(fnm env --use-on-cd)"
alias gs="git status -sb"
alias dev="npm run dev"
alias dj="uv run python manage.py"The dj alias is the one I use most. dj runserver, dj makemigrations, dj shell all go through the project's own virtual environment without me activating anything.
Git and SSH
One SSH key per machine, added to GitHub, with the passphrase stored in the macOS keychain. I also sign commits with the same key, which GitHub supports now and is much simpler than setting up GPG.
ssh-keygen -t ed25519 -C "sudip@macbook-air"
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global pull.rebase true
git config --global init.defaultBranch mainNode, Python and Flutter
Node: I use fnm to manage versions. Projects have a .nvmrc or engines field, and fnm switches automatically when I cd into a folder. My Next.js 16 projects all run on current LTS. With Turbopack as the default bundler, dev server start and hot reload on the M4 are fast enough that I stopped noticing them.
Python: uv replaced pyenv, pip and virtualenv for me. It installs Python versions, creates the environment, and resolves dependencies faster than anything I used before. For a Django 6 project, setup is:
uv sync
uv run python manage.py migrate
uv run python manage.py runserverFlutter: I install the SDK, then Xcode from the App Store and Android Studio for the Android SDK and emulator. This is the heaviest part of the setup by far. Xcode alone takes a big chunk of disk. I build Kanjiro, my Japanese-learning app, on this machine, and iOS simulator plus Android emulator running together is where the Air gets warm. It slows down a little under long sustained builds, since there's no fan, but it's never been a blocker for me.
Databases
I run PostgreSQL natively through Homebrew rather than in Docker. On a laptop with limited memory, not running a Linux VM all day makes a real difference.
brew services start postgresql@17
createdb novarestro_devEach project gets its own database. For anything on Supabase, I point the local app at a separate dev project rather than production. I don't keep Docker running in the background. When a project truly needs it, I start it, use it, and quit it.
Editor and AI tools
VS Code is still my main editor. The extensions I actually keep:
- ESLint and Prettier for JavaScript and TypeScript.
- Tailwind CSS IntelliSense. With Tailwind v4 it reads the CSS config directly.
- Python and Ruff for the Django side.
- Flutter and Dart.
- GitLens, mostly for blame and file history.
- Error Lens, so problems show inline instead of hiding in a panel.
AI is part of the setup now, not an extra. I use Claude in the terminal as a coding agent and keep ChatGPT open for quick questions and rubber-ducking. Each repo has an AGENTS.md describing the stack, folder structure and conventions, so the agents don't guess. I wrote about how that changed my workflow in how AI changed the way I build software.
Design and everyday apps
- Figma, desktop app. Every project starts there, as I described in my Figma to production workflow.
- Raycast replaces Spotlight. Clipboard history and window snippets alone are worth it.
- Rectangle for window snapping with keyboard shortcuts.
- Chrome for development, with a separate profile so extensions don't interfere with testing.
- TablePlus for looking at databases when psql isn't enough.
What I deliberately don't install
- Antivirus suites and "cleaner" apps. macOS handles this, and these apps mostly slow things down.
- Every new AI editor that launches. I try them, then usually go back. Switching editors costs more than most features save.
- Heavy menu bar utilities. Each one is small. Ten of them are not.
- A local Kubernetes setup. My deployments are Nginx and Gunicorn on a VPS, or Vercel. I don't need to simulate a cluster on a laptop.
Habits that keep it fast
- Restart weekly. Long-running dev servers, simulators and browsers leak memory over days.
- Clean build artifacts. Old
node_modules, Xcode derived data and Flutter build folders quietly eat tens of gigabytes. I run a cleanup every month or so. - One project open at a time. Two Next.js dev servers, a Django server, a Flutter emulator and Figma together is where I start to feel the limits.
- Back up dotfiles, not the whole machine. The repo plus the Brewfile means a new laptop is an hour of setup, not a weekend.
Where I've landed
You don't need the most expensive machine to do serious full-stack work. You need a setup you understand, a short list of tools you actually use, and the discipline not to pile on more. The Air M4 is quiet, portable and fast enough for everything I build, and the setup above is boring on purpose. Boring means I spend my time on the project, not on the laptop.
If you want to see the rest of what I build with, the tech stack post covers the frameworks and services side.
