# Daniel Immke - Complete Blog Content
> Personal website and blog by Daniel Immke, a software engineer and designer. Writing about web development, design, open source, and working in tech.
> This file contains the full text of all published articles.
> Site: https://daniel.do
## My favorite thing to do with AI doesn't really have a label
- URL: https://daniel.do/article/my-favorite-thing-to-do-with-ai
- Date: 2026-03-17
Today I came across an attention grabbing [headline on Hacker News](https://news.ycombinator.com/item?id=47414799) -- a New York Times op-ed piece by two criminologists describing a "true crime community" online where mass shooters earn saint status and attack footage gets archived and analyzed. The comment thread there decried the article as being too surface level and alarmist and instead pointed to a lengthy cultural criticism essay arguing that America has a nihilism problem, which is actually the *real* root cause of this. I didn't actually read either article. Instead, I pasted them into Claude and asked for detailed summaries.
After reading the summaries, I did something I've been doing more frequently lately. I started talking to Claude about it -- my initial reaction, asking follow-up questions, pushing back when something didn't track with my intuition. And over about an hour, through a conversation I didn't plan and couldn't have predicted, we ended up somewhere genuinely interesting. Not about mass shooters specifically, but about how complex systems produce consequences nobody designed.
I haven't written a blog post in a few years. In the intervening time, AI has made massive progress -- I use it every day now and love it. The same way I wrote about TikTok in 2022, I've wanted to write about it as technology that is transformative to my life. But I have resisted because I didn't feel like I had anything interesting to say.
Now that I find myself having these kinds of ponderous conversations with Claude more often, I thought it'd be a good angle to explore. People talk about AI in terms of what it can produce for you. Code, images, spreadsheets. This isn't that. It feels like something different - and worth writing about.
---
So here's where the conversation actually went.
I told Claude the nihilism as motivation framing bothered me but I couldn't quite say why. Then I figured it out mid-conversation: if "nothing matters" is really what these shooters believe, the logical response is apathy, not months of meticulous planning. A mass shooting takes enormous effort. That's not the behavior of someone who thinks life is meaningless. That's someone who desperately wants to matter.
That reframe opened things up. We talked about radicalization, how the mechanism is basically the same one that's always driven people into cults and extremist religious movements: a person in pain finds a community that offers a script for action. I asked how many of these shooters were involved in literally anything, any extracurricular at all. Claude found a study of 177 mass shooters identifying social isolation as the single most important indicator. Then I asked: what about kids in broke environments who feel the same way? Same vulnerability, different scripts. In a poor neighborhood, gangs are right there offering belonging and hierarchy. The suburban kid has none of that. Just a screen and a gore forum.
We landed on a term I found useful: social poverty. Not loneliness, which sounds like a feeling you can fix by reaching out more. Social poverty as a structural condition. Common discourse about America criticizes it: suburbia, no third places, primary social interface is a phone. You might have money and test scores. But the built environment is hostile to the kind of unstructured contact humans need. And nobody designed it that way on purpose. They were optimizing for privacy, safety, and square footage.
That's when I noticed what we were actually talking about. Not mass shooters. Emergent properties of complex systems.
---
I brought this up with Claude. It's tempting to look at these problems and conclude our society is uniquely broken, which is basically the nihilism essay's argument. But what if this is just a common side effect of the complexities of a society?
We looked at history. Medieval cities were dense, walkable, full of casual social contact. Also perfect incubators for plague. The printing press was optimized for spreading knowledge. It also enabled witch-hunting manuals and centuries of religious war. Same pattern every time: optimize for one set of values, get unintended consequences in a domain nobody was measuring.
Once I saw it that way, the doom dissolved a little. Obesity, declining birth rates, mass shootings: not evidence that civilization is uniquely sick. Evidence that we're in a civilizational transition, like every other one, experiencing the emergent costs before we've figured out how to address them. None of these were designed. They emerged.
Then I asked Claude the inverse: what are some positive emergent properties of right now? Global supply chains were built for profit. Unplanned consequence: the fastest vaccine development in human history, because the infrastructure already existed. Smartphones are probably damaging teenage mental health. They also put a camera in every pocket, which is why police brutality went from open secret to national political issue. That wasn't a planned feature of the iPhone.
We live in an age of actual miracles and we barely notice because the emergent costs are so visible and so loud. Both things are true at the same time. None of this was where I expected to end up when I pasted two links into a chat window.
---
This keeps happening to me. A couple weeks ago I had just finished the new Korean film *No Other Choice* and felt compelled to ask Claude why every breakout piece of Korean media (*Squid Games*, *Parasite*) seems to involve desperate poverty. That simple question turned into a conversation about chaebol wealth concentration, a housing deposit system that forces people into debt just to rent, and a generation of young people who've given up on marriage and home ownership. Then it got uncomfortable: South Korea is the best-case scenario for rapid capitalist development, and its own artists keep telling the world the system is crushing them. By the end I was arguing that modern Korean capitalism might be psychologically worse than feudalism for the people at the bottom, because at least a medieval peasant didn't have to internalize their position as a personal failure. I did not start the evening expecting to get there.
I was watching the TV show *For All Mankind* and realized I didn't actually understand why the US and USSR were so opposed. A basic question. Within an hour I was learning about Marx's stages of history, how every attempt at a moneyless society ended in famine or genocide, and what the 20th century might have looked like without the Bolshevik Revolution. By the end I was asking Claude whether it could even imagine political systems that don't already exist, and whether its trained biases were shaping everything I'd just learned. I went in curious about the Cold War and came out questioning the tool I was using to think about it. That kind of recursive, self-examining path doesn't happen when you're just reading.
These conversations share a structure. I come in curious about something, usually something I just encountered. I react to Claude's initial response with my own half-formed instincts. Claude engages with those, sometimes agreeing, sometimes pushing back. My reactions to the pushback generate new ideas. By the end I've arrived somewhere I couldn't have predicted at the start.
This was never marketed to me. Nobody told me to use AI this way. It emerged naturally from getting comfortable with the tool through more practical work: writing code, debugging, researching specific questions. At some point I just started talking to it. Not in a parasocial way. More like: I have a thought and I want to develop it, and this is the most responsive surface available to me right now.
The closest label I've seen is "thinking partner," but that implies something structured. A goal, a decision to make, a problem to solve. What I'm describing is more like thinking out loud with no destination in mind. I didn't sit down to figure out mass shooters. I sat down curious and followed the thread. The value isn't in arriving at a conclusion. It's in going somewhere you didn't know existed.
---
Most conversations with friends, even smart friends, require social calibration. You're managing the relationship while trying to think. You worry about monopolizing the conversation or sounding pretentious. The other person has their own tangents. They might not know anything about the topic, or they might know too much and have entrenched opinions. And honestly, most people aren't up for a 90-minute unstructured conversation about the emergent properties of suburban planning on a Tuesday afternoon.
AI removes all that friction. There's no social cost to following a weird tangent. No risk of boring the other person. No need to hedge your half-formed ideas. You can just think out loud and get back something useful to think against. The conversation can wander from mass shootings to the printing press to smartphones and nobody's eyes glaze over.
And then there's the part that matters most to me: you don't have to do any work beforehand. I didn't read those articles. I didn't go in with a thesis. I had two links and some feelings about the summaries. The AI meets you where you are. With a person, especially a knowledgeable one, there's an implicit expectation that you've done your homework before showing up. With AI, the homework happens during the conversation. You can be ignorant and curious at the same time and nobody judges you for it.
---
The obvious question is whether the thinking is actually good, or whether I'm just enjoying a mirror that makes me feel smart. I genuinely don't know. Maybe the emergent properties framing is shallow. Maybe an actual systems theorist would tear it apart. That's fine. The point isn't that every conversation produces a breakthrough. The point is that the thinking happened at all. I went from two article links to a framework for understanding unintended consequences across civilizations in about an hour. There's a cultural instinct to dismiss this kind of thing as "pseudo-intellectual," or something that two stoned people would cook up thinking they've made some profound discovery about the world. But I have really enjoyed my time thinking with Claude.
This post was ideated and partially written with Claude too. The conversation about mass shooters naturally turned into a conversation about the conversation itself, which turned into the idea for this post. I didn't sit down and decide to write about AI as a thinking tool. The idea emerged from using it as one.
AI didn't think for me. It couldn't have. The direction came from my own instincts, my discomfort with the nihilism explanation, my tendency to reach for structural causes instead of individual pathology. What AI did was remove the friction that usually prevents those instincts from going anywhere. It gave me a surface to think against, fast enough to keep up with the pace of my own curiosity.
I don't think this use case is going to stay obscure. It's too useful once you've experienced it. But right now, if you told most people you spent an hour talking to an AI about mass violence and suburban planning and the printing press and ended up with a theory about emergent properties of civilization, they'd look at you funny. Maybe this post is just me trying to make that less weird.
---
## Making noisy SVGs
- URL: https://daniel.do/article/making-noisy-svgs
- Date: 2023-11-30
> Adding noise texture with only code
* Addendum Dec 7, 2023
One of my ongoing fixations with the web is how improvements in technology inform web design. In an earlier post this year I [wrote about my theory](https://daniel.do/article/its-the-future-stop-using-jpegs/#some-background) that the increasing pixel density of displays galvanized the shift from photography to vector illustrations in the early to mid 2010s.
In recent years there has been a design trend that runs counter to this. Illustrations still rule in web design, but instead of clean, flat shapes there has been an emergence of texture, usually as part of a design’s lighting or shading and *usually* a “noisy” or grainy texture.
Studio Vellekoop & León
I’m not hip enough to know if this style has been assigned a pithy label, but I do enjoy it. At the same time, I find it frustrating — because as far as I can tell (the lack of examples I have seen in the wild supports this theory) there isn’t an easy way to replicate these illustrations with SVGs. They can probably be exported as such from illustration programs but it’s likely these applied textures are raster or if they are vector, quite large in size.
SVGs are an interesting subject to me, because the specification for them is dense and there are usually multiple ways to accomplish an effect. Most SVGs are simply exported directly from a graphics program and have a lot of inefficiencies etc… which has led to the emergence of tools like [SVGO](https://github.com/svg/svgo).
I’m not an expert on the subject (I feel like the older I get, the less I feel like I can claim that about anything) but in recent years have taken to hand tuning and occasionally writing my own SVGs from scratch so I am not a complete novice either.
I decided to give creating an SVG using this illustration style a shot. My goal was to use the regular SVG specification to write a simple illustration that had this noisy, textured shadow effect. An additional goal was for this illustration to be moderately flexible, something that could easily be turned into a component in Svelte or React and changed for different shapes and colors. For more direct inspiration, I looked to the designer Josh Warren who has experimented a lot with using this style and simple geometry to nice effect:
Josh Warren
## Basic shape and gradient
Drawing a circle or square in an SVG is really easy. There are primitives for them.
```html
```
The tricky part is everything else. If you want to apply a gradient, you can specify that as the `fill` - but what if you want a gradient that changes with the base color you specify? So you don’t have to define a custom gradient with specific colors if you want to reuse the component. Then you’ve entered [mask](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/mask) territory. The way masks work in SVGs is that you use the “colors” black and white to how you want a mask to work. It’s a little confusing, but I’ve tried to keep the code example simple.
(As an aside, I have to give huge kudos to MDN’s excellent documentation, this project could not have been done without it!)
This can actually be optimized a little more. We know we’re going to use the same circle shape multiple times, so we can define it once in ``, assign it an id and simply reference it with the [`use`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use) element. This makes the code a little more DRY:
```html
```
So we’ve got the shape and a gradient going, but how do we add a texture to that gradient? The answer is with a filter. [MDN’s documentation on SVG Filters](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Filter_effects) goes into better detail on the nuts and bolts of how filters work. I also found this [excellent article](https://tympanus.net/codrops/2019/02/19/svg-filter-effects-creating-texture-with-feturbulence/) that goes into great detail about creating textures for SVGs.
To create noise, I used the `` filter which is explicitly for generating artificial textures but required quite a bit of fiddling to get to my liking. Then, I had to use other filter effects to eliminate color variance and blend naturally with the fill color selected, and finally apply the filter to the circle.
## Result
```html
```
Full Demo
Adding a nice fill color and making the gradient a little more subtle and there we go!
With some additional playing around I was able to create [an illustration](https://danielimmke.github.io/noisy-shapes) I was quite happy with. It's not perfect, and notably renders differently in Safari than other browsers but it achieves what I set out to accomplish.
You can also check out the code in the [repository](https://github.com/danielimmke/noisy-shapes).
This method could certainly be improved with additional experimenting. It’s still a far cry from the complexity of some of the illustrations I linked, but I think it could potentially be refined to be usable in more situations.
#### * Addendum *Dec 7, 2023*
I submitted this post to Hacker News where it received some reception, and was pointed out that [CSS Tricks posted a great article](https://css-tricks.com/grainy-gradients/) written by Jimmy Chion about this subject in 2021. It's a great article, and the techniques we arrive at are similar.
I was not aware of this post at the time of this writing but am now linking to it here for supplementary reading.
---
## Manifest V3’s foibles
- URL: https://daniel.do/article/chromes-manifest-v3-foibles
- Date: 2023-03-04
> Beyond the wailing and gnashing of teeth
You have probably heard rumblings about [Chrome’s Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/). If you haven’t, here’s what you need to know: Google has been developing a new API for Chrome extensions for a while now. This API is more restrictive than its previous incarnation, [Manifest V2](https://developer.chrome.com/docs/extensions/mv2/).
Google claims this increases security and will lead to less incidents of malicious Chrome extensions. Detractors have argued this will prevent ad-blockers from functioning properly. This is further complicated by the fact that Firefox switched to using Google’s system for extensions in the mid-2010s now as well, and other browsers like Edge use Chrome under the hood, so the effects of this change reach further than Chrome.
I haven’t paid a lot of attention to this besides skimming a few of the articles on it. There’s been [a lot](https://www.theverge.com/2023/1/17/23559234/firefox-manifest-v3-content-ad-blocker) of [back and forth](https://www.theverge.com/2022/12/13/23506988/google-chrome-manifest-v3-v2-transition-ad-blocking-web-request-declarative-net) about it. I basically just assumed that ad blocking is so crticial that a way would be found to preserve the *status quo* and I'd switch if and when I had to.
The current situation is that since early 2022, you cannot submit *new* Manifest V2 extensions to the Chrome Web Store. Existing extensions on the store that use Manifest V2 (including ad-blockers) are slated to be completely removed at some point early in 2024.

A screenshot of the small visual change the extension does to Gmail
Today I [wrote a very small Chrome extension](https://github.com/danielimmke/gmail-cleanup) for my own personal use. I used Manifest V3 and after seeing so much drama surrounding it, decided to write about it. I have created a couple of simple Chrome extensions in the past using Manifest V2. I went in with some familiarity, but not a lot.
## First off, Google has a point
Google has a valid reason for rethinking extensions. Chrome extensions have long been a vector for spyware and malware. Sometimes a bad actor will buy a popular extension with a large install base so they can add things like data collection to it. It's a real problem -- not an invented excuse to ban ad blockers. Every time I have looked at my Dad's computer to help him with something, I have found several sketchy Chrome extensions installed that he has no memory of installing.
Companies can make decisions that are potentially positive for their bottom line while *also* having legitimate technical reasons for doing so. Too many of the takes I have seen about this situation are completely one-sided and dismiss the technical justifications out of hand.
**`` — Whew! Hopefully that wasn’t too long.**
To me, Manifest V3 falls into a very similar category. This is more than just "Google wants to kill ad blockers!" Just like with the above scenario there's a lazy cynical view and a more nuanced take that requires evaluating the facts and applying some critical thinking. So let's look at the facts.
Chromium, Blink, and V8 are all open source. Webkit is open source. Gecko is open source. There isn’t a moat for creating a web browser when the key, foundational technologies to do so are all open source and free to use. Also, users *love* ad blocking. If ad blocking became impossible in Chrome, I would switch the same day to an alternative. If not same day, same week or month. And there *would be* an alternative. Mozilla already claims that their implementation of the Chrome extension system and Manifest V3 would permit ad blockers.
Additionally, ad blocking has been around longer than Chrome has. If it was something Google wanted to tackle, they likely would have far before now.
On top of all of that, Google is already tied up in antitrust litigation regarding online advertising. This would be more grist for that mill.
*Maybe* Chrome’s marketshare dropping by 40% but the people still using it aren’t blocking ads is the desired outcome. But I really doubt it. To Google, Chrome is a form of soft power. It's a big stick they and everybody else knows they have and it brings other entities into alignment with them. Brazenly crippling it to juke ad revenue? That's a 90's era power move. Google knows more than anybody how fast browsers can rise and fall. Chrome hit the ground running in 2008 and never looked back. But there's nothing preventing that from changing. A large (+30%) marketshare transition could happen much faster today than marketshare shifts during the 2000s and 2010s, perhaps on the order of months instead of years. Chrome is worth far more to them in indirect ways.
The final thing I will say is that no matter what Google does or does not do, none of this is an existential threat to ad blocking on the web. Now on to my experience with Manifest V3!
## Building with Manifest V3
[The repository](https://github.com/danielimmke/gmail-cleanup), in case you missed it above.
It’s extremely simple in scope. It waits for a user to open Gmail and injects a script directly into the page that does some cosmetic DOM manipulation and style changes.
I encountered some issues both in building the extension and submitting it that I will go over in more detail. It’s also completely possible there’s a much simpler way to achieve this that I wasn’t able to figure out from the documentation, in which case I will happily update this post.
## You have to set up middleware to get verbose logging.
Manifest V3 requires you to register [service workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API), but it does not automatically start or persist them. I registered mine in the background and it triggers by navigating to a Gmail URL. However, without using a `try...catch` in some passthrough code if your actual code has errors it will just fail and you won’t get any usable logs. I’m sure there are workarounds I didn't think of, but I also didn't see a common pattern in place that prevented this either.
You can view this in `manifest.json` and `service-worker.js` it simply tries to invoke my actual code, located in `background.js`.
I like that they’re focusing on using WebAPIs, but I found this confusing and the documentation didn’t help a lot in clearing it up. Maybe I am supposed to trigger it differently.
## Injecting scripts and styles is much more restricted
My requirement was injecting my own function into a Gmail page after it had loaded, and this worked really well. It injects the script directly into the page itself, so you have access to `Document`, `Window` and all the other things you need. This was perfect for me, because it allowed me to move the debugging process directly to a tab with Gmail open instead of having to open the debug window for the extension.
However, Google Chrome has its own [lifecycle events](https://developer.chrome.com/docs/extensions/reference/webNavigation/#event) during navigation that you can hook into - and what I found was that when I was just injecting the script after `onComplete` or `onDOMContentLoaded` there was a second where the original content displayed before it was changed by my script.
I worked around this by just injecting `visibility: hidden;` on the document body at the `onCommitted` event and unsetting that on `onDOMContentLoaded` so the page is blank until it’s fully loaded instead of progressive. I can see this being an issue for content blockers (don’t want to load the content then hide it, but prevent it from loading to begin with) would have trouble with. However, it appears that there is a separate API for handling network requests that would be preferable to use anyways. I haven’t done a deep dive here, as I wasn’t building a content blocker, so maybe that API isn’t powerful enough to be used. I can’t speak to it.
## 3. The submission process doesn’t let you use WebP 😡

Google, what the fuck?
To submit to the Chrome Web Store, you have to submit example screenshots and a logo. Neither of which accept `webp`, which is a web image file format *created by Google*! Off the heels of my [last post](/article/its-the-future-stop-using-jpegs/) on how great it is, this was disappointing.
## 4. The submission process is more stringent
I was asked to justify every permission I asked for, as well as provide a description of exactly what the extension does.
I liked that - I don’t know how enforceable it is, but it felt more like Apple’s App review process. Less powerful APIs and a more stringent review process seem like a no-brainer to improving security around extensions.
At the time of this writing, the extension is still in review. I don’t care *that* much on a personal level if it is accepted or not. I wrote it for myself, and I’m already running the extension on my machine unpacked. But I will update this post with the result either way, just as a data point.
##### Update: *Feb 7, 2024*
The extension was approved and is available on the [Chrome Web Store](https://chromewebstore.google.com/detail/gmail-cleanup/dapfldihimbihndoeknipaiidpdlahbl).
## Conclusion
Aside from some annoyances and lack of example code to look at, I didn’t find the actual development experience to be that bad. That's why I titled this post the way I did -- it was basically just foibles. What I saw of the larger API seemed reasonable to me. I got the impression that Manifest V3 really was designed with the primary goal of increasing the security and performance of extensions. Admittedly, my extension was simple but I feel like I gained enough insight to write about it without going into intense technical detail.
Nobody can say what the future will hold, but I think Manifest V3 is an improvement and I hope this shakes out in a way where we can enjoy these improved protections and security without ruining ad blocking.
I have a pretty good feeling it will. The web is bigger than everybody, even Google.
---
## It’s the future — you can stop using JPEGs
- URL: https://daniel.do/article/its-the-future-stop-using-jpegs
- Date: 2023-01-18
> An overview of some compelling alternatives.
For the past several months, after [leaving Amazon](/article/laying-myself-off-from-amazon/) I have been hard at work building a software product. I anticipate probably another 1-2 months before I’m ready to share more details on that, but I wanted to take the time to highlight something that I’ve learned more about while working on this project.
I've always enjoyed reducing page weight on the front-end. Some front-end folk can get quite obsessive over this, and I've walked that line myself. Through the years our industry has embraced many techniques to accomplish a smaller page weight: concatenating and minifying files, tree shaking to reduce bundle sizes, etc...
I am also a big fan of projects like the [1MB Club](https://1mb.club/) that celebrate sites that put in extra work to make sure they are performant.
There is [a site](https://foodpartners.us/) on the 1MB Club that I built in 2016 that I am still very proud of. I had to make a lot of (at the time) hard decisions to get it to cold load under `1 MB`. Things like removing jQuery and writing native JS, reducing the number of custom fonts I was loading, and using gulp.js to crunch all the empty space scripts and stylesheets. I was like an ultralight backpacker giving away all my Clif bars to make weight.
By far the biggest task (both in time spent and impact), was optimizing the photographs. The site uses a lot of stock photography, and I had to make sure they were as small as they could be.
## Some background
*This is totally skimmable/skippable if you know this stuff already.*
Photographs are almost always saved and distributed digitally using the [JPEG file format](https://en.wikipedia.org/wiki/JPEG). Even when you purchase them from a stock photo site. JPEG is a [lossy](https://en.wikipedia.org/wiki/Lossy_compression) format, which means that no matter what, some information that was captured by the camera was lost when it saved as a JPEG. There’s a lot of nuance here that I am not going to go into for brevity (yes I know what RAW is, save your emails) but the end result is that some lossy conversion process is performed in the camera and you end up with a `.jpeg` (or `.jpg` -- they are interchangeable) file.
Another major image file format for the web is [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics). It is [lossless](https://en.wikipedia.org/wiki/Lossless_compression), but historically was only usable for things like digital graphics, or if you manually had cut an object out of a photograph and wanted alpha transparency. Re-saving a photograph that has already undergone some form of lossy conversion to PNG format does not improve the quality since that data has already been removed from the photo. In fact, saving a JPEG file as a PNG will often 10x the file size and accomplish nothing.
For a long time, if you wanted to put a photograph on a website, your only practical choice was to use JPEG. To make things worse, you often had to size down a very large JPEG (maybe 4000 x 2000) to a smaller JPEG (like 1200 x 600) and strip metadata, as well as possible manually set the quality percentage lower to hit a file size target. This resulted in the lossy compression process running *a second time*, causing the photo to lose even more detail. If you needed to edit this photo *again* at a later date, you better have saved the first version. Because every time it is saved again as a JPEG, it loses quality.
Lossy compression generally works using a percentage value, from 1 - 100. The lower the value, the more the algorithm compresses the image which lowers the file size but also removes detail and adds visual distortions called artifacts. Creating files of photographs to be used on websites was often the result of a careful compromise of file size vs. quality -- tweaking that percentage slider to find the best combination.
During the 2010s, screens got better. “HiDPI” and “Retina” became common on monitors and smartphones. This made things even harder, because photos that had previously successfully achieved that balance before now looked awful. I believe that the shift towards using illustrations in web design during this time was partially prompted by this. Aside from being more trendy than a photograph, an illustration could be represented by a PNG or SVG that is usually much smaller (like `<150 KB`.) Where even a carefully optimized and compressed JPEG can be `>600 KB`.
There were ways created to conditionally load images (media queries can detect display density and HTML introduced the [picture](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture) element) but browser support was bad and let’s be honest, unless there’s an automated system handling it for you it’s a huge pain. What ended up happening is that for images that could be PNGs, they were saved at 2-3x size but added to the page at their desired dimensions so the browser rendered them crisply on HiDPI screens (this eventually just switched to using SVGs in a lot of cases) and for JPEGs, they simply made them larger. This was part of the reason the average page weight of websites grew.
But browsing around the web today in 2023, you will find that if something is a photograph, it's probably still a JPEG. This is a shame, because there have been *major* improvements in this area in the form of new image file formats.
### WebP
I don’t consider myself a “cutting edge” technology person, I often don’t learn about a new technology until it has been around for a bit and is increasing in popularity. I recently fell in love with [Svelte](https://svelte.dev/) even though it’s been around since 2017.
I did not learn about the `.webp` file format until a couple of years ago even though Google first released it in 2010. In fairness, it [wasn’t practical to use](https://caniuse.com/webp) even with a fallback until around 2015 and only became usable without a fallback in the last 2-3 (ish?) years.
For those who don’t know what WebP is, skim the [Wikipedia article](https://en.wikipedia.org/wiki/WebP) for more detail but the important bits are:
* It’s an image format that supports both lossless and lossy generation. This means WebP can be used in situations you would previously have used both PNGs and JPEGs. though for photographs you should probably still only use it in lossy mode.
* The file size of WebP images is much smaller than JPEGs and PNGs in both lossy and lossless modes. Google quotes a 26% smaller size than PNG for lossless. That’s an impressive figure on its own, but its real strength lies in its lossy compression.

A photo I took during a *Día de Muertos* parade I went to a few months ago. (I’m not a photographer and this was the first cool photo I found scrolling my camera roll.)
Let’s put it to the test. I pulled this photo off my phone. In its original state it was `3024 x 4032` and had a `1.4 MB` file size. Since 2017, iPhones have used a file format called HEIC for photos (unless you have a newer high-end model and the [ProRaw feature](https://support.apple.com/en-us/HT211965) turned on) which is similar in size to JPEG and goes through a lossy compression process, it just uses a different codec and attempts to save more data from the camera sensors and allow more ability to edit the photo. This extra data is also used by automated software processing in smartphone cameras, but that’s an [interesting side tangent](https://www.youtube.com/watch?v=88kd9tVwkH8).
Because we are dealing with a photo that has already gone through a lossy process, converting it to lossless would be pointless. Let’s convert this to JPEG and WebP, using two different percentages for the lossy algorithms: **95%**, a very light touch, and **65%**, closer to a real world choice.
Additionally, I scaled this photo down to 1/3rd of its original size: `998 x 1331` because I think they will be easier to compare if they are smaller and I have my own bandwidth caps to worry about if this post receives a lot of traffic.
Converted to WebP at 65%. Apparently the lower you go, the greater the effect. I really can’t tell the difference between the two images, either.
90 KB ↓ 65%
These numbers aren’t just good - they’re *incredible*.
It's hard to determine the level of adoption that WebP has had, but my feeling is that it is rather low. I have tried to upload .webp files to many web applications and it was not allowed. A cursory check of big sites like Amazon.com shows they’re using jpegs for pretty much everything still. Even Imgur.com, a platform which I think would stand to gain *the most* from using this format seems to keep the format the image was uploaded in - JPEG or PNG. Not only do they not convert user uploaded images - they don’t support WebP *at all*. I tried uploading one.
I’m not sure why there hasn’t been a move to adopt WebP yet. The cost savings on object storage alone would make it worth it, even if you didn’t care about page loading size. You’d be cutting down heavily on egress fees without giving anything up. There might be a lingering impression that it’s not widely supported, or decision makers don't know about it. But the purpose of this post is to raise awareness.
That's not all! During my research, I encountered a second image format that is *even better than WebP* at compressing images! *
* (*...in some cases.* 😇)
### AV1 Image Format
[AVIF](https://en.wikipedia.org/wiki/AVIF) or `.avif` uses tricks that were invented for video compression and applies them to images. It also supports both lossless and lossy modes. This is the newest of the formats I'm outlining here, it debuted in 2019.
AVIF is also the riskier format to use in production as it's [not yet supported by Microsoft Edge](https://caniuse.com/avif) and has only partial support in Safari and Firefox. In the next year we can probably expect to see the situation improve.
But is it better than WebP, and if so by how much?
**Some notes about this test:** This format is new and I had to convert the HEIC image to another format before converting to AVIF, because AVIF does not yet support the codec used by HEIC. Additionally, there were some other differences in how I tested this which I will explain below.
I converted the HEIC file by using Mac OS (Apple has a built in HEIC file converter) to save it as a PNG. Then I used Sketch to export a smaller version of that PNG at the exact dimensions of the other photos. I chose to use PNG instead of WebP lossless to be absolutely sure that the WebP format had not touched the resulting AVIF files at any point. I also left in all the metadata and used none of the normal optimizations for web that are available. The resulting PNG file was `2.5 MB` and as close to the source HEIC file as I could think to make it, but it did lose some data because PNG files cannot handle the same type and amount of information as HEIC files can.
Secondly, an interesting quality about AVIF is that its lossy algorithm gives you a second lever to control the quality of the compression: CPU utilization (called Effort.) Other compressed formats only let you select a quality percentage, but AVIF allows you to choose how hard you want the CPU to work. The resulting file size is directly correlated to this, and file size is the only metric we’re looking at here. For the purpose of keeping the comparison as close as I could, I chose the maximum value allowed for “effort” and the 95/65 percentage values for “quality” when converting.
The third thing about this test was that I actually used two different tools to generate AVIF files. There is a [node package](https://github.com/lovell/avif-cli) that you can run at the command line and a [website with a convenient GUI](https://avif.io/).
The results I got were consistent at the *tool* level (same settings + same tool = same file size) but the output from the tools was inconsistent (same settings + different tool = very different file sizes.) Notably, the website produced much smaller files compared to the CLI, in some cases 50% smaller. I carefully reviewed the CLI settings and believe I was using them correctly. All of this was done on a MacBook Pro with an M1 Pro CPU. The website uses your own machine via WASM/Rust to do the conversion.
The only theory I have for the discrepancy is that WASM/Rust is just much more efficient than the Node runtime (or there's a bug in the Node package) if that is the case, your experience with this image format is going to vary highly depending on how much CPU/what environment you can give to it. If you were converting images to be uploaded to an object storage service to this format, you might consider a compute optimized VPS vs. an undifferentiated serverless option. Running a Node based lambda for this would probably not be a good idea.
Here’s the WebP images compared to the AVIF images I got from the website.
A nice 29% decrease in file size at the 95% tier, but at 65% the AVIF file actually was slightly larger than the WebP. I tested this multiple times in two different browsers. I even closed as many other processes as I could to see if that would have an effect. It came out to 94 KB every time.
AVIF seems to not be linear in its compression efficiency at different quality levels and may be better used for some types of images than others, luckily even in this scenario where it came out larger than the WebP file it was only by 4 KB.
I’ve linked them all for you to compare. I was hard pressed to spot a difference comparing JPEG, WebP and AVIF at the 65% level. The only thing I noticed is that the AVIF file seemed more washed out - but that might be because it lost color profile data when I switched from HEIC to PNG.
## Conclusion
The future is here and it’s amazing.
Regardless of whether AVIF ends up being better than WebP, it's clear that there are viable alternatives you can use *today* that are massive improvements over JPEG. When I think about things our industry has done to improve performance (CDNs, Edge functions come to mind), this ranks as one of the easiest wins I have ever discovered. But it's seemingly ignored.
Switching to WebP could cut the egress cost of your cloud bill down by an amount that would make it a good line item on a resume or a thing to discuss in a performance review.
My new project uses custom artwork in a big way and I will definitely be using WebP for everything I can. Also, all user uploaded images will be converted and stored as WebP unless I find some compelling reason for this being a very bad idea. We'll see how it goes.
*Woohoo* 🥳, first blog post of 2023 and it's still January! If I had made some kind of resolution to blog more I'd be crushing it right now.
---
## Laying myself off from Amazon
- URL: https://daniel.do/article/laying-myself-off-from-amazon
- Date: 2022-11-16
Yesterday, I resigned from Amazon. My final day is next week, right before Thanksgiving. I realize the timing of this is quite coincidental— as this week Amazon began layoffs. My team was not affected by these layoffs (as far as I know, apparently the full scope is not yet known at the time of this writing.)
A lot of people might think this is a terrible decision. Quitting your “cozy” job in big tech during a time when every company seems to be tightening their belt and the economy seems to be in a recession? I certainly empathize with the fear that comes with a job loss and with the people who did not get to make this decision voluntarily. They’re right to be worried. Most people have mortgages, kids, debt, and maybe little to no savings to cover those expenses while they look for another job.
I don’t have any of those obligations. That doesn’t make me a better or worse person, it’s just the circumstances of my life right now. What I did have was a job that I really didn’t like. A job that paid more and was more “prestigious” than any job I've ever had, but also a job that made me feel more unhappy than any other job I’ve ever had.
I’ve always thought of writing code as a form of art. I think of creating software almost akin to writing a novel. The popular open source project WordPress has a tagline that I’ve always enjoyed: *Code is Poetry*. Of course, the metaphor isn’t perfect. Features get added and removed, software can be very ephemeral.
My role didn’t allow for a lot of that. If I had to split my time into rough percentages, I’d say I spent about:
* 40% of my time trying to tame the bad internal tooling I was forced to use to submit my code, get it merged, deploy it, check logs, etc…
* 20% of my time in meetings
* 20% of my time writing unit tests to hit the 100% coverage requirement of the codebase I worked on.
* 10% of my time tracking down bugs in other team’s codebases for either internal tools or frameworks and trying to get them to acknowledge the problem by filing tickets.
* 10% of my time writing code for tasks I was assigned.
This is not counting the weeks where I was “on call” and forced to drop all of this to work on a backlog of DevOps related issues.
This felt severely dysfunctional. And the worst part is, I feel like the product we were shipping was really bad. It was slow and kludgy. It was the opposite of the qualities I value in software products. I didn’t feel like I was adding any value, and I was miserable. I had a meeting scheduled with my manager to “retro” or go over what went wrong with a particular feature launch, and I realized that there was no outcome of that meeting that would make me want to continue working there. That’s when I knew it was time to leave.
I could have stayed a few more months, built up more savings. But I know that I have enough to get by for a while. I would have just been chasing that feeling of security and safety, that no matter how much money I have never seems to quite materialize. It felt so much better to just rip the band-aid off.
Maybe I will look back on this as a bad decision. Something that sets me back financially several years. However, through years of work in therapy and self reflection my tolerance for uncertainty in my life has risen. At Amazon, they emphasize the idea of a “one way” or “two way” door decision. This is a two way door decision. I feel fairly employable as a front-end developer, if I end up having to take another job.
I don’t hate Amazon, my manager, or any of the people on the team I am leaving. I also know that every team at Amazon is different, so please don’t take my description for what it's like working there as a whole. I just was not a good fit and wasn’t willing to continue to try to contort myself to fit the mold needed for that job.
As for what’s next, I have an idea for a product that I want to build. It’s something I feel really passionate about right now. So I’m going to take some time to do it. I’m really glad I’ve reached a point in my life where I can make a decision like this and feel confident and at peace in it, instead of terrified. It’s something I’d wish for everybody to feel.
---
## The “je ne sais quoi” of TikTok
- URL: https://daniel.do/article/the-je-ne-sais-quoi-of-TikTok
- Date: 2022-09-02
> How a misunderstood platform has completely taken over the world.
*Note: When I originally wrote this post, TikTok oEmbeds did not auto-play. I recommend pausing them and pressing play when ready to view.*
TikTok has taken over the world. Every other social media has a shallow copy of it that sucks. I stopped using most [traditional social media about 5 years ago](/article/quitting-social-media/). I was happy without it -- I didn't feel like anything was missing from my life. If I stopped using TikTok, I would miss it. TikTok is different from everything that has come before it in many ways that are difficult to articulate. In French this concept is called “je ne sais quoi.” I also believe it's the future of social media. As in, every subsequent successful social media product will incorporate some aspect of TikTok's innovations. The problem is, I don't think a lot of people understand what those innovations actually are. I'm a big fan of TikTok, so I thought I'd try to lay it out in this post.
Recently this [great article](https://www.surgehq.ai//blog/tiktok-vs-instagram-reels-personalized-human-evaluation) did a deep dive with metrics and data to try to quantify exactly *why* TikTok is better. This post is not that. It's unapologetically anecdotal. Additionally, I'm aware that TikTok's popularity has geo-political implications which are the subject of intense debate. This post doesn't deal with that at all--it's purely about TikTok as a product and platform.
***
From MySpace onward, the paradigm of social media has always been about telling. Telling the platform--and everybody else--*who you are*. You tell it your gender, your date of birth, your interests, your friends, your thoughts about this or that subject. You have this persona you craft and present to the world. A quick look over my [LinkedIn](https://www.linkedin.com/in/danielimmke/) profile shows this in action. I'm presenting myself as a competent and experienced professional. I have even taken little quizzes to show proficiency in this or that skill. This is probably overkill. My work history is enough to establish my bona fides. But the reason it's so fleshed out is that I am indulging in this ritual -- this act of creating and heightening a persona. If you're my age, you've been doing it in some form or another on social media since you were a teenager or even younger.
The problem with these personas is--it's not *quite* actually you. The act of describing yourself causes distortion. It's who you *think* you are, or it's how you wish people saw you. Maybe it actually is you--on your best day. This has been widely noted and decried. The compare and despair effect of comparing everybody's manicured outside to your inside. At it's worst, a "who has the best life" contest. Attention and validation (both valid human needs) is a scarce resource that must be scraped together with performative posts that start with phrases like "I am humbled to announce..."
That's just for personal social media. The situation is even worse if you're trying to make art and reach people, like with writing, music, or live streaming. The winners take all the attention. You will find people commenting on popular music videos begging anybody to try out their content.
***
When I first tried TikTok probably some time in 2018 or 2019, it didn't ask me for *anything*. Not even my name. It certainly didn't ask me to construct a persona the way other social media does. That appealed to me, but the content it showed me was also different from anything I'd seen before. Of course there were comedy sketches and traditional content like you might have seen on YouTube or Vine. But when TikTok is discussed, people focus on "the algorithm" and how it shows you content that is specifically interesting to you. What they miss is that TikTok enables types of content that simply *cannot* exist on other platforms.
One day, this video came across my feed. A quick swipe over to his account shows that's all he posts- just videos of him dancing his heart out to ecletic pop music. There's no grand value proposition like you might see on a short form Instagram video about how to make cute popsicles for summer. At the end he didn't approach the camera and say "Hey if you liked that, be sure to like and subscribe and hit that notification bell." It's just someone dancing their heart out and enjoying themselves.
That's it. You can take it or leave it. When I watch this video, it makes me feel happy. I enjoy seeing someone give themselves over to music so passionately. I think his song choices are great and he publishes a Spotify playlist that has led me to discover some of my new favorite music. Sometimes he dances outside, sometimes he dances in his kitchen. I don't know anything else about him, and don't really need to.
His TikTok account has over 25,000 followers. He has a fanbase for his videos and clearly gets his needs as a human being (attention, validation, connection) met by posting those videos.
It's almost impossible for me to imagine someone posting the same content on YouTube or Instagram and being successful without an established following. They'd be regarded as an oddity/insane for posting videos of themselves dancing to 10-20 views per video.
This is my favorite kind of TikTok. I don't have a well defined categorization system, but this falls under what I would term "impressionistic" - It's a window into someone else's experience and emotions. Almost like a slice of life. It connects you to another human being in a way that Facebook always claimed to. Here's another one of my favorites.
Just a moment posted by a D.J. of a set he was playing, but when the drop hits I can *feel* the pure expression of joy, condensed into a moment in time.
Other impressionistic style videos can capture the essence of a place, or an intimate moment.
Not every video has to be the star of the show, you can have these utility players making up elements of your "For You" page.
Even when not impressionistic, there's space for introspective or "negative" content that explores the full spectrum of what it's like to... be a person. It feels authentic. Not created to elicit sympathy, rather, commiseration.
Like this person expressing how they feel after moving to another country.
Collaboration is so easy. A user can write a raw, vulnerable verse to someone else's song and achieve the emotional connection that music can faciliate with hundreds of thousands of people. Without even showing their face or name. To me, this is *incredible*. Especially when you consider that the closest other platforms get to this is spammy "Plz check out my music 🙏" comments on a Drake music video.
Or, people can get together and mock some highly polished performative content. The ability to stitch and layer new videos on top of each other is incredibly unique.
For all of the cynicism I've seen about social media over the last 7 years, TikTok has felt like the opposite. A scroll through a Facebook or Instagram feed can leave one feeling less than. TikTok has never made me feel that way. It's made me feel seen and understood by complete strangers. It's helped me understand myself and other people better. It made me feel a lot less alone during the pandemic.
That's the point I am trying to get at with this post. It's very tough to explain, especially to "Product Managers" focused on KPIs who think of TikTok as "short videos." It's not just a format change or a tab you can add to your app's navigation. It's an unambiguously positive change in social media, on pretty much every front. To try to get it down to a bulleted list:
* Organic audience acquisition without need for self promotion.
* Types of content that can flourish is much broader.
* Incredible collaboration tools, leading to mixing and remixing art on the platform. The only other example of this I can think of this on other social platforms is textual. Quoting someone's tweet and commenting on it and the like.
* Manages to maintain a platform-level "zeitgeist" of sorts, similar to Twitter, while also giving users highly customized experiences. It does this without the need for trending topics or curated hashtags, it's all in the algorithm.
* Fosters empathy instead of sowing division. Much less emphasis on "culture war" and politics.
That's the other thing I wanted to address in this post. While TikTok is unique and innovative, it is not all encompassing. It cannot take over the role that Facebook plays. Especially when it comes to things like Groups or Marketplace. I feel like ever since MySpace, the narrative in social media has been "the next one will pop up, then yours will die."
But I think the space has matured. Facebook should take an approach of pivoting to becoming the "Oracle" of social media. A legacy player that's always going to be there and play to it's strengths. It has a successful and profitable portfolio of companies with entrenched userbases. Are these rushes to copy surface level features from new social media apps even successful? Because they're definitely embarrassing. Recently Instagram users [revolted](https://www.theguardian.com/technology/2022/jul/31/tiktok-video-instagram-revolt-update-kardashians) because the platform was morphing to focus too heavily on video. Why not just focus on what makes Instagram special and try to keep innovating on that? Or better yet, look at how TikTok is *actually* different and try to apply those concepts to your own product.
Anyways, this is my attempt to narrow down what I find so compelling about TikTok. To effable the ineffable. I hope I was able to write something true. I believe that thinking about technology in a broader way like this is really important. I am going to try to do it more often.
---
## On being “currently based anywhere”
- URL: https://daniel.do/article/currently-based-anywhere
- Date: 2022-06-11
> A pithy slogan for an unusual lifestyle.
Currently based anywhere. That’s what I landed on when I changed the copy on my homepage indicating that I was based out of Atlanta. I really dislike the term “digital nomad” - it manages to sound corny– like something out of a cyberpunk novel while also conjuring up images of Instagram-perfect laptops on beaches and sketchy “make money online” schemes. But because the term has caught on and I can’t think of anything better, I do use it when discussing my lifestyle.
If you haven’t gathered yet, I no longer live in the United States. I am writing this from a studio apartment in Mérida, Mexico. In March of this year, I made the decision to sell my house and travel full time. This is an ambition I have had for a long time, but I never went through with it. It always seemed too extreme. However, with my new remote job at Amazon and the world opening back up from COVID, combined with my fears about inflation and the housing market in the United States I decided to finally do it.
My intention is to live in many different countries, perhap with Mexico as a “home base” of sorts. There are a lot of different ways to be a digital nomad, but I definitely favor the “slow-mad” variety, where you spend multiple months in a country.
My life has changed significantly - I don’t drive a car anymore but instead walk to most places and take taxis to places I can’t walk. This is a huge difference from suburban sprawl existence in the United States where everywhere has a nice parking lot. Sometimes even getting my shopping or laundry done can feel like an accomplishment when I’m physically carrying all of it. It’s also hot as fuck, averaging 95° and above most days. A simple walk can turn grueling if you can’t find enough shade.
I still don’t speak Spanish, but can peck my way through most interactions. It’s something I’m working on and find myself getting better at slowly. Once I feel good about my fluency, I want to visit Spain. I’ve met a lot of really interesting people. Expats, other nomads and natives of wherever I am.
A few days ago I was in Belize City, getting my immigration paperwork together so I could get a temporary residency visa in Mexico (It’s complicated, but going to Belize was the best way to do this.) I met another nomad on Reddit who was in town doing the same thing and we met in person at a bar. We commiserated on our struggles but the thing he said that stuck out to me the most was that a lot of people who are attracted to this lifestyle enough to actually do it are neurodivergent in some way, and how he has embraced that in himself. I really liked that.
Because make no mistake, this is an extreme and at times very difficult way to live. It can be lonely, expensive and dangerous. But at least it’s not boring. I was so bored in Atlanta. It would be so easy to paint a glossy picture too on social media - I could just post about how I went jet skiing in Belize, or the ruins I toured. I could omit how unsafe I felt when I was walking around Belize City or dealing with scamming taxi drivers and government corruption.
People ask me why I’m here. Vacation? work? What’s your plan? The true answer is I don’t know. I just want to be here right now. And maybe in a few months I will want to be somewhere else. It’s a great feeling not having a five year plan. I feel like for the first time in my life I’m actually experiencing it as it comes instead of waiting for the next thing to happen.
So for now, until some point in the future, I am currently based anywhere.
---
## Building a new personal website
- URL: https://daniel.do/article/building-a-new-personal-site
- Date: 2021-02-15
Yesterday I launched a new version of this website. When finishing big projects, I always experience this odd phenomenon where the final product just seems... simple and effortless. The end result doesn't *feel* like something that took months of work and painstaking attention to detail. But that's how it actually happened, and it feels great to finally complete it.
The impetus for this change was that I wanted to focus more on writing as opposed to having a traditional "portfolio" site. I think the utility of having work examples these days is questionable for anybody other than new developers trying to get their first job. Over the last 10 years, web development seems to have morphed from a somewhat creative endeavor into the more rigid "programmer" mold of a list of bullet points on your resume that you get drilled about in interviews.
But I get a lot of enjoyment out of reading blog posts from other people, especially the ones that rise to the top of [Hacker News](https://news.ycombinator.com/). I like writing comments there and wanted a comfortable space to write longer form material. I was frustrated by the blogging experience of my old site. The old design had featured images, so whenever I wanted to write a post I had to create an image to go with it. The design of the site wasn't well suited to long form reading either. I wanted to eliminate that friction and update the look and feel of the site.

### Gatsby
The biggest under the hood change is that I moved from [WordPress](https://wordpress.org) to [Gatsby](https://www.gatsbyjs.com/). As of this writing, I'm still not 100% sure I made the right decision. There has been quite a lot of hype around static site generators in the last few years. Matt Mullenweg (the creator of WordPress) generated controversy when he said "JAMstack is a regression for the vast majority of the people adopting it" - but it's plainly obvious that that is true.
First there's the basic logistical stuff. You can't just install a plugin if you want to do a contact form, you have to write the form markup yourself and connect it to a backend. It's the same if you want an admin interface for someone who isn't comfortable writing code to do content management. Solutions for all those things exist, but now instead of using a single open source backend you host yourself, you're signing up for and relying on several different services that are all trying to make money off of you. It's more complicated, more expensive and just flat out worse in most cases. This isn't a huge problem for me and this site, but if I was still doing client work there's no way I would choose Gatsby to build with.
Secondly — and this is the bigger and more worrisome aspect of this to me — is how much complexity Gatsby adds to regular websites. Using React components and routing enables advanced features like smooth page transitions and animations... but how many Gatsby sites actually employ those features? And how many newer developers are learning how to build inside of Gatsby without fully understanding the fundamental elements those frameworks abstract on top of?
To be clear, WordPress has a lot of its own baggage and problems that would make this post too long to go into. I don't regret going with Gatsby because this is a personal project that I have full control over and maintain, but it's important to acknowledge that the hot new framework isn't always the best choice overall. That's a lesson that is continually reenforced in my day to day life as a front end developer.
### Inspiration
As much as I want to pretend that I create things in a vacuum, the truth is almost everything I produce is influenced in a lot of different ways. Both other websites but also music and visual art. I really enjoy the lush, stylistic typography that is making a big wave in web design these days. It almost feels retro/mid century modern to me.
#### Sites
- [robsimpson.digital](https://robsimpson.digital/) *Big fan of the look and feel as well as the animations.*
- [daverupert.com](https://daverupert.com/) *Love the unique homepage and it's not just a big list of posts.*
- [joshwcomeau.com](https://joshwcomeau.com/) *Enjoy the site and the content.*
- [thelotoseaters.com](https://thelotoseaters.com/) *Wish I had the confidence to design something this off the wall for my personal site.*
#### Typefaces
Because I was creating a site focused on writing, emphasizing the text in the design was essential. The personality these typefaces lend the site had a large influence on the rest of the design.
I'm using [Geograph](https://klim.co.nz/retail-fonts/geograph/) and [Tiempos Headline](https://klim.co.nz/retail-fonts/tiempos-headline/) (which was also the main typeface from the previous iteration of this site) from the wonderful [Klim Type Foundry](https://klim.co.nz/). I'm using regular [PT Serif](https://fonts.google.com/specimen/PT+Serif) for the main body typeface.
#### Soundtrack
For most of the time I was designing this site, I was listening to Flume. The dreamy electronic music definitely set the right mood for what I was trying to design, with vivid shapes floating around the screen in abstract patterns.
### RSS & Socials
Similarly to how Gatsby is in some ways a regression, the disappearance of RSS from the internet has been a widely noted and decried phenomenon. I used to use RSS all the time but I also stopped when it fell out of favor. I made an intentional decision to offer an RSS feed with this site, with a persistent link in the footer. I wonder if it will get any use!
I also [don't use regular social media](/article/quitting-social-media/) like Twitter or Facebook, but I came to the realization recently that I do use some social media sites that are less common but I get a lot of value out of. I added those to the homepage as well so I can hopefully connect with more people on there.
---
## Hacktoberfest 2020: Government edition
- URL: https://daniel.do/article/hacktoberfest-2020-govcon-edition
- Date: 2020-10-15
> Focusing entirely on government contributions this year.
It’s been a tumultuous year, but as the leaves changed I found myself getting excited for [Hacktoberfest](https://hacktoberfest.digitalocean.com/) again. I am in the middle of buying a house which is probably the most stressful thing I’ve ever done, but I still wanted to make time to do some open source work. Because of that, my contributions this year are smaller in scope. I also focused specifically on U.S. government projects this year.
Here’s the rundown of my pull requests this year!

#### 1. Fix missing icons, USA banner design — [\#3292](https://github.com/GSA/digitalgov.gov/pull/3292)
This was posted as an [issue](https://github.com/GSA/digitalgov.gov/issues/3027) and identified in the repository for [digital.gov](https://digital.gov). Basically, the banner at the top was missing an icon. As I dug in, I found that other icons were also missing and some of the CSS also needed to be updated.
This banner is a [component](https://designsystem.digital.gov/components/banner/) in the U.S. Web Design System so I referenced that and saw how it had diverged from that source. I corrected the paths and polished things up and submitted.
My PR was accepted and merged in almost immediately, and minutes later was reflected on the site as they have a great continuous deployment system set up (I would kill to have something like that at my day job.)

#### 2. Fix USA top banner — [\#1798](https://github.com/cloud-gov/cg-site/pull/1798)
While I was researching my fix for the last pull request, I noticed that some other .gov sites had an issue with their banner. I found [cloud.gov](https://cloud.gov/) was not displaying the icons in the banner correctly and some of the CSS was broken.
Despite both being managed by the GSA agency and both utilizing the U.S. Web Design System, the cloud.gov site actually has a different setup and backend. The digital.gov site uses the Hugo static site generator while cloud.gov uses Jekyll. The compile time for cloud.gov after making changes was much longer, and I’m not sure if that’s a side effect of Jekyll or if the configuration could just be updating.
I don’t have a lot of experience working with static site generators, I missed that trend when it was first coming to prominence (although I did just build my first site in Gatsby) so it was a good learning experience.
Even though the issue was similar, the code fix was actually very different for this site. I also updated the copy on the banner to the [new copy](https://designsystem.digital.gov/whats-new/updates/2020/09/08/Improvements-banner/) that was standardized last month.
#### 3. Add template info — [\#5](https://github.com/CDCgov/react-starter-kit/pull/5)
Earlier this Fall, the team I work on decided to standardize on React as our JavaScript framework. Going forward we needed an easy way to start React projects with a consistent code style and properties. The most popular and supported starter kit, Create React App, is far too opinionated and doesn’t work well for the environment we deploy our React code in.
Because I am the most experienced with React on the team, the task fell to me to create a starter kit that standardized things for us and was much lighter weight. I built that and decided to open source it for future usage.
This particular pull request is fairly minor, it’s me adding some additional information to the README on how to leverage Github’s template feature to use this as an actual starter for a new project instead of having to clone or fork the repository. I had never used this feature of Github before, and was happy to find out it exists.
#### 4. Fixing HTML errors — [\#3318](https://github.com/GSA/digitalgov.gov/pull/3318)
Back to digital.gov. I wanted to find other projects to contribute to, but due to the rule’s change requiring opt-in, digital.gov was the only government repository I could find where a maintainer had specifically labeled items for Hacktoberfest.
This PR involved fixing HTML errors. Since the HTML is generated by markdown in static site generators, I had to go in and trace how the markdown was improperly formatted and leading to bad HTML. While this wasn’t very challenging, it was still a good insight into some of the pitfalls of static site generators vs. a more traditional CMS. I think there were more errors from people having to manually write markdown code than if they were using a WYSIWYG. But a proper linter, like the one they installed recently that caught these errors should ameliorate that mostly.
Overall, I love the completely open approach that the GSA takes with their repositories. All of the content and code is done in the open, viewable by anybody. That takes guts. I think I have convinced my team to follow in their footsteps on *some* of our projects going forward.
### Conclusion
This was definitely a scaled down year for me in terms of effort, but I still feel like all of my pull requests added value and I learned a little something from each of them. The truth is, this event can take quite a bit of time and can be challenging to participate in.
This year I became aware of how disliked this contest is by a lot of people in the open source world. It’s understandable, the massive amount of spam PRs outnumber the amount of people who legitimately participate. After an intense wave of criticism, Hacktoberfest was made opt-in this year which I think was the right move.
I do think there are additional changes that should be made to the contest to make it easier for people who legitimately want to participate to do so, and I will write more about that in a separate blog post.
But for now, that’s another year in the books. See you next year for Hacktoberfest 2021!
---
## My time fighting COVID-19 as a CDC software engineer
- URL: https://daniel.do/article/my-time-fighting-covid-19-as-a-cdc-software-engineer
- Date: 2020-09-05
> The most stressful period of my career.
*Disclaimer: I am a contractor at the CDC not an employee. These opinions and thoughts are entirely my own.*
Early in my career, I did something that is almost a rite of passage for junior developers: I accidentally pushed the wrong code to production. This caused the blog of a major American company to start malfunctioning. I didn’t find out about my mistake until several hours later when I got added to the fraught email thread from the client that included the ominous phrase *“This is being escalated to the highest levels of the company…”*
Yikes.
Luckily, I was part of a good team and my head did not roll. One of the senior developers consoled me by saying “At least we make websites and our work isn’t life or death. The world isn’t going to end because a blog post wouldn’t load.” And it’s true, most of the time when developing software or websites the stakes are pretty low in the grand scheme of things. So it was a change of pace to find myself in a position earlier this year as a developer at the CDC where the stakes were very high.
I don’t remember when I first heard about COVID-19. I’m sure I started seeing blurbs about it some time in January. I didn’t pay much attention to it, I just assumed it was a media panic disease like Bird Flu that was unlikely to ever affect my life directly. I think early March was the demarcation point of “Oh shit, this is a real thing” for most people. The NBA cancelled their season, Tom Hanks got it. I remember having lunch with two of my coworkers the week after that and saying “Isn’t it kind of weird that we’re still in office?” I haven’t seen almost any of my coworkers in person since that day.
So began what was easily the most stressful period of my entire career. Nothing else even comes close. It started with me getting pulled into a meeting at 5:30pm on a Friday night. We needed to update the official Coronavirus page with a new design, and it needed to happen immediately. The updates were being reviewed and approved directly by the White House as we made them. I stayed on that conference call all night working feverishly and finally finished at 10 the next morning. I went and got a bunch of tacos before passing out.
I became responsible for updating the new COVID homepage. They needed new designs and content constantly. This was in addition to my mapping software was being used on the official U.S. Case Count page. New features and bug fixes were coming in a constant stream. When 12+ million people are using your software every day, issues you weren’t aware existed tend to crop up. When I wasn’t busy with those tasks, I was also writing a new version of the CDC mobile app which desperately needed an update. It was a rough time. Working weekends and 60 hour weeks became routine. The architects on my team had it even worse.
This whole year and lockdown has been very weird and surreal, but being so close to it with my work was another layer on top of that. It was this brushing up against the zeitgeist where random things stuck out to me as notable. The rarefied air of submitting builds to Apple that were reviewed in hours (sometimes under an hour), not days. Seeing the user reviews for the app become a political battleground to discuss the CDC instead of the app itself. Seeing Elon Musk tweeting his infamous bad COVID-19 predictions and referencing CDC data and knowing that this person I had looked up to for years (though not quite so much anymore) had used things I built.
The work was exhausting but almost a welcome diversion because I was locked down like everybody else. All I did when I was done working was read all the terrible news that had come out that day about how many people had died. A lot of people didn’t have anything else to do but spend their entire day reading the news and stressing out. At least I had a stable job and something productive to focus on that made me feel like I was helping.
As time went on, I struggled. The long hours and isolation really took a toll. I feel some guilt talking about it because I know that this pandemic has destroyed so many lives, I got off pretty light overall. It has been even more demoralizing that this whole thing has taken place during an election year and somehow no candidate still in the running has decided to advocate for an improved healthcare system that isn’t tied to employment and doesn’t bankrupt people.
Over the months, work has improved. Things are not back to normal and I am still working to support the CDC as it responds to COVID-19 but the pace has slowed a lot. I wanted to write about this time in my life while it was still somewhat fresh because I didn’t want it to continue to be warped by time and the imperfection of memory. This might end up being the most notable period of my entire career, and I wanted to hopefully capture a bit of it in writing. Also, I haven’t written a blog post in 8 months, though I have a pretty great excuse!
The thing I learned about myself from this is that I enjoy building things that benefit everybody. Doing work for the government is harder than the private sector. Things move more slowly and there’s a lot of bureaucracy, but the work really is important, and it needs people like me to help move it forward. I also find it rewarding.
---
## 2019: Lessons learned
- URL: https://daniel.do/article/2019-lessons-learned
- Date: 2019-12-13
> Looks like I've got it all figured out.
It’s the end of the year — and the decade — as endless listicles remind me every day. I wrote an end of year blog post[ last year](/article/2018-a-year-in-review/) so I figured I’d do one this year. When writing, I struggle to really express my thoughts and sometimes view it as a perfunctory task to be performed. Just another thing to check off my to-do list. This year I wanted to try something a little different and experiment with the format.
Every year I sit down and write a list of lessons learned for the year. This list is generally for my eyes only, and it’s my own Type A way of accepting that life is always going to have problems and I should at least try to grow from those experiences.
This year, I am going to share an abridged version of this list here, for you! It’s way too long (and personal) to share entirely but I plucked some random ones ranging from really light to introspective.
#### Budget airlines are the best
People are always ragging on airlines like Spirit or Frontier, but I personally learned to love them this year. You can usually fly in the equivalent of a first class sized seat on them for the same price as Delta’s rock bottom fare where you get randomly assigned a middle seat and can’t cancel or change anything.
Also, because it’s a budget airline less people opt to purchase the more expensive seats so your chances of getting someone sitting next to you are even lower. With Delta and others, expect any nice seat to be filled with rewards people.
I also love how they don’t add anything extra. You pay a base fare and then for exactly what you need. Flying sucks, and some of the stuff regular airlines do make it even worse. It’s so much more efficient to just pay for your drink or food than to have a stewardess spend half the flight coming up and down blocking the aisle handing out peanuts to everybody.
Want carry-ons? Pay for it separate, and you don’t have to deal with every single overhead bin being full. And all told, it’s still cheaper or about the same price as a Delta flight. Easy choice for me.
I took Frontier to Denver this year to do some hiking and check the city out and snapped the beautiful shot that is the hero image for this post!
#### Don’t send dramatic emails
My original draft of this was “don’t send emails after 7pm” because most of the emails I have sent that fall into this category were sent after that time. Usually when I am lying in bed worrying about the outcome of a situation and feeling powerless to change it.
But that didn’t concisely capture my meaning. Basically if I’m spending a long time writing a draft and reading and rereading and trying to control something through that, there’s a really good chance I shouldn’t send that email. It has never ended well, not even once.
Instead, I’ve started to understand my anxiety a little better and see myself as separate from it. When I’m spinning out of control about something, I load a YouTube playlist and just embrace how I’m feeling. In those cases, the best thing to do is nothing but accept that I’m going to feel shitty for the next 3-4 hours and that feeling won’t last forever.
#### Don’t install beta software on things you need to use
I’m sure most people reading this are like “duh” but I used to do this a lot. It’s fun to try new features. However, the stability of Apple’s beta software has gotten bad. Like *really* bad. I read this super interesting — and very plausible — [blog post](https://tidbits.com/2019/10/21/six-reasons-why-ios-13-and-catalina-are-so-buggy/) about why. It bums me out. The bugs do seem to get fixed before official release, but I was using the first public Catalina beta and it was going to be a huge effort to downgrade and it made things really tough for me.
#### Slow down
I move every year. As of this writing, I am a couple days settled into my new apartment.
Moving is crazy stressful, and I’m really growing tired of it. I’m ready for things to be more stable and less in flux in my life. I’m going to try to focus on that in the coming year.
### Conclusion
This year was a mixed bag for me. I spent a lot of it hunkered down coding. That paid off, I became a **much** stronger programmer this year. From building and releasing [CDC Maps](/article/what-its-like-open-sourcing-software-created-for-the-government/) to [creating my first iPhone app](/article/building-launching-first-iphone-app/) to [Hacktoberfest](/article/my-hacktoberfest-2019/) and there’s a lot of stuff I didn’t even write about.
A couple months ago I came up with the idea for a Chrome extension that would make the lives of myself and my coworkers easier and I just…wrote it. Looked up the relevant docs and built it in an afternoon. I never would have had the confidence to even try something like that last year. And I use it every day, which is rad.
I’m also currently leading the front-end architecture for another CDC project and it’s going very well.
All of that progress came at a cost though. I kind of isolated myself and worked really hard. I did do some traveling but really didn’t live life as much this year. It’s led to some depression, if I am being honest. I am pausing my work on extra curricular coding stuff for a little bit while I try to develop healthier mental and physical habits. It’s feels super vulnerable to admit that on a blog post, but I’ve always hated the artifice of social media, even though I am swayed by it too.
It’s super tempting to just say “Yup this year was AMAZING look at all this cool stuff I did” while omitting the downsides, but it’s not honest.
That’s it for this post, I hope you got something out of it. See you in the new year!
---
## My Hacktoberfest 2019
- URL: https://daniel.do/article/my-hacktoberfest-2019
- Date: 2019-10-26
> Hardest I've ever worked for a free t-shirt.
This year I participated in [Hacktoberfest](https://hacktoberfest.digitalocean.com) for the first time. I became aware of it last year and really wanted to participate, but I had just started a new job, was moving and buying a new car all in one month! Hacktoberfest was definitely not on the priority list. I was excited to give it a go in 2019.
The basic concept is that you submit 4 pull requests to open source projects during the month of October, and they give you a free t-shirt.
Easy right? Well, it can be. Hacktoberfest doesn’t evaluate the pull requests based on merit/effort so as long as the maintainer of the repository doesn’t mark it invalid it counts towards the 4. This means a pull request to correct a typo can count as much as a pull request that is a major refactor of a codebase.
Since I did this challenge more because I wanted to learn than because I *really* wanted a free t-shirt (though that was definitely a motivator!) I decided to embrace the spirit of Hacktoberfest and try to submit pull requests that addressed existing issues in projects but weren’t *huge* commitments.
This is where I ran into my biggest issue — **finding good issues is really hard!** Or rather, issues that I wanted to work on. I wanted to work with projects that were used by a lot of people, presented some challenge and were somewhat within my domain of expertise. Every time I would find a Github issue that looked perfect, somebody had called dibs. I eventually expanded out from using the #hacktoberfest tag and just looked at medium sized projects with issues.
So, without further ado… these are my Hacktoberfest pull requests!

#### 1. Fixes issue where next button doesn’t automatically focus — [\#553](https://github.com/gilbarbara/react-joyride/pull/553)
React Joyride is a React component that lets you create a guided tour through a page. A little window pops up next to a feature you want to highlight and when you click “Next” on a button it takes you to the next step in the tour. As reported by [this issue](https://github.com/gilbarbara/react-joyride/issues/551), even though in the code it tries to focus on the “Next” button of in the next step, this wasn’t working.
I was able to get a simple fix working in 20 minutes. The project had some really good instructions on onboarding with it. It didn’t feel like a super clean fix, but I decided to submit it as a PR anyways.
After submitting, the person who originally submitted the issue reviewed the code. He pointed out that my fix didn’t *guarantee* that the element was ready for the focus call, and suggested I use [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame), which is a DOM API that was added to browsers somewhat recently to help with this sort of thing.
I had heard of requestAnimationFrame but never actually used it before. The documentation was straightforward and I was able to implement it fairly quickly. It was cool learning a little bit about something I’ve never used before.
As of this writing, I am still waiting for the maintainer of the repository to review the PR and come back to me with any changes or merge it in.

#### 2. Add pass event — [\#492](https://github.com/nicolodavis/boardgame.io/pull/492)
[Boardgame.io](https://boardgame.io/) describes itself as an “Open Source Game Engine for Turn-Based Games.” It manages the state and though it is deeply integrated with React, can be utilized with any frontend. Under the hood, it functions as a layer on top of Redux and lets you declare all of the basic logic you need for your game in a simple object.
This is a really big project, and I was a little intimidated to work on it because it seemed very involved, however I noticed the creator and maintainer goes out of his way to be very welcoming to new contributors so I decided to give it a shot. I noticed he had posted [an issue](https://github.com/nicolodavis/boardgame.io/issues/477) requesting the addition of a “pass” event so I gave it a shot.
This was definitely the most time consuming PR on this list. It took me 4-5 hours to really wrap my mind around how the framework functions and probably an additional 4-5 hours to write something I was happy with. A lot of new features had been added to the project that weren’t well reflected in the examples in the repo and I had to make sure the feature I was adding accounted for these more advanced concepts (like phases.)
It also wasn’t just about creating something that “works” it was about matching the current style of the codebase and trying to work within that paradigm.
At one point, I had to [ask for clarification](https://github.com/nicolodavis/boardgame.io/issues/477#issuecomment-539033939) and he was very responsive. When I submitted, he had some minor style changes he wanted but I was actually surprised at how little additional feedback there was. At the time of this writing, he wanted me to write some unit tests for the new functionality which I plan to do so very soon and hopefully get the code merged in!
#### 3. Update packages — [\#2](https://github.com/gilbarbara/react-joyride/pull/553)
This one felt a little like cheating, because it’s for one of my own repositories. A couple years ago I created a [Pardot Starter Kit](/article/pardot-starter-kit/). I don’t make Pardot landing pages anymore in my day job, so I haven’t had much incentive to keep it updated.
However at the beginning of this year somebody did [open an issue](https://github.com/danielimmke/pardot-starter/issues/1) saying they were having trouble using the starter kit because the packages were out of date. Even though there isn’t a lot of activity on Github, I think people *do* use this starter kit. My analytics show that it’s actually one of the more popular posts on my blog. It definitely needed a little love.
Originally I tagged it as #hacktoberfest and wanted someone else to pick it up, but after a few days I decided to do it myself. I updated all of the packages. Gulp’s version 4 was a major breaking change. Their API surface changed significantly, so I had to refactor the Gulpfile.
This took some time. I also went through and updated the README to explain things better and made some other changes to keep things chugging along smoothly. For people finding it in 2019, it should still be a good option to get started building custom Pardot landing pages.
#### 4. Change JS filenames to bring them in line with the Google JavaScript … — [\#116](https://github.com/thamara/time-to-leave/pull/116)
I saved the hardest, most substantial pull request for the very last. This one will **definitely** knock your socks off.
Just kidding, this was definitely the quickest PR. I traveled through a good chunk of mid October and my day job had started to get busy and I am gearing up to do some more work on other personal projects. I didn’t have the bandwidth to spend a lot of free time working on a bigger issue so I decided to go with a simple one I found through the Hacktoberfest’s website!
Even though it was a basic task, it still addressed a real issue in a project and I still learned something new! It turns out that the `git diff` command has a flag titled `--name-only`, which lets you see just filenames that were changed.
### Was it worth it?
Before I started this I had open sourced [my own work](/article/what-its-like-open-sourcing-software-created-for-the-government), but hadn't contributed much to other open source projects. I got to see how popular open source projects are run and how issues are triaged. Each project does things slightly differently and has processes that work for them. I learned a lot about things I want to do in my own open source projects (definitely adding unit tests!)
Participating was absolutely worth it. I expect to contribute more frequently to open source projects going forward and will probably be participating in Hacktoberfest 2020.
---
## What it’s like open sourcing code created for the government
- URL: https://daniel.do/article/what-its-like-open-sourcing-software-created-for-the-government
- Date: 2019-09-09
> Bureaucracy? You betcha!
Recently I released a project I [built for the CDC as open source](https://github.com/CDCgov/CDC-Maps) out into the world. It’s called CDC Maps, and I wrote a case study about it on my portfolio [here](https://daniel.do/case-study/cdc-maps/). This presented some really unique problems to solve so I thought I’d write about the experience.
### A little history
There has been a big push in recent years for the federal government to open source more code. In August 2016, Obama’s white house issued [M-16-21](https://sourcecode.cio.gov/) which was a memorandum encouraging federal agencies to develop procedures around open sourcing code. I believe there was also a mandate to try to open source 20% of custom code written for a certain amount of time.
I’m fuzzy on how all of this was enforced, but I do know from my research that it led big federal agencies to develop their own sites, tools and guidelines for open sourcing software. NASA created [code.nasa.gov](https://code.nasa.gov/) and the CDC created [open.cdc.gov](https://open.cdc.gov). There’s also [code.gov](https://code.gov/) which serves as kind of an aggregator for open source work released by the government. The fact that all this existed made it way easier to consider open sourcing my code. Without it, the amount of red tape probably would have made me shelve the idea entirely.
The CDC also has internal advocates for open sourcing, so I was able to carve out some of my time at work after launching the project to dedicate specifically to preparing to open source it. This was a huge help, it meant I didn’t have to do it on nights and weekends.
### Technical challenges
Of note, an interesting side effect of all this push for open source work is that when I was tasked with architecting a rebuild of the mapping tool, I was basically told that I cannot use proprietary software at all. Certain centers inside the CDC do choose to use their budget to pay for software that has mapping capability, but I work on a team that is building software to make available for all the different centers to use.
I spent some time researching the current landscape and there were some decent options out there but they were all paid – either a big up front license fee or an API with usage metering. These weren’t ideal for the business purpose especially since the codebase for the existing version was already using the open source [D3 library](https://d3js.org/). I don’t want to get too far into the technical nitty gritty of it, but using vanilla D3 was going to be really challenging.
It’s an old library with a big learning curve and its API has changed a bunch. One of the big considerations in doing a recode was using more modern technology that would be easier for a lot of developers to pick up and maintain and raw D3 just seemed like it wouldn’t work well for that. Luckily, I found an open source project that solved the major pain points by abstracting out D3’s Geo library into some React components called [React Simple Maps](https://github.com/zcreativelabs/react-simple-maps).
I was already planning on using D3 inside React, but the problem is that they both directly manipulate the DOM and I was going to have to use some kind of glue code like [react-faux-dom](https://github.com/Olical/react-faux-dom) but that still would have required using D3’s function calls and didn’t solve the problem I talked about above, plus seemed overly complicated. I am very grateful for React Simple Maps. And if someone hadn’t chosen to open source that work, it wouldn’t have been available for me to use and avoid a lot of pain and extra development time. It’s in that spirit I really wanted to publish the work I did as well.
### My process
The first step was stripping out all of the CDC specific stuff. This was the vast majority of the time I spent. The maps are loaded on cdc.gov through an iframe using an internal system we call the “widget loader” and it was designed and built to be a completely standalone React application. The way people edit the maps and publish them interfaces directly with the backend.
Additionally, there was a backwards compatibility system to read and convert *old* config files from the previous mapping system plus the CDC had a lot of specific requirements that weren’t a good fit for a general release. I kind of had to wear my product hat and think about a cohesive set of functionality that other people would want to take, use and build upon.
I converted all of it into an actual component that could cleanly accept props and modify the editor to let people enable it with a simple boolean and copy config JSON when they’re done. This also involved rewriting a lot of CSS to be more self contained and removing viewport relative units like `vw`.
The end result is that the codebases for the two projects has diverged. There really wasn’t a way to avoid that. I actually think it’s healthy, as new features developed on both sides can be moved between each other but they are no longer 1:1 linked. If the CDC really wants something niche I can build it but don’t have to worry about releasing it to a wider audience.
### Will anybody care?
The main benefit from open sourcing code is having other developers add features to it as well, and if nobody uses it or cares, then it doesn’t matter. You can’t just build something with super specific requirements for your day job, strip out private server info and passwords and throw it on Github. Unfortunately, I saw a fair amount of repos that fell into this category.
This was the second big part of the process. I wanted to make it accessible for other people to use to even have a hope of it gaining any sort of traction.
I spent a fair amount of time on the README and making sure that people building React apps can quickly pull this off the shelf and use it. My main thought was “What would I want as a developer?” and I want to quickly be able to install it and get it working to play around with it and see if it’s actually a good fit for what I need. I think the project does great on that front.
### Finally, the bureaucracy
This was the most intimidating part: getting it through the approval process. Luckily, the CDC has some people internally who are very passionate about open source software. These people have developed guidance and were very helpful to ask for next steps. I also had to deal with the contracting company I work for, Northrop Grumman, and get it cleared through them.
The main concern in open sourcing code from their perspective is security. Does it have known vulnerabilities? Does it have private server information or passwords? I had to get the code scanned by an automated tool, make sure there were no NPM vulnerabilities and have other developers look at it to make sure it’s okay. I also had to make sure the license was correct and I had a bunch of appropriate disclaimers and other text in my README.
Finally, I had to submit that I had done all of this to my team’s Information System Security Officer (ISSO) and get final clearance from him.
All of this sounds like a lot— and it was, but it could have been way worse. I think this would have been way harder to do 3-4 years ago which is really encouraging.
### Future plans
So CDC Maps is published!
View Repository
I plan to maintain it for as long as I work on it and I hope it’s valuable to other people. I already have ideas for a lot of things I want to add in the next release. Things like unit tests, automated linting and some additional refactoring that is scheduled for the main codebase. I think it’s going to be a great way for me to improve my skills while hopefully providing value to other people.
---
## Building and launching my first iPhone app
- URL: https://daniel.do/article/building-launching-first-iphone-app
- Date: 2019-06-29
> (And doing it the hard way.)
**Update Late 2020: I decided to take the app down to focus more on other endeavors, so you cannot download the app any longer. I am leaving this up for posterity though.**
Yesterday, my first iPhone app [Day Plus](https://apps.apple.com/us/app/day-plus/id1470333828?ls=1) launched in Apple’s app store. Why specifically choose to build an iPhone app when I’m a web developer? The idea of dipping my toe into a completely different area of development was appealing to me. I am also trying to get better at building and shipping products. An iPhone app seemed like a good self contained project.
### Doing it the hard way
Going in, I dismissed the idea of using React Native or something similar to build the apps. I probably could have gotten this app built much, *much* quicker using that tool or something equivalent, but I’ve heard that those products can be pretty limited and often don’t function as well as native apps. Plus, it kinda felt like cheating.
The second big technical decision I made somewhat early on was to build the UI completely programmatically. For people not in the know, Apple has a system called “Interface Builder” that allows you to drag and drop user interface elements and connect them with code. I was not a fan of this setup at all. It felt very janky to me and I am used to writing everything in code. This was definitely a much harder road to take, and I am not sure in the end if it was worth it.
I didn’t realize I had this expectation going into this project, but I actually thought it would all be pretty easy. After all, it’s one programming language, and you know exactly what devices you’re optimizing for right? It’s not like web development where it’s a chaotic ecosystem of libraries and frameworks that rise and fall in popularity and you have to test in a bunch of different browsers.
Also, I had read about Swift when it first came out. I assumed that Apple had smoothed out all the rough edges of developing apps and the learning curve would be pretty small unless I was trying to be real fancy. I was wrong!
Swift is a very strongly typed object oriented language. It’s a completely different paradigm to work in. It took me two weeks of studying Swift before I could even do basic algorithmic stuff and for loops without XCode barking at me. I am very glad that I spent several weeks just trying to learn Swift before actually doing app development, I think I would have been too frustrated to keep going if I hadn’t.
### When in doubt, use a CocoaPod
There are several package managers for iOS development. I ended up using both [CocoaPods](https://cocoapods.org/) and Carthage because one package I needed didn’t have CocoaPods support.
You’d expect to use third party packages when you need a special kind of UI functionality or animation, but the thing that really surprised me is how much I ended up relying on these packages for very core app functionality.
For laying out the elements on the screen, I used [TinyConstraints](https://github.com/roberthein/TinyConstraints) which has a much simpler and more declarative syntax than the official Apple way of doing things. For storing data on the phone, I ended up using [Realm](https://realm.io/) because Apple’s way of doing things, called Core Data, was a huge pain in the ass.
It got to the point where to save time, I didn’t even try to learn the “Apple way” of doing something. I just looked to see what the most popular way of doing something was and did that instead. If I could do it over again, I’d probably use something like [Yoga](https://github.com/facebook/yoga) for layouts since I’m very comfortable with Flexbox.
I think Apple understands that they have a long way to go on improving their native APIs. While I was building this app, they introduced [SwiftUI](https://developer.apple.com/xcode/swiftui/) which should improve things somewhat for building UIs, but I think they have a long way to go in other areas too.
My next project is going to be a game, and I just don’t trust SpriteKit enough to use it after reading horror stories so I am probably going to have to use Unity.
I hope this doesn’t come across as too negative, I now know that I went about things in a bit of an odd way and if I had spent more time doing tutorials and stuck to using the interface builder/storyboards I probably would have had a better time.
### My approach
While this was my first app, I did not want to go the route that I think a lot of people go and make some kind of “todo list” app which is basically just a re-skinned tutorial. I wanted my application to be something people could actually use.
I knew I definitely couldn’t compete on features, every additional feature I added was quite a bit more time for me. Plus there are hundreds of other “day counter” apps in the store. So I decided to focus on a very basic feature set and use my design skills to try to make a user interface that stands out.
Even though the user facing functionality is pretty basic for my first version, I made sure not to skimp on other areas that are important for user engagement and retention. I added a package that prompts the user to review the app after several uses, and Firebase so I could get an idea of how many people are using the app and how to improve retention etc…
### Sticking to my requirements, but knowing when to cut a feature
I did something that surprisingly I have not done for many other projects I have built. I sat down and wrote a requirements list for version 1.0. Part of the reason I did this is because every time I described the app to someone they had a different suggestion for a potential feature and I found I was sitting down and kind of aimlessly exploring different options. Building a requirements list gave me a solid check list of items to get through and I knew exactly what was going in.
I did end up having to cut a few small things. For example, there is a progress indicator in the top left corner of the app that visually displays how much of the day has gone by. I was able to get this working but really wanted it to be animated. After spending 5 hours trying to get animation working and feeling lost, I decided to move that feature to a future release.
After I finished the app earlier this week, I was in a lot of fear that it would be rejected by Apple for being too simple. I lurk a lot of iOS developer forums and apparently there has been a large increase in rejections because of this. I thought that maybe I should try to add some of my features that I have planned for my next version.
But I looked at my initial requirements list and saw that I had completed all the items and decided to submit it anyways. I felt the app was complete for a version 1.0 and if Apple disagreed then I would proceed from there.
I put my best foot forward, took good screenshots and wrote thoughtful marketing copy. I even setup a domain to host the privacy policy (with a real website coming at some point maybe) and made it through the submission process on my very first try!
### Where to go from here
I’m really happy that I now have a product I can market, and I’m going to learn about increasing app installs and every aspect of promoting it for a while before I work on a next version. This blog post is the first step in promoting the app, in a way.
This project was really challenging for me. I’m working on a very large project at my day job right now (a recode of a large data mapping system in React) and sometimes I would come home feeling drained, and still put the time in. I would guess some days I was coding for 12+ hours and feeling like I was making very little progress. But it made me a better programmer and a better shipper so I’m happy I went through it, even if Day Plus doesn’t end up being a success.
---
## 2018: A year in review
- URL: https://daniel.do/article/2018-a-year-in-review
- Date: 2018-12-22
> It's the end of the year, time for some reflection on how things went!
It’s the end of the year, and I’ve been reflecting on what I accomplished this year and what I didn’t, as well as what I can do better next year. I’ve decided to write one of these because I really enjoy reading them from other people and it’s nice to catalog things for posterity.
This is my first blog post in about 6 months — I’m pretty far off from my goal of one blog post a month! I knew I would get there eventually, so I’m not that bummed out about it. I wish I hadn’t fallen off *quite* so hard though.
### Career
My focus this year really shifted away from writing blog posts and doing freelance work to doing more practical things to focus on my career. This includes a lot of studying and practice, really drilling down on improving the quality of the code I write. Specifically JavaScript, though I think that doing things like practicing algorithmic problems and really digging deep into the foundations of the language has given me a lot more solid footing with computer science concepts that will apply to any additional languages I pick up. I have a lot of thoughts on this subject that I might be putting in a different blog post later on.
All of this work enabled me to make a change in my career that I’ve been wanting for a while – moving away from doing agency work to a more traditional software development environment. My entire career up until this point has been working at agencies – building websites and sometimes web apps for clients. I am now working at a place in a more senior role, with agile processes in place and helping maintain and build a very large codebase. It’s a lot more responsibility, it pays a lot better and it’s rounding out my career experience in a way that I feel was sorely needed for where I want to be in 5 years.

### Health
My health was a really prominent focus this year for me. Specifically eating and exercise. I’ve always been a bigger guy who likes to eat, so keeping my eating under control was a challenge. The results were a mixed bag – I was able to lose some weight and keep it off. As of this writing, I’m about 60 pounds down from my highest ever weight. But I still have about 80 pounds I need to lose. I really hope I am able to continue making progress on this next year. I was a lot more successful with exercise however – I signed up for a gym membership in January and I’m still going 2-3 times a week. It’s super cool to not need to make “getting back into the gym” a new year’s resolution!
Working with a trainer has really helped me be consistent and I really enjoy how it makes me feel. I also bought a bike and went on a lot of bike rides and hikes with people this year. It’s something I’m hoping to continue to do and maybe even expand on in the new year.

### Travel
I didn’t do any traveling in 2017, and I found I really missed it. I made it a goal to travel more in 2018. My friend Greg was doing some graduate work down in Guatemala, so I was able to visit him for a week and he drove me all around the country. This was only my second time visiting another country (my first was Canada – and I’m not even sure if that really counts) and it was amazing. I’m super grateful that I got the chance to go do that. I really felt like I soaked the country in.
I also went to Maine and Austin this year. The header picture for this post is from a beautiful bridge I saw as I was driving through Maine during the fall foliage. I think traveling solo is really nice. I love meeting new people wherever I go and I’ve learned a lot about how to do solo travel successfully this year. Next year, I’m planning on visiting Japan and possibly Iceland.
### Looking Forward
I have really ambitious plans for next year, and I think I’m in a better place than ever to accomplish my goals. I’m not sure what my blog post schedule is going to look like next year – but I will probably be more active than I was this year. I’ve found that the kind of blog posts I enjoy writing are more editorial than technical. I have a lot of opinions on the industry that I work in that I think might be worth sharing.
I’m excited for what the next year is going to bring. See you in 2019!
---
## Behind the syntax: let and const variables
- URL: https://daniel.do/article/behind-es6s-syntax-changes-let-and-const
- Date: 2018-07-11
> There is a lot more going under the hood than simple syntax changes.
Back in 2015, the JavaScript language got it’s first significant update in 6 years. ES2015 – more colloquially known as ES6 – was released and started making its way into people’s workflows. With it came a type of article on JavaScript that I have come to really dislike: The “Here’s what is new in ES6!” primer.
They usually cover the very visible changes in the language like the new variable declaration keywords. I have found that these articles tend to cover the same ground in an extremely shallow way that does a disservice to the changes in the language and to the reader. They often present these new features as simple syntax changes and don’t mention the underlying changes in functionality going on.
That’s not to say the stuff I cover in these posts isn’t discussed or written about extensively, they are. I just wanted to write something specifically for people who might be coming from one of these very basic ES6 primer articles.
#### What they tell you: `let` and `const`
Now in JavaScript, you declare your variables with the `let` and `const` keywords. You use `let` for variables you know the value is going to change and `const` for ones that won’t.
Amazingly, this is the level of detail I’ve seen a fair amount of articles give on the topic. But there is more going on under the hood.
#### What they don’t: Immutability, block scoping and hoisting
The biggest practical tip I can give about these new variable declarations is that you will not need to use `let` very often. Outside of using counter variables or in rare cases working with primitive data types that need to change you will almost always be using `const`.
The reason for this is because with `const`, only primitives are **immutable**. If your `const` variable is an object (or array, which is a type of object), you can add and remove properties as you please. This [blog post](https://mathiasbynens.be/notes/es6-const) has more on the subject if you’re into the nitty gritty details.
Secondly, these new declarations are **block scoped** instead of function scoped. This can seem like a small change, but it’s actually really important to understand. Having a solid understanding of how scope works in JS is very important, but I will leave that to other articles. When a variable is declared with `var`, it’s scope is the function it currently resides in (or global, if it isn’t inside any function.) with the new keywords, putting them inside a block gives them scope relative to that block. I’ve attached an example to illustrate.
```javascript
const newFunction = () => {
var oldVar = "Function Level";
const newVar = "Function Level";
if(1 === 1) { // Just need a conditional statement to be true for the sake of this example.
var oldVar = "Block Level";
const newVar = "Block Level";
}
console.log(newVar); // Returns "Function Level" because the second declaration of newVar is only accessible to code inside the if block statement.
console.log(oldVar); // Returns "Block Level" because JS reads the second variable declaration as a "re-declaration"
}
newFunction();
```
Something else you will notice if you run that code is that JS doesn’t have any issue with the two `const` declarations even though they are both string primitives. That further demonstrates that they are considered to be two different scopes by JS. If you try to redeclare const in that way in the same scope, JS throws an error.
This is important to know even if you are new to JS (and therefore don’t have any other reference point to learn from) because it’s key to understanding scope in JS, will help you debug older code and understanding the history of JavaScript can be really useful in gaining a deeper understanding of the language.
Block scoping is a useful feature that exists in a lot of other programming languages and was considered a “wish list” item by developers for a while. The creator of JS even admitted that not adding it was not a deliberate decision, but rather the result of a [deadline crunch](https://twitter.com/brendaneich/status/349768501583548416). People wrote [complicated workarounds](http://adripofjavascript.com/article/drips/emulating-block-scope-in-javascript.html) just to emulate it. In his book, [JavaScript: The Good Parts](http://shop.oreilly.com/product/9780596517748.do) (published in 2008) Douglass Crockford imagines a new, streamlined version of JS that gets rid of the “bad parts”. In this new language, he implemented block scoping.
Finally, the last major point that these new variable declarations change is **hoisting**. With traditional variable and function declarations, JavaScript will move the declarations to the top of the scope before executing. However, for variables it only moves the *declarations* up, not the initializations. So if you have the code `var test = "foo";` it is only moving up `var test;` and giving it a value of `undefined` (which, despite what you’d think, is actually a value. So if you were checking if the variable existed, JS would tell you it does)
So JS will know the variable exists, but can’t detect the value until the initialization is called. It can be confusing, and if you want to learn more you can check [this article](https://scotch.io/tutorials/understanding-hoisting-in-javascript) out to do a deeper dive with the concept and numerous code examples.
The new variable keywords do not hoist in the same way as `var`. They still technically hoist (under the hood), but attempting to reference them before they are declared will cause an actual error: JS will act like they don’t exist. Here’s an example (Comment out line 2 to avoid the error stopping the full code from running.)
```javascript
console.log(hoistedVar); // "undefined" - hoisted declaration only
console.log(nonHoistedConst); // Throws an actual error in JS: nonHoistedConst is not defined
var hoistedVar = "Hoisted";
const nonHoistedConst = "Definitely not hoisted";
console.log(hoistedVar); // Actually displays the value of the variable.
console.log(nonHoistedConst);
```
Why the change? Well, to avoid confusion. Generally, using hoisting has been considered poor form when writing code and led to countless hours of debugging for people who did not understand this concept. This change is simply enforcing what already was good practice when writing code.
There is also a way to write functions that avoids hoisting and is the generally accepted way to do it by most style guides. Using a [*function* expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function#Function_declaration_hoisting) instead of a declaration. Here’s a simple code example that demonstrates these concepts for both variables and functions.
```javascript
hoistedFunction();
// This declaration is moved to the top before the JS is executed.
function hoistedFunction() {
console.log('Hoisted function. Bad!');
}
// If we tried to call this function before this expression, JS would throw an error!
const nonHoistedFunction = function() {
console.log('Not hoisted! Good!')
}
nonHoistedFunction();
```
There is a newer ES6 syntax for creating functions: [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). Those bring along their own changes and are going to be the subject of the second post in this series.
I hope that a little bit of a deeper dive helped give some further context behind these changes. Writing these posts helps me go back over and clear up any lingering misunderstandings myself. I’m looking forward to writing part 2!
---
## How I write blog posts every month
- URL: https://daniel.do/article/how-i-write-blog-posts
- Date: 2018-02-17
> What I've learned after writing regularly for half a year.
Back in September of last year I started this blog and seeded it with a few posts. I wrote in my [first post](http://daniel.do/article/so-why-write-a-blog/) that my goal was to write one blog post a month, and that has turned out to be a pretty good cadence for me. I think if I had tried to do any more than that, I would have fallen off the wagon immediately. Carving out 2-3 hours on a Saturday once a month is doable. I’m pretty happy with the posts I’ve written, though I’d like to get even better. It’s pretty cool after working with WordPress for 10 years to finally have a blog of my own that I maintain.
I wanted to take this month’s post to go over my writing process, what an ideal blog post looks like for me and how my focus and the subjects I write about has shifted. While I’m certainly not a blogging rockstar with tons of traffic, I’m writing this because this is the type of blog post I *love* to read from other people. I like learning about how people live and work.

### My process
Only needing to write one post a month gives me a lot of time to think about and generate ideas. I keep a list of potential blog post ideas in [Dynalist](https://dynalist.io/) and can quickly sketch out the outline of a post from there. I try to have the major beats of the post outlined before I sit down to write.
When writing about web development, there is no way a blog post I write is going to be on the scale of something that would come out of Smashing Magazine. I just don’t have the time or inclination to try to write posts of that scope here. Also, while I certainly am very good at my job I am not someone who lives and breathes web development and lives on the cutting edge. Work/life balance is important to me. Most times I’m not going to be the guy who is writing the primer about some brand new cutting edge technology that just came out. There are a lot of people putting out that kind of content, and while I think I could compete if I really made it a focus, I’m just not willing to. So when writing technical posts, I focus on small practical functionality, or giving broad primers on things. But I also don’t want to cover ground that has been covered a million times over, because then the whole exercise is pointless. It can be a little tricky at times.
After choosing my subject and feeling confident in my outline that I have some value, I sit down to write. Usually on a Saturday morning. I love that saying “I hate to write, but I love having written.” That’s how I feel every time I sit down to write a post. The first 30 minutes are usually full of wailing and gnashing my teeth. Sometimes I start writing and completely abandon my outline. Or I get stuck writing the first paragraph for an hour. Eventually the post starts to come together. I’m not going to lie, sometimes it is a sprint to the end.
I give myself a 3 hour time limit for a blog post, which includes finishing the outline, writing and editing and creating a photo. So after finishing, I do a quick proofread and choose a photo. When I designed this blog, I thought a lot about whether or not I even wanted to have featured images. It can be pretty difficult to figure out what image to choose for a topic like “blogging” that isn’t a hideous, generic stock photo. What I have settled on recently is using duotone images. They add a great splash of color and it goes with the aesthetic styling of the site. Choosing an image and editing it has become the most enjoyable part of putting together a blog post for me.
Then I hit publish! Having a new blog post up on my site feels really good. Because I know that I am living up to a commitment I made to myself to maintain this blog and I’m helping other people in the process.
### Changing focus & goals
When I started this blog, it was to complement my portfolio. I wanted to help people and raise my profile and Google search results. I still think that’s important, but in my personal life I have changed my focus from taking on a lot of freelance work and trying to build myself up professionally to focusing on self care and self improvement. Instead of spending my nights and weekends coding, I go to the gym and cook a nice meal. Hang out with friends. I’ve been traveling more. I just got back from spending a week in Guatemala and visiting a friend down there. It’s all been really cool and positive, but has changed the things that I think about a lot and want to write about. Instead of a WooCommerce code snippet, maybe I’d rather write about how I prep my meals for the week or how I’ve [improved my productivity](/article/leveling-up-with-productivity/). But if I am expending the time each month to do this, I’d really like it to help improve my professional profile and prospects. It’s a delicate balance.
The truth is, a lot of my life feels in flux right now. I’m not really sure what I want my next steps to be professionally and personally. This blog is a reflection of that. I’ve considered everything from moving to a different country to building my own startup. I’m still figuring it out.
I don’t have any specific, concrete goals for this blog. Like I don’t hope that it helps me get to a certain keyword ranking on Google, or gets me to a certain conversion rate. Right now I’m content to just keep writing each month. Later this year I would like to see if I can write some guest posts for other blogs and generate some backlinks and organic traffic, but if I do that it’s going to be in a very limited capacity.
### Doing better going forward
There’s always ways to improve, and I know there’s a lot I can do to do better with blogging. Firstly, I want to **write better**. I feel like my personality doesn’t come through in my posts often enough. I could be more expressive and write some jokes—it doesn’t need to be so dry. I’d also like to improve my grammar and spelling. I know sometimes I publish this stuff with small errors.
I also plan on eventually tweaking the design of the blog to support things like photo galleries and try to improve readability for long content. I don’t think my current blog design is the most legible for long form reading. So that would probably include switching to a serif typeface for body text.
I also want to promote my posts better. See if I can get links back to my posts when I write them after I hit publish. I haven’t done a great job in that area.
So that’s it! That’s how I write my blog posts. As always, I hope you got something out of this that can help you in your own endeavors or at least found it interesting! Maybe I’ll do this again when I hit a year.
---
## Improving my productivity in 2018
- URL: https://daniel.do/article/leveling-up-with-productivity
- Date: 2018-01-13
> Here's how I'm tackling becoming a lot more productive in the new year.
2017 was a really good year for me. I did a lot of freelance work, improved my financial situation, built this site and started blogging, moved, and generally accomplished a lot of stuff personally and professionally. But getting all of those things done came with a downside: I was constantly stressing out about them.
Over the years I had built my own system to manage my life which basically involved me writing short term projects down in different iCloud notes with a daily todo list and writing down longer term projects in documents in Google Drive. I would find often myself staring at these documents for way longer than I needed to and going over and over them in my head. I think this is partly because I have some low level anxiety, but also because my system was very disorganized and wasn’t actually decreasing my cognitive load at all (what’s the point in writing it down if you’re constantly thinking about it anyways?)
When I started thinking about what I wanted to focus on in 2018, I knew something needed to change. I have a lot of things I want to accomplish this year, and because I have gotten better at paring down my goals and making sure my motives are correct (I want to write a blog post about this someday) I knew that they were all reasonable and achievable, but I was still worried about not being able to get them done… **because how will I manage that many things?** I knew that I physically *could* do all the things I want to, but was worried about managing them and making sure I get them done. To me, that was the final straw in moving to a better productivity system.
### Building a new system
It’s been a couple weeks since I began this project and I’ve tried a lot of different things. I did a deep dive and read about a lot of the different systems out there like Kanban and Pomodoro. Eventually I settled on one that I really liked: **Getting Things Done**. Here’s a [quick primer](https://lifehacker.com/productivity-101-a-primer-to-the-getting-things-done-1551880955) on the system if you aren’t familiar with it. It can be a little complicated and I’m not sure I’m working it 100% yet, but already things have improved quite a bit. I don’t have to plan my week anymore, I just keep all my tasks in a “Next Actions” list and work on them when I feel like I can. I also don’t plan to follow GTD as closely as possible. I will mix and match with other systems and find what works best with me. It’s nice to have a base to work from.
After I had a system I wanted to figure out some focused productivity software to use with it. Now, there are a million productivity apps out there that all pretend to be the one that has it all figured out. In truth, after doing a lot of reading, I don’t think there’s any specific application or productivity system that will work for everybody. I think everybody has to find exactly what works best for them. Also, what works for you might change. I genuinely think each of these apps starts with a developer going “Well, this app kind of works but it should do *X* this other way because that’s how I like to do it!” and so spawns yet another productivity app.
Because of that, I chose an app that was very simple but allowed a lot of flexibility: **Workflowy**. Basically, the only data type is a list. Everything is nested inside a list. It’s a really cool concept and you can implement several different kinds of productivity systems in it. Unfortunately, the project needs a lot of help on the design/development front: it feels very ancient and the iOS app was so bad it was almost unusable. After searching around I found an app that implements the core concepts of Workflowy but with more features and much better UI: **Dynalist**.
This service has been a game changer for me. It really helps me get things done more efficiently. I still have a lot of work to do before I feel the system is perfect for me, but it is already way, way better than what I was doing before.
I hope this post helps somebody out there find the motivation to get their todo list under control!
---
## Handling advanced product imports in WooCommerce
- URL: https://daniel.do/article/handling-advanced-product-imports-in-woocommerce
- Date: 2017-12-09
> Learn how to handle advanced things like core fees when importing products into WooCommerce.
*I recently wrapped up a big WooCommerce project that required quite a bit of customization. I’ve decided to write about a few of those customizations and share code snippets. See a previous entry in the series [here](http://daniel.do/article/selectively-disabling-payment-forms-in-woocommerce/).*
### The Problem
I had a client with over 9,000 products for their WooCommerce store. That is a crazy amount of products on it’s face, but a lot of the products were connected to each other, and had specific attributes. This was all managed with a carefully curated spreadsheet. I needed a way to enable them to reliably import these products whenever they had new ones without having to manually go in and add them in the administration panel.
I searched around and found [WP All Import](http://www.wpallimport.com/). This powerful plugin handled a lot of the heavy lifting. It lets you upload a spreadsheet and map that spreadsheet to data in WordPress. Great! The only problem was, some of these products had attributes that couldn’t simply be mapped to things in WooCommerce.
#### Core Fees (The advanced part)
I’ll give an example. Some of the items designated as “products” in the spreadsheet were actually core fees. If you don’t know what a core fee is, Ebay gives a [pretty good explanation](http://www.ebay.com/gds/What-is-a-core-charge-Why-do-I-have-to-pay-for-it-/10000000095744644/g.html). It’s common for people who manufacture expensive and specialized parts to require this. In the spreadsheet, the part that the fee was tied to was designated in a specific column.
I had installed another WooCommerce plugin called [Force Sells](https://woocommerce.com/products/force-sells/) that allowed two products to be tied together. This plugin worked well, but there was no way to map the data when importing with WP All Import to the Force Sells plugin. I needed a way to tie the data together programmatically, after the actual import had occurred.
### The Solution: Functions and hooks
Luckily, WP All Import has several useful hooks in their plugin including `pmxi_after_xml_import`. This lets you run code after the import is complete.
When importing I was importing in the admin area, I designated rows in the spreadsheet that had a value in the “Core Fee” column to have a custom field named `core_fee`. Every product that had a core fee attached had the ID of that core fee stored in a custom field. Then, using the `mxi_after_xml_import` hook I built a function that would take all of these core fee items, hide them from public view and associate them with the correct product. This way, the only time a user saw the core fee was after they had added a product to their cart.
#### Here’s the code:
```php
'product',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'core_fee',
'value' => '',
'compare' => '!=',
),
),
) );
$products = $core_query->posts;
foreach ($products as $product) {
$core_id = get_post_meta($product->ID, 'core_fee', true);
// Grab a post object by the core fee ID
$core_fee = get_page_by_title( strval($core_id), OBJECT, 'product' );
// Add the ID to a special custom field for the Force Sells plugin.
add_post_meta($product->ID, '_force_sell_synced_ids', array($core_fee->ID), true);
// Disable visibiity on core fees so they won't show up where they aren't supposed to by default.
wp_set_object_terms( $core_fee->ID, array('exclude-from-catalog', 'exclude-from-search'), 'product_visibility', true );
// Remove original custom field to keep things tidy
delete_post_meta($product->ID, 'core_fee');
}
} ?>
```
### Conclusion
This method worked reliably for several unusual things that didn’t fit within the normal parameters of importing products. And because of WP All Import’s easy to use interface and ability to save import templates, I was able to hand off this advanced importing system to my clients confident that they would be able to import whenever the need arose without having to involve me further. Hope you got something out of this!
---
## Beginner interaction design with Principle
- URL: https://daniel.do/article/beginner-interaction-design-with-principle
- Date: 2017-11-30
> I was able to pick up this powerful motion design tool in about 10 minutes and you can too!
Earlier this year when I was designing this site, I had a bit of a problem: I wanted to go above and beyond with the animations and interactions, something more than basic CSS. I’ve always been interested in animations on the web, and I’ve had the experience of building out advanced CSS animations, using the [GSAP](https://greensock.com/gsap) library and even working with SVG animations in the past. But I’ve had a persistent problem during all this time: I didn’t have an easy way to mock up interactions, so I had to visualize how they would go in my head and then code them.
I think in browser design is great, and I use it here and there, but for complicated animations it is really tricky. In the past, I have spent hours building one interaction only to figure out that it doesn’t really work the way I thought it would or I can’t get the timing quite right. This is incredibly frustrating.
I knew that if I really wanted to build something I was happy with, I needed a way to design and view the animations *before* they went into code. Eventually, I settled on the application [Principle](http://principleformac.com/). I’ve decided to write a guide that will get you the background you need and making your own designs in Principle in as quick as 10 minutes!
### Picking the right tool
It’s crazy to me that up until this year, I was still doing the majority of my design in Photoshop and Illustrator. I think my hesitance towards motion design tools came from that place: I knew that the tool that a lot of the pros were using for this kind of work was After Effects, and I was intimidated by the thought of having to learn how to use the same program people use to put CGI in movies with to figure out how to make a button do some cool stuff when you hover over it!
Luckily, just as when I discovered Sketch and realized there were quite a few very innovative screen design applications that didn’t have the same amount of bloat and baggage as Adobe’s tools, I discovered that there were *many* easier motion design options to choose from that focused specifically on user interface animation. In fact, there were so many that it was almost overwhelming!
When comparing tools, the thing that jumped out at me about Principle was how easy it was to get started and its integration with Sketch. After watching a few videos about how an interaction could be built in a minute, I was hooked.
### Using Principle
Principle’s user interface is simple it almost doesn’t even need an explanation. Basically, you use the same concept of “artboards” that other design applications use, but you modify them and connect them with an interaction, with Principle doing the tweening and animation magic.
So if you have an artboard in Sketch with a button and you want to figure out what the hover state will look like, you simply need to paste that artboard into Principle twice. Then, you can the second artboard to be a hover state and connect the two via the “mouseover”to the interactions. Then, you can actually interact with the button in a preview panel to make sure it works exactly the way you intend. I love it because it took something that could be very messy and complicated and made it dead simple.
Now, you might be thinking “Isn’t this overkill?” For many cases yes, mocking up a button hover is indeed overkill. However, on my site I wanted something complex for my calls to action. I wanted a border to form and the arrow to move. It was much easier to put it together in Principle than working out and tweaking the code for hours.
Principle is very easy to use but has a surprising amount of depth. I mentioned tweening earlier. Principle will take care of the heavy lifting automatically, but you can actually go in and tweak all settings on how that tweening works, including using timing functions. I haven’t had need to get heavily into that area yet, but it’s nice to know if I ever want to do something advanced the option is there without having to use a different tool.

### Conclusion
Ultimately, Principle served exactly the purpose I had for it: Whenever I was stuck in a design, I could copy and paste my Sketch artboard and generally mock up what I wanted in a few key frames. It is not the most powerful tool on the market, but if you aren’t looking to achieve total mastery and instead want an easy way to level up your skills in this area, it’s a no-brainer. Head over to [their site](http://principleformac.com/) and download the trial today!
---
## Tips for a successful WooCommerce project
- URL: https://daniel.do/article/tips-for-a-successful-woocommerce-build
- Date: 2017-10-29
> Building your first WooCommerce site? Here are 4 things to consider.
I recently wrapped up a very large WooCommerce build that I am planning on writing a case study for next month. In the meantime, I thought I would share some of the lessons I learned and pitfalls I hit. This is obviously not a comprehensive list, but these are the things that became big issues for me and I think it would be useful for other freelancers. These items are both technical and business related.
### 1. There *is* a plugin for that—but be careful
Just like with WordPress, there are *tons* of plugins for WooCommerce. If you are encountering a problem, it’s likely that someone else has solved it and is trying to sell it to you for $70. In fact, because plugin authors know that an e-commerce site is more likely to pay for a plugin they create them for small functionality. I saw plugins that were maybe 30 lines of code functionality with an admin panel slapped on.
There’s nothing wrong with that, but if you are doing a custom build these plugins add a lot of technical debt. They are highly variable in quality, and after buying a few and installing them only to find that they didn’t do *quite* what I needed or were a security risk or they just plain sucked I decided to just build my own solutions whenever possible.
Obviously for larger scale functionality it is worth it to go with a reputable, popular plugin but I saved myself a lot of grief and my client a fair amount of additional cash by keeping extraneous plugins to the minimum.
### 2. Know your vendors
Know exactly what third party services your client is planning on using, **especially** their payment processor and how good their WooCommerce integrations are before you submit a proposal. My client had a specific company in mind to handle their payments that they wanted to use because that company also did their bookkeeping. I said “Sure, we can use them- as long they have a WooCommerce plugin.” They did, so I wrapped that into my quote.
After getting into the project, it turned out that their online payment stuff was a complete mess. The payment processor had a legacy system and a new system and poor documentation for both. Their plugin was developed by a third party so we had to talk to *two different support teams* when trying to figure out where the errors were coming from. The issues we had with this delayed the project by **months**.
Definitely do your research, and if your client isn’t married to a specific option it’s generally best to go with the most popular options like Stripe or Authorize.net.
### 3. A lot of things changed earlier this year
If you have a snippet from StackOverflow that isn’t working, it might be because WooCommerce made some big changes when they moved into 3.x earlier this year. This includes stuff like accessing stored information about a product etc…
More than once I ran into a situation where a code suggestion or explanation from a third party site didn’t work and I had to dig into the official documentation to come up with my own solution.
### 4. Stick to the established UI patterns
While a very powerful part of WooCommerce is how extensible and easy to change it is, there are certain things that WooCommerce is very opinionated on. These things are hard to change without extensive additional development time. As an example, my clients wanted to split the checkout process into several parts. This is actually fairly difficult to do using the normal tools that WooCommerce provides. Even the plugin I found that did it used a pretty hacky workaround that involved hiding sections with CSS.
If your client wants to do things with the purchase flow that are outside of the WooCommerce default, research them and work that into your quote.
### That’s it!
Those are the big ones. I hope I helped or at least gave you a heads up. I’m planning on doing a lot more WooCommerce work in the future, so I might keep writing on this topic. Thanks for reading.
---
## Selectively disabling payment gateways in WooCommerce
- URL: https://daniel.do/article/selectively-disabling-payment-forms-in-woocommerce
- Date: 2017-09-20
I recently wrapped up a big WooCommerce project that required quite a bit of customization. I’ve decided to write about a few of those customizations and share code snippets.
### Here’s a Scenario
The companies that process credit card transactions charge a fee to do so. It’s usually a flat amount plus a small percentage of the transaction. It’s why sometimes at locally owned gas stations you will see “$5 minimum card purchase” signs. This is a cost of doing business that is usually built into the amount something costs—but what if you have a product that costs a lot of money and is so low margin that the fees will eat up any profit you’ll make? That might sound like an edge scenario, but it’s actually pretty common for certain types of businesses. The solution is to disable credit cards and force the purchaser to use an ACH transfer gateway.
With WooCommerce it is simple to selectively disable gateways based on the total amount of a cart. Check it out:
```php
cart->cart_contents_total >= 3000.00 ) {
// If it is, remove the gateway.
unset($gateways['gateway_name']);
}
return $gateways;
}
add_filter('woocommerce_available_payment_gateways','danieldo_filter_gateways',1);
```
Here we are checking to see the total amount and if it is above $3000 we are disabling `gateway_name`. Of course, change `gateway_name` to the name of your credit card gateway when using this code and the total amount.
---
## My Pardot landing page starter kit
- URL: https://daniel.do/article/pardot-starter-kit
- Date: 2017-09-05
> Because building Pardot landing pages sucks.
Over the past year, I’ve built an increasing amount of Pardot landing pages in my day to day role. I think landing pages are a really interesting niche to optimize for, and it’s been a cool experience going over analytics and statistics and using tools like [Hotjar](https://www.hotjar.com/) to see end users interact with what I build. However, throughout this process I keep running into one major issue…
### The Problem
**Pardot sucks!** Or, rather, that’s what I exclaimed the first time I was confronted with having to build one. I am used to having modern tools to help me build websites. Things like SASS and version control and deploying from the command line. With Pardot, you code the page and manually copy and paste the code into the web application. If you want to host assets, you have to manually upload those as well and put them in your code.

Additionally, Pardot is fairly limited in how it enables end users to edit content on landing pages. You have to define sections as “regions” with data attributes and clicking on a region opens up a WYSIWYG (or text) editor for them. Perfect, right? Well the editor does not load external assets like stylesheets, so the only way to get a styled design that actually looks like the landing page they will be editing is to **put all those styles inline in the actual template.** What a pain, right?
Also, unlike a traditional website where (in a perfect world) the client approves the design and you code it, Pardot landing pages can be very agile creatures. Sometimes there will be 5 different versions to test user response and sections will be added and removed daily. This resulted in my copying and pasting code all over the place, losing track of what file was which version and generally causing a lot of stress.
Eventually, it became clear that I needed to bring some of the tools that I use in regular web development to the landing page world.
### A Starter Kit
I built a simpler starter kit with the essential features I felt I had been missing: **version control, reusable templates, sass and the ability to minify and put stylesheets and scripts in the actual html file.** As I outlined above, that last feature is crucial. The difference is huge:

I’ve also integrated the Nunjucks templating engine, which is incredibly powerful. It allows me to build “component libraries” of sections and quickly add or remove them from different pages. Building out A/B versions is simple and quick.
{#snippet icon()}{/snippet}
View on Github
I’ve been using this kit for a little while now and making improvements here and there, and it has been a game changer in terms of getting these landing pages out quickly and at the best possible quality. I still have a few major things I’d like to eventually include, namely automating the deployment process, if the API allows me to do so.
Until then, I am happy to offer this tool to other developers. If you like it, let me know on Github! I’m very interested to hear how people are using it and if there are other features that could be added.
---
## How I quit social media
- URL: https://daniel.do/article/quitting-social-media
- Date: 2017-09-02
> Earlier this year I quit social media. I would recommend trying it.
Just to keep things clear, I consider social media to be any service where you’re presenting yourself using your real name. I don’t think sites like Reddit count. Also, I don’t really count sites that have a social element that are for professional development or some other purpose like LinkedIn (though I did get rid of my LinkedIn account) or Github/Dribbble.
### My motivation
In short: I was sick of nonstop posts about politics, I realized that I was very negative on it, and it often made me feel like I wasn’t living a good enough life.
The reasons are going to be different for every person and it doesn’t ultimately matter. The big thing for me is *how* I did it, and what my life is like today with no social media.
I didn’t wake up one day and say “I’m done with all social media!” It was actually a slower process that begun with me just trying to clean up the multitude of accounts I had floating around. The whole process took about 6 months and I did it in a series of steps.
#### Starting at the edges
I realized I had a Snapchat that I pretty much never used. Maybe once or twice a month I would get a snap from somebody. Instagram I was a little more active on and I liked that I had a grid of photos from specific memories in my life, but those were easily backed up. It was easy to remove a lot of peripheral apps like that.
#### Closer to home
Then I started evaluating my relationships with services I used every day. I had a Twitter account with hundreds of followers. People I’d met professionally, people I knew from doing standup, regular friends who just happened to have an account, etc… Twitter was by far my most heavily used social media. I took pride in how unfiltered I was on there. But Twitter was one of the first Google results for my name. How many potential opportunities did I pass up because of that? If you had asked me then, I would have said I didn’t care. But the truth is somewhere in-between. I don’t ever want to work somewhere or have a relationship where I feel like I can’t be myself, but I also now recognize and acknowledge that there are different levels of sharing in relationships and it’s not the worst thing in the world to have a little restraint.
I also realized how negative I was on there. Twitter was my favorite place to go on a rant and read things to get upset about. I don’t think I was a very fun follow. I was also obsessed with my follower count. I feel like on Twitter, everybody is trying to be a somebody. And there is that ridiculous blue check mark system, as if having one makes you a more valid person. Twitter encouraged some of my worst social media habits and getting rid of it was the first thing that really stung. But Twitter didn’t affect my real social life. The biggest battle was to come.
#### The big one: Facebook
Finally I was down to the big scary one: Facebook. Of all of the accounts I got rid of, Facebook was the only one that deleting actually had an effect on my life in real ways. That’s kind of scary and dystopian, but it’s so ubiquitous that I almost can’t blame apps and services for connecting to it. For a long time even Tinder didn’t let you use its service without a Facebook account, though that’s no longer the case (stoked to be able to match with people again and be too timid to message them!)
The weirdest/craziest side effect of this was when a friend of mine that lived out of state who I only was connected with through social media noticed that I wasn’t on Facebook anymore, checked and saw I had deleted all my social media and was worried I was suicidal. Getting a text message from a worried friend on a Friday night thinking I’m on the edge when I was actually just out to dinner with some friends was really jarring.
But aside from all of that, when I looked at how I actually *used* Facebook day to day. There was some value there: Messenger was a fairly valuable tool to be able to talk to people I wasn’t as close to, so was getting event invites. But the day to day deluge of status updates, the constant bragging and attention seeking (that I was also a part of) made it not worth it. I wasn’t using Facebook in a healthy way and it was making my life worse. So I got rid of it.
#### Tips
* Check your motivations. Do you actually want to be done with these services? Is this a change you could actually commit to?
* Definitely start slow. Any big sweeping change is likely to be so jarring you will revert back and not really change at all.
* I regret not communicating more that I was doing this. You don’t need to post a big dramatic Facebook status, but it might be worth it to let people in your life know you are doing it.
### What it’s like now
As of this writing it’s been about 6-7 months since I’ve had any social media. Now that I am “detoxed”, I really prefer it. I put active effort into maintaining friendships and most of all, I am not trying to impress anybody anymore. I live my life, I try to treat other people well and expect the same in return. I still get invited to stuff, though less often I think. The coolest thing for me is the friendships I’ve developed *after* Facebook. I love really getting to know someone just based off the things they tell me. I can’t go on and see everything they’ve said and thought since they were in middle school.
Another really interesting thing I’ve noticed is how little social media or the things that happen on it are discussed in real life. It never gets mentioned with friends or in group texts. **It’s like this whole meta thing that doesn’t really exist.**
There have been a lot of doom and gloom predictions about social media in popular media. Kudos to you if you recognize the Black Mirror episode that is the header image for this blog post. It basically depicts a world where everybody has a social media account and their ability to participate in society is intrinsically linked to their popularity on the service. There is a [funnier take](http://community-sitcom.wikia.com/wiki/App_Development_and_Condiments) on the same concept in the show Community.
I don’t really think we are headed towards something like that. Really, I don’t think that social media is *inherently* good or bad. I think social media is something that can make life better if you are using it intentionally and have really considered its role in your life. For me, I ultimately decided it was a complication I didn’t need and my life is more peaceful without it.
---
## So why write a blog?
- URL: https://daniel.do/article/so-why-write-a-blog
- Date: 2017-09-01
> I want to share my knowledge and help others the way people helped me.
I’ve never been good at maintaining a “professional” profile on the web. It’s bitten me in the ass when I’ve really needed to show off work and didn’t have a good site to point people to. Historically, the problem has always been that I have trouble designing something that feels like it represents “me” and it never seems good enough.
I’ll start out and get discouraged and then decide I don’t *really* need a good portfolio anyways and give up or throw up something quick. This year I set out to break that pattern, and I’m really happy to have done so. It was a several month long journey of self doubt and testing my determination, but this is the first time I’ve ever had a personal site I am really happy with.
When I was outlining the content I wanted for the site, I knew that I wanted a blog. I’ve been reading other people’s blog posts since I started using the internet. I’ve learned great web development techniques from them but also I’ve really appreciated getting to know other people through their blog posts. I want to be able to share thoughts and ideas with a larger audience. Also, writing seems to help me organize my thoughts.
It’s my hope that in a small way I can contribute to the web development community and add my knowledge to what else is out there. I’ve benefited from countless other people doing the same thing over the years.
So now I have a blog. It’s going to be a mix of personal entries and web development items. For now, it’s my goal to write **one post a month.** That will probably slip but hey, it’s worth trying to maintain for a while right?