Het is me al wel een fietsweek geweest. Vorige week dinsdag ben ik voor de eerste keer “Bosques” gaan doen, dat wil zeggen: gaan fietsen in Bosques de las Lomas. Vandaag was ik er opnieuw en ik moet zeggen: damn, dit is toch wel de eigen grenzen verleggen.
Hier in Mexico-Stad heb je een aantal fietsclubs. Die vertrekken vroeg in de ochtend voor een ritje. Je kan als je wil elke dag wel met een fietsrit meedoen.
Je hebt voor zover ik weet de clubs van de winkels (People for Bikes, The Service Course), van een koffiezaak (Rutas café) en dan een paar aparte clubs.
Ze adverteren hun ritten op Instagram. Het enige dat je moet doen is opdagen en meerijden. Vandaag ging ik mee met Compitas Cycling team.
In januari kocht ik mezelf een koersfiets en begon ik met de “social ride” van Rutas Café. Dat is een toertje in het Chapultepec park op de kaart hieronder. Je gaat een 5 tot 7-tal keer rond het park, en dan zijn er een aantal technische oefeningen om je fiets te leren kennen. Ideaal voor een beginner.
Wat ik ook veel doe is op zondag de ciclothon gaan doen: er wordt dan een 40-50km wegen in de stad vrijgemaakt voor fietsers om naar hartelust te fietsen. Dat is leuk, maar je moet wel bijzonder veel stoppen. Een goeie oefening voor de klikpedalen maar echt moe wordt je er niet van.
Na een 10+ keer naar de social ride te gaan en een 10+ keer de volledige ciclothon te rijden wou ik graag eens iets anders en uitdagender.
In augustus was ik even in België en checkte ik een stukje Ronde van Vlaanderen. Dat sterkte me om eens iets méér te proberen. Het klimmen in en rond Oudenaarde smaakte naar meer.
Nu, de twee ritten die ik erop heb zitten waren wel héél wat uitdagender dan ik verwacht had: een 600-tal hoogtemeters (ouch), een paar super snelle stukken… je moet je hoofd erbij houden. Het klimmen is niet evident maar de ontlading als je snel de berg afknalt is een geschenk.
Mijn truukje vandaag was tellen tot 60 en blijven trappen, maar soms stond de mentale teller op 80+ en was ik nog altijd aan het trappen. Ik ben één keer moeten afstappen wegens te steil; en nog één keer moeten afstappen wegens probleempje met de ketting. Dat kan beter.
Ook nog: het is hier fietsen op 2240 meter, dus een klein beetje “permanente hoogtetraining” ook.
I’ve been doing some digital digging while creating some much needed backups.
I found this old map project where I was trying to put markers on a map. I remember I made that project when I just arrived in Mexico. I had implemented it in Svelte and in React but I was not very happy with it. That led me to try to make an iOS app simply by prompting.
I’m a firm believer that we all stay the same person. Let’s say you are interested in something 10 years ago, there is a big chance you are still interested in it today.
In this sense it’s sometimes interesting to look at some work from a few years ago, to relate it back to today. Maybe you acquired some new skills, maybe there is some external factor that can help push it forward. This could be a new person in your life with certain skills, a market shift… an LLM perhaps?
I tried to take a structural approach to look through all my old code.
I started making an index of every repository I ever made along with the reason why I made it. For every repository I read the README (if there was one, heh…) to figure out if it was my code or someone else’s and what the context was.
For some projects I tried to run them locally to get a sense of what I was doing. For others I just know what it was, typically when I worked on it long enough.
I tend to keep my websites in the macOS ~/Sites and then never really organize that folder (except for making some Archive type folders and dumping everything in there when I am ready for a clean slate).
Every computer I’ve ever had at one point has 50+ folders with different websites in it, mostly for various work reasons but also a lot of them free time experiments.
So far the trends of my digging reveal:
The repos for the end of year list projects, such as Best of 2019 (and 2018, 2017…) – I seem to like making lists and experimenting with new technology.
The repo for Clank – an early (2013) framework for trying to do web apps with animated views. The trend is that I dislike native apps, not because of their UX, but because of walled gardens and for having to write software multiple times. This is still true.
I also found several re-implementations of Kana Master, but in Svelte: same trend here, why can’t a cool app be a web app?
Keynote Extractor – this is an old macOS app to convert Keynote files to HTML-based presentations. Again this is related to my belief that you want info to be public & spreadable; locked up in a .key file somewhere on a computer is the opposite of that.
Some OCR-related repo’s: I’ve always been interested in data transformation and OCR, mostly for efficiency reasons as a designer. The Screenshot to Layout project came from that interest.
Some WordPress related things: I’ve always found WP to be an amazing community project and a great CMS. I hope the recent rummagings will not affect WP as a project.
Why am I doing all of this digging? I am actively looking for a new direction (see my posts about that) and I am checking out what interested me in the past.
Projects that I never finished; projects that deemed impossible at the time; in all that old code, I figure there must be something there.
This is a preview of the Obra Icons 2.0 blog post. Obra Icons 2.0 has not actually been released, but I am looking to gather feedback via this blog post about the changes and the proposed API.
I started working on Obra Icons in August 2023 with a first release in november 2023.
Now one year later, the project is stronger than ever with it’s 2.0 release. It grew from 350 icons to over a thousand icons; and the quality of the set has vastly improved.
Just two weeks ago, we released a React package and a Figma plugin, to be able to use the icons in more contexts.
So why 2.0? There was still a missing piece in the drawings, where I found the quality of some filled icons subpar, especially for the different stroke weights. To fix this I revised the drawing technique of the icons in full. The errors are very apparent in this example from 1.0. Notice that when changing the weight, the outside shape would not change along:
This was a fundamental problem caused by the way they icons were drawn. In the new version, the icon variants looks like this:
When I started Obra Icons, I was looking for a way to be efficient in icon creation and to have variants of icons generated from the same source. The idea was to generate the three stroke variants (2px, 1.5px, 1px) from the thickest variant (2px).
However, for filled icons, to get to the desired equivalent of a stroke icon (one that looks good when hovering over it), you often need to do a few operations:
find any enclosed shape
fill the equivalent stroke shape, but with a stroke on the outside
flatten that shape
apply boolean operations (often subtract) for whatever is inside these enclosed shapes (often a + icon, an arrow, something small)
The result of these boolean operations on the top level of the boolean operation is a filled layer, where it’s not possible anymore to adjust the thickness. You can keep the source in Figma for easy adjusting, but when exporting boolean groups, you will always end up with a fill-based path anyway.
The source of Obra Icons 1.0 was a flat list of icons where an icon might or might not have a filled version. You would have a frame called oi-umbrella and another one called oi-umbrella-fill.
In the source of Obra Icons 2.0, every icon has a top level frame, for example oi-umbrella, with 6 child frames: 2-stroke, 1.5-stroke, 1-stroke, 2-fill, 1.5-fill, and 1 fill.
Through a combination of plugins, scripts and a ton of manual work, I converted all 1000+ Obra icons to this new format.
The new format leads to a much higher quality level.
On the website you will see that there is a switch between “stroke” and ”fill”. The stroke icons contain the original lines, and can also easily be changed to other stroke widths — like 0.75 or 1.25 — by changing stroke-width in CSS. The filled icons contain a flattened version of the vectors and are restricted to the three base sizes. Changing strokes will have no effect since everything contained in those icons are fills.
For the website imports, every existing import will still work without changing anything.
import { IconAdd } from 'obra-icons-react'
When you change the icon through the props, you will be served a different source:
<IconAdd weight={2} type="fill" />
The strokeWeight prop was changed to an overall weight prop (defaults to 1.5). A type property was added. It defaults to stroke, but you can set it to fill.
The size and color attributes stay the same (where color accepts any CSS color):
<IconAdd weight={2} size={64} color={red} />
If you would look at the source of every Svelte or React components, you will see that it actually contains multiple sources to allow for the flexibility of changing the weights and having it look correct. You will see that these give an error when trying to use combinations the set was not designed for.
Make sure you use a bundler that removes unused code paths (which should be any bundler nowadays). This logic provides the best developer experience: you can tweak the style of an icon easily, and never have to rearrange your imports.
Migrating existing projects
To migrate existing projects, install the relevant obra-icons package with a new major version number:
npm update obra-icons
To migrate existing projects, you would change every strokeWidth prop to a weight prop. Every import of an icon that is a filled icon, for example IconAddRoundrectFill, you would take of the Fill part and add a type="fill" as a prop.
All in all, I am happy with this quality improvement, and to take Obra Icons to the next quality level. Onwards!
My Obra Icons project has always been available from the website, but now you can also use the Figma plugin. Earlier this week, we also released a package for React. Any feedback is welcome!
Yesterday I took the idea of prompting to make an iOS app much further than with my experiments of last week. I have this web-based version of a currency conversion app – which you can try here – and I converted most of the logic to an iOS app.
I wanted to see how far I could take things. After an intense 7-ish hours of working on the app (and at least 3 coffees) I had something that I almost consider releasable to a general public.
This is a video of the almost-final result, where I was testing some non-phone cases:
When reading this post, keep in mind I am not a developer by trade, I am a UI/UX designer that likes to make front-end prototypes, but most of the time sticks to designing in Figma.
The only apps that I (mostly) coded myself are Screenshot to Layout, a Figma plugin and Obra Icons, my icons project. My day job is design.
After recording this, I fixed a few more bugs and called it a day. About the app itself:
I first implemented the basic functionality: calling the API, making sure you could convert between 4 static currencies
Then I implemented the ability to change currencies. I was impressed how the default List in SwiftUI handled item deletion without needing any custom implementation.
I then implemented how to hide the API key secret in a proper way, using a Secrets.xcconfig file
I implemented a custom logic for the cursor and text field to work in combination with the virtual keyboard, so that the keyboard can stay on the screen whenever the fields have a value.
I learned how to work with Localizable.xcstrings to provide a dictionary for localisation. The app is currently working in 7 languages and I can easily add more.
I tested the app for accessibility with VoiceOver and it worked fairly well.
Then I went on to make things look nicer. I learned more about SwiftUI layout (VStack, HStack, Spacer, and their modifiers). Also, using the system colours (Color(.systemGray6) and font logic (.font(.caption))
Finally I tested the app for several cases like dark mode, iPad usage and horizontal usage
Using the app on my real device led to some findings, for example when you kill the app, the chosen currencies should persist in some sort of user storage. I fixed that.
In the workflow atmosphere, here’s my notes about how I worked:
I used Claude in the browser until I ran out of credits, at one point it was 1PM and it said I didn’t have credits until 4PM. I then switched to using Cursor Pro using Claude Sonnet 3.5 in the background. (I actually cancelled my ChatGPT subscription recently)
I used a single large ContentView.swift (936 lines now) so I could easily paste that into Claude.
When I switched to Cursor, I would have it just survey the whole codebase using ⌘+Enter.
I never used the composer feature in Cursor, not sure if I am missing out. This feature can work across multiple files. Might be useful if I restructure the code.
In general, I could copy paste the answers of Claude into my code to provide the fix. In the Cursor workflow, I would not have Cursor apply the changes but I would do it manually so I could read what the code was actually doing, to get a better sense of my program instead of blindly copy-pasting.
I sometimes found myself on the Apple docs to find out how certain APIs behaved or what was the expected input, but this was rare.
Sometimes, proposed changes would lead to a compile error, after which I would put both the code state after the provided change, and the error as a separate artifact in Claude. This would usually lead to Claude understanding how to fix the problem. This problem happened less in Cursor since it understood my whole codebase and a compile error is usually the result of multiple files not matching up.
Sometimes I would have to backtrack on my working code, so I kept a git repository in the background with checkpoints. In general, there was not that much backtracking.
I sometimes asked Claude how to fix things with screenshots where I would put clear red or blue lines or arrows on, and then asked with a prompt how to fix the “alignment here”. Claude understood that I was talking about the area marked in the screenshot.
I also manually edited some parts in XCode for clarity, or when I knew how to continue coding myself and it made more sense to change it myself instead of prompting.
All in all I am extremely impressed with this workflow.
It was fast because I didn’t have to bother with implementation details like the exact shape of API calls or how fetching data actually works.
I didn’t have to bother thinking about syntactical details like for example why there is a backspace in this code .environment(\.locale, Locale(identifier: appSettings.language.rawValue) or why the last step in storing data after retrieving it from the API is a .store(in: &cancellables). All of this was handled by prompting and putting some functions logically together (fetchAvailableCurrencies / fetchExchangeRates etc.)
I am sure you can learn to get good at all of that stuff and learn each API by hand, but really, at some point it’s maybe better if a machine talks to a machine than that I as a person need to worry about matching 2 data shapes.
I feel like I’ve gotten some app creations superpowers, enabling me to not get stuck at the point that I used to get stuck (the data part).
There’s still much more to do to make the app the ultimate quality and have something shippable that I am proud of, but I am so happy with the progress so far.
With my “newfound” prompting superpowers, I tried to generate the code for an iPhone app and see how far I could go.
Once again, I was pretty amazed by the Claude/Cursor workflow. In a rather limited time I had the scaffolding for a wedding app done. I ended up getting a subscription to Cursor which I believe is totally worth it.
The idea behind the app is that it shows a map of locations and a calendar, so people can have a reference of things they could do around a wedding. For destination weddings, there is also travel involved, so people might want to receive the couple’s specific tips for a neighorhood.
This idea could also be transformed to a generic “travel guide” type of app, where you have lists of things to do around a certain location.
My tests creating a native iOS app went well. I was able to implement:
A table view with some important dates for the wedding (the calendar tab)
A map view with markers, where each marker shows a sheet with info
Within the sheet with info, details about said location
Location permissions and the ability to see your own location
Basic support for iPad
SwiftUI is pretty elegant and readable.
The only problem with the code generation at this point is that it doesn’t really know how to fix some issues around scrolling and combining views. It tries to fix things by wrapping (scrollable) NavigationViews into each other ultimately creating so many problems you have to revert back to working code.
Also, the iPad implementation was kind of broken from the start and I had to prompt quite a bit to fix it. I am sure a senior iOS engineer looking at the specific code to “fix” the views would avert their eyes in horror.
Another thing that I haven’t tried saving data to a database yet, and I can imagine that that part of dev might also lead to some “parts unknown” where I wouldn’t really know how to debug anything. I think prompting superpowers only happen when you have an idea of how you could fix code it generates, not when you are absolutely clueless. I have a fairly good grasp about how iOS apps work and should work (from designing them) – so I can prompt with the right terminology.
Anyway, I just wanted to report on my journey with these new tools as this is quite exciting.
Last work week I spent a good chunk of time on my projects Screenshot to Layout and Obra Icons. I also spent some time investing the hype around Cursor and oh boy… the hype is real.
I built a mobile-optimized Currency Converter app in a few hours of work mostly by prompting what I wanted. I estimate Cursor wrote around 80% of the code. I added some features that would be time intensive like language support for RTL languages, flipping the entire UI, just with a single prompt. Something like dark mode was just a prompt away too.
You might have seen videos of 8-year olds coding entire apps using Cursor. It’s pretty amazing what you can build. You have to be quite specific in your prompting but if you know what you want this is definitely a hyper productivity boost for a certain kind of work.
Naysayers will say this will lead to unmaintable code but in the prototyping/ideas stage most of my work lives in, the productivity is unmatched.
In my Twitter/X circle I see talented designers taking their product design skills to AI prompting and hacking things together that a few years ago really needed at least a 2 person team of designer and developer. For example Gabriel built Almanac and Christine a Chinese phrasebook app.
Around nine years ago I really needed a dev to help built Kana Master. Dev agency Underlined jumped in to help at the time. I believe current prompting abilities I could probably build that myself.
I haven’t tried creating anything in the iOS spheres yet (mainly because I don’t want to write the same software three times) but I am curious how far I could take things.
When I said I would quit my main contract my fiancée was worried about me finding new work – I told her that it would not really be a problem. In just one week I’ve been contacted for a short-term UI redesign project and to consult about implementing Figma in an organization.
I am exploring startup ideas, talking to different people about possibilities and overall enjoying some time figuring out what’s next. In the meantime I am available for short freelance opportunities.
My search for a new adventure is starting in earnest after some holidays.
Two weeks ago I wrote about two main options, one was getting a product designer role in a US startup/scaleup, the other one was restarting agency life.
I’ve been looking at jobs on read.cv and on workatastartup.com. Ideally I can find a role at a startup that does something exciting in the software space.
Another part of me thinks I should just build that startup. That’s been a lingering idea in the background.
The new agency idea seems pretty hard to pull off “from a distance” (my network is in Europe). I also feel like I could also do that in ten years, I don’t have to do it now.
I feel like I have to make use of the unique part of my life I am in now: no kids (yet), US time zone, easy flights to US, real-life access to build a local team (for example of local devs).
Back to the job sites – it’s pretty rare to see a cool job on the job sites. Some companies are already too big to do meaningful design work and make an impact. Most companies do something I can’t really get enthusiastic about (like crypto and blockchain things, ugh).
When I look at different companies I am focussed on the main ideas behind the company, their business model and (possible) engineering prowess. I am not stopped by a poor current state of design (I can come in to help fix that).
I applied to one company and got rejected outright because of my location in Mexico. Many US jobs are “US remote only” and “US and Canady only”. If anybody knows the logic behind that, I’d be happy to know. When I was an employer myself in Belgium, I didn’t like candidates outside Belgium for administrative reasons, so perhaps something similar is going on.
Some part of me thinks I need to fly to the US and network at the right conferences, but at the moment I don’t have a clear idea of where I would go or which conference makes sense.
In general, I plan to take enough time to find the right project/employer/business to work on and will be working as a freelancer while I figure it out.
I am available for freelance projects. Check out my portfolio to get an idea what I could help with and get in touch if you think I could help you with your project.
Fresh from the plugin press, this plugin by Vijay Verma provides some shortcuts to easily access important vector tools In Figma. This can help as a bit of a bandaid, since Figma’s UI team inexplicably decided to hide the vector tools behind extra clicks in UI3.
Did you know that macOS comes with some wonderful, super high quality fonts that normally cost hundreds or thousands of euros to license? I believe they came with an update to Pages templates a few years ago.
If you open Font Book — the app used to manage fonts on macOS — and then search for the fonts below, like “Graphik”- you can download the fonts directly there. These are fonts by some of my favorite foundries.