Software development on an iPad Pro
Looking back at all the work I did over the last decade one thing was mostly constant: how my system was setup, which tools you could find on it and how I worked on projects. But things changed a little bit when I decided to do more work on my iPad. When traveling I usually do not write a lot of code, if any at all. But incidents happen or sometimes there is simply enough downtime to get some coding done between meetings, mentoring and architecture sessions. When traveling I usually focus on those three things and the iPad is the perfect device for me for all three of them. But writing code? I usually had a MacBook with me for that.
If your first thought reading this article is “everything comes around, he is talking about thin clients” you are not that far off. But first let us take a step back and talk about the things I did not particularly like about my old setup.
Dependency management. Jumping between legacy projects and greenfield / explorative projects usually means different versions of a compiler or interpreter, different versions of libraries, sometimes incompatible with each other and service dependencies in various versions like databases or key value stores. There are some solutions to this problem, but none that are mostly seamless and pain free to use. And even after those problems are solved you might not be able to run the production version of a dependency on your laptop which means you either end up with some form of Docker or VM setup or you yolo through development and hope the CI does its job well.
Reliance on one system. I obviously backup data, configs and usually the whole system. And document how to setup a project. While this might not be the case for every project you will ever touch, it should be. But what happens when your system is damaged or stolen while you are traveling? You likely buy a new one and start setting up everything as good as you can – maybe you are lucky and got a backup with you. If you do not trust your own hardware you can provision an instance hosted by one of the larger cloud providers.
Keeping systems in sync. You would expect this to be a solved problem considering all the options to synchronise files across multiple devices. But the moment you add caching and database systems, maybe an S3 compatible server to test against the actual API things get a lot trickier. I usually synced my MacBook, which was unused for weeks somewhere on a shelve, a few days before traveling. You read that right, I had a MacBook which I touched three to four times a year. I do not work on the couch or in the living room. I might read a bit, pull up a code review, maybe draw an architecture diagram from time to time, but I do not sit on the couch coding. When I write code I am in my office in front of my iMac. With the screen positioned at a suitable high, on a proper chair with all the bells and whistles to make it as comfortable and ergonomic as it can be.
When macOS Catalina was released I did a clean installation on my iMac Pro and promised myself to not install project related software or dependencies on it anymore.
So I started out with the most obvious solution. PyCharm with a remote interpreter setup. With one VM powered by Parallels for each project running the Linux distribution and dependencies mirroring production. Now some might be curious why I opted for Parallels and not Docker. I am more comfortable using a real VM, it is way easier for me to configure, work with, snapshot – including the filesystem – and resource usage was roughly the same. Parallels is shockingly good at managing resources. Also I am working on a way to powerful iMac Pro for simply putting text in a file, resources are plenty and if they were not it would be cheaper to acquire more resources than spend my time on bending Docker to my will.
This worked nicely for a side project and the Node.js stack we are using at Nurx. But it tied me to my iMac, which was not optimal considering that I will surely not ship it to where I travel. So I had to figure out how to write code on my iPad.
One solution many people figured out before me is pretty simple, especially when you wrote code while the year started with a 1. Vim. Well, a slightly newer fork – NeoVim. Together with CoC which brings the Language Server Protocol to NeoVim it seemed like a pretty good choice. And it is. Together with Blink the experience is actually really nice. A few days in I was starting to remember why I did not like vim when more complex plugins were being used – debugging why it stopped working is a nightmare. I already see the die hard vim fans lining up to tell me this either never happens or that I should not be using plugins at all – good points, thanks for the input, moving on.
I started to explore browser based IDEs. I knew about Eclipse Che and if this would be the answer I would be ordering a 16″ MacBook Pro right now. Other options were worse in some aspects. But someone, somewhere did something smart. They took a desktop editor which can be bloated with plugins to behave like an IDE build with web technology and made it possible to run it as daemon and connect to it via a browser. code-server brings VSCode to the browser. In nearly all its glory. And it actually works really well.
Here is the summary on how you use it:
- download latest version
- start it and point it to your project directory
- there is no step three
It is simple. It is powerful. It is well supported with a ton of plugins. And it is actively being maintained. Even Microsoft is working on making VSCode viable from anywhere. The integrated terminal means I do not have to run two apps side by side on the iPad to work on code, but can simply keep a browser open.
This seems like a pretty decent setup to work with. But it still forced me to keep two systems in sync. I tried using code-server as main development environment for a bit, but constantly switching to the correct browser tab or running a different browser for easy access was a bit annoying.
The good news is that Visual Studio Code with its remote capabilities solves all of this. I can connect to the exact same box code-server is running on and once settings sync is setup keeping the editor configuration the same should be fairly straight forward.
Moving to Visual Studio Code was nearly painless. It does not really use much more resources than a Java based IDE – what a benchmark, I know. IntelliSense works really well except for Djangos models which, thanks to an obscene amount of meta programming, always causes some problems for completion providers and I am still impressed how well JetBrains solved this problem. Debugging is not implemented as nicely as you are used to by some IDEs, but more than functional enough and it is improving. Overall I am happy with it. I always eye NeoVim and think it would make things a bit easier, but somehow the VSC setup feels good, so “meh”.
Let us talk about accessories for a bit. You want a keyboard and a mouse. Thanks to iPad OS you can use a mouse and for the sake of comfort and usability you want one. The cursor is stupidly large, I hope they will introduce an option to make it more like a regular one at some point. Other than that it works really well. Except when you want to use a Magic Mouse which needs like five additional steps to pair and is horrible to use – makes sense, right? I chose to get another Logitech MX Ergo, I really like trackballs and this one is amazing. As keyboard I chose a Magic Keyboard. Works really well, it is light and easier to transport. I tried the Smart Folio Keyboard for the iPad, but I neither like the tilt when the iPad is standing in it nor the feel of the keys. As a stand I am using the standard Smart Folio which I like from a viewing angle and can easily put it on a box or some books to elevate it when I feel like it. Luckily all three choices are easily replaceable with whatever you prefer.
There is another reason I like this approach, even if it was not the driving factor. Cost. A decent server for the basement in my basement, regularly updated is cheaper – as in total cost of ownership – than an iMac Pro or Mac Pro. I do not believe Apples hardware is overpriced, it provides a lot more than what the server needs in this case. The server needs CPUs, memory and storage. Fast and a lot. I currently run 40 cores with 256GB memory, an SSD raid and one NVMe. This is is fast. It has more resources than most people need. I can run a whole production stack of some startups from memory, including all the data. If you do not want to host hardware some instance somewhere in the cloud might do the trick and with only running it while you actually work this can be relatively cheap.
Now comes the tricky part – what would I use as desktop? I could actually use the server itself. I could connect my iPad to an external screen, but sadly this messes with the resolution and keeps the iPads aspect ratio which is annoying to look at and I would prefer some window management capabilities for more than two apps for my primary driver, even when I primarily work with one or two windows on screen – Samsung DeX handles this pretty nicely. I could use an Asus ChromeBit. Maybe Apple comes around and fixes all annoyances when connecting an iPad to a larger screen.
As long as I have to occasionally work on iOS and Android projects my iMac Pro is here to stay. The “iPad coding setup” works extremely well for web development and some data / reporting / analytics related projects – the Jupyter client Juno Connect is amazing – but I currently do not see any nice way to get full desktop access on a remote system. This includes VNC, Jump Desktop and RDP. Believe me, I tried.
So how did this setup treat me so far? Excellent. I have been using it for over three months now. I spent roughly 10 days working only with the iPad which equals one long business trip. I never felt limited in any way and even tried to put more time in coding to see if I can find any problems when using it for longer periods than I expect my regular use to be. In the long run I might consider provisioning a VPS before traveling (maybe I can setup a LXC sync with proxmox – which is currently powering my VMs) just in case something happens at home and my VPN is down or the server is literally on fire. I would prefer to not have to re-provision my environment during a trip, which I could since all configs are in git and accessible to me, but this would also require VPN access to my home network, so the single point of failure is the same. Since most work is happening in the browser latency was not really an issue. Can I recommend this setup to everyone? The answer is clearly “no”. But I can say it is more than functional and might work well for you if you give it a try.