<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://blakewatson.com/">
  <title>Personal Webpage of Blake Watson</title>
  <subtitle>The personal webpage of Blake Watson</subtitle>
  <link href="https://blakewatson.com/feed.xml" rel="self"/>
  <link href="https://blakewatson.com/"/>
  <updated>2026-02-18T19:18:38Z</updated>
  <id>https://blakewatson.com/</id>
  <author>
    <name>Blake Watson</name>
    <email>blake@blakewatson.com</email>
  </author>
    <entry>
      <title>I used Claude Code and GSD to build the accessibility tool I’ve always wanted</title>
      <link href="https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/"/>
      <updated>2026-02-18T19:18:38Z</updated>
      <id>https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Because of a severe mobility impairment—spinal muscular atrophy—I &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/&quot;&gt;use a Mac for almost everything&lt;/a&gt; I do, and I have a &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/&quot;&gt;particularly unique way of interacting with it&lt;/a&gt;. One of my biggest challenges—&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/&quot;&gt;aside from typing&lt;/a&gt;—is the rather mundane &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;act of scrolling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m unable to manipulate a scroll wheel or perform a swiping gesture. That means the usual methods for scrolling on a mouse or trackpad are out. The method I do use is probably something you haven’t thought about in a long time—I click on and drag the scrollbar.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; In most instances, it’s not too bad. But it can be very annoying in cases where the scrollable area is very long or in newer apps that tend to hide the scrollbar when not in use.&lt;/p&gt;
&lt;p&gt;For years now, I’ve been able to ease my scrolling burden with a fantastic browser extension called &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt;. It works great on most web pages and I do use the web a lot. That said, there are a ton of places where it doesn’t work. Even in the web browser, it doesn’t work in reader mode and it doesn’t work in browser settings views and other built-in browser pages. And obviously it doesn’t work in other apps or in the operating system itself.&lt;/p&gt;
&lt;p&gt;Several months after posting about my &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;scrollbar woes&lt;/a&gt;, Ryan Ohs sent me an email with a delightful surprise. He had been learning about Apple’s Accessibility API and after reading my post he put together this quick and dirty &lt;a href=&quot;https://github.com/ryanohs/omniscroll&quot;&gt;drag and scroll program&lt;/a&gt; that worked at the operating system level. It was a cool experiment. And while I was grateful for the gesture, it didn’t turn out to be practically usable in my day-to-day workflow.&lt;/p&gt;
&lt;p&gt;Time passed. I helplessly watched as app after app shipped with inaccessible scrollbars. I made do with a cumbersome workaround—macOS has a &lt;a href=&quot;https://support.apple.com/guide/mac-help/use-dwell-mchl437b47b0/mac&quot;&gt;dwell action&lt;/a&gt; for scrolling. The way it works is when you enable dwelling, you hover your mouse over where you want to scroll and wait for a short delay. Some UI appears with arrows which you can then hover your mouse over to scroll the area in that direction. It’s slow and annoying but effective when needed.&lt;/p&gt;
&lt;p&gt;In other cases where apps are built with customizable web technology—like &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt;—I was able to write CSS styles to make scrollbars large and in charge.&lt;/p&gt;
&lt;p&gt;Fast-forward to now. AI is everywhere. Many developers I follow are blogging or &lt;a href=&quot;https://www.youtube.com/watch?v=g_Bvo0tsD9s&quot;&gt;making videos&lt;/a&gt; about the moment they realized AI is a force to be reckoned with. Other developers I follow loathe the technology, citing ethical concerns over environmental impact and intellectual property theft. I have a ton of cognitive dissonance. It’s amazing and horrible all at the same time.&lt;/p&gt;
&lt;p&gt;I would say that 90% of my current AI use is Copilot autocomplete in VS Code. This saves me a ton of time because I’m using an onscreen keyboard, pecking out code character by character. Yes, there is standard editor completion, especially when you’re using &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;typed languages&lt;/a&gt;. But AI autocomplete goes far beyond, inferring what I want to do based on just a handful of characters. I can often complete an entire line or perhaps an entire code block after a half-dozen keystrokes in a fraction of the time it would have taken me to enter it manually.&lt;/p&gt;
&lt;p&gt;The remaining 10% (I’m totally guesstimating here obviously) of my usage is queries I make to ChatGPT. This is usually stuff where I expect my query has one correct answer based on a consensus. Otherwise, I will turn to searching the web with &lt;a href=&quot;https://kagi.com/&quot;&gt;Kagi&lt;/a&gt;. I’ve dabbled with things like &lt;a href=&quot;https://claude.com/product/claude-code&quot;&gt;Claude Code&lt;/a&gt; on small side projects, mostly as an AI dev assistant. I haven’t yet done what people call &lt;em&gt;vibe coding&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There’s a new kind of coding I call “vibe coding”, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. It’s possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. Also I just talk to Composer with SuperWhisper so I barely even touch the keyboard. I ask for the dumbest things like “decrease the padding on the sidebar by half” because I’m too lazy to find it. I “Accept All” always, I don’t read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I’d have to really read through it for a while. Sometimes the LLMs can’t fix a bug so I just work around it or ask for random changes until it goes away. It’s not too bad for throwaway weekend projects, but still quite amusing. I’m building a project or webapp, but it’s not really coding - I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class=&quot;caption&quot;&gt;— &lt;a href=&quot;https://x.com/karpathy/status/1886192184808149383&quot;&gt;Andrej Karpathy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Until now.&lt;/p&gt;
&lt;p&gt;The idea of vibe coding was previously off-putting to me. There are several reasons for that. One of which is that I enjoy coding. Another reason is responsibility and accountability. If I’m going to put something out there for people to use, particularly if I’m charging for it or promoting it, I want to know how the code works. I also don’t really enjoy working by chatting and doing multiple follow-up prompts. I don’t want to have to include all the right magic words to make the AI do what I’m talking about. I don’t want to be a prompt engineer.&lt;/p&gt;
&lt;p&gt;But then I came across this &lt;a href=&quot;https://zeldman.com/2026/02/09/claude-code-for-designers&quot;&gt;post by Jeffrey Zeldman&lt;/a&gt;. He linked to an article about building an app from a Figma mockup. In that article, the author mentions using Claude Code and &lt;a href=&quot;https://github.com/gsd-build/get-shit-done&quot;&gt;Get Shit Done&lt;/a&gt;, a “meta-prompting system” that makes Claude Code behave a certain way and essentially encapsulates context management and prompt engineering so that you don’t have to think about it.&lt;/p&gt;
&lt;p&gt;I was intrigued and I had an idea. Maybe my scrolling problem was solvable after all. This was the perfect candidate for a vibe coding project. I didn’t have the mental bandwidth to learn enough Swift and native macOS programming to do it on my own. I’d considered hiring other developers to make assistive tech software for me before, but it never went anywhere, usually because of lack of interest. This seemed like a small enough project that AI could reasonably handle it.&lt;/p&gt;
&lt;p&gt;And handle it, it did.&lt;/p&gt;
&lt;h2 id=&quot;introducing-scroll-my-mac&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/#introducing-scroll-my-mac&quot;&gt;Introducing Scroll My Mac&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2026/ScrollMyMac.jpg&quot; alt=&quot;Scroll My Mac settings window showing scroll mode toggle, click-through options, hold delay setting, and hotkey assignment.&quot; /&gt;
  &lt;figcaption&gt;The Scroll My Mac settings window&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Not only was I able to put together this native app for scrolling at the OS level, I was able to add a ton of quality of life features that make it really nice to use. Most people are not going to find this app useful. I get that. But it’s incredibly useful for me and a handful of people I know who have tried it.&lt;/p&gt;
&lt;p&gt;The main purpose of &lt;a href=&quot;https://scrollmymac.blakewatson.com/&quot;&gt;Scroll My Mac&lt;/a&gt; is to allow me to click and drag my mouse over any area to scroll it like you would on a phone or tablet—no reliance on a scroll wheel, a finger swipe, or manipulating a tiny scrollbar. It achieves this goal with a handful of other features that make it more practical.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can toggle scroll mode with a keyboard shortcut or by the menu bar icon.&lt;/li&gt;
&lt;li&gt;If you enable click-through, you can still click on things normally.&lt;/li&gt;
&lt;li&gt;By default, doing a dragging action will invoke the scrolling engine. That means you cannot drag to select text, move windows around, or do drag-and-drop actions on a web page. For this reason there is an optional setting called &lt;em&gt;click-and-hold passthrough&lt;/em&gt;. It could use a better name, but what it does is allow you to click and hold the mouse button down, keeping it stationary, for a short delay. After that delay, the scroll engine will deactivate and allow you to perform a drag action as you normally would. The delay is adjustable. This quality of life feature is necessary if you want to keep scroll mode on all the time.&lt;/li&gt;
&lt;li&gt;You can reconfigure the hotkey to be whatever key combo you want.&lt;/li&gt;
&lt;li&gt;You can have Scroll My Mac launch at login.&lt;/li&gt;
&lt;li&gt;If you’d like certain applications to be ignored by Scroll My Mac, you can add those to an excluded apps list in settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve only had it for a few days and I’m already blown away by how much easier it is for me to use certain applications.&lt;/p&gt;
&lt;h2 id=&quot;how-i-built-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/#how-i-built-it&quot;&gt;How I built it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, I didn’t really build it at all of course. This project was 100% vibe-coded.&lt;/p&gt;
&lt;p&gt;I already had Claude Code installed. I followed the instructions for installing &lt;a href=&quot;https://github.com/gsd-build/get-shit-done&quot;&gt;GSD&lt;/a&gt;. I should put a disclaimer here that I don’t think using this directly on your machine is a super great idea. &lt;em&gt;I&lt;/em&gt; did it. But I think if I were doing a non-macOS project with it, I would install it in a VM. You’re probably relatively safe using Claude Code only, but once you start including prompts from external sources that you aren’t really monitoring, that’s when you set yourself up for prompt injection attacks.&lt;/p&gt;
&lt;p&gt;Anyway, once I had everything set up, I ran the new project command. Right off the bat, what was fascinating about this process is that Claude began asking me a ton of questions about my project. It made me think of aspects of it I hadn’t considered.&lt;/p&gt;
&lt;p&gt;Throughout the process, I would do a good bit of back and forth describing what I wanted and answering follow-up questions about it. Everything I discussed with the AI went into markdown files in the project. GSD runs its own software development lifecycle. There’s a discuss phase, a planning phase where it may do some research and map out a detailed plan, and the execute phase where the actual code is written. Lastly, it will do a verification phase. This is where it will ask you to verify things and describe issues. At every point in this process, the current state of things is written to markdown files. This means you don’t lose context over multiple chats.&lt;/p&gt;
&lt;p&gt;One by one, we completed phases of development. First creating a settings window and keyboard shortcut. Then doing the basic scroll functionality. Then adding inertial scrolling. And so it went, discussing milestones and letting the AI do its thing.&lt;/p&gt;
&lt;p&gt;I have the Claude Code Pro plan, which is $20 per month. I blew through my included usage pretty rapidly and was routinely dipping into extra usage. The entire project took roughly 8 hours (done over a few days) and cost me about $80 worth of extra usage. I believe this could have been mi less if I had not been using GSD and leaning into its whole planning phase (as opposed to using its quick task mode, which gives similar benefits with a bit less work on the planning and discussion phases).&lt;/p&gt;
&lt;p&gt;Still though, if the app I ended up with was on the Mac App Store for $99, I would buy it in a heartbeat. I don’t know if this app could make any money or not, but I’m not charging for it. I’m making it &lt;a href=&quot;https://github.com/blakewatson/scroll-my-mac&quot;&gt;available on GitHub&lt;/a&gt; for anyone who might need it. You don’t need to build it from source. I’m &lt;a href=&quot;https://github.com/blakewatson/scroll-my-mac/releases&quot;&gt;uploading releases&lt;/a&gt; as I get them out. I do have an Apple Developer account (I have an old Electron app called &lt;a href=&quot;https://d20app.me/&quot;&gt;d20&lt;/a&gt; on the App Store), so I was able to code-sign and notarize it. That means you can download it and run it without a bunch of security warnings. Still though, just know that the code was 100% written by AI and use it at your own risk.&lt;/p&gt;
&lt;h2 id=&quot;what-does-it-all-mean%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/#what-does-it-all-mean%3F&quot;&gt;What does it all mean?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is a feeling of existential dread permeating the industry. It’s countered by what is possibly the biggest hype machine I’ve ever seen. I’ve felt both extremes of this over the past three or four days.&lt;/p&gt;
&lt;p&gt;On one hand, I think it’s absolutely incredible to think that users with all kinds of different disabilities could create their own assistive technology by describing to AI what they need. It is hard to describe how slow that bottleneck is sometimes. There is an industry built up around assistive tech, but it often is either too expensive or doesn’t do what the person needs. And lots of things just don’t exist because there isn’t sufficient motivation to work on them (for example, the onscreen keyboard situation on Linux completely blows).&lt;/p&gt;
&lt;p&gt;But now these apps &lt;em&gt;can&lt;/em&gt; exist. All it takes is the motivation of one person to spend a day or so working with an AI to develop an assistive technology that exactly meets their needs. Right now, you have to be a developer to use this stuff. But it’s not hard to imagine this technology becoming more mainstream and easier for non-developers to use.&lt;/p&gt;
&lt;p&gt;And that’s the other side of it—the existential dread. Is AI going to replace me, the developer? What will I do instead? My only skills are knowledge and information work (&lt;a href=&quot;https://blakewatson.com/work/&quot;&gt;coding and design&lt;/a&gt;). I can barely move a few fingers on my hands, so I’m not going to be getting a manual labor job anytime soon. If we are to believe the biggest of the AI hype men, then it won’t matter because we will be living in a land of plenty where no one will have to work. Somehow I doubt that’s the case.&lt;/p&gt;
&lt;p&gt;Until then, I continue to dabble in order to hopefully keep myself relevant. Only in personal projects, though. Vibe-coding is expressly forbidden in &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;my current role&lt;/a&gt; and I’m grateful for that. We’ve been told that we are responsible for the code we ship and that means understanding why and how it works. It doesn’t mean I don’t get the occasional AI assist. But the way I use it is more akin to the way I used to use Stack Overflow.&lt;/p&gt;
&lt;p&gt;I don’t know what’s going to happen, but I guess I’m joining the refrain of many a developer that has said it before me—it seems like this shit is here to stay.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;You will see frequent use of the em dash in my writing. That’s not because AI wrote it for me, it’s because I love the em dash. I say don’t let AI claim our em dash and our sparkle ✨ emoji. &lt;a href=&quot;https://blakewatson.com/journal/i-used-claude-code-and-gsd-to-build-the-accessibility-tool-ive-always-wanted/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>New: link blog and RSS feeds</title>
      <link href="https://blakewatson.com/journal/new-rss-feeds/"/>
      <updated>2026-01-28T10:01:54Z</updated>
      <id>https://blakewatson.com/journal/new-rss-feeds/</id>
      <content xml:lang="en" type="html">&lt;p&gt;A bit of website housekeeping. I’m constantly finding cool things on the web. Usually I end up sharing them with different group chats or via direct messages. But I figured I’d start off the new year by &lt;em&gt;finally&lt;/em&gt; adding a link blog to my website—something I’ve been itching to do for a while.&lt;/p&gt;
&lt;h2 id=&quot;rss-feeds&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-rss-feeds/#rss-feeds&quot;&gt;RSS feeds&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I started by publishing my link posts on my main feed, but I think that is a bit noisy. So I’ve reverted the main feed back to journal posts only. Links have their own feed and if you &lt;em&gt;really&lt;/em&gt; want to keep up with me (I don’t know why) you can also subscribe to the microblog feed, which is mostly just my Mastodon posts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Journal feed: &lt;a href=&quot;https://blakewatson.com/feed.xml&quot;&gt;https://blakewatson.com/feed.xml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Links feed: &lt;a href=&quot;https://blakewatson.com/links/feed.xml&quot;&gt;https://blakewatson.com/links/feed.xml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microblog: &lt;a href=&quot;https://blakewatson.com/microblog/feed.xml&quot;&gt;https://blakewatson.com/microblog/feed.xml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>Default apps, 2026</title>
      <link href="https://blakewatson.com/journal/default-apps-2026/"/>
      <updated>2026-01-27T18:19:56Z</updated>
      <id>https://blakewatson.com/journal/default-apps-2026/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I first published this list after seeing a similar post by Robb Knight (&lt;a href=&quot;https://rknight.me/blog/app-defaults/&quot;&gt;2023&lt;/a&gt;, &lt;a href=&quot;https://rknight.me/blog/app-defaults-2026/&quot;&gt;2026&lt;/a&gt;) and &lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;many others&lt;/a&gt;. For each category, I’m listing the app I’m using now, plus my response in 2023 for comparison.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mail Client&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Fastmail.app&lt;/li&gt;
&lt;li&gt;2023: Mail.app&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mail Server&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Fastmail&lt;/li&gt;
&lt;li&gt;2023: Pobox (Pobox has been owned by Fastmail for a while; they eventually discontinued it and migrated all the accounts to Fastmail proper.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Obsidian, iA Writer&lt;/li&gt;
&lt;li&gt;2023: Bear, Tot, Bike, iA Writer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;To-Do&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Things, Obsidian&lt;/li&gt;
&lt;li&gt;2023: Things&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phone Photo Shooting:&lt;/strong&gt; n/a (Camera, but I don’t/can’t really take photos myself)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Photo Management&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Photos.app&lt;/li&gt;
&lt;li&gt;2023: Photos.app&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calendar&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Fantastical. This should be the default calendar in macOS.&lt;/li&gt;
&lt;li&gt;2023: Fantastical&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud File Storage&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Dropbox, iCloud Drive&lt;/li&gt;
&lt;li&gt;2023: Dropbox, iCloud Drive&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RSS&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Feedbin web. I still don’t find myself reading much from my RSS feed, but I’m trying to take some time this year to collect some more feeds.&lt;/li&gt;
&lt;li&gt;2023: Feedbin web&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contacts&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Cardhop. I don’t love it but I get it bundled with Fantastical and it’s better than Contacts so…&lt;/li&gt;
&lt;li&gt;2023: Cardhop&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Chrome for work, Firefox and Vivaldi for personal&lt;/li&gt;
&lt;li&gt;2023: Arc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chat&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Discord, &lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/&quot;&gt;Brainwave Chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2023: Discord&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bookmarks&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;My DIY bookmarks app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2023: &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;My DIY bookmarks app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read It Later:&lt;/strong&gt; n/a&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Word Processing&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Pages&lt;/li&gt;
&lt;li&gt;2023: Pages&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spreadsheets&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Numbers&lt;/li&gt;
&lt;li&gt;2023: Numbers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presentations&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: iA Presenter&lt;/li&gt;
&lt;li&gt;2023: iA Presenter&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shopping Lists&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#groceries&quot;&gt;My DIY groceries app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2023: &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#groceries&quot;&gt;My DIY groceries app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meal Planning&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: lol&lt;/li&gt;
&lt;li&gt;2023: n/a&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Budgeting and Personal Finance&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Numbers&lt;/li&gt;
&lt;li&gt;2023: Numbers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;News&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Mastodon (Ivory), Hacker News, &lt;a href=&quot;https://www.readtangle.com/&quot;&gt;Tangle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2023: Mastodon (Ivory), Hacker News&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Spotify&lt;/li&gt;
&lt;li&gt;2023: Spotify&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Podcasts&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: n/a, haven’t really been listening to podcasts&lt;/li&gt;
&lt;li&gt;2023: no dedicated podcast app, just a web browser&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password Management&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: 1Password&lt;/li&gt;
&lt;li&gt;2023: 1Password&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bonus stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Visual Studio Code (a different theme/font all the time because I get bored)&lt;/li&gt;
&lt;li&gt;2023: Visual Studio Code (Rainier theme)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terminal&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Warp. For one reason and one reason only—you can manipulate text with all the Mac keyboard shortcuts you are used to and it just works, including highlighting text and using your mouse.&lt;/li&gt;
&lt;li&gt;2023: iTerm2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;2026: Kagi, ChatGPT (😭). Kagi really is great. I rarely ever bounce out to Google with the &lt;code&gt;!g&lt;/code&gt; shortcut, and when I do the results aren’t any good anyway.&lt;/li&gt;
&lt;li&gt;2023: Kagi&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>I tried solo RPG with Ironsworn: Starforged</title>
      <link href="https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/"/>
      <updated>2026-01-25T12:54:00Z</updated>
      <id>https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/</id>
      <content xml:lang="en" type="html">&lt;p&gt;You may already know about tabletop role-playing games (TTRPGs) like D&amp;amp;D. They typically have a lot of rules and mechanics and one player serves as the game master, adjudicating these rules as the players describe their actions and roll dice for their various abilities.&lt;/p&gt;
&lt;p&gt;Solo RPG is when you play games like this by yourself instead of in a group. This sounded kind of depressing to me when I first heard about it. But there are a lot of reasons for wanting to do this, not the least of which because it’s fun. You might want to check out a game before you introduce it to a group. Or you might want to play games that the rest of your group isn’t really into. Or maybe it’s hard for your group to get together to play as often as you’d like. Or maybe you’re having trouble finding a group in the first place (okay that one is kinda sad).&lt;/p&gt;
&lt;p&gt;When playing in a group, you’re typically describing your actions together in a collaborative storytelling environment. “I draw my sword and strike at the skeleton,” you might say. “Roll your attack dice,” the game master (GM) responds. The GM lets you know if your attack worked based on the outcome of the roll. You may roll damage or use other abilities and your teammates may help you take on this skeleton or maybe give you a heal if you have received damage.&lt;/p&gt;
&lt;p&gt;Solo RPG is a bit different as you’re not exactly acting things out with a group of people. They often involve some sort of writing down what happens. I’ve learned that this is a spectrum from bullet points to full-on prose (my personal choice). I like to think of solo RPG as a series of writing prompts with rules. You absolutely don’t have to treat it that way and don’t have to think of it as writing if that’s not something that interests you.&lt;/p&gt;
&lt;p&gt;Almost any TTRPG can be solo—people even play D&amp;amp;D solo—but I think rules-light games are more conducive to solo play. These are game systems that have less mechanics and things to track than heavier systems like D&amp;amp;D. &lt;em&gt;Ironsworn: Starforged&lt;/em&gt; (I’ll refer to it as simply &lt;em&gt;Starforged&lt;/em&gt; now) is probably somewhere in the middle—a good amount of rules but less than D&amp;amp;D. It was written with solo play in mind, but also multiplayer. It’s a flexible system that can work with just you, multiple players without a GM, or a full party with a GM.&lt;/p&gt;
&lt;p&gt;As I was looking into solo RPGs, I found that on the other end of the spectrum, extremely rules-light systems exist. These are called &lt;a href=&quot;https://www.ehimeajet.com/vampires-witches-skeletons-mesoamerican-gods-and-a-big-bloody-castle-an-introduction-to-solo-journaling-ttrpgs/&quot;&gt;solo journaling RPGs&lt;/a&gt; and are focused on the writing or journaling. They typically have very few, if any, mechanics. They may not even need dice. If that sounds interesting to you, I’ve heard a lot of good things about &lt;a href=&quot;https://thousandyearoldvampire.com/&quot;&gt;Thousand Year Old Vampire&lt;/a&gt;. Personally, I’ve got my sights set on &lt;a href=&quot;https://fantasticjean.itch.io/reminiscence-of-decay&quot;&gt;Reminiscence of Decay&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-ironsworn%3A-starforged&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#introduction-to-ironsworn%3A-starforged&quot;&gt;Introduction to Ironsworn: Starforged&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://tomkinpress.com/pages/ironsworn-starforged&quot;&gt;Ironsworn: Starforged&lt;/a&gt; is part of the &lt;em&gt;Ironsworn&lt;/em&gt; series of RPGs published by &lt;a href=&quot;https://tomkinpress.com/&quot;&gt;Tompkin Press&lt;/a&gt;. First off, the writing, art, and design is absolutely fantastic. It comes as a book and or PDF (with various formats available) and immediately pulls you into an immersive world of spacefaring.&lt;/p&gt;
&lt;p&gt;Thematically it’s sci-fi fantasy akin to Star Wars, Firefly, and similar titles. The game sets up an overall backdrop—in the past, humans left a spiral galaxy to travel to a small globular satellite galaxy called the Forge.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2026/forge.jpg&quot; alt=&quot;This infographic shows a large spiral galaxy that has a small red-orange globular galaxy called the Forge not too far above its galactic plane. The bottom edge of the forge is called Terminus. Beyond that a little ways is the Outlands. The vast majority of the forge is called the Expanse. And the sparse, mostly empty area around the Forge is called the Void.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The Forge serves as the setting for your adventures. It’s a place where humanity has a foothold in a settled region called Terminus, a less-settled frontier called the &lt;em&gt;Outlands&lt;/em&gt;, and a vast unexplored &lt;em&gt;Expanse&lt;/em&gt; beyond. The game gives you a nice starting point while still giving you endless possibilities to create your own universe and stories within it.&lt;/p&gt;
&lt;p&gt;A tenet of solo RPG is that &lt;em&gt;prep is play&lt;/em&gt;. &lt;em&gt;Starforged&lt;/em&gt; has a good amount of prep, helping you create your world and a character to explore it, before your adventure even begins. But as soon as you crack open the book (or PDF), you are considered to be playing the game. Learning about the game, preparing for your adventure, and creating your character is all part of playing the game.&lt;/p&gt;
&lt;h2 id=&quot;oracles&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#oracles&quot;&gt;Oracles&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before I go any further, it’s worth mentioning that as the book takes you through your preparation and into your adventures, you will be making a lot of decisions—what happens when your character attempts something and succeeds? What if they fail? Success or failure may be dependent on the outcome of a dice roll. Sometimes what happens will be based on your own writing and imagination—whatever you decide happens, happens.&lt;/p&gt;
&lt;p&gt;But as you explore the Forge and take on your quests, you don’t have to shoulder the burden of inventing everything on your own. The book includes many &lt;em&gt;oracles&lt;/em&gt; to help you along the way. These are essentially random tables that you can roll dice against to choose anything from names, places, and attributes to themes and ideas. When you’re stuck and you don’t know how to proceed, consult an oracle table or three.&lt;/p&gt;
&lt;p&gt;I’ve really enjoyed the interplay between my own imagination, the outcome of predefined moves, and rolling against oracle tables to see what happens or to get inspiration. As we will see later, you will create areas of the Forge, called sectors, procedurally using oracle tables to define stars, planets, and settlements. It’s quite fascinating.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-your-world&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#setting-up-your-world&quot;&gt;Setting up your world&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you’ve learned a bit about the rules (more on this later) the book takes you through a setup process where you create the broad strokes of your world (called Truths), your player character, and a starting sector within the Forge.&lt;/p&gt;
&lt;h3 id=&quot;truths&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#truths&quot;&gt;Truths&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This brilliant setup strategy pulled me into the world. Even among sci-fi fantasy, there can be a lot of differences in the way the world works. For example, one of the truths you choose is &lt;em&gt;Magic&lt;/em&gt;. Does it exist in your world at all? If it does, is it really just technology and not magic in the true sense of the word? Or does magic flow through your universe, powering all sorts of unnatural abilities? The choice is yours. The book gives you three options to choose from (roughly the ones I mentioned), which you can roll dice for if you want an element of chance. But you are also welcome to write your own definition or modify the ones they provide. There are no limits here.&lt;/p&gt;
&lt;p&gt;You move through these truths defining how religion works, how communication works, what was the cataclysm that made humans flee to the forge in the first place, etc. As you work through the truth categories, you build out a unique world little by little. This section in particular got my creative juices flowing. Sometimes I would take options from the book wholesale, other times I would write my own. As I was working through, I started having ideas for my character already. I started visualizing places in the Forge. I find that this rich starting point gave me a lot of creative ideas. A lot easier than a blank page, that’s for sure!&lt;/p&gt;
&lt;h3 id=&quot;create-your-character&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#create-your-character&quot;&gt;Create your character&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Creating a character in &lt;em&gt;Starforged&lt;/em&gt; is similar to doing it in other games like D&amp;amp;D. &lt;em&gt;Starforged&lt;/em&gt; focuses on humans, so there isn’t really an equivalent to species like D&amp;amp;D has. Of course, this is your game, so you’re free to do whatever you want. But the game offers a number of paths, which are somewhat similar to selecting a class in D&amp;amp;D.&lt;/p&gt;
&lt;p&gt;For example, I chose these two paths for my character: &lt;strong&gt;Courier&lt;/strong&gt; and &lt;strong&gt;Empath&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2026/starforged_paths.webp&quot; alt=&quot;Side-by-side view of the Courier Path card and Empath Path card. Each card has information about features that these paths grant your character. The first feature on each card is checked. The others are unchecked as you get them at a later time. See below for verbatim transcription of the cards.&quot; /&gt;
  &lt;figcaption&gt;If you&#39;re playing with the physical book, you can either purchase or print these handy reference cards.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;details&gt;
  &lt;summary&gt;Transcript of card text&lt;/summary&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;PATH: COURIER&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you &lt;strong&gt;Swear an Iron Vow&lt;/strong&gt; to transport and protect something precious, set its safety to &lt;strong&gt;5&lt;/strong&gt;. When you &lt;strong&gt;Undertake an Expedition&lt;/strong&gt; or &lt;strong&gt;Set a Course&lt;/strong&gt; and score a weak hit or miss, you may suffer &lt;strong&gt;-1 safety&lt;/strong&gt; as the cost. On a miss with a match, you must suffer &lt;strong&gt;-2 safety&lt;/strong&gt; as the cost. When safety falls to &lt;strong&gt;0&lt;/strong&gt;, envision a major complication related to this mission. If you overcome the threat, mark progress twice on this quest. Then, set safety to &lt;strong&gt;3&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When you &lt;strong&gt;Fulfill Your Vow&lt;/strong&gt; to an unbonded connection by completing a courier mission, mark progress twice on the relationship.&lt;/p&gt;
&lt;p&gt;When you &lt;strong&gt;Sojourn&lt;/strong&gt; during a courier mission, you may roll &lt;strong&gt;+safety&lt;/strong&gt;. On a strong hit, take &lt;strong&gt;+1 safety&lt;/strong&gt; or &lt;strong&gt;+1 momentum&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Safety track: &lt;strong&gt;5 4 3 2 1 0&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;PATH: EMPATH&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you read the intent, emotions, or memories of a nearby being, roll &lt;strong&gt;+heart&lt;/strong&gt;. On a strong hit, you glimpse a helpful aspect of their inner self. Envision what you learn, take &lt;strong&gt;+2 momentum&lt;/strong&gt;, and add &lt;strong&gt;+1&lt;/strong&gt; when you make moves to interact with them in this scene. On a weak hit, the visions are murky; take &lt;strong&gt;+1 momentum&lt;/strong&gt;. On a miss, you reveal a troubling motive or secret; &lt;strong&gt;Pay the Price&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;As above, and if you score a hit as you read them, you may subtly influence their attitude or actions, such as making a hostile being hesitate. Take another &lt;strong&gt;+1 momentum&lt;/strong&gt;. If in a fight, mark progress.&lt;/p&gt;
&lt;p&gt;When you &lt;strong&gt;Face Danger&lt;/strong&gt; to soothe a being’s distress by creating an empathic bond, roll &lt;strong&gt;+spirit&lt;/strong&gt; and take &lt;strong&gt;+1 momentum&lt;/strong&gt; on a hit. If they are an ally, also give them &lt;strong&gt;+2 spirit&lt;/strong&gt; on a hit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/details&gt;
&lt;p&gt;These cards are called &lt;em&gt;assets&lt;/em&gt; and there are different categories. As you create your character, you will have the choice between different asset cards. Each one grants you certain features and abilities, or represent something you can use (like your starship, for example).&lt;/p&gt;
&lt;p&gt;The book will guide you through creating a backstory for your character. You’ll use your paths as inspiration and of course there are oracle tables if you need them. You’ll also give your character a background vow. This is a sort of long term mission or quest your character has taken on.&lt;/p&gt;
&lt;p&gt;You’ll also assign stats to your character:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Edge:&lt;/strong&gt; quickness, agility, and prowess when fighting at a distance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heart:&lt;/strong&gt; courage, willpower, empathy, sociability, and loyalty.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iron:&lt;/strong&gt; physical strength, endurance, aggressiveness, and prowess when fighting at close quarters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shadow:&lt;/strong&gt; sneakiness, deceptiveness, and cunning.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wits:&lt;/strong&gt; expertise, knowledge, and observation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you flesh out a few more details and name your character, you’re ready to set up a starting location.&lt;/p&gt;
&lt;h3 id=&quot;starting-sector&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#starting-sector&quot;&gt;Starting sector&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A neat aspect of &lt;em&gt;Starforged&lt;/em&gt; is generating the areas that your character will explore. You do it by a mix of your own whims, a few rules, and a healthy dose of oracle table rolls.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2026/sector_crimson_maw.png&quot; alt=&quot;This graphic shows a hexagonal grid labeled, Sector: Crimson Maw. In the top left corner is a Death Star icon labeled Farpoint. There is a single line connecting it to a planet toward the bottom right called Sepulcher. The icon is a planet that looks to have an orbital habitat around it. There is an arrow pointing from Sepulcher to the bottom edge of the map indicating that you can leave the Sector from that direction. In the middle toward the top, not connected by any lines, is another Death Star icon labeled Mudd.&quot; /&gt;
  &lt;figcaption&gt;
    My starting sector, the &lt;em&gt;Crimson Maw&lt;/em&gt;, located in the &lt;em&gt;Outlands&lt;/em&gt;.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You end up with a couple of settlements of interest you can explore. The neat thing about it is that you generate some surface level information about every settlement in your starting sector, but you don’t need to worry about giving a specific area more detail until you actually arrive there. At that point, you can roll on oracle tables or look through the different types of locations to flesh out the area—what it looks like, what its laws are like, even what kind of trouble you’re in when you arrive, if any.&lt;/p&gt;
&lt;h3 id=&quot;swearing-an-iron-vow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#swearing-an-iron-vow&quot;&gt;Swearing an iron vow&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Swear an Iron Vow&lt;/strong&gt; is how you accept a quest in &lt;em&gt;Starforged&lt;/em&gt;. It’s an official move your character can make. Your character will usually quite literally hold a piece of iron that is important to them and make the vow of the thing that they are trying to accomplish. Mechanically, this will generate a progress meter that you will then make moves toward filling up and completing. Once you swear your first iron vow, you are ready to begin your adventure.&lt;/p&gt;
&lt;h2 id=&quot;the-rules-system&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#the-rules-system&quot;&gt;The rules system&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m not going to rehash all the rules here as the book does a much better job than I can do of explaining them. But I will give you an idea of the mechanics of the gameplay. The book has a list of moves and what kind of events will trigger those moves. The rule system is based on the popular &lt;em&gt;Powered by the Apocalypse&lt;/em&gt; system. Many TTRPGs have been created using this system as a base. I’ve written about one of them—&lt;a href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/&quot;&gt;Monster of the Week&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;dice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#dice&quot;&gt;Dice&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In &lt;em&gt;Starforged&lt;/em&gt; a “move” is a mechanic that requires rolling dice and determining the outcome based on whether the result was a &lt;em&gt;strong hit&lt;/em&gt;, a &lt;em&gt;weak hit&lt;/em&gt;, or a &lt;em&gt;miss&lt;/em&gt;. You roll a d6 called an &lt;em&gt;action die&lt;/em&gt; against 2d10, called &lt;em&gt;challenge dice&lt;/em&gt;. You’re always rolling a stat, similar to D&amp;amp;D, so add you add the appropriate stat bonus. You then add any other bonuses given by features or the situation. The sum of your d6 plus these bonuses is your &lt;em&gt;action score&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strong hit:&lt;/strong&gt; your action score is higher than each challenge die&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weak hit:&lt;/strong&gt; your action score is higher than one of the challenge dice&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Miss:&lt;/strong&gt; your action doesn’t beat either challenge die&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ties go to the challenge dice.&lt;/p&gt;
&lt;p&gt;Depending on what move you’re making, you may have the option to choose which stat to roll. I’ll give you an example.&lt;/p&gt;
&lt;p&gt;Your character is traveling across the sector through an uncharted path to an outpost settlement. You make the move &lt;strong&gt;Undertake an Expedition&lt;/strong&gt;. That move has a detailed description and it gives us three options for which stat to roll, depending on how the character is approaching the situation. My character opts to stay vigilant, rolling &lt;em&gt;+wits&lt;/em&gt;. If his wits stat is 2, a roll might look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1d6: rolled a 3&lt;/li&gt;
&lt;li&gt;210: rolled a 4 and a 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My action score is 5 (my d6 + wits) and that beats the one challenge die (the 4) but not both. This is a &lt;strong&gt;weak hit&lt;/strong&gt;. The move description says that on a weak hit I make progress, but the progress costs me. How it costs me, story-wise, is up to me. The move description gives me some options for how to mechanically handle a weak hit.&lt;/p&gt;
&lt;h3 id=&quot;moves&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#moves&quot;&gt;Moves&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve discussed a few moves now, but it’s important to note that not everything is a move. In &lt;em&gt;Starforged&lt;/em&gt; moves represent something important, uncertain, that has the possibility of failure and consequences. If I want to ride my hover bike across a bustling futuristic city so that I can question an old friend, I can just do that. It’s not particularly dangerous. I don’t need to &lt;strong&gt;Undertake an Expedition&lt;/strong&gt;. If I’m confronting something dangerous or I’m discovering something important to a quest or entering into combat, these are the types of things that will require a move.&lt;/p&gt;
&lt;p&gt;If you’re curious, here is the description text for one of the moves.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Undertake an Expedition&lt;/summary&gt;
  &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When you trailblaze a route through perilous space, journey over hazardous terrain, or survey a mysterious site, give the expedition a name and rank.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then, for each segment of the expedition, envision your approach. If you…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Move at speed:&lt;/strong&gt; Roll +edge&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep under the radar:&lt;/strong&gt; Roll +shadow&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stay vigilant:&lt;/strong&gt; Roll +wits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On a &lt;strong&gt;strong hit&lt;/strong&gt;, you reach a waypoint. Envision the location and mark progress per the rank of the expedition.&lt;/p&gt;
&lt;p&gt;On a &lt;strong&gt;weak hit&lt;/strong&gt;, as above, but this progress costs you. Choose one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Suffer costs en route:&lt;/strong&gt; Make a suffer move (-2), or two suffer moves (-1).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Face a peril at the waypoint:&lt;/strong&gt; Envision what you encounter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On a &lt;strong&gt;miss&lt;/strong&gt;, you are waylaid by a crisis, or arrive at a waypoint to confront an immediate hardship or threat. Do not mark progress, and &lt;strong&gt;Pay the Price&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/details&gt;
&lt;p&gt;I won’t describe all the moves here as, again, the book does that much better. But I will say that the book does a nice job of categorizing the moves and giving you enough to feel like there are options, but not so many as to be bewildering.&lt;/p&gt;
&lt;h3 id=&quot;progress&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#progress&quot;&gt;Progress&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Whenever you are trying to accomplish something, be it a quest, a journey, or improving a relationship with an NPC, you will track the progress on what &lt;em&gt;Starforged&lt;/em&gt; calls a progress track.&lt;/p&gt;
&lt;p&gt;You can think of it as a series of ten checkboxes. Depending on how you’ve ranked the difficulty of that track will inform how many boxes you’re able to check off whenever significant progress is made. This gives you a clear structure for knowing when you are close to completing something. In my case, I’m writing my game as a story, so when I make progress and I’m reaching the end of a track, that will prompt me to guide the fiction, that quest or expedition, whatever it is, to an ending.&lt;/p&gt;
&lt;h3 id=&quot;advancement&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#advancement&quot;&gt;Advancement&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As you fulfill your iron vows—your quests—you will have the opportunity to advance your character and gain new features and abilities.&lt;/p&gt;
&lt;h2 id=&quot;starfall%3A-my-starforged-playthrough&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#starfall%3A-my-starforged-playthrough&quot;&gt;Starfall: my &lt;em&gt;Starforged&lt;/em&gt; playthrough&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m trying out solo RPG for the first time as a way to inspire me to write creatively more often than what I’ve done in the past (which was essentially to attempt &lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/&quot;&gt;NaNoWriMo&lt;/a&gt; once a year). As a way to keep me motivated—and also as an excuse to make another website—I decided to publish my game on the web.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://starforged.blakewatson.com/&quot;&gt;https://starforged.blakewatson.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the time of this writing, I’m a few chapters in. I’m posting chapters of my game as I play them. This isn’t great fiction or anything, but I’m trying to make it somewhat interesting as a story. It might also be helpful to anyone who wants to get started but doesn’t know how (I’m definitely still a n00b, though; fair warning).&lt;/p&gt;
&lt;p&gt;How you record the antics of your character is up to you. You don’t need to write full prose like I’m attempting to do here. You can journal from your character’s perspective. You can make short bulleted lists on index cards for what happens. However you would like to record your game is fine!&lt;/p&gt;
&lt;p&gt;So far I’ve decided to post the main game as chapters and then fill out some of the backstory and other lore as a group of pages.&lt;/p&gt;
&lt;h2 id=&quot;playing-in-obsidian&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#playing-in-obsidian&quot;&gt;Playing in Obsidian&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are an infinite number of ways to go about playing &lt;em&gt;Starforged&lt;/em&gt;. The book and PDF include character sheets and more for recording various aspects of the game. If I were &lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/&quot;&gt;still able to write by hand&lt;/a&gt;, I would probably be playing this game very &lt;abbr title=&quot;in real life&quot;&gt;IRL&lt;/abbr&gt; with a journal and physical dice, etc.&lt;/p&gt;
&lt;p&gt;But alas, my world is mostly digital. Fortunately, there are excellent digital tools available. I have been using &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; for &lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/&quot;&gt;note taking&lt;/a&gt; for a while. Obsidian’s superpower is its wealth of quality themes and plugins that allow it to do just about anything. Obsidian is turning into &lt;a href=&quot;https://orgmode.org/&quot;&gt;org mode&lt;/a&gt; for non-programmers.&lt;/p&gt;
&lt;p&gt;I’m using the fantastic plug-in &lt;a href=&quot;https://ironvault.quest/&quot;&gt;Iron Vault&lt;/a&gt; along with a &lt;a href=&quot;https://github.com/insanum/obsidian_gruvbox&quot;&gt;vintage color scheme&lt;/a&gt; and a quirky monospaced font. Iron Vault gives you an interactive character sheet. This is what mine looks like.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2026/ironvault-1.webp&quot; alt=&quot;Obsidian app window with the Iron Vault plugin open to a character sheet for Roland Duval. The left sidebar shows a vault folder tree, the center pane shows character details and attributes, and the right pane lists Starforged oracles and moves.&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;I’m writing my chapters in a folder called Journals. Whenever I feel it’s time to make a move, I can open the command bar and start typing the name of the move. Iron Vault will roll dice for me (with animations included) and then output a nice display of the results directly into my text.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2026/ironvault-2.webp&quot; alt=&quot;Obsidian window in dark mode with a journal note titled “Chapter 02.” The note contains story text and an Iron Vault move card showing “Undertake an Expedition” with a dice roll result, while the right sidebar lists Ironsworn: Starforged oracles and moves.&quot; /&gt;
  &lt;figcaption&gt;
    Iron Vault displays the &lt;strong&gt;Undertake an Expedition&lt;/strong&gt; move with the dice results as well as the two follow-up moves that I needed to adjudicate the outcome.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;first-impression-and-closing-thoughts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-tried-solo-rpg-with-ironsworn-starforged/#first-impression-and-closing-thoughts&quot;&gt;First impression and closing thoughts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I often spend my holiday break catching up on personal coding projects. I lovingly call this my holiday sprint. But for the second week of my two weeks off in December, I started playing this game as a way to chill out and slow down. I found it relaxing and freeing—the writing didn’t have to be great because it’s a game and it’s for myself. It gives me an excuse to &lt;em&gt;play to see what happens&lt;/em&gt; (another core tenet) and not to get hung up on the little things. As I said, I’m using it as a way to write more. You might approach it differently. Totally fine!&lt;/p&gt;
&lt;p&gt;I’m impressed with the flexibility of this game. The fact that you can play it solo without a GM or with a GM is pretty impressive. You can tell the creator took a lot of time to get the design and artwork and ethos of the book just right.&lt;/p&gt;
&lt;p&gt;I envision my game as a long-term project. I’m not trying to release chapters on a schedule. When I felt like I want an escape, I will play. And if I play, I will post.&lt;/p&gt;
&lt;p&gt;This has been pretty enlightening and now I’m curious about games that have less rules and mechanics. With &lt;em&gt;Starforged&lt;/em&gt;, I sometimes have decision paralysis about when to activate a move, but so far I am managing. On the other hand, solo journaling RPGs, as I described, have even less mechanics and rely even more on journaling and writing. I think that could be fun too, and I may try one of those next.&lt;/p&gt;
&lt;p&gt;If you’ve read this far and you have any experience playing solo RPGs, let me know how you are enjoying them and what your approach is. You can email me (below) and I’m on &lt;a href=&quot;https://social.lol/@bw&quot;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>2025: my year in review</title>
      <link href="https://blakewatson.com/journal/2025-my-year-in-review/"/>
      <updated>2025-12-31T15:44:26Z</updated>
      <id>https://blakewatson.com/journal/2025-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I always feel like I didn’t accomplish much during the year until I start looking at my notes and commit history. Then I find myself pleasantly surprised. I’m eternally intertwined in a battle against routine. I need it—routine—but as the years fly past me, I feel an urgent need to break up the monotony. I want to slow time down. I tried to embrace some spontaneity this year. I managed to push myself out of my comfort zone on several occasions. It didn’t slow time, unfortunately, but I’m still glad I did it.&lt;/p&gt;
&lt;h2 id=&quot;goals-for-2025&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#goals-for-2025&quot;&gt;Goals for 2025&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As is tradition, I set a few personal goals for myself last year. Let’s see how I did.&lt;/p&gt;
&lt;h3 id=&quot;read-five-books&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#read-five-books&quot;&gt;Read five books&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ll see Past Blake’s five books and raise him one! I finished two meaty Brandon Sanderson novels—Oathbringer and Rhythm of War. Things are headed toward a cosmic collision and I’ve been told that the next book in the series, book 5, brings some much-awaited resolution. Guess I’ll find out.&lt;/p&gt;
&lt;p&gt;In between those I read a handful of shorter works as palate cleansers. My favorite of the three was Project Hail Mary by Andy Weir. If you like space exploration, you’ll probably love it. I’m absolutely stoked that they’re making a movie adaptation with Ryan Gosling. Do yourself a favor and don’t watch the trailer.&lt;/p&gt;
&lt;p&gt;I also read&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; The Anthropocene Reviewed by John Green, a lovely set of essays on humanity’s hopes and fears. In a complete 180 I read Dungeon Crawler Carl, book 1. And I read the classic novella The Man Who Was Thursday by G. K. Chesterton.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: A+&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;write-an-article-every-month&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#write-an-article-every-month&quot;&gt;Write an article every month&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I did it! Including this one, that’s 14 articles on the year. I accidentally started this streak a few years ago and it’s been one of my favorite things to keep going. &lt;strong&gt;A+&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;write-one-work-of-fiction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#write-one-work-of-fiction&quot;&gt;Write one work of fiction&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I attempted to write a novella as part of NaNoWriMo (despite its &lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/&quot;&gt;unfortunate demise&lt;/a&gt;) this year. I wrote a full outline and I started the project, but after getting a few chapters in, I couldn’t stomach the story anymore. I’m giving myself a &lt;strong&gt;D-&lt;/strong&gt; because the fact that this &lt;a href=&quot;https://www.writersdigest.com/getting-published/what-is-a-pantser-in-writing&quot;&gt;pantser&lt;/a&gt; wrote a full-fledged outline should count for something.&lt;/p&gt;
&lt;h3 id=&quot;make-one-game&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#make-one-game&quot;&gt;Make one game&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dammit! I keep not getting around to this one. I really want to take another stab at a &lt;a href=&quot;https://pixijs.com/&quot;&gt;PixiJS&lt;/a&gt; game—I’ve made two so far, one of them being &lt;a href=&quot;https://www.watsonbrosgames.com/solitaire/&quot;&gt;kinda fun&lt;/a&gt;. After failing to do this twice now, maybe I can turn things around in 2026. &lt;strong&gt;Grade: F&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;ship-a-new-software-project&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#ship-a-new-software-project&quot;&gt;Ship a new software project&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At first I thought I failed this one, but as part of my rewrite of &lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/&quot;&gt;A Fine Start&lt;/a&gt; I shipped a little &lt;a href=&quot;https://github.com/blakewatson/datastore&quot;&gt;utility for using IndexedDB like local storage&lt;/a&gt;. It’s working for my purposes, but use it at your own risk. 😅 &lt;strong&gt;Grade: A-&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;go-on-a-date&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#go-on-a-date&quot;&gt;Go on a date&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I actually did this! Not particularly good at it but hey. &lt;strong&gt;Grade: A&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;avoid-turning-40&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#avoid-turning-40&quot;&gt;Avoid turning 40&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’m &lt;em&gt;still alive&lt;/em&gt;, as &lt;a href=&quot;https://en.wikipedia.org/wiki/The_First_Law&quot;&gt;Logen Ninefingers&lt;/a&gt; would say, so I failed this goal. But I passed some cool milestones this year so giving myself a &lt;strong&gt;C&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;work&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#work&quot;&gt;Work&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I spent this year working on a new TPS system for NASA. &lt;a href=&quot;https://www.youtube.com/watch?v=LTxHvqGiFHg&quot;&gt;Office Space&lt;/a&gt; jokes abound and we even managed to incorporate a red stapler icon into the app. Unfortunately, I can’t seem to remember the cover sheet.&lt;/p&gt;
&lt;h2 id=&quot;milestones&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#milestones&quot;&gt;Milestones&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Photo of me sitting in my wheelchair in the driveway outside my house wearing a lab coat.&quot; src=&quot;https://blakewatson.com/uploads/2025/madg_labcoat.jpg&quot; /&gt;
  &lt;figcaption&gt;Me in 2015 after receiving my personalized Mad Genius employee lab coat.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Earlier this year, I hit a &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/&quot;&gt;decade of being employed&lt;/a&gt;. In that article I describe how I spent six years after college largely unemployed as a disabled developer with no full-time experience in the aftermath of the 2008 financial crisis. It was brutal and I almost gave up on working altogether. But with a mix of persistence and luck, I managed to get a job in 2015. May 4—Star Wars Day—marked ten years of being in the workforce.&lt;/p&gt;
&lt;p&gt;In June I turned 40 and &lt;a href=&quot;https://blakewatson.com/journal/40/&quot;&gt;remarked on feeling behind in life&lt;/a&gt;. I’ve been fortunate—hashtag blessed, even—so while I don’t love hitting 40, I’ll take it.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;My brother and in our wheelchairs and our mother sitting between us with the dog. An angel-topped Christmas tree glows with white lights behind us.&quot; src=&quot;https://blakewatson.com/uploads/2025/watsons-christmas-2025.jpg&quot; /&gt;
  &lt;figcaption&gt;
    My brother &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt&lt;/a&gt; (left), our mother holding Pepper, and me (right).
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In much cooler news, &lt;a href=&quot;https://blakewatson.com/journal/blakewatson-com-turns-twenty/&quot;&gt;my website turned 20 years old in August&lt;/a&gt;. The fact that I’ve kept a website running for that long is a source of immense pride for me. I think &lt;a href=&quot;https://blakewatson.com/journal/blakewatson-com-turns-twenty/#you-should-have-your-own-website&quot;&gt;everyone should have a website&lt;/a&gt; to combat the sameness and corporate control of social media. If you’re a tech beginner and you’re curious about how to make a website the manual way, check out my free web book, &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;magnoliaconf-2025&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#magnoliaconf-2025&quot;&gt;MagnoliaConf 2025&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I &lt;a href=&quot;https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/&quot;&gt;ranted to an audience&lt;/a&gt; at the Mississippi Museum of Art about my annoyance with frontend build steps.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Yours truly wearing an HTML shirt and sitting in my wheelchair by the podium at the Mississippi Museum of Art. I&#39;m looking at my laptop as I give my talk.&quot; src=&quot;https://blakewatson.com/uploads/2025/blake-magnolia-2025.jpg&quot; /&gt;
  &lt;figcaption&gt;
    Giving my talk, &lt;a href=&quot;https://blakewatson.com/notes/ba10b901/&quot;&gt;No build tool? No problem!&lt;/a&gt; at MagnoliaConf 2025
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I enjoyed giving this talk, although I think I tried to cover too much material. But I hope my central message got through—it’s a-okay to use simple tools when they are appropriate. And oftentimes a simpler tool can go farther than you might think.&lt;/p&gt;
&lt;h2 id=&quot;projects&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#projects&quot;&gt;Projects&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I didn’t ship many new projects this year, but it was a year of refactoring and rewrites for me and I published some new versions of my favorite projects.&lt;/p&gt;
&lt;h3 id=&quot;a-fine-start&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#a-fine-start&quot;&gt;A Fine Start&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2025/afs-dark.webp&quot; alt=&quot;Screenshot of a new tab in Chrome showing A Fine Start. There are three columns of text links that are sorted into groups such as My Stuff and Media. The links are two destinations such as Netflix, New York Times, Hacker News, etc. There is a toolbar for creating and editing bookmarks.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/&quot;&gt;released version 3&lt;/a&gt; of my &lt;a href=&quot;https://afinestart.me/&quot;&gt;new-tab page browser extension&lt;/a&gt;. From my perspective it was a big undertaking—a total rewrite where I abandoned Vue.js and rolled my own vanilla JavaScript. From the user perspective, I introduced some long-standing feature requests, like more columns (or less), some new themes, the ability to rename groups, and a way to open an entire group of links at once.&lt;/p&gt;
&lt;p&gt;I had some hiccups with the rollout, but I think everything is ironed out now. I’ve made it render quickly and I’ve added some quality of life improvements throughout the year, with a few more planned.&lt;/p&gt;
&lt;h3 id=&quot;minimal-character-sheet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#minimal-character-sheet&quot;&gt;Minimal Character Sheet&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2025/minimal-character-sheet-screenshot.jpg&quot; alt=&quot;A screenshot of my character sheet app. It has a minimalist style, black and white with a monospaced font. Character information like name, background, species, and class are visible as well as the major abilities and some of the character skills.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In the summer, I &lt;a href=&quot;https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/&quot;&gt;posted about a ton of updates&lt;/a&gt; to my freeform digital character sheet app. As part of my holiday time off, I did even more work on the app, completely rewriting the UI. The mobile experience should be much better now. I added a new section for tracking arbitrary resources. This is helpful for lots of classes who have superiority dice, focus points, or other consumable resources.&lt;/p&gt;
&lt;p&gt;But the coolest feature is an initial implementation of integration with the &lt;a href=&quot;https://open5e.com/&quot;&gt;Open5e&lt;/a&gt; API. You can now search for spells and character backgrounds and easily copy and paste content into your character sheet. There’s still a ton of work ahead to widen this integration. I can ultimately imagine being able to pre-generate character sheets with random features. I’d love to add a dice rolling utility as well. So much to do. I’m happy to report that usage of the app has picked up and the changes so far have been well received.&lt;/p&gt;
&lt;h3 id=&quot;html-for-people&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#html-for-people&quot;&gt;HTML for People&lt;/a&gt;&lt;/h3&gt;
&lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2024/html-hero.webp&quot; alt=&quot;Illustration of a computer desk. There is a lot of space decor. The computer monitor shows a cartoon space probe zooming past a logo that reads &#39;HTML for people,&#39; stylized as an HTML comment.&quot; /&gt;
&lt;/a&gt;
&lt;p&gt;I released this &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;free web book about making your first website&lt;/a&gt; with HTML back in 2024. But I wanted to mention that, though it technically happened at the tail end of 2024, HTML for People was graciously &lt;a href=&quot;https://victorhck.gitlab.io/htmlparapersonas/&quot;&gt;translated into Spanish&lt;/a&gt; and hosted by &lt;a href=&quot;https://victorhckinthefreeworld.com/2024/12/11/aprende-html-desde-cero-y-crea-tu-propio-sitio-web/&quot;&gt;Victorhck&lt;/a&gt;! I really love that it’s accessible to more people and I’d love to see even more translations in the future.&lt;/p&gt;
&lt;h2 id=&quot;goals-for-2026&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#goals-for-2026&quot;&gt;Goals for 2026&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Read five books&lt;/li&gt;
&lt;li&gt;Write an article every month&lt;/li&gt;
&lt;li&gt;Write creatively (not forcing myself to complete anything)&lt;/li&gt;
&lt;li&gt;Make a game (it’s been a while)&lt;/li&gt;
&lt;li&gt;Go do things&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m going to keep it short and let some of my goals be vague this year. Might as well give myself some wiggle room when it comes to determining my success.&lt;/p&gt;
&lt;p&gt;I hope your new year is everything you want it to be.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Well, I &lt;em&gt;listened&lt;/em&gt;. I’ve been using audiobooks for several years now. I’d love to read physical books but my disability prevents me from handling them. I’ve been using Audible, but I recently joined my library’s &lt;a href=&quot;https://www.loc.gov/nls/how-to-enroll/&quot;&gt;BARD program&lt;/a&gt;, which offers free audiobooks to people who have difficulty accessing print books. &lt;a href=&quot;https://blakewatson.com/journal/2025-my-year-in-review/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>I ranted about frontend build steps at MagnoliaConf 2025</title>
      <link href="https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/"/>
      <updated>2025-11-30T11:20:00Z</updated>
      <id>https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/</id>
      <content xml:lang="en" type="html">&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/1XMuxmY-Fp4&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;Back in October, I had the pleasure of speaking at &lt;a href=&quot;https://magnoliajs.com/&quot;&gt;MagnoliaConf 2025&lt;/a&gt;. I was thrilled that the organizers decided to put it together this year after skipping last year. It was perfect timing because I had the chance to talk about something that has been increasingly bothering me: our industry’s addiction to complexity.&lt;/p&gt;
&lt;p&gt;My talk was titled &lt;strong&gt;No build tool? No problem!&lt;/strong&gt; (&lt;a href=&quot;https://blakewatson.com/magnolia2025&quot;&gt;notes and slides here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you’ve been following my writing on &lt;a href=&quot;https://blakewatson.com/search/?q=home-cooked%20apps&quot;&gt;home-cooked apps&lt;/a&gt; or my (free!) web book &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt;, you know I’m a fan of keeping things simple. But &lt;em&gt;simple&lt;/em&gt; in modern web development is a loaded term. NPM installing something is simple, right? In the short term, maybe. In the long term, build step dependencies are rife with problems.&lt;/p&gt;
&lt;p&gt;The core thesis of my talk is that while we were busy Webpack-ing our way to success, the web platform got good.&lt;/p&gt;
&lt;p&gt;We used to &lt;em&gt;need&lt;/em&gt; build tools for a good developer experience. We needed Sass for variables and nesting. We needed Babel to use modern JavaScript. We needed bundlers to manage dependencies. But browsers have leveled up enough that they obviate the need for many build step features.&lt;/p&gt;
&lt;h2 id=&quot;the-highlight-reel&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/#the-highlight-reel&quot;&gt;The highlight reel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I had a ton of things to cover and not enough time to cover them all in depth. But here are the takeaways.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS has since gained many of the features of Sass, and in some cases, like variables, CSS actually does them better.&lt;/li&gt;
&lt;li&gt;Using CSS plus some newer components of HTML, you can recreate controls that were only possible with JavaScript previously. For example, HTML now has native modal dialogs.&lt;/li&gt;
&lt;li&gt;Leverage your editor’s support of TypeScript and &lt;a href=&quot;https://jsdoc.app/&quot;&gt;JSDoc&lt;/a&gt; to get type support for regular JavaScript files.&lt;/li&gt;
&lt;li&gt;The browser supports JavaScript modules natively, so you can skip the bundler.&lt;/li&gt;
&lt;li&gt;You can use many popular JavaScript frameworks directly in the browser using their ESM-compatible versions. Frameworks like &lt;a href=&quot;https://alpinejs.dev/&quot;&gt;AlpineJS&lt;/a&gt; can be included and used immediately without any build setup whatsoever.&lt;/li&gt;
&lt;li&gt;Web components offer a browser-native way to encapsulate functionality and are a resilient option compared to fragile builds.&lt;/li&gt;
&lt;li&gt;While there is a buildless alternative to Tailwind (&lt;a href=&quot;https://litewindcss.com/&quot;&gt;Litewind&lt;/a&gt;), the only way to get true Tailwind support is via a build step. However, they offer a CLI that can do it without involving a separate build tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;embracing-runtime&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/#embracing-runtime&quot;&gt;Embracing runtime&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is a specific kind of joy in writing code that just runs. You save the file, refresh the browser, and there it is. No watchers crashing, no &lt;code&gt;node_modules&lt;/code&gt; black hole, no cryptic webpack errors. It reminds me of why I fell in love with the web in the first place—the ability to just make something and share it.&lt;/p&gt;
&lt;p&gt;I’m not saying you should never use a build tool again. If you’re building the next Facebook, sure, bundle away. But for small websites, internal tools, or that fun side project? Try skipping the build step. You might find that the browser is enough.&lt;/p&gt;
&lt;h2 id=&quot;watch-(or-read)-the-talk&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-ranted-about-frontend-build-steps-at-magnoliaconf-2025/#watch-(or-read)-the-talk&quot;&gt;Watch (or read) the talk&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want to check out the notes, code demos, or see a full text version of the talk, I’ve made them available here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/notes/ba10b901/&quot;&gt;&lt;strong&gt;Talk notes and links&lt;/strong&gt;&lt;/a&gt; (includes the slides and demos)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/notes/3bcc26ab/&quot;&gt;&lt;strong&gt;HTML version&lt;/strong&gt;&lt;/a&gt; (a full transcript/slide combo if you prefer reading)&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>NaNoWriMo is dead, long live NaNoWriMo!</title>
      <link href="https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/"/>
      <updated>2025-10-26T13:50:40Z</updated>
      <id>https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/National_Novel_Writing_Month&quot;&gt;National Novel Writing Month&lt;/a&gt; (NaNoWriMo) entered my life in 2010. I was fresh out of grad school and unemployed. I was talking to a friend of mine who had picked up writing as a hobby in retirement. He described this wild writing challenge where thousands of people across the world would each attempt to write a 50k-word novel during the 30 days of November. As daunting as it sounded, I was intrigued.&lt;/p&gt;
&lt;p&gt;When I was a kid, I enjoyed writing stories. One of my first memories of creative writing was when, in first grade, we were asked to keep a journal. There was a time during each day when we were allowed to take out our spiral bound notebook and write something in it. First grade me began by writing things such as “I like girls” or “I like to eat.” But I quickly got bored of that and began the real fun of writing my own stories. They were usually fan fiction (not that I knew what fan fiction was) involving Batman and his outsmarting the Joker.&lt;/p&gt;
&lt;p&gt;Novel writing seemed like an impossible task. I never thought to attempt it. I mostly stuck with writing terrible poetry and maybe a few short stories. But talking to my friend about his rekindled love for writing, and the idea that normal people were out there trying to write novels in a month, inspired me to visit the website and sign up.&lt;/p&gt;
&lt;p&gt;I quickly discovered a large internet community, all focused on this ridiculous writing challenge. I found discussion forums like the Adoption Society, where one could share characters, villains, chapter naming schemes, and even entire plots with others—offering them up for “adoption” so that someone else could breathe life into one’s unused material. I found that I could join a local region on the website—essentially a small forum with people who were in geographic proximity. And not only that, but my region had an official volunteer, a &lt;em&gt;municipal liaison&lt;/em&gt;, who would organize in-person writing events throughout the month.&lt;/p&gt;
&lt;p&gt;I was too shy to join any in-person activities, but I did attempt the challenge in November 2010, getting about 19k words into it before giving up. It was pretty terrible, but it was the most I had ever written toward a single work. It was stressful, but I enjoyed it. I knew I would be attempting it again.&lt;/p&gt;
&lt;hr class=&quot;thematic-break&quot; /&gt;
&lt;p&gt;National Novel Writing Month began in 1999 when one man, Chris Baty, emailed his friends with the idea of sharing a goal to write a novel in a month. As the event blew up in following years and took hold on the internet, Chris formed a nonprofit that ultimately became NaNoWriMo, an organization that ran the event and promoted creative writing. The organization took on running the website and forums. They also handled organizing volunteers to serve as municipal liaisons in regional areas, giving them resources and supplies needed to host local writing events, called write-ins. The organization developed curricula for teachers of various grade levels to use in the classroom.&lt;/p&gt;
&lt;p&gt;NaNoWriMo, the nonprofit, was funded by donations from the community and from sponsorships (and presumably some grants).&lt;/p&gt;
&lt;p&gt;Each year, NaNoWriMo ran the flagship November writing challenge of the same name in addition to several other writing challenges throughout the year. The forums were a popular hangout spot and formed a rather large, diverse writing community. In-person write-ins popped up all over the world and at its peak 400,000+ people participated in the flagship November event.&lt;/p&gt;
&lt;p&gt;In March 2025, after suffering reputational damage from &lt;a href=&quot;https://theweek.com/culture-life/books/nanowrimo-generative-ai&quot;&gt;their position on AI&lt;/a&gt;, a &lt;a href=&quot;https://docs.google.com/document/d/e/2PACX-1vSYcdosGLoPFI_Dc--vuC9Bl4-OUFGcmHgBRt2aHSRVWBPc6su4AMFY5iDgZGyC379Zm8C7zhBd2zuf/pub&quot;&gt;forum safety scandal&lt;/a&gt; and—as a board member &lt;a href=&quot;https://www.youtube.com/watch?v=TR6NnjgeIIY&quot;&gt;described in a video&lt;/a&gt;—years of financial hardship, NaNoWriMo the organization &lt;a href=&quot;https://www.theguardian.com/books/2025/apr/02/creative-writing-nanowrimo-to-close-after-20-years&quot;&gt;announced it was going away&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As of the time of this writing, the website no longer loads. It’s a sad ending to what was once a whimsical writing community event adored by many.&lt;/p&gt;
&lt;hr class=&quot;thematic-break&quot; /&gt;
&lt;p&gt;In 2011, I attempted the challenge again. As much as I romanticized the idea of writing an outline and planning out the entire story before writing, I was cursed to be a pantser (i.e., writing &lt;em&gt;&lt;a href=&quot;https://dictionary.cambridge.org/us/dictionary/english/by-the-seat-of-pants&quot;&gt;by the seat of your pants&lt;/a&gt;&lt;/em&gt;). I gave it my best shot. I didn’t make it to 50k, but I managed to get well into the 30k range and something clicked. I could visualize what writing a 50k-word novel would look like.&lt;/p&gt;
&lt;p&gt;My next attempt in 2012 was the one that took me over the finish line. I actually gave up a part-time job (that I was close to giving up anyway) in order to focus 100% of my time on completing the novel. The story I ended up with isn’t all that good, but it’s a completed thought. There’s a beginning and a middle and an end. There are at least one or two semi-interesting characters. It felt &lt;em&gt;great&lt;/em&gt; to finish the rough draft of a novel—a &lt;em&gt;novel&lt;/em&gt;… I was a &lt;em&gt;novelist&lt;/em&gt;. I bought a NaNoWriMo t-shirt, and I bought one almost every year during the 2010s.&lt;/p&gt;
&lt;p&gt;I finished a story the next year, although I didn’t quite make it to 50k before the story ended. This was the story I’m most ashamed of as it was just ridiculous. It also has my favorite side character—a paranoid 60-something private investigator with a messy office and a conspiracy theory for everything. In 2014 I wrote what I feel is the best of my completed 50k-word drafts. It ended up being somewhat of a paranormal drama which surprised me as I’m not usually into that sort of thing.&lt;/p&gt;
&lt;p&gt;I also became the municipal liaison for my region for several years. I would organize write-ins, including one that happened at my house! Me, a weird introvert—this is how important NaNoWriMo was to me. It was fun and I met some great people.&lt;/p&gt;
&lt;p&gt;In the years following I participated off and on but I was usually pretty busy with work, having &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/&quot;&gt;landed my first full-time job&lt;/a&gt; in 2015, and I never really made the time to finish another novel.&lt;/p&gt;
&lt;p&gt;My disability progressed during that time as well and typing became more of a chore. In 2022, I became a NaNo rebel&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; by adjusting the November goal from 50k to 20k and focusing on writing novellas. I completed that goal twice.&lt;/p&gt;
&lt;p&gt;I didn’t participate in 2024 and it seems that a lot of people also skipped out. 2024 was the first year that NaNoWriMo happened without any forums. The once-thriving forums had been shut down the previous year by the organization’s board of directors after the &lt;a href=&quot;https://docs.google.com/document/d/e/2PACX-1vSYcdosGLoPFI_Dc--vuC9Bl4-OUFGcmHgBRt2aHSRVWBPc6su4AMFY5iDgZGyC379Zm8C7zhBd2zuf/pub&quot;&gt;forum safety scandal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It was always just a fun hobby for me. I never published anything and I never really edited anything beyond the rough draft. I was content with my audience of two (thanks mom and &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt&lt;/a&gt;!).&lt;/p&gt;
&lt;hr class=&quot;thematic-break&quot; /&gt;
&lt;p&gt;This event was a big part of my identity for many years. I collected t-shirts from the event. I have a poster still hanging on my wall. Even though I haven’t participated as much in recent years, I still reminisce on some good times and good people. I think what really irks me is the unceremonious ending. I’m not usually one to get too deep into the drama of things like this, but I can’t help but feel a little slighted by NaNoWriMo’s board of directors. If they really cared about this event, they could have at least ensured that a static one-page website remained to communicate the legacy of NaNoWriMo—something to describe its history, what it meant to people, and maybe some encouragement to continue writing. You can host a static website for free.&lt;/p&gt;
&lt;p&gt;Instead, when visiting the website, we are left with the arch-nemesis of every writer—a blank page.&lt;/p&gt;
&lt;p&gt;But even as NaNoWriMo the organization (and website) is gone, NaNoWriMo the challenge endures. There will still be thousands of people attempting to write a novel during the month of November. They may change the rules, and they may call it something else, but they will write the words all the same.&lt;/p&gt;
&lt;p&gt;Many of us have found other groups to commiserate with. We’ve found other sites and tools for tracking our writing. I’m still not sure if I’m going to participate myself this year. If anyone in Mississippi is interested, there is a Discord server formerly representing this region’s NaNoWriMo group which is now called &lt;a href=&quot;https://discord.gg/9vAgqeMtxE&quot;&gt;Mississippi Porchlight Writers&lt;/a&gt;. If I do end up attempting the challenge, I will be hanging out there and probably using &lt;a href=&quot;https://writingmonth.org/&quot;&gt;this website&lt;/a&gt; to track my word count.&lt;/p&gt;
&lt;p&gt;To Wrimos old and new, I hope you continue to write too. I will leave you with NaNoWriMo’s old tagline.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The world needs your novel.&lt;/strong&gt;&lt;/p&gt;
&lt;hr class=&quot;thematic-break&quot; /&gt;
&lt;p&gt;&lt;strong&gt;Update 10/28:&lt;/strong&gt; I just found out that the founder NaNoWriMo, Chris Baty, and some other people have created a website called &lt;a href=&quot;https://nano2.org/&quot;&gt;NaNo 2.0&lt;/a&gt;. This new version of the event is essentially like the old one but with the change that you can set any writing goal you want and you don’t need to sign up on the website or do anything further (but you can sign up for their emailed pep talks and whatnot). They encourage the use of any writing groups, apps, and other resources that you have available rather than trying to be a monopoly on it.&lt;/p&gt;
&lt;p&gt;I can’t really endorse something I only just found out about, but it looks promising. I guess there’s something nostalgic and comforting about the fact that someone is attempting to keep the spirit of the event alive.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Many people would adjust the November challenge to fit their own personal goals, perhaps changing the word count or focusing on collections of short stories, stage plays, and other types of writing other than the standard novel. NaNo rebel was the endearing term for these people. &lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This quote appears as the main graphic element on a shirt that I have called “Baty-isms” which incorporates a bunch of Chris Baty’s quotes and sayings into its design. &lt;a href=&quot;https://blakewatson.com/journal/nanowrimo-is-dead-long-live-nanowrimo/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Understanding, not slop, is what’s interesting about LLMs</title>
      <link href="https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/"/>
      <updated>2025-09-28T13:40:16Z</updated>
      <id>https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Now that LLMs have been around for a little while, we can discern what they’re good at and what they’re not. Clearly they are good at using a lot of energy and resources and tend to make things up. But they have also demonstrated to be good summarizers, decent coders, and helpful teachers.&lt;/p&gt;
&lt;p&gt;But that’s not what I find truly novel about LLMs. They can generate a lot of content, much of which you will see people refer to as AI slop. But what’s interesting to me is the emergent property of understanding that LLMs seem to have.&lt;/p&gt;
&lt;h2 id=&quot;example%3A-support-documentation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/#example%3A-support-documentation&quot;&gt;Example: support documentation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AI integration is hit and miss in a lot of products and often it’s super annoying and unwanted. That said, when I was trying to figure out how to do something in Cloudflare a while back I noticed that the AI assistant was very good at directing me to relevant support documentation.&lt;/p&gt;
&lt;p&gt;When is the last time you went to a support site, ran a search and got back anything close to what you were looking for? In my experience, it’s usually futile. To be fair, I find Cloudflare’s docs in general to be better than most services, so that probably has something to do with it.&lt;/p&gt;
&lt;p&gt;That said, the AI assistant &lt;em&gt;seemed&lt;/em&gt; to understand the question I was asking and in addition to giving me an answer in its own words, it was able to point me to relevant articles to read. (Look, I realize this is anecdotal and I’ve also run into problematic uses of AI in customer support. But the point here is that it &lt;em&gt;was&lt;/em&gt; able to improve a previously horrible interaction.)&lt;/p&gt;
&lt;h2 id=&quot;what-is-understanding%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/#what-is-understanding%3F&quot;&gt;What is understanding?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I use the word “seem” because it doesn’t actually understand what I’m saying. At least not in the way that we humans think of understanding.&lt;/p&gt;
&lt;p&gt;But this advanced processing of natural language feels like it’s the closest we’ve come to a computer &lt;em&gt;understanding&lt;/em&gt; natural language and intent. It’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Office_Assistant&quot;&gt;Clippy&lt;/a&gt; on steroids.&lt;/p&gt;
&lt;p&gt;There are AI integrations everywhere and I’m skeptical about letting AI do things on my behalf since they do make many mistakes. That said, as integrations improve, and especially safety around AI doing things on my behalf, I can imagine a world where &lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/&quot;&gt;humans can act more like humans&lt;/a&gt; and have computers respond appropriately.&lt;/p&gt;
&lt;h2 id=&quot;accessibility-implications&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/#accessibility-implications&quot;&gt;Accessibility implications&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What I mean by humans acting like humans is that from the dawn of computers we’ve had to adapt ourselves to &lt;em&gt;them&lt;/em&gt;. If you want the computer to do something you have to speak its language, a programming language. So programmers build software that lets us use mice and keyboards to interact with the computer giving us a more human friendly way to instruct them.&lt;/p&gt;
&lt;p&gt;Before ChatGPT we had the ability to turn our own speech into text and digital assistants like Siri and Google could process that speech and formulate a decent response in some cases (and fail miserably in many cases—looking at you Siri). But the experience was and is often subpar. It still feels like you are having to speak in code to the computer so that it will understand you.&lt;/p&gt;
&lt;p&gt;But now we are closer and closer to being able to use natural language to communicate with computers &lt;em&gt;for real&lt;/em&gt;. Rather than needing to know specific sequences of words and specially formulated sentences, we can just be ourselves. The computer is starting to be able to &lt;em&gt;understand&lt;/em&gt; our intent.&lt;/p&gt;
&lt;p&gt;The accessibility implications of this are staggering. I know people who struggle to use the computer to write, to game, to access the internet because of the physical actions needed to interact with computers through keyboards, mice, and other peripherals.&lt;/p&gt;
&lt;p&gt;I know people who struggle to use voice recognition software because of speech impediments caused by physical disabilities.&lt;/p&gt;
&lt;p&gt;I just experienced these barriers first hand while I was on a road trip. Since I didn’t have my Mac with me and I’m unable to hold and handle a phone I was forced to use &lt;a href=&quot;https://support.apple.com/en-us/111778&quot;&gt;Voice Control&lt;/a&gt; and Siri to do things like check and respond to messages. It was a huge pain because Voice Control often misunderstands commands and you have to say them in a very particular way for them to work. I would love to be able to chat with my phone, to ask if certain people have messaged me, help me respond, and do other things reliably without needing to physically handle the device.&lt;/p&gt;
&lt;p&gt;But the computer’s ability to process speech is getting even better. And its ability to act on that transcribed speech is also getting better.&lt;/p&gt;
&lt;p&gt;This could open up whole worlds to people who were previously isolated.&lt;/p&gt;
&lt;h2 id=&quot;criticisms&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/#criticisms&quot;&gt;Criticisms&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay, let me come back down from the clouds for a moment. I do think the concerns about AI are valid. I’m interested to see how some of this stuff is going to play out. In particular, I hate that AI summarizers and training bots exploit information freely given on the web to the point that &lt;a href=&quot;https://arstechnica.com/ai/2025/03/devs-say-ai-crawlers-dominate-traffic-forcing-blocks-on-entire-countries/&quot;&gt;websites are being DDoSed&lt;/a&gt;. Website owners aren’t even rewarded with human eyeballs because the AI just summarizes the content for the user who doesn’t need to click through any longer.&lt;/p&gt;
&lt;p&gt;That’s not to mention things like copyright, environmental impact, etc.&lt;/p&gt;
&lt;h2 id=&quot;cautiously-optimistic&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/understanding-not-slop-is-whats-interesting-about-llms/#cautiously-optimistic&quot;&gt;Cautiously optimistic&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Despite everything, I am still cautiously optimistic that we’ll be able to enjoy these accessibility benefits while mitigating the negative effects of LLMs.&lt;/p&gt;
&lt;p&gt;I currently maintain enough strength to &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/&quot;&gt;use a mouse to type&lt;/a&gt; with an &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/&quot;&gt;onscreen keyboard&lt;/a&gt;, combine &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/&quot;&gt;Talon&lt;/a&gt; and &lt;a href=&quot;https://www.cursorless.org/&quot;&gt;Cursorless&lt;/a&gt; to code by voice, and employ &lt;a href=&quot;https://superwhisper.com/&quot;&gt;Whisper&lt;/a&gt; to transcribe prose. But my condition, &lt;a href=&quot;https://www.curesma.org/about/&quot;&gt;spinal muscular atrophy&lt;/a&gt;, is progressive and will continue to get worse (albeit slowly thanks to modern treatments). As I begin to lose the ability to operate peripherals, I am hopeful that I will be able to replace that interaction with natural language.&lt;/p&gt;
&lt;p&gt;That will keep me productive for longer and allow me to continue to do my job as a software engineer (assuming AI doesn’t take my job, *&lt;em&gt;nervous laughter&lt;/em&gt;*).&lt;/p&gt;
&lt;p&gt;In summary, the slop is not the interesting part of LLMs, it’s their &lt;em&gt;potential&lt;/em&gt; (not saying we’re there yet) to simplify human-computer interaction and meet people where they are.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>I changed my fonts after six years of using Cloud.typography</title>
      <link href="https://blakewatson.com/journal/i-changed-my-fonts-after-six-years-of-using-cloud.typography/"/>
      <updated>2025-08-24T21:38:07Z</updated>
      <id>https://blakewatson.com/journal/i-changed-my-fonts-after-six-years-of-using-cloud.typography/</id>
      <content xml:lang="en" type="html">&lt;p&gt;For years, I’ve used Hoefler&amp;amp;Co.’s webfont service, &lt;a href=&quot;https://www.typography.com/webfonts&quot;&gt;Cloud.typography&lt;/a&gt;, for several of my websites—including, until today, this one. I purchased &lt;a href=&quot;https://typography.com/blog/introducing-operator&quot;&gt;Operator Mono&lt;/a&gt; in 2017 for my code editor and I still use it today.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/i-changed-my-fonts-after-six-years-of-using-cloud.typography/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I’ve long admired Hoefler&amp;amp;Co.&#39;s work, although I was a bit bummed when they were acquired by &lt;a href=&quot;https://www.monotype.com/&quot;&gt;Monotype&lt;/a&gt;. I used &lt;a href=&quot;https://typography.com/fonts/ringside/overview&quot;&gt;Ringside&lt;/a&gt; when I &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/&quot;&gt;redesigned my website in 2019&lt;/a&gt;, and that has been the primary typeface on my website until today.&lt;/p&gt;
&lt;p&gt;I’m now using fonts from the &lt;a href=&quot;https://klim.co.nz/collections/soehne/&quot;&gt;Söhne collection&lt;/a&gt; by Klim Type Foundry. I have a soft spot for the &lt;a href=&quot;https://en.wikipedia.org/wiki/International_Typographic_Style&quot;&gt;Swiss style&lt;/a&gt;, as a long-time Helvetica fan. But I didn’t make this change just for the sake of change. From the very beginning, my webfonts served from Cloud.typography produced a noticeable flash of unstyled text (FOUT), which is when a fallback system font is shown until the webfont is loaded and rendered.&lt;/p&gt;
&lt;p&gt;This irked me, but I assumed it was part of the price of using webfonts, and I admittedly didn’t spend much time looking into it. But over the years, it became more and more annoying, and I noticed that &lt;em&gt;my&lt;/em&gt; website, in particular, seemed to have more FOUT than other websites using webfonts. Even then, I never took the time to really look into it. Until this past week. I went to my website, saw the usual flash, and something inside of me just snapped.&lt;/p&gt;
&lt;p&gt;The flash of unstyled text is somewhat normal in the world of webfonts, but it shouldn’t continue to happen as you browse a website because your font files should be cached by the browser. But clearly that wasn’t happening with my website.&lt;/p&gt;
&lt;p&gt;I began looking into the problem but my web searches did not reveal much. I remembered from setting up the service that their font delivery mechanism is fairly unique and convoluted compared to the way many webfonts are delivered. Essentially, they give you a folder of CSS files to host on your own server. But they give you a link to request a CSS file from &lt;em&gt;their&lt;/em&gt; server. That request gets some browser information and determines the optimized font file that should be used and redirects to &lt;em&gt;your&lt;/em&gt; self-hosted version of that file.&lt;/p&gt;
&lt;p&gt;Phew.&lt;/p&gt;
&lt;p&gt;To make matters worse, the fonts are delivered as base64 encoded strings inside the CSS files. The performance is pretty bad and a consequence of this whole mechanism is that the browser is unable to cache the font. So as the reader moves from page to page, they will see a flash of unstyled text on each one.&lt;/p&gt;
&lt;p&gt;I found one article about &lt;a href=&quot;https://csswizardry.com/2019/08/making-cloud-typography-faster/&quot;&gt;making the best of this situation&lt;/a&gt; to improve performance. But that wasn’t good enough for me. I was kind of over the whole thing.&lt;/p&gt;
&lt;p&gt;My first thought was, “Well, I will just buy a license to host Ringside myself and serve it directly.” I figured it would be costly, but was shocked to find that there would be an annual fee of around $2,400. I am a believer in paying for fonts, especially when it’s supporting indie designers. But I’m not about to shell out $2,000+ per year to the largest type company in the world for a font on a personal website that gets about 1,000 page views a month.&lt;/p&gt;
&lt;p&gt;So today I switched to using Söhne via normal self-hosted font files that are loaded directly and can be cached by the browser. I’m using Söhne for the body text, Söhne Breit for large article titles, the main navigation, and meta text like dates. Finally, I’m using Söhne Mono for code and preformatted text. I’m a sucker for the double story “g,” so I’m using the appropriate stylistic set for the body text. And for the monospaced font, I’m using the slashed zero alternate (&lt;code&gt;0&lt;/code&gt;) to better distinguish the numeral from the uppercase letter “O.” One more nicety is that if you are viewing my website in dark mode, I’m using the 300 weight of Söhne so that the text doesn’t feel as heavy.&lt;/p&gt;
&lt;p&gt;Klim Type Foundry offers a reasonable pay-once license for webfonts based on the number of expected page views per month.&lt;/p&gt;
&lt;p&gt;I still have one more website, &lt;a href=&quot;https://synthwave.live/&quot;&gt;synthwave.live&lt;/a&gt;, that uses fonts delivered by Cloud.typography. But I am going to source some replacements for those as well. Once I do that I will be able to cancel my Cloud.typography subscription. It’s the end of an era for me, but I’m pleased with the new look.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I have a bit of a monospaced-font-collecting problem, so I use various monospaced fonts when coding. &lt;a href=&quot;https://blakewatson.com/journal/i-changed-my-fonts-after-six-years-of-using-cloud.typography/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>blakewatson.com turns 20</title>
      <link href="https://blakewatson.com/journal/blakewatson-com-turns-twenty/"/>
      <updated>2025-08-08T11:20:24Z</updated>
      <id>https://blakewatson.com/journal/blakewatson-com-turns-twenty/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Nowadays I’m used to signing up for services and discovering that the username &lt;code&gt;blakewatson&lt;/code&gt; is already taken—yes I’m one of those people who uses their real name everywhere. But that’s okay because I have something the other Blake Watsons don’t. Back in 2005 when I was learning HTML and obsessed with the incredible knowledge that you could just upload a file to the internet and everyone could see it, I made the decision to purchase the domain, &lt;a href=&quot;http://blakewatson.com/&quot;&gt;blakewatson.com&lt;/a&gt;. To this day, that decision stands as one of my best. It was cool and nerdy to have your own personal homepage. And okay, maybe it’s still a little nerdy now. But in an age where corporate social media is the default, a personal homepage is a breath of fresh air.&lt;/p&gt;
&lt;p&gt;It’s obviously very cringe for me to look at now, but here is a screenshot of the earliest version that I have a record of. This was probably the first one I published.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2025/blakewatson-com-first-version.png&quot; alt=&quot; This is a screenshot of BlakeWatson.com. It&#39;s a simple website with the domain name stylized at the top as a banner. Then it has what looks like a table layout of different sections you can click on: Bio, poetry, music, games, and stuff. Each category has a description of what it&#39;s for. The footer says copyright 2005 Blake Watson. It&#39;s simple white and blue colors with borders on a grey background.&quot; /&gt;
  &lt;figcaption&gt; This is the first version of my website&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Before purchasing the domain name, I had made various personal homepage sites using free hosting and free subdomains of other services. But this represented the first step I took to take ownership of my web stuff. I was learning HTML and a little CSS and for the first time I wasn’t using WYSIWYG editors but writing the code myself.&lt;/p&gt;
&lt;p&gt;My website went along like this for a few years until I graduated college and started attempting to freelance. At that point, I turned my website into a web designer’s portfolio inspired by the web designers I looked up to and admired at the time.&lt;/p&gt;
&lt;p&gt;As I posted in &lt;a href=&quot;https://blakewatson.com/journal/hard-refresh/&quot;&gt;Hard refresh&lt;/a&gt;, you can see how my website’s design progressed over the years until I took a full-time position and stopped freelancing.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/screenshots.jpg&quot; alt=&quot; A screenshot of a bunch of my personal websites from 2005 to 2013. The designs progressed from personal site vibe to experienced designer.&quot; /&gt;
  &lt;figcaption&gt;Early history of blakewatson.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Once I stopped using my site for freelancing, I converted it back into a personal webpage. This time, more like a web designer’s blog. I built it using the now defunct, Python-based, static site generator &lt;a href=&quot;https://github.com/mythmon/wok&quot;&gt;wok&lt;/a&gt;. It started off as a super simple text-based design, but I finally &lt;a href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#everything-old-is-new-again&quot;&gt;gave it some love in 2016&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/blakewatson.com-2016-1024x713.png&quot; alt=&quot;Red background with a sleek, modern for 2016 feel. Clean design. The homepage is sparse and shows the three latest posts.&quot; /&gt;
  &lt;figcaption&gt; As seen in 2016.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It definitely has some text contrast issues that I was a bit ignorant to at the time. I got around to giving it a small refresh about a year-ish later.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2025/blakewatson-com-late-2016.png&quot; alt=&quot;Same design as the 2016 version except the red background is a darker red-to-dark-blue gradient an the type contrast is improved.&quot; /&gt;
  &lt;figcaption&gt; Some time later in 2016 or possibly 2017. &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In 2019, I &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/&quot;&gt;moved my site onto WordPress&lt;/a&gt;, self-hosted.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2025/blakewatson-com-2019.png&quot; alt=&quot;Similar elements to the previous design, sparse with three posts on the homepage and a sidebar, but the colors are completely redesigned using a deep purplish black background with light text for the foreground. Still using clean sans serif type and a minimal layout.&quot; /&gt;
  &lt;figcaption&gt; My site as seen in 2019 after moving to self-hosted WordPress &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Finally, &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/&quot;&gt;in 2024, I rebuilt it&lt;/a&gt; using the static-site generator, &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, with the design that is seen today.&lt;/p&gt;
&lt;figure&gt;
  &lt;img id=&quot;home-dark&quot; src=&quot;https://blakewatson.com/uploads/2024/homepage-2024-dark.png&quot; alt=&quot;Screenshot of my homepage in dark mode inside of a Safari window. There are 5 journal articles listed in the widest column. A card with my avatar, a one-sentence bio, and some social links are in the sidebar. Below that are 3 microblog posts.&quot; width=&quot;1500&quot; height=&quot;1486&quot; /&gt;
  &lt;img id=&quot;home-light&quot; src=&quot;https://blakewatson.com/uploads/2024/homepage-2024-light.png&quot; alt=&quot;Screenshot of my homepage in light mode inside of a Safari window. There are 5 journal articles listed in the widest column. A card with my avatar, a one-sentence bio, and some social links are in the sidebar. Below that are 3 microblog posts.&quot; width=&quot;1500&quot; height=&quot;1486&quot; hidden=&quot;&quot; /&gt;
  &lt;figcaption&gt;Screenshot of the homepage for posterity. Try changing the color theme :-)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;script&gt;
  (function() {
    const theme = document.querySelector(&#39;html&#39;).getAttribute(&#39;data-theme&#39;);
    const lightImg = document.querySelector(&#39;#home-light&#39;);
    const darkImg = document.querySelector(&#39;#home-dark&#39;);

    setImg(theme);
    window.addEventListener(&#39;theme-change&#39;, (e) =&gt; setImg(e.detail));

    function setImg(theme) {
      if (theme === &#39;light&#39;) {
        darkImg.setAttribute(&#39;hidden&#39;, &#39;hidden&#39;);
        lightImg.removeAttribute(&#39;hidden&#39;);
        return;
      }
      lightImg.setAttribute(&#39;hidden&#39;, &#39;hidden&#39;);
      darkImg.removeAttribute(&#39;hidden&#39;);
    }
  })()
&lt;/script&gt;
&lt;h2 id=&quot;you-should-have-your-own-website&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/blakewatson-com-turns-twenty/#you-should-have-your-own-website&quot;&gt;You should have your own website&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All the cool kids are doing it. Well, maybe not all of them. But some of them. Having your own website is a way to have more agency over how you are represented on the information highway—the living digital library that represents the sum of human knowledge.&lt;/p&gt;
&lt;p&gt;Lots of people are saying this.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nora.zone/manifesto.html&quot;&gt;You should have a website&lt;/a&gt; by Nora&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gregpak.com/how-and-why-to-make-a-personal-website/&quot;&gt;How to (and why you should) make a personal website&lt;/a&gt; by Greg&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coryd.dev/posts/2024/your-site-your-home-your-web&quot;&gt;Your site, your home, your web&lt;/a&gt; by Cory&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rscottjones.com/why-you-should-have-a-website/&quot;&gt;Why you should have a website&lt;/a&gt; by Scott&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://maya.land/internet/personal-site/&quot;&gt;Why you might want a personal site&lt;/a&gt; by Maya&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay, that’s five people, but I was kind of in a hurry when writing. I’m sure there are many, many more.&lt;/p&gt;
&lt;p&gt;Working on your website is just a lot of fun. If you want to kill some time and feel like doing something nerdy, there are at least a &lt;a href=&quot;https://jamesg.blog/2024/02/19/personal-website-ideas&quot;&gt;hundred things you can do with your website&lt;/a&gt;. &lt;a href=&quot;https://32bit.cafe/&quot;&gt;32-bit cafe&lt;/a&gt; also has &lt;a href=&quot;https://32bit.cafe/websiteideas/&quot;&gt;a bunch of ideas&lt;/a&gt;. It can be quite addicting as you wield your newfound power and see it come to life.&lt;/p&gt;
&lt;p&gt;If you don’t know how to code and don’t want to learn, there are plenty of services that will help you build a website without coding.&lt;/p&gt;
&lt;p&gt;If all you want is a simple text based website with a blog, try these super easy indie services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pika.page/&quot;&gt;Pika&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bearblog.dev/&quot;&gt;Bear blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re looking for something a bit more, try these.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ghost.org/&quot;&gt;Ghost&lt;/a&gt; - great for blogs and more sophisticated websites.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webflow.com/&quot;&gt;Webflow&lt;/a&gt; - Great for having granular control of your design without coding.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.squarespace.com/&quot;&gt;Squarespace&lt;/a&gt; - The popular web-builder you’ve already heard of that’s decent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are just a few services. I can’t vouch for all of them, but when I asked around online, these are the responses I got back. Many of them from web developers who recommend these services for their non-coder friends.&lt;/p&gt;
&lt;p&gt;If you are interested in coding your own website but don’t know how to get started, check out my web book, &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt;. It’s easier than you think!&lt;/p&gt;
&lt;h2 id=&quot;twenty&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/blakewatson-com-turns-twenty/#twenty&quot;&gt;Twenty&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s pretty surreal to think back on those early days. 2005-me had no idea how the next 20 years would pan out. But, I think he’d be happy knowing he made at least one smart decision amidst some of the dumb ones.&lt;/p&gt;
&lt;p&gt;Hopefully this site will live on for twenty more years. If it gets slurped up by the &lt;a href=&quot;https://web.archive.org/&quot;&gt;Wayback Machine&lt;/a&gt; or, heck, even AI, then who knows, maybe it will live on forever.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Your freeform digital character sheet for D&amp;D 5e</title>
      <link href="https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/"/>
      <updated>2025-07-23T23:42:00Z</updated>
      <id>https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/</id>
      <content xml:lang="en" type="html">&lt;p&gt;My first foray into digital character sheets was the 5th edition form-fillable PDF, the official ones from Wizards of the Coast. Those quickly became annoying as there just wasn’t enough space to write everything down, even though it was typed instead of handwritten. I wasn’t planning to print my character sheet, yet I was being bound to unnecessary physical constraints.&lt;/p&gt;
&lt;p&gt;That’s when I began to explore the various other digital character sheets available. I don’t remember most of them now, but I did find &lt;a href=&quot;https://www.dndbeyond.com/&quot;&gt;D&amp;amp;D Beyond&lt;/a&gt;. It was a rather good character sheet even before they were fully integrated with Wizards of the Coast. But something about that character sheet and other digital ones rubbed me the wrong way—I had to go by their strict rules on what abilities and features my character could have. Yes, there was a mechanism to do homebrew. But I just didn’t feel like fiddling with all of the details. Those are all necessary if you are going to have a nice automated character sheet experience, so I get it—especially from a developer point of view. But I was looking for something different.&lt;/p&gt;
&lt;p&gt;So in 2019, I built &lt;a href=&quot;https://minimalcharactersheet.com/&quot;&gt;Minimal Character Sheet&lt;/a&gt;. It tries to be space efficient, yet give you space to write all of the information you want to record. It gives you fields for the common things that you would find on your character sheet. While it &lt;em&gt;does&lt;/em&gt; do a little bit of automation, such as calculating modifiers, most everything is freeform and flexible.&lt;/p&gt;
&lt;p&gt;I used it off and on for years, but recently started using it again and immediately realized it needed some quality of life updates. I also realized I never properly introduced it on my blog. So here we go!&lt;/p&gt;
&lt;h2 id=&quot;features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/#features&quot;&gt;Features&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I mentioned, this app is all about giving you a freeform character sheet in a digital format. It does mean that editing your character sheet is a more manual thing than with automated tools, but it also means you have much fewer limitations about what features and abilities your character has. There’s also flexibility in how you organize things since you can be as verbose or concise as you want to be.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dense character information&lt;/strong&gt;&lt;br /&gt;
Information about your character, including your class, species, and background, as well as your AC and hit points and related stats of that nature. These are packed together in a dense display that is always viewable. Input fields auto expand as needed and textareas grow in height as needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modifier calculations&lt;/strong&gt;&lt;br /&gt;
Once you enter in your ability scores, the modifiers are automatically calculated. Skill modifiers will calculate themselves (including proficiency and expertise) but you can override these values if you have an ability that enhances one of your skills.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Spell management&lt;/strong&gt;&lt;br /&gt;
You can add a list of spells at each spell level. Each spell is a single rich text area, so you can write whatever you want and link out to other resources. You can reorder your list of spells and track which ones are prepared. You can also track the number of spell slots and how many are expended at each level.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Weapon info and notes&lt;/strong&gt;&lt;br /&gt;
You’ve got the fields you would expect—name, attack bonus, damage —plus a rich text notes field to write out anything else you’d like to know about your weapons.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Collapsible sections&lt;/strong&gt;&lt;br /&gt;
Most sections of the character sheet are collapsible so that you can focus on just the stuff you care about. I’ve got plans for spells in this area as well—the ability to collapse spell descriptions and open them up only when needed. That feature will hopefully be coming soon.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;D&amp;amp;D 5e 2024 updates&lt;/strong&gt;&lt;br /&gt;
Thanks to the freeform nature of the app, it more or less already supported the &lt;a href=&quot;https://www.dndbeyond.com/posts/1804-start-playing-today-with-the-2024-d-d-free-rules&quot;&gt;2024 rules&lt;/a&gt;. But I’ve made some improvements such as giving &lt;em&gt;background&lt;/em&gt; its own field and renaming &lt;em&gt;race&lt;/em&gt; to &lt;em&gt;species&lt;/em&gt;. I renamed or altogether deleted a few other fields. Other than that, there’s not a material difference between the 2014 version—which is still supported—and the new 2024 version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mobile updates&lt;/strong&gt;&lt;br /&gt;
Because of my disability I don’t use phones very much and sometimes that shows in my side project work. As part of a recent round of updates I greatly improved the mobile experience—that is to say, there actually is one now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Public character sheet (optional)&lt;/strong&gt;&lt;br /&gt;
Character sheets are private by default, but if you opt to make your character sheet public, anyone with the link can view a read-only version of it. This is useful for sharing it with your party or DM.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those are the main features. There are a few goodies like appearance options and I have a road map of little useful things to add.&lt;/p&gt;
&lt;h2 id=&quot;free-and-open-source&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/#free-and-open-source&quot;&gt;Free and open source&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I run this service for free and anyone can sign up. In addition, the &lt;a href=&quot;https://github.com/blakewatson/minimal-character-sheet&quot;&gt;code is on GitHub&lt;/a&gt; under an MIT license, so anyone is free to use it however they see fit. Please don’t judge me too harshly as the codebase is somewhat old. I would do things differently if I were starting over, but that’s how it goes in the software development game.&lt;/p&gt;
&lt;p&gt;I don’t regret the decision to use PHP and SQLite. Both of these are pretty &lt;a href=&quot;https://css-tricks.com/simple-boring/&quot;&gt;boring&lt;/a&gt;, reliable technologies. If I get around to making any significant changes to the architecture, it would be removing the build step from the frontend. I’m currently using Vue.js, but I wouldn’t mind eliminating the build step and either use the browser version of Vue or its cousin, &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/&quot;&gt;Alpine.js&lt;/a&gt;. Anywho, it is what it is.&lt;/p&gt;
&lt;h2 id=&quot;i%E2%80%99m-happy-to-be-playing-d%26d-again&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/your-freeform-digital-character-sheet-for-dd-5e/#i%E2%80%99m-happy-to-be-playing-d%26d-again&quot;&gt;I’m happy to be playing D&amp;amp;D again&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Any D&amp;amp;D fan can tell you the worst part of the hobby is when you don’t have anyone to play with. This happens for various reasons. Sometimes you’re in a group and things fall apart because of conflicting schedules or the DM gets burnt out or what have you. I had several years of no D&amp;amp;D after a couple of years of failed attempts to either run games or play in games. Fortunately, D&amp;amp;D is back in my life. I’m currently DMing one game and playing in another game. Things seem relatively stable for the moment. So, I’m just enjoying it while it lasts.&lt;/p&gt;
&lt;p&gt;If you know of other good character sheet apps, apps for DMs, cool generators, or any other D&amp;amp;D things that you love, please &lt;a href=&quot;https://blakewatson.com/about/#contact-me&quot;&gt;email me or at me on Mastodon&lt;/a&gt; because I would love to know about it. And if you happen to try &lt;a href=&quot;https://minimalcharactersheet.com/&quot;&gt;minimal character sheet&lt;/a&gt;, let me know if you have any trouble or any feature requests.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>40</title>
      <link href="https://blakewatson.com/journal/40/"/>
      <updated>2025-06-24T20:57:33Z</updated>
      <id>https://blakewatson.com/journal/40/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I don’t know how it got here so fast. I feel behind in life for many reasons, not the least of which is &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/&quot;&gt;my late start to being employed&lt;/a&gt;. But many people feel behind. And there’s no reason to. It’s not a rule that everyone do the same things by a certain age. Everyone’s different. Overall I’m happy where I ended up, even if I have a few regrets.&lt;/p&gt;
&lt;p&gt;The past decade has brought with it the increasingly accelerating passage of time. After transitioning to remote work in 2018, the days, weeks, and months blended together and flew by. The beginning of the pandemic feels like a couple of years ago, not five. I need to break up the monotony and slow things down.&lt;/p&gt;
&lt;p&gt;I’ve made some things I’m proud of over the years, but it feels like I should have done more. Feels like I should have had my big idea by now; some side-project-turned-flagship-product. But all I have is &lt;a href=&quot;https://afinestart.me/&quot;&gt;a new tab page&lt;/a&gt; and &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;a long-winded tutorial about HTML&lt;/a&gt;. The speed at which the tech industry moves makes it seem like you could build a billion dollar company, sell out, and move on to your next idea—all in the span of a few months. My aims aren’t that high. All I want is my little lemonade stand on the internet. That’s the dream.&lt;/p&gt;
&lt;p&gt;That said, I’m happy at my job. Glad I have one. Glad that I get to build cool things and have a direct impact on the products we ship.&lt;/p&gt;
&lt;p&gt;I feel older. Not necessarily any wiser. A bit tired. But still with a sense of wonder. You know what, I’ll take it.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>A decade of employment</title>
      <link href="https://blakewatson.com/journal/a-decade-of-employment/"/>
      <updated>2025-05-04T09:17:58Z</updated>
      <id>https://blakewatson.com/journal/a-decade-of-employment/</id>
      <content xml:lang="en" type="html">&lt;p&gt;May 4 is a special day. Not only because it’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Star_Wars_Day&quot;&gt;Star Wars day&lt;/a&gt;, but because it was on that day in 2015 that I was hired for my first full-time job. Today marks one decade of being employed.&lt;/p&gt;
&lt;p&gt;I don’t suppose ten years of being employed is a milestone most people think about. And why should they? Most people work for many years—decades. One decade isn’t so special.&lt;/p&gt;
&lt;p&gt;But it’s a sentimental milestone for me, a man with spinal muscular atrophy who, back in 2014—six years unemployed out of grad school—was close to giving up on ever being part of the workforce. After being passed over time and again, I began to believe that my disability was too great an obstacle.&lt;/p&gt;
&lt;p&gt;No one will ever hire me, I thought. They won’t take a chance on me when there are plenty of people my age with more experience who don’t have the severe physical limitations I do. They won’t hire me because I make them feel uncomfortable and they don’t know how to act around me. I know that feeling because, inexplicably, I’m the same way. If I meet someone with a severe disability, I, too, feel uncomfortable and don’t know how to act. So how can I blame them?&lt;/p&gt;
&lt;p&gt;But all along there was another voice. Quiet and sometimes drowned out, but never fully silenced, it reminded me that I had a knack for making websites. I needed to improve, yes, but I knew my website-making abilities were good and I knew they would get better. More importantly I &lt;em&gt;loved&lt;/em&gt; it. I had the bug. It was the perfect medium to work in, melding visual creativity, writing, systems, and problem solving all into one. There was no way I was &lt;em&gt;not&lt;/em&gt; going to be making websites.&lt;/p&gt;
&lt;p&gt;So make websites I did, any chance I got, for anyone who would take them and (sometimes) pay for them. Eventually I had evidence I could point to and say, “I can make websites like this.” And long though it took, someone finally noticed.&lt;/p&gt;
&lt;h2 id=&quot;what-to-do-when-you-can%E2%80%99t-do-anything&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#what-to-do-when-you-can%E2%80%99t-do-anything&quot;&gt;What to do when you can’t do anything&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I went through the same phases many kids went through. When I pondered what I wanted to be when I grew up, I thought of the usual suspects—police, firefighter, doctor. I naively assumed I could do anything, and since no one told me otherwise, I went on happily through my childhood assuming I would do what anyone else would.&lt;/p&gt;
&lt;p&gt;By high school, reality began setting in. Okay, clearly I’m not going to be a construction worker. What am I good at? What do I like? Can I get paid to play video games? What even is that—video game tester? Alas, these were the olden days before streaming was a way people could get paid to play video games.&lt;/p&gt;
&lt;p&gt;I knew even back then in the late 90s that my future was intertwined with the computer—that humble, dorky machine with its quaint desktop metaphors laid atop a promising blue sky. I remembered that first fascination of using Windows 95 and playing solitaire and pinball. I remembered being amazed by the Weezer video on the Windows 95 installation disc. As a kid in the 90s, I immediately and intuitively realized that the computer was a creation machine. I began using it for art and writing. I didn’t know then just how important the computer was going to be in my life, but I knew I would be using one in whatever job I got.&lt;/p&gt;
&lt;h2 id=&quot;the-world-wide-web&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#the-world-wide-web&quot;&gt;The world wide web&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a kid in the 90s, my first experience with the internet was using AOL via a 14kbps dial-up connection. It was an embarrassingly long time before I knew there was a web &lt;em&gt;outside of AOL&lt;/em&gt;. In high school, a friend of mine was into sports writing and he published his articles on a website. That was my first taste of web publishing and I thought it was so cool. I started helping him with his website and I began publishing my own website about my favorite freeware games.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2025/gameZone.png&quot; alt=&quot;A screenshot of my game page in 2005, shortly after learning a bit of HTML and CSS. It has a simple, old-school feel to it with some image buttons and a sidebar. It has a list of featured games, along with a little thumbnail image in the main content area. The featured pick is a game called Gene Rally that looks to be a racing game. And among the other games is Space Invaders, Tetris, and a game called Inn, where your character is a ninja.&quot; width=&quot;&quot; height=&quot;&quot; /&gt;
  &lt;figcaption&gt; A screenshot of my game page in 2005, shortly after learning a bit of HTML and CSS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I started with WYSIWYG builders and sketchy free hosting. But in the fall of 2005—the start of my junior year of college, majoring in business information systems—I took a course that in hindsight I can say was life-changing. It was Advanced Languages I with Dr. Rodney Pearson. In that course he taught JavaScript and HTML&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; and &lt;em&gt;I couldn’t get enough&lt;/em&gt;. I eagerly looked forward to homework assignments (for the first time ever) and I would complete them as quickly as I could without procrastination (which I rarely did for other courses). Even the interactive coding exams were fun.&lt;/p&gt;
&lt;p&gt;That course sealed the deal—I was going to learn HTML, CSS, and JavaScript, and I was going to be a ✨ Web Designer ✨. I took to converting with voracity my fledgling web empire from WSYIWYG slop to handcrafted HTML and CSS. I felt the power coursing through my veins with every click of the refresh button. And in August 2005, using a friend’s credit card, I purchased this very domain, &lt;a href=&quot;http://blakewatson.com/&quot;&gt;blakewatson.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I spent the remainder of my college years (including grad school) learning everything I could about web design, which is what I called it back then. I read formative books like &lt;a href=&quot;https://designingfortheweb.co.uk/&quot;&gt;Designing for the Web&lt;/a&gt; by Mark Boulton. I followed revered professionals like &lt;a href=&quot;https://zeldman.com/&quot;&gt;Jeffrey Zeldman&lt;/a&gt; on Twitter and read industry publications like &lt;a href=&quot;https://alistapart.com/&quot;&gt;A List Apart&lt;/a&gt;. I slurped up everything I could about making websites and I continued to build my own. I got started with a new up and coming CMS called WordPress.&lt;/p&gt;
&lt;h2 id=&quot;six-long-years&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#six-long-years&quot;&gt;Six long years&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After grad school I began to apply for jobs. It was tough because Mississippi isn’t exactly a tech hub. We are usually behind in just about any kind of metric, especially ones that are based on technology. But disability programs are notoriously difficult to get on, and each state does them differently. So moving to another state and potentially starting over was not an option I wanted to tackle. I was on a good program that paid for caregivers, and I would need those caregivers if I planned to work. So I was stuck in Mississippi, for better or worse. One promising interview was with that of my alma mater, Mississippi State University.&lt;/p&gt;
&lt;p&gt;At least I thought it was promising. After doing pretty well with the technical interview, save for one slightly embarrassing moment, I met with a department head who’s expression as I entered his office told me exactly what was about to happen—I wasn’t getting hired.&lt;/p&gt;
&lt;p&gt;No matter, there will be other interviews. And there were. But each one was similar—employers were interested in my work, but upon learning of my disability, they’d pass. At least that’s what it felt like. Maybe that wasn’t it at all. But I didn’t know and as years went on that thought was eating at me.&lt;/p&gt;
&lt;p&gt;It wasn’t so bad at first—not having to go to school, not having to go to work; spending my time making websites for fun or just goofing off playing video games. I received a modest SSI check and lived at home with my mother, so there wasn’t a dire need for me to work. And that seemed to fit most people’s expectation of what I should have been doing. Nobody would blame me for &lt;a href=&quot;https://www.youtube.com/watch?v=_qlNEmpxQxI&quot;&gt;sitting this mother out&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nobody but me. My own self-worth seemed inextricably linked to having a job and contributing something to society. Why? Was it part of an American ethos? Was it a &lt;a href=&quot;https://www.biblegateway.com/passage/?search=2%20Thessalonians%203%3A10&amp;amp;version=ESV&quot;&gt;biblical imperative&lt;/a&gt;? Was it a way to make up for my lack of masculine physicality?&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; No matter how you look at it, society normally takes a dim view of people who don’t work even though they could. I assumed society figured I couldn’t work but I &lt;em&gt;knew&lt;/em&gt; I could and it was killing me. Some nights I’d cry myself to sleep, wallowing in despair, and praying that somehow I’d find a job and be more than a burden to those around me.&lt;/p&gt;
&lt;p&gt;In hindsight I can see that I was far too hard on myself. I didn’t give myself enough credit for the things I did manage to accomplish—picking up the odd freelance job making a website, volunteering with a local nonprofit to produce nearly all of its media. Making connections, learning.&lt;/p&gt;
&lt;h2 id=&quot;we-still-have-our-dreams&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#we-still-have-our-dreams&quot;&gt;We still have our dreams&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In one of the most defining moments of my unemployed years, I was ghosted by a company after interviewing in person for three hours and being told that the decision was between me and one other candidate. I took it pretty hard. That year in particular had been rough because I was nearly hired by Automattic,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; the company that runs &lt;a href=&quot;http://wordpress.com/&quot;&gt;WordPress.com&lt;/a&gt; (and is currently &lt;a href=&quot;https://techcrunch.com/2025/01/12/wordpress-vs-wp-engine-drama-explained/&quot;&gt;mired in a controversial legal battle&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the aftermath of those two events I was inspired by an episode of &lt;a href=&quot;https://bigwebshow.fireside.fm/&quot;&gt;The Big Web Show&lt;/a&gt; and ended up penning a blog post, called &lt;a href=&quot;https://blakewatson.com/ihs/we-still-have-our-dreams/&quot;&gt;We still have our dreams&lt;/a&gt;, in which I strengthened my resolve to be a website maker, whether anyone would pay me to do it or not.&lt;/p&gt;
&lt;p&gt;That emotional roller coaster defined my six years of unemployment as I careened between the pit of despair and the seed of hope. But as the years passed, despair was winning. Then suddenly…&lt;/p&gt;
&lt;h2 id=&quot;a-wild-mad-genius-appears&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#a-wild-mad-genius-appears&quot;&gt;A wild mad genius appears&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There weren’t a ton of web development jobs available in Mississippi. Well, maybe there were more than I thought, but I didn’t know where to look. I did find a handful of marketing agencies and one in particular caught my eye. &lt;a href=&quot;https://madg.com/&quot;&gt;Mad Genius&lt;/a&gt; seemed like an &lt;em&gt;awesome&lt;/em&gt; place to work. It looked like a breeding ground for creativity and I experienced FOMO immediately.&lt;/p&gt;
&lt;p&gt;I contacted them and interviewed even though they didn’t have an open position. It was a casual interview at a coffee shop with then-interactive-lead &lt;a href=&quot;https://madg.com/people/ryan-farmer/&quot;&gt;Ryan Farmer&lt;/a&gt;. It was such a refreshing interview because we mostly talked shop. Ryan complimented my work, I complimented Mad G’s work, and we shared our mutual nerd crush on &lt;a href=&quot;https://chriscoyier.net/&quot;&gt;Chris Coyier&lt;/a&gt; and &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A year later, they had an opening for an Interactive Designer role and I immediately applied. I got a trial offer and I was ecstatic. They threw me right into the fray and I immediately needed to learn new skills like SVG animation. It was hard, but it was &lt;em&gt;fun&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Several weeks later, on May 4, 2015, I got the full-time offer.&lt;/p&gt;
&lt;p&gt;After several years at Mad Genius, I got the opportunity to join &lt;a href=&quot;https://www.mricompany.com/&quot;&gt;MRI Technologies&lt;/a&gt; out of Houston, TX, working (remotely) on hardware management apps for NASA and Collins Aerospace. For a space fan, this was great. And as it was a remote position, I was able to stay in Mississippi. I’ve been working with the team at MRI since 2019. I’ve loved both of these jobs and learned a ton at each one.&lt;/p&gt;
&lt;h2 id=&quot;working-with-a-disability&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#working-with-a-disability&quot;&gt;Working with a disability&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you have a disability as severe as SMA, you’re going to run into a number of challenges in work, and in life in general. In the United States, there are disparate programs available to help with it by providing education, career help, and personal care assistance. It’s hard to navigate these programs, and they tend to differ between states, which makes it even more difficult.&lt;/p&gt;
&lt;p&gt;I know people with severe disabilities who would work if they had the opportunity, if they didn’t fear losing their benefits, and if someone would give them a chance. I would love to see the situation improve, and I have a little bit of a wish list (unfortunately, government moves at a snail’s pace and some of this stuff is either far away or never going to happen).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Home and community-based programs—the ones that supply caregivers to those of us who need them—need to be administered at the federal level, or otherwise in such a way that frees participants to move between states. At present, moving is difficult because of differing state rules and the need to reapply for services.&lt;/li&gt;
&lt;li&gt;We need consistent Medicaid buy-in rules across all states that remove means testing for people with disabilities who are working that require personal care and or other medical necessities to be able to work. I know people who have multiple degrees paid for by state programs who can’t get a job when they graduate because the amount of money they would make would cause them to be ineligible for services, which would then prevent them from working and making the money in the first place.&lt;/li&gt;
&lt;li&gt;Finally, we need better and consistent documentation and application of these rules. Too often they’re confusing bordering on incomprehensible. And that doesn’t just confuse participants. It can confuse government workers who might apply the rules incorrectly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;looking-forward&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#looking-forward&quot;&gt;Looking forward&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If someone had told me in 2014 where I would be at in 2025, I would have been shocked. I’m excited to see what lies ahead. I have fears, of course. I have the fear of my condition worsening to the point where I can no longer work. I fear that AI might render my skill set meaningless eventually.&lt;/p&gt;
&lt;p&gt;But I still enjoy making websites. And I think I’ll continue to enjoy making websites in the future. Things get bogged down from time to time with framework wars, technical debt, and questionable design trends. But  the fundamental principles of building for the web don’t change so rapidly. When I published &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt; last year, the primary inspiration was to tap into that feeling I had those 20 years ago now, when I was learning HTML and putting it on the web for the first time. That magic is just as relevant now as it was then, maybe even more so because it stubbornly eschews the walled gardens and exploitive practices of the big corporate platforms that thrive today.&lt;/p&gt;
&lt;p&gt;We can always look for ways to improve our work for the people that use it. I’ll never tire of putting the humanity into my work. And I’ll never lose my wonder for the web.&lt;/p&gt;
&lt;p&gt;I’m grateful to be working in this field, and to all the people along the way that helped me cross this ten-year milestone.&lt;/p&gt;
&lt;p&gt;May the fourth be with you.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m intentionally listing JavaScript first because that’s what the course felt like. We were primarily learning to program with JavaScript and learning enough HTML to give us a playground to work in. I know that sounds a bit backward, and I’m not sure he’d even teach it that way now, but it was effective. But just to make it clear that I’m not some JavaScript bro zealot, here’s &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;proof of my adoration of HTML&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://www.curesma.org/about/&quot;&gt;Spinal muscular atrophy&lt;/a&gt; causes just that: muscular atrophy. The muscles become extremely weak, resulting in a multitude of problems, including scoliosis that needs to be corrected with spinal fusion. SMA is progressive, so it continues to worsen as time goes on. &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I was hired for a customer support role on a trial basis but chose to leave the trial for various reasons. &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-employment/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>I’m fascinated by the scale of things in space</title>
      <link href="https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/"/>
      <updated>2025-04-28T17:17:15Z</updated>
      <id>https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m fascinated by videos and other visual mediums that compare the sizes of objects and structures in the universe. I can’t get enough of them. And I’m not exclusively talking about planets, stars, black holes, etc. There is also the vast, yet tiny microcosmos. Unfathomable sizes and distances reign supreme in both the microscopic world and the universe at large.&lt;/p&gt;
&lt;p&gt;Just for fun I thought I would share some of my favorite examples.&lt;/p&gt;
&lt;h2 id=&quot;epic-spaceman&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#epic-spaceman&quot;&gt;Epic Spaceman&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This guy took off (heh) almost as soon as he got started on YouTube. It’s easy to see why. His stuff is incredible. He taught himself Blender and has only been doing VFX for a few years. He just won a bunch of &lt;a href=&quot;https://winners.webbyawards.com/search?sort=0&amp;amp;searchTerm=toby%20lockerbie&quot;&gt;Webbys&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-mind-blowing-scale-of-the-milky-way-galaxy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#the-mind-blowing-scale-of-the-milky-way-galaxy&quot;&gt;The mind-blowing scale of the Milky Way galaxy&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/VsRmyY3Db1Y&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h3 id=&quot;i-shrink-10x-every-21s-until-i%E2%80%99m-an-atom---the-micro-universe&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#i-shrink-10x-every-21s-until-i%E2%80%99m-an-atom---the-micro-universe&quot;&gt;I shrink 10x every 21s until I’m an atom - The Micro Universe&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/rn9dkV4sVYQ&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h3 id=&quot;i-poured-all-the-galaxies-in-the-universe-into-a-pool&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#i-poured-all-the-galaxies-in-the-universe-into-a-pool&quot;&gt;I poured all the galaxies in the Universe into a pool&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/7J_Ugp8ZB4E&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h2 id=&quot;other-videos&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#other-videos&quot;&gt;Other videos&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are many videos on YouTube that visualize the scale of the universe in different ways. Here are some of my favorites.&lt;/p&gt;
&lt;h3 id=&quot;powers-of-ten-(1977)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#powers-of-ten-(1977)&quot;&gt;Powers of Ten (1977)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/0fKBhvDjuy0&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h3 id=&quot;you-are-the-center-of-the-universe-(literally)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#you-are-the-center-of-the-universe-(literally)&quot;&gt;You Are The Center of The Universe (Literally)&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/Z_1Q0XB4X0Y&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h3 id=&quot;vfx-artist-reveals-the-true-scale-of-the-universe&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#vfx-artist-reveals-the-true-scale-of-the-universe&quot;&gt;VFX Artist Reveals the True Scale of the Universe&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/GCTuirkcRwo&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h3 id=&quot;to-scale%3A-the-solar-system&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#to-scale%3A-the-solar-system&quot;&gt;To Scale: THE SOLAR SYSTEM&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/zR3Igc3Rhfg&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h2 id=&quot;interactive&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#interactive&quot;&gt;Interactive&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Finally, here are a couple of fun, interactive expressions of the size of things in the universe.&lt;/p&gt;
&lt;h3 id=&quot;if-the-moon-were-only-one-pixel&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#if-the-moon-were-only-one-pixel&quot;&gt;If the Moon were Only One Pixel&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://joshworth.com/dev/pixelspace/pixelspace_solarsystem.html&quot;&gt;
    &lt;img src=&quot;https://blakewatson.com/uploads/2025/moon-one-pixel.png&quot; alt=&quot;Screenshot of a website that is mostly black with a round yellow circle in the center labeled Sun. There is a scale at the bottom indicating that you can scroll horizontally to see more.&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Scale representation of the solar system&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I absolutely love this one. My favorite thing about it is if you click on the light speed button in the bottom right corner, you can experience in real time how fast light travels away from the sun out into the solar system. Even though light speed is mind-bogglingly fast, it is also much slower than you would think. You hit the button and you think you’re going to go warp speed, but instead the window starts slowly scrolling to the right. In fact, if you were to sit the watch through the whole thing, it would take hours for you to get to Neptune.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://joshworth.com/dev/pixelspace/pixelspace_solarsystem.html&quot;&gt;https://joshworth.com/dev/pixelspace/pixelspace_solarsystem.html&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;scale-of-the-universe&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/im-fascinated-by-the-scale-of-things-in-space/#scale-of-the-universe&quot;&gt;Scale of the universe&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://scaleofuniverse.com/&quot;&gt;
    &lt;img src=&quot;https://blakewatson.com/uploads/2025/scale-of-the-universe.png&quot; alt=&quot;Screenshot of the Scale of the Universe app. There is an icon of a human and clip art of various human-sized objects. There is a slider at the bottom that indicates that you can zoom out or in from the size you are at.&quot; /&gt;
  &lt;/a&gt;
&lt;/figure&gt;
&lt;p&gt;This is one of the first ones I came across. It’s cool because it allows you to go from human-sized things and zoom out to the size of the universe or venture down into the microcosmos.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://scaleofuniverse.com/&quot;&gt;https://scaleofuniverse.com&lt;/a&gt;&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>My computer treats me like a computer</title>
      <link href="https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/"/>
      <updated>2025-03-20T17:56:11Z</updated>
      <id>https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m coming up to a curve in the road. If I’m honest, I’ve already started the curve. My ability to use a hardware keyboard left me a long time ago, but fortunately I’ve retained my ability to use a mouse, albeit with more and more difficulty. I’ve taken to using &lt;a href=&quot;https://plentycom.jp/en/steermouse/&quot;&gt;SteerMouse&lt;/a&gt; to push the sensitivity, acceleration, and speed of my mouse past what most people would be comfortable with. I use an &lt;a href=&quot;https://hitclic.shop/en/products/contacteur-ultra-sensible-l-20mm-h-20mm-10-grammes&quot;&gt;external switch&lt;/a&gt; that takes a minute amount of force to activate as my clicking mechanism. And I’ve lost the ability to scroll via touch or a wheel or a gesture. I now &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;rely on scrollbars&lt;/a&gt; heavily.&lt;/p&gt;
&lt;p&gt;But even with &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/&quot;&gt;just a mouse&lt;/a&gt;, I’m able to type and use the keyboard thanks to the built-in &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;macOS accessibility keyboard&lt;/a&gt;. It’s super customizable and I’ve decked mine out with all sorts of shortcuts and macros. But even then, typing is a chore. So several years ago, I started learning how to use &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;, a hands-free input tool, to perform tasks on my computer (depending on the situation; sometimes I prefer voice, sometimes I prefer onscreen keyboard). I’ve gotten pretty good at that at this point, though it struggles to understand me at times.&lt;/p&gt;
&lt;p&gt;But I’m getting to the point where even using the mouse is difficult. I fear that I will have to move on to using different mechanisms for moving the mouse cursor—probably eye gazing. And this is the curve in the road I mentioned—my post-mouse era. When you have a progressive condition like mine, you have many of these curves. And I’ve managed to overcome each one as I’ve come to it. But this one really freaks me out.&lt;/p&gt;
&lt;p&gt;Voice control software can do a lot, but it’s only as good as its ability to understand you. It does okay for me but doesn’t understand me well enough to take away the frustration. I get by, but that’s it. The great thing about Talon, however, is that it is customizable with voice commands, a phonetic alphabet, and ability to do all sorts of things that are more difficult to do with mainstream voice tools like &lt;a href=&quot;https://www.nuance.com/dragon.html&quot;&gt;Dragon&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; This is what allows me to &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/&quot;&gt;use Talon for programming&lt;/a&gt; without pulling my hair out.&lt;/p&gt;
&lt;p&gt;Having said that, Talon needs me to utter specific sequences of commands. If those commands are misheard, then Talon will either reject them outright or perform a wrong action instead. It makes me speak like I’m a computer. If I commit the spoken equivalent of missing a semicolon, then I get an error. That’s annoying, but that’s the state of things. (This is in no way a criticism of Talon. Talon is great. I’m a big fan and I support the project financially. I’m just describing where technology is at now versus where I’m imagining it could be in the future.)&lt;/p&gt;
&lt;p&gt;But I’m a person, and I don’t enjoy being a computer. It suddenly occurred to me that I’m accommodating my computer rather than my computer accommodating me. It took me a long time to come to this idea, and the way it happened is that I used &lt;a href=&quot;https://openai.com/index/whisper/&quot;&gt;Whisper&lt;/a&gt; and LLMs for the first time. I saw that it was possible for a computer to hear my utterances and transcribe them with an extremely high amount of accuracy. I’m dictating this blog post right now. By the time you’re reading it, I will have gone back over it and edited and reworded things, yes. But I’m able to vomit this article onto the page just by speaking. And it feels incredible.&lt;/p&gt;
&lt;p&gt;But dictating is one thing. As I’ve said, Talon and Dragon do that, even if they don’t do it well for my purposes. I want to do more. I want to speak to my computer as if I had a human assistant right next to me who understood my context, my life, and my intentions. That’s where the LLMs come in. I realize that they don’t understand me per se, but this feels like the first time in computer history that software has come so close to understanding the intention of language. Yes, I know it’s merely predicting the next token or whatever. I get it. Nevertheless, I can &lt;em&gt;see&lt;/em&gt; it now. I can visualize this new accessible world and it feels like we’re close to it. I’ve gotten a taste of this vision, and now I can’t put it out of my mind.&lt;/p&gt;
&lt;p&gt;I want to start up my computer and not worry about moving my mouse or typing things. I want to tell my computer to open my code editor and go to a particular project. I want to tell it to create a new file and open a function block and type the code I tell it to.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; I want to tell it to flip over to the terminal and run that code, check it in the browser, etc. I want it to use the browser for me and I want to tell it where to navigate and what to do. I don’t want to mess with a keyboard or a mouse. And I don’t want to speak like a computer. I want to talk normally and have my intentions carried out.&lt;/p&gt;
&lt;p&gt;I want to play games that I used to play before I lost the strength to play them. I want to write faster and work better without the struggle of peripheral inputs. I want the computer to help me make the computer more accessible to me. Why should I need to wait for another developer, or even myself, to implement assistive technologies if the computer can understand how it works and make affordances for me?&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fn2&quot; id=&quot;fnref2:1&quot;&gt;[2:1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;And don’t tell me this already exists. I’m not talking about accessibility tools that require me to speak or input a certain way. I’m talking honest-to-goodness natural language with a human-like capacity of understanding. Maybe that’s AGI. I don’t know.&lt;/p&gt;
&lt;p&gt;I digress. I realize that is a lot to ask for. And if you feel the need to, you can roast me over on Mastodon.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; But while meaningful human interaction with computers has been the stuff of science fiction, it now feels like, in the not-too-distant future, it could be reality.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;To be fair, it’s been several years since I’ve used Dragon because it is no longer available on Macs. It’s possible that Dragon is much better nowadays on Windows than I’m giving it credit for. But I still imagine I would have some frustrations using it. &lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I have some cognitive dissonance here because I want my computer to know how to code but not replace me as a programmer. Lol, rip. &lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fnref2:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I think AI training and power consumption present legal and ethical dilemmas, which I hope can be resolved. I’d love to use responsible AI that doesn’t trample people’s rights or use excessive resources. &lt;a href=&quot;https://blakewatson.com/journal/my-computer-treats-me-like-a-computer/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Introducing A Fine Start version 3</title>
      <link href="https://blakewatson.com/journal/introducing-a-fine-start-version-3/"/>
      <updated>2025-03-04T22:04:19Z</updated>
      <id>https://blakewatson.com/journal/introducing-a-fine-start-version-3/</id>
      <content xml:lang="en" type="html">&lt;figure&gt;
  &lt;a href=&quot;https://afinestart.me/&quot;&gt;
    &lt;img alt=&quot;A banner image for the Chrome Web Store for A Fine Start. The heading says &#39;Unleash the Hyperlink,&#39; and it is accompanied by a screenshot of Google Chrome with the A Fine Start new tab page open. There are three columns of text links that are sorted into groups such as My Stuff and Media. The links are two destinations such as Netflix, New York Times, Hacker News, etc. There is a toolbar for creating and editing bookmarks.&quot; src=&quot;https://blakewatson.com/uploads/2025/afs3-marquee.png&quot; /&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;Chrome Web Store banner image&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In my &lt;a href=&quot;https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/&quot;&gt;last post&lt;/a&gt; I mentioned that I was working on a rewrite of my &lt;em&gt;*checks notes…*&lt;/em&gt; eight-year-old (!) browser extension. In fact, I called it the &lt;em&gt;final rewrite&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Well, that rewrite is finished and &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; is out on the Chrome, Firefox, and Edge stores (and at &lt;a href=&quot;https://afinestart.me/bookmarks&quot;&gt;https://afinestart.me/bookmarks&lt;/a&gt; for everyone else).&lt;/p&gt;
&lt;p&gt;I started this rewrite in December and worked my long Christmas holiday on it. Progress slowed down when I went back to work in January, but I finally got it out the door last week.&lt;/p&gt;
&lt;h2 id=&quot;new-features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#new-features&quot;&gt;New features&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Fine Start’s biggest new feature is that it can now support anywhere from one to seven columns of text links. Previously, and ever since its inception, A Fine Start was one to three columns of text links. I finally got enough power users and people asking to make it worth expanding that number and making it flexible.&lt;/p&gt;
&lt;p&gt;Another new feature is the introduction of themes. I’ve wanted to do this for a long time but never got around to it. The first version of A Fine Start had only a light theme, and then during the version 2 rewrite, I introduced a dark theme. It’s been that way for several years now. The handful of themes I’ve added are a start (a &lt;em&gt;fine&lt;/em&gt; start?). But I wouldn’t mind creating a few more based on popular color schemes and maybe even open up the variables to the user to define their own theme.&lt;/p&gt;
&lt;p&gt;I introduced a few smaller features as well. Groups are now directly editable, and in addition to renaming a group you can perform a one-off alphabetical sort. There’s a new setting that will let you open an entire group of bookmarks at once.&lt;/p&gt;
&lt;h2 id=&quot;fixes-and-improvements&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#fixes-and-improvements&quot;&gt;Fixes and improvements&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I made the settings page nicer and made it its own page rather than bundling it along with the bookmarks view as a single page application. This makes it easier to link directly to the Settings page and its corresponding pages.&lt;/p&gt;
&lt;p&gt;A big part of A Fine Start is being able to drag and drop bookmarks and entire groups to reconfigure the layout of your page. I wanted to make the drag and drop experience nicer, and I think I achieved that. It  uses the same library (&lt;a href=&quot;https://sortablejs.github.io/Sortable/&quot;&gt;SortableJS&lt;/a&gt;) but I tweaked the settings and styles to make things look and feel smoother.&lt;/p&gt;
&lt;h2 id=&quot;premium-for-syncing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#premium-for-syncing&quot;&gt;Premium for syncing&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All the features that I’ve mentioned are part of the free extension. The premium subscription exists for people who would like to sync their bookmarks between different browsers and devices. That’s it. That’s all Premium does and probably all it ever will do. I’ve accepted that this project is never going to be a quit-your-job money maker, but I’m proud of it, and I use it every day as I have for the past eight years.&lt;/p&gt;
&lt;p&gt;Premium is five dollars a month, and there’s an annual sub which has been pretty popular over the last year or two that I’ve had it. You get a whole third off when you pay annually. The syncing service is fast and it doesn’t require an extra password—just your email address.&lt;/p&gt;
&lt;h2 id=&quot;development-notes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#development-notes&quot;&gt;Development notes&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the part where I talk a little bit about the development of A Fine Start. I wanted to get rid of frontend dev complexity by eliminating build steps and using only the dependencies I needed, doing everything else with vanilla JavaScript, HTML, and CSS.&lt;/p&gt;
&lt;p&gt;I don’t think I achieved less complexity. But I am happy to be off the &lt;a href=&quot;https://laravel-mix.com/&quot;&gt;aging build setup&lt;/a&gt; I was using. I wasn’t in a hurry to get sucked into another one, and I wanted to maintain the extension in the future with little hassle, no matter what was in vogue in JavaScript Land.&lt;/p&gt;
&lt;p&gt;Funnily enough, A Fine Start began as a vanilla JavaScript app. Then, in version 2, I migrated it to Vue, and now I’ve migrated it back to vanilla again.&lt;/p&gt;
&lt;p&gt;I do have one regret, which is that I moved the data storage functionality from local storage to IndexedDB. I was using Indexed DB in v2 for the restores feature, and I decided to move everything to IndexedDB because I thought it was a more robust data storage option with less likelihood to be removed by the browser automatically. I also wanted one API for storing data locally. This is why I created the DataStore package.&lt;/p&gt;
&lt;p&gt;It was only after launching the update that I discovered that private browsing in Firefox prevents the extension from using IndexedDB. That kind of sucks but I do have one idea for a workaround but still wish I would have known that going in. My fault.&lt;/p&gt;
&lt;p&gt;Otherwise, I’m pretty happy with the codebase. I was able to move away from Webpack, and though I’m not using any frontend build per se, I am using Eleventy (which I was already using to generate the website) to generate the code for every platform. That mostly involves copying certain files together into a target location. There are also a few tweaks to environmental variables depending on whether the target is a particular extension, any extension, or the web version.&lt;/p&gt;
&lt;p&gt;So the build step still exists, but I’m much happier with this one because I believe the stewards of Eleventy care more about ensuring compatibility than many other npm packages. And even if they don’t, the work is mostly copying files and creating slight variations—I can come up with another option if I have to.&lt;/p&gt;
&lt;h2 id=&quot;roadmap&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#roadmap&quot;&gt;Roadmap&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Don’t let the term “final rewrite” fool you. Part of the goal of it was to make it easier for me to add features later on. A Fine Start is as alive as ever.&lt;/p&gt;
&lt;p&gt;As I mentioned one goal is to expand themes and give users the ability to create their own.&lt;/p&gt;
&lt;p&gt;I’ve made more progress on accessibility in this version, and I want to improve it—partially by doing things under the hood to support keyboard and screen readers better, and with explicit accessibility settings that users can try to make A Fine Start work better for them.&lt;/p&gt;
&lt;p&gt;In fact, I built a couple of accessibility settings into version 2 for &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;my brother&lt;/a&gt; and me, but I didn’t make them publicly available because they were (in my opinion) too niche.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I’m happy to report those accessibility settings are now available to everyone,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; and I have ideas for more to come.&lt;/p&gt;
&lt;p&gt;For the syncing service—and this is more of a under-the-hood thing—I would like to migrate the database over to SQLite and simplify my backup process. There are no front-facing features to that, but I’d like to think removing backend complexity will extend the life of the syncing service and make it even less likely for anything to go wrong.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;My brother and I have difficulty using scroll wheels and similar mechanisms, so we rely on a very old-school way of scrolling— clicking and dragging the scrollbar. That can get pretty annoying, though, because &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;scrollbars are increasingly small targets&lt;/a&gt;. So, in A Fine Start, I built in a feature that lets you scroll the page by clicking and dragging the entire page, similar to how you would scroll on a touch device with your finger. My version of this is a poor facsimile of what the excellent browser extension &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt; can do for every web page. &lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m just now realizing that I held back a feature that other people could have potentially used because I thought no one would want it—even though I know two people who needed it, and I’m a person with a disability who understands that people have different needs. If that kind of blind spot can happen to me as a disabled developer, it can happen to anyone. &lt;a href=&quot;https://blakewatson.com/journal/introducing-a-fine-start-version-3/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>IndexedDB made easy like localStorage</title>
      <link href="https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/"/>
      <updated>2025-02-07T00:52:08Z</updated>
      <id>https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m nearly done rewriting my browser extension, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;, moving away from Vue 2 and using vanilla JavaScript. I’m calling this the final rewrite, as I’m trying to make it as easy for me to maintain going forward as possible, using as few dependencies as I can get away with.&lt;/p&gt;
&lt;p&gt;A Fine Start is a new tab page replacement. It shows columns of text links on your new tab page, which you can organize into groups and sort how you see fit. I’ve been using it (and previously, &lt;a href=&quot;https://start.blakewatson.com/&quot;&gt;its ancestor&lt;/a&gt;) every day for almost a decade now. I love it.&lt;/p&gt;
&lt;p&gt;In the current release of my extension, those columns of links are stored as JSON in localStorage. Kind of. If you are using the web hosted page, that’s true. If you are using the browser extension, then it’s using &lt;code&gt;browser.storage.local&lt;/code&gt;, which acts like local storage for all intents and purposes but is the special browser extension kind. I’m not 100% sure what all the differences are, but best I can tell, extension storage is less likely to be purged by the browser and operations for interacting with storage are asynchronous.&lt;/p&gt;
&lt;p&gt;But localStorage has some disadvantages that become annoying the more you work with it. For me, the biggest one is that you can only save strings. If you have a big nested object (like columns of text links that are sorted into groups) you first need to &lt;code&gt;JSON.stringify&lt;/code&gt; that sucker before you can save it.&lt;/p&gt;
&lt;p&gt;Another downside is that you only get about 5MB of storage space theoretically. That’s a pretty good bit, so maybe you won’t run into that. I don’t think I’ve run into that either. But it’s something to be aware of depending on what kind of app you’re making.&lt;/p&gt;
&lt;p&gt;Because my app has a web version plus extension versions, it needed to work with the various APIs for storage depending on whether it’s running in the context of a webpage or a browser extension. I wanted to use Just One Thing no matter the context.&lt;/p&gt;
&lt;p&gt;So I turned my attention to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB&quot;&gt;IndexedDB&lt;/a&gt;, the fancypants if somewhat stuffy database system that’s built into the web browser. The nice thing about this is that it can store much more data than localStorage. And most importantly,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; you can save data other than strings. If you have an object, you can just save that object directly in the database—no stringification needed.&lt;/p&gt;
&lt;p&gt;But using IndexedDB is pretty annoying and verbose. Especially since I’m not really using any of its features—I’m still just saving key value pairs for the most part. Luckily, a library called &lt;a href=&quot;https://github.com/localForage/localForage&quot;&gt;localforage&lt;/a&gt; grabbed my attention. It lets you use easy old localStorage methods like &lt;code&gt;getItem&lt;/code&gt; and &lt;code&gt;setItem&lt;/code&gt; but saves data in IndexedDB. I integrated it deeply into my app before running into an issue that I learned was not going to be fixed because the project is purportedly to be archived soon.&lt;/p&gt;
&lt;p&gt;Well, dangit.&lt;/p&gt;
&lt;p&gt;That’s fine, I thought to myself. I didn’t want to bring in a bunch of extra bloat anyway. I will just Do It Myself™. So I started writing a class and before I knew it I was putting the finishing touches on a full blown npm JavaScript package.&lt;/p&gt;
&lt;h2 id=&quot;introducing-datastore&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/#introducing-datastore&quot;&gt;Introducing DataStore&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I decided I wanted the benefits of IndexedDB, even though I’m not saving and querying complex data. Specifically DataStore offers these benefits over localStorage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;More storage space&lt;/li&gt;
&lt;li&gt;Save structured data without &lt;code&gt;JSON.stringify&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Asynchronous operations&lt;/li&gt;
&lt;li&gt;Multiple stores&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s easy like localStorage, though it does have this one a bit of extra setup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const store = new DataStore();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you do that, you can perform all of the CRUD operations you are used to.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;async myFunction() {
	const store = new DataStore();

	await store.setItem(&#39;email&#39;, &#39;blake@example.com&#39;);
	
	const email = await store.getItem(&#39;email&#39;);
	console.log(email); // blake@example.com
	
	await store.removeItem(&#39;email&#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, that’s the easy mode. Behind the scenes, DataStore is creating a default database with a default data store and saving everything to that store. But if you have more advanced needs, you may want to specify a database name and one or multiple stores in which to put data.&lt;/p&gt;
&lt;p&gt;In that case, you can set up a database first before using it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;DataStore.setupDb({
  name: &#39;My Database&#39;,
  storesToCreate: [&#39;posts&#39;, &#39;comments&#39;];
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can use those stores to save different groups of data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;async myFunction() {
	const postStore = new DataStore(&#39;My Database&#39;, &#39;posts&#39;);
	
	// we can save structured data directly!
	await postStore.setItem(3, {
		title: &#39;My third post&#39;,
		body: &#39;In west Philadelphia born and raised...&#39;
	});
	
	const commentStore = new DataStore(&#39;My Database&#39;, &#39;comments&#39;);
	
	await commentStore.setItem(3, [
		&#39;FIRST&#39;,
		&#39;Remember the playground?&#39;,
		&#39;YES, where we spent most of our days&#39;
	]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay if you were actually saving blog posts and comments in browser storage, you would probably want to use IndexedDB directly so you could write queries and what not. But just as an example, this is how you can easily save structured data.&lt;/p&gt;
&lt;p&gt;It’s fast, convenient, and flexible storage.&lt;/p&gt;
&lt;h2 id=&quot;how-do-i-get-it%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/#how-do-i-get-it%3F&quot;&gt;How do I get it?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I published DataStore as an npm package, so if that’s your kind of thing, you can:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm i @blakewatson/datastore
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But if you are like me and tired of npm and build steps, you can &lt;a href=&quot;https://unpkg.com/@blakewatson/datastore/dist&quot;&gt;download the ESM or global version&lt;/a&gt; from the CDN or &lt;a href=&quot;https://github.com/blakewatson/datastore&quot;&gt;GitHub&lt;/a&gt; release.&lt;/p&gt;
&lt;p&gt;I haven’t used this heavily yet, so it’s extremely possible that there are bugs. Please open an issue if you run into anything.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/blakewatson/datastore&quot;&gt;readme on GitHub&lt;/a&gt; for more details installing and using DataStore.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Most importantly, &lt;em&gt;for me&lt;/em&gt;. I imagine if you had a bunch of data you wanted to query, than actual database features would be among the most important. But remember, all I’m trying to do here is replace localStorage. &lt;a href=&quot;https://blakewatson.com/journal/indexeddb-made-easy-like-localstorage/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Things I got from specific people</title>
      <link href="https://blakewatson.com/journal/things-i-got-from-specific-people/"/>
      <updated>2025-01-16T15:37:06Z</updated>
      <id>https://blakewatson.com/journal/things-i-got-from-specific-people/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Sometimes it surprises me how things that I consider essential in my life—things that form parts of my identity—might have never found me. Only though happenstance did I learn about these things. People happened to enter my life and introduce me to these things I love. I thought it might be fun to call out a few of them. I’m indulging in a bit of nostalgia here. But that’s ok. When you &lt;a href=&quot;https://hamatti.org/posts/you-should-start-a-blog-today/&quot;&gt;have your own blog&lt;/a&gt;, you can &lt;a href=&quot;https://robinrendle.com/notes/take-care-of-your-blog-/&quot;&gt;do what you want&lt;/a&gt;. &lt;a href=&quot;https://bell.bz/just-post/&quot;&gt;Just post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;entertainment-i-got-from-mike&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#entertainment-i-got-from-mike&quot;&gt;Entertainment I got from Mike&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Mike is the lead on the &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;dev team I work with&lt;/a&gt; at MRI Technologies. I’ve known him for five years now, so I’ve had time to pick up a few things.&lt;/p&gt;
&lt;p&gt;One of them is the fantastic game &lt;a href=&quot;https://en.wikipedia.org/wiki/Slay_the_Spire&quot;&gt;Slay the Spire&lt;/a&gt;. I’m generally terrible at roguelikes and deck-building, but I still had a lot of fun with this one. It’s a good one for me because it’s fully playable by mouse only and it doesn’t require any quick reaction times.&lt;/p&gt;
&lt;p&gt;The other thing I got from Mike is books. I hadn’t kept up much of a reading habit, but thanks to the intermittent book club at work, I started reading again. Mike loves fantasy series and won’t shut up about his nerd crush on Brandon Sanderson. I’ve enjoyed a bunch of Mike’s book recommendations, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The First Law series&lt;/li&gt;
&lt;li&gt;The Mistborn series (I’ve read the first three)&lt;/li&gt;
&lt;li&gt;The Stormlight Archive (I’m on book 3 as of press time&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-music-i-got-from-dylan&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#the-music-i-got-from-dylan&quot;&gt;The music I got from Dylan&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My childhood friend &lt;a href=&quot;https://bsky.app/profile/dylanmclemore.com&quot;&gt;Dylan&lt;/a&gt; is responsible for a number of artists and albums I like. But one towers over all the others.&lt;/p&gt;
&lt;p&gt;It was sometime in 2007 when Dylan visited me in my apartment on campus at Mississippi State University. He was a DJ at his college radio station and he brought some new music for me to check out.&lt;/p&gt;
&lt;p&gt;I didn’t really listen to contemporary Christian music for reasons&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; but I liked what I heard. The lyrics were cryptic with the hint of a story and the music hit all the buttons that a 2000s me (ok ok and a now me) wanted—crisp guitar, soaring vocals, piano, and cinematic background.&lt;/p&gt;
&lt;p&gt;The album was &lt;a href=&quot;https://album.link/i/716184123&quot;&gt;Captiva&lt;/a&gt; by Falling Up.&lt;/p&gt;
&lt;p&gt;I would go on to become a huge fan of Falling Up, experiencing their transition into sci-fi fantasy concepts, separation from their label, disbandment, resurgence as an indie band, the final album, and now the metamorphosis into a new band, &lt;a href=&quot;https://thechillingalpineadventure.bandcamp.com/album/the-chilling-alpine-adventure-3&quot;&gt;The Chilling Alpine Adventure&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-intro-to-web-dev-i-got-from-dr.-pearson&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#the-intro-to-web-dev-i-got-from-dr.-pearson&quot;&gt;The intro to web dev I got from Dr. Pearson&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was interested (and participated) in making websites before I went to Mississippi State University in 2003. But I wasn’t good at it. I was using apps and services that let you make websites without coding. I was frustrated with them but intimidated by the prospect of writing code myself.&lt;/p&gt;
&lt;p&gt;In 2005, I took Dr. Rodney Pearson’s Advanced Languages 1. It turned out to be what I would now call &lt;em&gt;JavaScript + HTML&lt;/em&gt;. Dr. Pearson had a unique teaching style that really forced you to learn things bit by bit and apply them. What at first was intimidating became comprehensible, then fun, then addictive. I couldn’t get enough. I started tearing down my WYSIWYG sites and rebuilding them from scratch. I learned how to &lt;a href=&quot;https://blakewatson.com/rdo&quot;&gt;make games&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That course sent me down a path that would lead to a fulfilling career in web development. A career which turns a decade old this year! More on that in a future post.&lt;/p&gt;
&lt;h2 id=&quot;a-nicer-social-media-from-adam&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#a-nicer-social-media-from-adam&quot;&gt;A nicer social media from Adam&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In December of 2023, I wrote a post called &lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/&quot;&gt;omg.lol: an oasis on the internet&lt;/a&gt;. Much of it was gushing about &lt;a href=&quot;https://adam.omg.lol/&quot;&gt;Adam&lt;/a&gt;’s internet service, &lt;a href=&quot;https://omg.lol/&quot;&gt;omg.lol&lt;/a&gt;. Part of the service includes an optional Mastodon account. I had heard about the federated social media system, but I had not joined yet as I had server decision paralysis.&lt;/p&gt;
&lt;p&gt;Also I had quit using Twitter after Elon Musk turned off access to third-party clients, which was my preferred way of using Twitter.&lt;/p&gt;
&lt;p&gt;The timing just worked out. Here I was wondering what I was going to do about my social media situation. And there it was. A Mastodon instance ready to go, administered by a good fellow, and inhabited by the nicest people.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-job-i-got-from-my-brother&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#the-job-i-got-from-my-brother&quot;&gt;The job I got from my brother&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt&lt;/a&gt; tells it, we were both looking for jobs in web dev and he found a listing from MRI Technologies and put it in the shared spreadsheet we were using. We were kind of dividing the opportunities between us and he decided that I could apply for this one.&lt;/p&gt;
&lt;p&gt;Turns out that &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;worked out pretty well&lt;/a&gt; for me. :)&lt;/p&gt;
&lt;h2 id=&quot;there-are-obviously-so-many-more&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#there-are-obviously-so-many-more&quot;&gt;There are obviously so many more&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I guess I shouldn’t be surprised about all the good things I got from people. I mean, I had to get them from somewhere. But it’s just interesting to me to see which things I latched on to and contemplate what different paths I might have taken if I had met different people who gave me different things.&lt;/p&gt;
&lt;p&gt;I didn’t really set out to write a blog post about being grateful but I guess now that I’ve written it, that’s kind of what it is. I guess I was just feeling appreciative today. In a world like the one we have, it’s good to savor moments like that.&lt;/p&gt;
&lt;p&gt;Maybe I will do a part two one day.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I just like the sound of that phrase. Makes my blog sound fancy. &lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;When I was a kid, the church I went to was so strict that they discouraged listening to Christian rock because it was entertaining rather than reverent. &lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I need to write a separate blog post about TCAA. This album is so good. &lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m serious. I’m not the only one who has said this. People on social.lol are just so nice and pleasant. &lt;a href=&quot;https://blakewatson.com/journal/things-i-got-from-specific-people/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>2024: my year in review</title>
      <link href="https://blakewatson.com/journal/2024-my-year-in-review/"/>
      <updated>2024-12-31T10:44:25Z</updated>
      <id>https://blakewatson.com/journal/2024-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Well, here we are again—another year. They seem to go by faster and faster, and this one in particular did. I’m just now getting used to the number 2024. The idea that it will be 2025 is surreal to me. This next year holds several sentimental milestones for me, which I’ll be writing about when they get closer.&lt;/p&gt;
&lt;p&gt;I accidentally started a tradition in 2022 of listing out some goals for the new year. So, let’s see how I did this past year.&lt;/p&gt;
&lt;h2 id=&quot;2024-goals&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#2024-goals&quot;&gt;2024 goals&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s start with the one I totally nailed.&lt;/p&gt;
&lt;h3 id=&quot;read-5-books&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#read-5-books&quot;&gt;Read 5 books&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I did it again! I know a lot of folks read upward of 50 books a year, but that’s not me. Five books is a lot for me. I’m trying to build up a reading habit after not reading much of anything longform for years.&lt;/p&gt;
&lt;p&gt;This year was The Year of Brandon Sanderson. I enjoyed the Mistborn trilogy (The Final Empire, The Well of Ascension, and The Hero of Ages). My first big dive into Sanderson’s fantasy novels&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; left me entertained and inspired to write.&lt;/p&gt;
&lt;p&gt;I then started on Sanderson’s meaty series, The Stormlight Archive. These books are huge, and I think they should count for two points each. I finished The Way of Kings and Words of Radiance. At the time of this writing, I’ve just started on book 3, Oathbringer.&lt;/p&gt;
&lt;p&gt;So that’s a total of five books, with bonus points for two of them being ginormous. &lt;strong&gt;Grade: A+&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;write-one-article-every-month&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#write-one-article-every-month&quot;&gt;Write one article every month&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For some reason I like to call my blog posts, &lt;em&gt;articles&lt;/em&gt;. Makes me feel more important and accomplished I guess. I’m a blog post snob, I’m now realizing (but only when it comes to my work—I love &lt;em&gt;your&lt;/em&gt; blog posts so keep &#39;em coming).&lt;/p&gt;
&lt;p&gt;This is another tradition I accidentally started. Last year, I had the goal to write five blog posts in a year, but by May, I realized I had written one post every month. Then, I just decided to keep it going. I’m really glad I did because writing for my website is so satisfying. You’ll never hear anyone say they regretted blogging more. It’s always a good thing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: A+&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;write-a-novella-(bonus%3A-not-sci-fi)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#write-a-novella-(bonus%3A-not-sci-fi)&quot;&gt;Write a novella (bonus: not sci-fi)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We have now arrived at my first failure. Not only did I fail to write a non-sci-fi novella, I failed to write a novella at all.&lt;/p&gt;
&lt;p&gt;But I have a scapegoat. I’m blaming NaNoWriMo for this one. Yes, I’ve had a longstanding tradition of writing during National Novel Writing Month each November, but this year was different.&lt;/p&gt;
&lt;p&gt;NaNoWriMo the organization is going through a controversial time right now. Part of it included shutting down the NaNoWriMo forums, including my beloved Adoption Society—a forum dedicated to sharing plots, characters, running gags, opening lines, chapter-naming schemes, and more with your fellow writers.&lt;/p&gt;
&lt;p&gt;The forums are the soul of the event for me, so shutting them down bummed me out.&lt;/p&gt;
&lt;p&gt;But part of it was that I was busy writing something &lt;em&gt;else&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: F&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;make-one-game&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#make-one-game&quot;&gt;Make one game&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Well, dammit, I failed again. I never got around to making a game this year. I didn’t really have any ideas. I’m still interested in getting better at game dev using &lt;a href=&quot;https://pixijs.com/&quot;&gt;PixiJS&lt;/a&gt;, and I do have some game genres I’d like to experiment with—tower defense and idle/incremental/clicker. Maybe next year.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: F&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;watch-at-least-some-of-the-video-courses-i-bought-in-2023&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#watch-at-least-some-of-the-video-courses-i-bought-in-2023&quot;&gt;Watch at least some of the video courses I bought in 2023&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Yeah, I’m bad about this. Ok, I kind of kept this goal, but not really.&lt;/p&gt;
&lt;p&gt;At work, I have been building a web component library for use in the &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;COSMIC suite of applications&lt;/a&gt; we build for NASA. I wanted to quickly get up to speed on the nitty-gritty details of web components.&lt;/p&gt;
&lt;p&gt;As it happened, Scott Jehl came through just in time with an excellent course called &lt;a href=&quot;https://scottjehl.com/learn/webcomponentsdemystified/&quot;&gt;Web Components Demystified&lt;/a&gt;. I haven’t finished the whole course yet, but I got through the big lessons and learned a ton.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: C+&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;spend-more-time-with-friends&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#spend-more-time-with-friends&quot;&gt;Spend more time with friends&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I could always do better at this, but this year went better than some. I had coffee with a longtime &lt;a href=&quot;https://dylanmclemore.com/&quot;&gt;friend of mine&lt;/a&gt;, and I had the chance to catch up with my old friends at &lt;a href=&quot;https://madg.com/&quot;&gt;Mad Genius&lt;/a&gt;. I also hosted a voice call in the SMA Chat Discord server. I always enjoy catching up with my crippled cyborg peeps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade B+&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;five-years-of-building-software-for-nasa&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#five-years-of-building-software-for-nasa&quot;&gt;Five years of building software for NASA&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I really can’t believe it’s been so long. It feels like maybe it’s been two years. But no, it was August 2019 when I joined the &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;COSMIC&lt;/a&gt; team at &lt;a href=&quot;https://www.mricompany.com/&quot;&gt;MRI Technologies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I mentioned earlier, I enjoyed diving into the world of web components and helping us pay off some technical debt. I’m hoping to do more of that, and the word on high is that we have some exciting work coming down the pipeline this next year. It should be fun.&lt;/p&gt;
&lt;h2 id=&quot;html-for-people&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#html-for-people&quot;&gt;HTML for People&lt;/a&gt;&lt;/h2&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2024/html-hero.webp&quot; alt=&quot;Illustration of a computer desk. There is a lot of space decor. The computer monitor shows a cartoon space probe zooming past a logo that reads &#39;HTML for people,&#39; stylized as an HTML comment.&quot; /&gt;
&lt;p&gt;My biggest accomplishment of the year was writing and publishing a web-based book called &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt;. It’s a beginner-friendly introduction to HTML that rests on the idea that making websites with HTML is for everyone, not just professional web developers.&lt;/p&gt;
&lt;p&gt;This thing took months to write and transform into a website. It’s part of the reason I didn’t do my usual creative writing in November—I was kind of burned out on writing.&lt;/p&gt;
&lt;p&gt;If you’re interested in the backstory, I &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/&quot;&gt;wrote all about it back in October&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-fine-start%2C-version-3&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#a-fine-start%2C-version-3&quot;&gt;A Fine Start, version 3&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In December, I began what I’m calling the Last (frontend) Rewrite of my minimal new tab page browser extension, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;. The current version relies on an aging Webpack-based build step to process the Vue-based code. I still like Vue and its nimble cousin, &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/&quot;&gt;Alpine&lt;/a&gt;, but browser extensions have a more strict environment. You can’t use the CDN versions of these frameworks—if I wanted to keep using Vue, I would need a build step to turn templates into render functions.&lt;/p&gt;
&lt;p&gt;But I’m tired of build steps. They’re fine for certain situations, but a more vanilla approach serves a browser extension well. For example, Firefox (and maybe Chrome?) discourages using obfuscated code. There are strict rules about third-party dependencies. It’s much easier for me to manage versions and ensure Firefox reviewers can verify my code. It’ll make maintenance easier in the long run to go vanilla.&lt;/p&gt;
&lt;p&gt;It’s not out yet, but I expect to finish it in January or February at the latest. Longtime fans should continue to enjoy the features they love, and some new features are coming!&lt;/p&gt;
&lt;h2 id=&quot;other-projects&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#other-projects&quot;&gt;Other projects&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My dice roller, &lt;a href=&quot;https://d20app.me/&quot;&gt;d20&lt;/a&gt;, is on its last legs. I still haven’t updated it, and I’m not sure if I want to. I’m considering making d20 a web app. It’s already based on Electron (essentially HTML, CSS, and JS), so it wouldn’t be a huge leap.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&quot;https://synthwave.live/&quot;&gt;synthwave mix&lt;/a&gt; site is still up and running. I haven’t made any new updates, but I keep running the update script weekly (well, when I remember).&lt;/p&gt;
&lt;p&gt;I added a few features to my D&amp;amp;D character sheet app, &lt;a href=&quot;https://minimalcharactersheet.com/&quot;&gt;Minimal Character Sheet&lt;/a&gt;. These are mostly things it should have already had—a place for notes, a field for your initiative position, and strikethrough support in the text blocks. If you want the convenience of digital with the flexibility of paper, check it out.&lt;/p&gt;
&lt;h2 id=&quot;music&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#music&quot;&gt;Music&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m currently obsessed with &lt;a href=&quot;https://album.link/i/1783785988&quot;&gt;The Chilling Alpine Adventure&lt;/a&gt;, but as it was just released on December 27, it won’t appear in my music stats until next year probably. I listened to a good bit of electronic this year while working on stuff. After The Chilling Alpine Adventure, I’d say my favorite album releases of the year were &lt;a href=&quot;https://album.link/us/i/1752196202&quot;&gt;Infinite Health by Tycho&lt;/a&gt; and &lt;a href=&quot;https://album.link/s/4NFeATnC0BhLtvXInTdO9R&quot;&gt;A Life&lt;/a&gt; by new-to-me artist Christian Löffler (discovered by way of &lt;a href=&quot;https://somafm.com/&quot;&gt;SomaFM&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I wanted to get this article in before the end of the year, but as soon as my 2024 &lt;a href=&quot;http://last.fm/&quot;&gt;Last.fm&lt;/a&gt; report is available, I will link to it here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; here’s my &lt;a href=&quot;https://www.last.fm/user/blakewatson/listening-report/year&quot;&gt;Last.fm annual report&lt;/a&gt;. They don’t do permalinking very well so I’ll have to remember to come back to this post next year and append &lt;code&gt;/2024&lt;/code&gt; to the &lt;a href=&quot;http://last.fm/&quot;&gt;Last.fm&lt;/a&gt; URL.&lt;/p&gt;
&lt;h2 id=&quot;goals-for-next-year&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#goals-for-next-year&quot;&gt;Goals for next year&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Read five books (keep the streak alive!)&lt;/li&gt;
&lt;li&gt;Write an article every month&lt;/li&gt;
&lt;li&gt;Write one work of fiction&lt;/li&gt;
&lt;li&gt;Make one game (not letting the dream die yet)&lt;/li&gt;
&lt;li&gt;Ship a new software project&lt;/li&gt;
&lt;li&gt;Go on a date&lt;/li&gt;
&lt;li&gt;Avoid turning 40&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I read Tress of the Emerald Sea last year, which I believe was my first ever Sanderson work. But as it was a sort of smaller one-off, I’m calling Mistborn my first real foray into the world of Brandon Sanderson. &lt;a href=&quot;https://blakewatson.com/journal/2024-my-year-in-review/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Alpine.js for home-cooked apps</title>
      <link href="https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/"/>
      <updated>2024-11-26T15:00:00Z</updated>
      <id>https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m a big fan of home-cooked apps—a &lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;term I first heard from author Robin Sloan&lt;/a&gt; and have since run with. A home-cooked app is one that you create for yourself, friends, or family. It’s typically not something you are releasing to the general public. For me, this takes the form of various web applications. I &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps&quot;&gt;gave a talk on home-cooked apps&lt;/a&gt;, which you can check out if you want to deep dive.&lt;/p&gt;
&lt;p&gt;Here are some examples of home-cooked apps I’ve made:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/&quot;&gt;Discord-like chat app&lt;/a&gt; just for me and my brother&lt;/li&gt;
&lt;li&gt;A homemade app for &lt;a href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/&quot;&gt;saving bookmarks online&lt;/a&gt; (this one is &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;open sourced&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An app for settling up IOUs between family members&lt;/li&gt;
&lt;li&gt;An app for receiving job applications from caregivers and sorting through them &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;An app for tracking our caregivers’ hours worked&lt;/li&gt;
&lt;li&gt;A shared grocery list app for the household&lt;/li&gt;
&lt;li&gt;A scratchpad similar to &lt;a href=&quot;https://tot.rocks/&quot;&gt;Tot for Mac&lt;/a&gt; that syncs pieces of temporary text&lt;/li&gt;
&lt;li&gt;An app that allows me to interact digitally with a deck of cards called &lt;a href=&quot;https://writeremergency.com/&quot;&gt;Writer Emergency Pack&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have a lot of ideas for these kinds of apps, but I have extremely limited time. With working full-time and managing aspects of my disability, I have precious little time to build these projects. I need to plow through them quickly. I need to play to my strengths—prioritize frontend because I’m better at that, minimize backend logic, and simplify data storage and retrieval.&lt;/p&gt;
&lt;p&gt;One aspect of an app that can bog things down is interactive UI. But that’s no problem because I have a secret weapon.&lt;/p&gt;
&lt;h2 id=&quot;alpine.js&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#alpine.js&quot;&gt;Alpine.js&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My brother introduced me to &lt;a href=&quot;https://alpinejs.dev/&quot;&gt;Alpine&lt;/a&gt; a couple of years ago when he used it at &lt;a href=&quot;https://storyware.co/mattwatson/&quot;&gt;Storyware&lt;/a&gt;. I didn’t see the point of Alpine at first. It’s based on Vue’s reactivity engine, so why not use Vue instead? And what’s with all the inlined JavaScript code? 🤮&lt;/p&gt;
&lt;p&gt;But then I used it, and oh man, did it feel like having frontend superpowers. If you’ve never worked with a reactive UI library, prepare to have your mind blown. But even if you have worked with Vue, React, or the other usual suspects, Alpine can still be a breath of fresh air.&lt;/p&gt;
&lt;p&gt;Let me give you the obligatory counter button example. First, I’ll pull in Alpine via CDN (no build step needed—grab and go).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;head&amp;gt;
  &amp;lt;script defer src=&amp;quot;https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now for the component:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div x-data=&amp;quot;{ count: 0 }&amp;quot;&amp;gt;
  &amp;lt;p x-text=&amp;quot;count&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;
  
  &amp;lt;button @click=&amp;quot;count++&amp;quot;&amp;gt;Add +&amp;lt;/button&amp;gt;
  &amp;lt;button @click=&amp;quot;count--&amp;quot;&amp;gt;Subtract -&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the &lt;code&gt;x-data&lt;/code&gt; attribute to an HTML tag to create an Alpine component anywhere. In this example, we’re initializing our data object with a single variable, &lt;code&gt;count&lt;/code&gt;, set to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, I’ll create a paragraph element to display the count’s value. By setting its &lt;code&gt;x-text&lt;/code&gt; attribute to &lt;code&gt;count&lt;/code&gt;, I’m saying, “Make the &lt;code&gt;innerText&lt;/code&gt; of this paragraph show the current value of the &lt;code&gt;count&lt;/code&gt; variable.”&lt;/p&gt;
&lt;p&gt;Then, I’ll add two buttons—one for adding and one for subtracting. I can handle the click event with the &lt;code&gt;@click&lt;/code&gt; attribute, which will run its value as a JavaScript expression. In this case, the expression is to increment or decrement the &lt;code&gt;count&lt;/code&gt; by one.&lt;/p&gt;
&lt;p&gt;As I click the buttons, the value of &lt;code&gt;count&lt;/code&gt; is updated, and the DOM automatically refreshes itself to show the current value&lt;/p&gt;
&lt;p&gt;Here’s a demo of that component in action.&lt;/p&gt;
&lt;div class=&quot;breakout&quot;&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;VYZZeEE&quot; data-pen-title=&quot;Untitled&quot; data-user=&quot;blakewatson&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/blakewatson/pen/VYZZeEE&quot;&gt;
  Untitled&lt;/a&gt; by Blake Watson (&lt;a href=&quot;https://codepen.io/blakewatson&quot;&gt;@blakewatson&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;I imagine many readers will find this example straightforward—it’s reactive UI 101. But the upside is that it took zero setup, no build, and no npm dependencies—we didn’t even need a JavaScript file!&lt;/p&gt;
&lt;p&gt;I will review Alpine in some detail here. These points are relevant whether you’re building a home-cooked app or not. I’m looking at Alpine in that context because that’s how I use it most of the time. And because these projects are solo and small, I don’t need the tooling and type support that other libraries offer. That said, Alpine is flexible and can certainly fit different workflows.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-alpine&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#benefits-of-alpine&quot;&gt;Benefits of Alpine&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While you can totally &lt;code&gt;npm install&lt;/code&gt; Alpine and bundle it like other packages, I’ll mainly refer to the CDN version. This is where Alpine shines the brightest.&lt;/p&gt;
&lt;h3 id=&quot;easy-setup&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#easy-setup&quot;&gt;Easy setup&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Alpine is easy to install, as we saw in the example. Just include it in a &lt;code&gt;script&lt;/code&gt; tag. There’s no build step required. I recommend downloading the CDN version and hosting it yourself rather than hotlinking from the CDN. You can even check the file into your Git repo.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;inline-code&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#inline-code&quot;&gt;Inline code&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Alpine’s most defining and controversial feature is its ability to write much, if not all, of your JavaScript code inline in the HTML. It is both awesome and horrible. Check this out.&lt;/p&gt;
&lt;div class=&quot;breakout&quot;&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;qEWWNmb&quot; data-pen-title=&quot;Alpine.js: inline fetch example&quot; data-user=&quot;blakewatson&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/blakewatson/pen/qEWWNmb&quot;&gt;
  Alpine.js: inline fetch example&lt;/a&gt; by Blake Watson (&lt;a href=&quot;https://codepen.io/blakewatson&quot;&gt;@blakewatson&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;In this example, I’m displaying a link to a specific post of mine on Mastodon. When you click the &lt;em&gt;Preview post&lt;/em&gt; button, the code sends a request to the Mastodon API, fetches the data for that individual post, and displays the post’s content on the page.&lt;/p&gt;
&lt;p&gt;You can see that I can write multiple lines of JavaScript inline inside the &lt;code&gt;@click&lt;/code&gt; attribute. This is super convenient when you need to do something quick and dirty or one-off. But you have to be careful because writing your code this way can get unwieldy fast.&lt;/p&gt;
&lt;h3 id=&quot;plugins&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#plugins&quot;&gt;Plugins&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Though I haven’t used them, Alpine has some plugins that help you achieve common UI tasks. I won’t list them all here, but to give you an example, the &lt;a href=&quot;https://alpinejs.dev/plugins/mask&quot;&gt;Mask plugin&lt;/a&gt; lets you easily limit text in an input to follow a particular pattern (like a date). The &lt;a href=&quot;https://alpinejs.dev/plugins/sort&quot;&gt;Sort plugin&lt;/a&gt; lets you apply drag-and-drop sorting to any group of elements.&lt;/p&gt;
&lt;h3 id=&quot;powerful&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#powerful&quot;&gt;Powerful&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Alpine can help you achieve a lot with a little, so it’s great for building UIs quickly. For example, here’s a todo list where I use as little code as possible.&lt;/p&gt;
&lt;div class=&quot;breakout&quot;&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;MYggQLG&quot; data-pen-title=&quot;Alpine.js: todo app in 20 lines&quot; data-user=&quot;blakewatson&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/blakewatson/pen/MYggQLG&quot;&gt;
  Alpine.js: todo app in 20 lines&lt;/a&gt; by Blake Watson (&lt;a href=&quot;https://codepen.io/blakewatson&quot;&gt;@blakewatson&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;First, I define an Alpine component on the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element by adding the &lt;code&gt;x-data&lt;/code&gt; attribute. I define one variable, &lt;code&gt;tasks&lt;/code&gt;, that will represent the array of tasks.&lt;/p&gt;
&lt;p&gt;From there, the app is split into two parts: the form for adding tasks and the list for displaying them.&lt;/p&gt;
&lt;p&gt;The form needs to track whatever is in the text input, so I’ll add an &lt;code&gt;x-data&lt;/code&gt; attribute with the variable &lt;code&gt;task&lt;/code&gt; and set it to an empty string. This defines another Alpine component. Anything inside the form has access to &lt;code&gt;task&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By using the &lt;code&gt;x-model&lt;/code&gt; attribute on the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element, Alpine will automatically bind the input value to the variable, &lt;code&gt;task&lt;/code&gt;. When the form is submitted, I handle that event with the &lt;code&gt;@click&lt;/code&gt; attribute (&lt;code&gt;.prevent&lt;/code&gt; is a shortcut to call &lt;code&gt;preventDefault()&lt;/code&gt; on the event, which I need to prevent a page reload). Since I can access the input’s current value via &lt;code&gt;task&lt;/code&gt;, I’ll push that value to the &lt;code&gt;tasks&lt;/code&gt; array. Finally, I’ll set &lt;code&gt;task&lt;/code&gt; to an empty string. This clears the value of the input, thanks to &lt;code&gt;x-model&lt;/code&gt;’s two-way binding.&lt;/p&gt;
&lt;p&gt;My list of tasks will show up when at least one task exists. The list remains hidden until that time, thanks to the &lt;code&gt;x-show&lt;/code&gt; attribute. I’ll use &lt;code&gt;x-for&lt;/code&gt; to create a loop inside the list. Alpine requires &lt;code&gt;x-for&lt;/code&gt; to be added to a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag. Whatever element you include inside the template tag will be rendered for each item in the list.&lt;/p&gt;
&lt;p&gt;In this case, I’ll loop over &lt;code&gt;tasks&lt;/code&gt;, defining a variable &lt;code&gt;task&lt;/code&gt; for each one. It’s important to note that the variable &lt;code&gt;task&lt;/code&gt; here has no relation to the variable &lt;code&gt;task&lt;/code&gt; that I defined in the form. This list item isn’t within the scope of the form, so I don’t have access to the form’s &lt;code&gt;x-data&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;Back to the loop, I’ll output an &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tag for each task using &lt;code&gt;x-text&lt;/code&gt; to display the task. I’ll include a checkbox so I can mark tasks as done.&lt;/p&gt;
&lt;p&gt;That’s it! This is an admittedly barebones todo app (you can’t edit tasks or even delete them), but thanks to Alpine’s power, I was able to complete it in 20 lines.&lt;/p&gt;
&lt;h2 id=&quot;drawbacks-of-alpine&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#drawbacks-of-alpine&quot;&gt;Drawbacks of Alpine&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Alpine shines when supplementing existing HTML. That said, as you saw in my todo app example, it’s possible and quite easy to render HTML on the client side with Alpine. Conventional wisdom says the more HTML you can pre-render, the better. But when you need it, Alpine can do some heavy lifting. This is a feature but also a drawback because the more client-side HTML rendering you use, the slower your page, the lesser your SEO, and, potentially, the lesser your page’s accessibility.&lt;/p&gt;
&lt;p&gt;Despite the homepage calling it “lightweight,” I think the library is a bit chunky at 109kb. That said, its gzipped size is about 22kb, as best I can tell. In this age of massive JavaScript bundles, this probably isn’t too bad. Still, it’s something to consider. You might not want to pull in Alpine if you have an isolated case where a few lines of vanilla JavaScript would do the trick.&lt;/p&gt;
&lt;p&gt;Finally, despite Alpine’s inline JavaScript capability being a feature, it can also be a drawback. The more JavaScript you stuff into your HTML code, the more unreadable it becomes. It can quickly grow unwieldy. And you’ll most likely be missing out on editor support for JavaScript—the kind you would expect inside a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag or standalone JavaScript file. And not only that. If you’re in an environment that has a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP&quot;&gt;&lt;em&gt;content security policy&lt;/em&gt;&lt;/a&gt; disallowing &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe-eval&quot;&gt;unsafe-eval&lt;/a&gt;, you can’t use the inline syntax at all. Fortunately, Alpine has an answer to both of these scenarios—a &lt;a href=&quot;https://alpinejs.dev/advanced/csp&quot;&gt;CSP-friendly build&lt;/a&gt; that doesn’t rely on unsafe-eval and &lt;a href=&quot;https://alpinejs.dev/globals/alpine-data&quot;&gt;&lt;code&gt;Alpine.data&lt;/code&gt;&lt;/a&gt;, a way to define component behavior in JavaScript rather than inline HTML (we’ll look at this a bit later).&lt;/p&gt;
&lt;h2 id=&quot;alpine-alternatives&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#alpine-alternatives&quot;&gt;Alpine alternatives&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve heard Alpine being called “the new jQuery,” which makes sense because you can get up and running with minimal fuss, the old-school way before the days of webpack, npm, and friends. jQuery itself &lt;a href=&quot;https://youmightnotneedjquery.com/&quot;&gt;isn’t needed as much&lt;/a&gt; these days, seeing as &lt;a href=&quot;http://vanilla-js.com/&quot;&gt;vanilla JavaScript&lt;/a&gt; is more powerful than it used to be. But vanilla JavaScript is worth mentioning as an alternative.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; You might be able to accomplish your goals more easily than you thought. It’s always a good idea to consider whether you even need to pull a third-party library into your project.&lt;/p&gt;
&lt;h3 id=&quot;vue&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#vue&quot;&gt;Vue&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When it comes to reactive UI libraries, the closest alternative to Alpine is &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;. Although, it’s probably more accurate to say Alpine is an alternative to &lt;em&gt;Vue&lt;/em&gt; since Alpine is built atop &lt;a href=&quot;https://alpinejs.dev/advanced/reactivity&quot;&gt;Vue’s reactivity engine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vue has long been my preferred JavaScript framework. In my opinion, Vue’s “progressive” nature (i.e., its ability to be used incrementally in more complex ways) is grossly underrated. For example, a totally valid way to use Vue is to grab the CDN version and start using it on your page—just like I did with Alpine in the demos I’ve shown.&lt;/p&gt;
&lt;p&gt;I think Alpine has the upper hand in cases like home-cooked apps where you want to blaze through some UI quickly, whereas Vue is better if your project is larger and needs more reusable frontend components.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;react-and-friends&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#react-and-friends&quot;&gt;React and friends&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’m not a React guy, but it’s the most popular way to build reactive frontend UI. I will lump other reactive libraries in this group—Preact, Angular, Solid, Svelte, etc. These frameworks shine when they have their tooling available. I’m trying to avoid the complexity of build steps for most of my projects these days. I’m sure these libraries are great, but they’re not for me. You do you, though.&lt;/p&gt;
&lt;h3 id=&quot;reef&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#reef&quot;&gt;Reef&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://reefjs.com/&quot;&gt;Reef&lt;/a&gt; is a little reactive library from &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt;. I like it because—surprise—there’s no build step. It follows the familiar reactivity patterns of other libraries by giving you the tools needed to observe state (i.e., variables) and re-render the UI when the state changes. It’s nice, simple, and a great use of JavaScript’s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals&quot;&gt;template literals&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;lit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#lit&quot;&gt;Lit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If components are what you’re after, &lt;a href=&quot;https://lit.dev/&quot;&gt;Lit&lt;/a&gt; is a great choice. Lit is a library from Google that extends native web components with convenient features like better reactive props and the ability to pass data to components via props. It also uses JavaScript template literals and efficiently updates the DOM when your component state changes. Lit docs favor TypeScript, but they have JavaScript examples as well. You can use Lit without a build step.&lt;/p&gt;
&lt;h2 id=&quot;alpine-for-the-organized&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#alpine-for-the-organized&quot;&gt;Alpine for the organized&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As cool as it is to do so much stuff inline, looking at tons of JavaScript in my HTML makes my eyes twitch. I come from the old school where we were taught the separation of concerns. It all depends on what I’m doing, but if I have a significant amount of business logic, I like to externalize some of the JavaScript to get it out of the template.&lt;/p&gt;
&lt;p&gt;To give you an example, I will add some features to the todo list example from earlier. I’ll add the ability to edit and delete tasks and show a status message that displays a few stats about the tasks. I’ll externalize much of the JavaScript in this example using &lt;code&gt;Alpine.data&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;breakout&quot;&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;vEBBVoN&quot; data-pen-title=&quot;Alpine.js: todo app improved&quot; data-user=&quot;blakewatson&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/blakewatson/pen/vEBBVoN&quot;&gt;
  Alpine.js: todo app improved&lt;/a&gt; by Blake Watson (&lt;a href=&quot;https://codepen.io/blakewatson&quot;&gt;@blakewatson&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;In this example, I listen for the &lt;code&gt;alpine:init&lt;/code&gt; event and use &lt;code&gt;Alpine.data&lt;/code&gt; to define a component in the JavaScript. There, I store the array of tasks, the new task input field, the status message, and various methods for interacting with the list of tasks.&lt;/p&gt;
&lt;p&gt;I’ve expanded the tasks to be objects rather than strings so that I can track which ones are completed. On the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; component, I used the &lt;code&gt;x-effect&lt;/code&gt; attribute. &lt;code&gt;x-effect&lt;/code&gt; takes a JavaScript expression or a method name. In this case, I gave it a method name, &lt;code&gt;effects&lt;/code&gt;. Alpine will run the &lt;code&gt;effects&lt;/code&gt; method every time one of its dependencies changes (i.e., if one of the variables it uses changes). I’m using it to generate a status message that will update itself automagically as the task counts update.&lt;/p&gt;
&lt;p&gt;The new task input works similarly to the old one, except now a task is an object. I’m tracking whether a task is completed and whether it’s currently in edit mode. Adding a task creates a new task object and pushes it to the array of tasks. I’m also giving each task a unique ID.&lt;/p&gt;
&lt;p&gt;Once a task is added, the &lt;code&gt;ul&lt;/code&gt;’s &lt;code&gt;x-show&lt;/code&gt; attribute will become &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Truthy&quot;&gt;truthy&lt;/a&gt; and the list will appear. Like the last example, I’m using &lt;code&gt;x-for&lt;/code&gt; to loop over the tasks. I’m passing the task ID as the key. This will help Alpine track each task so that it knows which DOM elements to update when I start editing or removing tasks.&lt;/p&gt;
&lt;p&gt;I have two elements inside the list item. One displays the task, and the other edits a task (this one is initially hidden).&lt;/p&gt;
&lt;p&gt;When displaying a task, I’m hooking up the checkbox with &lt;code&gt;x-model=&amp;quot;task.completed&amp;quot;&lt;/code&gt;. When I check a task, its &lt;code&gt;completed&lt;/code&gt; value updates, which causes my &lt;code&gt;effects&lt;/code&gt; method to run again and update the &lt;code&gt;status&lt;/code&gt; message.&lt;/p&gt;
&lt;p&gt;Then, I provide two buttons, “edit” and “delete.” Clicking the delete button runs the &lt;code&gt;deleteTask&lt;/code&gt; method, passing the current task to it so it can filter it out from the list.&lt;/p&gt;
&lt;p&gt;Clicking the edit button puts the task in editing mode. That causes the task editing form to appear. The edit form has an input value bound directly to the task’s &lt;code&gt;text&lt;/code&gt; property via the &lt;code&gt;x-model&lt;/code&gt; attribute. As I type in the input, the task text is directly updated. The task is taken out of edit mode when I submit the form.&lt;/p&gt;
&lt;p&gt;And that’s that! That last example might have been a little overwhelming if you’re new to reactive UI. However, it demonstrates that Alpine can handle more complex UI elegantly if you practice discipline.&lt;/p&gt;
&lt;h2 id=&quot;use-whatever-works-for-you&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#use-whatever-works-for-you&quot;&gt;Use whatever works for you&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve enjoyed using Alpine on my home-cooked apps and felt like talking about it. But as always, you should use whatever tools help you get the job done. Shipping is the name of the game for home-cooked apps.&lt;/p&gt;
&lt;p&gt;Remember, if you’re working on public-facing websites or apps, ensure a good, accessible user experience. Alpine is great for those projects, too! I don’t want you to think it’s only suitable for personal or toy projects. It all depends on what you need. But for rapid creation without a build step, Alpine really shines.&lt;/p&gt;
&lt;p&gt;If you’ve made anything cool with Alpine, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;tell me about it in email&lt;/a&gt; or on &lt;a href=&quot;https://social.lol/@bw/113551316983885958&quot;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The actual application form doesn’t qualify as a home-cooked app as it’s designed for public use. But the site’s admin area, where Matt and I sort through applications, make notes, and update the status of applications, is very much a home-cooked thing. &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Before the days when everything was an NPM package, I managed dependencies by downloading pre-built bundles and checking them into Git. That was peak dependency management if you ask me. &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;When I say “vanilla,” I mean JavaScript without a framework. Not a framework &lt;em&gt;called&lt;/em&gt; “Vanilla JavaScript.” The site I linked to is a tongue-in-cheek way to say, “JavaScript is pretty nice on its own now.” &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Alpine doesn’t have as robust support for reusable frontend components as other frameworks. Alpine’s primary use case is supplementing backend-generated templates with interactivity. That said, Alpine is capable of reusing component logic with &lt;a href=&quot;https://alpinejs.dev/globals/alpine-data&quot;&gt;&lt;code&gt;Alpine.data&lt;/code&gt;&lt;/a&gt; and if you &lt;em&gt;really&lt;/em&gt; want to reuse markup too, you can do that by extending Alpine as demonstrated in this &lt;a href=&quot;https://codepen.io/blakewatson/pen/BabREeM&quot;&gt;CodePen where I create an &lt;code&gt;x-component&lt;/code&gt; directive&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>The making of HTML for People</title>
      <link href="https://blakewatson.com/journal/the-making-of-html-for-people/"/>
      <updated>2024-10-27T14:06:50Z</updated>
      <id>https://blakewatson.com/journal/the-making-of-html-for-people/</id>
      <content xml:lang="en" type="html">&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2024/html-hero.webp&quot; alt=&quot;Illustration of a computer desk. There is a lot of space decor. The computer monitor shows a cartoon space probe zooming past a logo that reads &#39;HTML for people,&#39; stylized as an HTML comment.&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;On Thursday, October 10, I released &lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt; into the wild. I emailed the 300-ish people who had signed up to be notified and then &lt;a href=&quot;https://social.lol/@bw/113283972108556527&quot;&gt;posted on Mastodon&lt;/a&gt;. The response blew me away. In a couple of days, my post got boosted over 2,000 times. The URL made it to the front page of Hacker News. Analytics shows tens of thousands of visits to the site.&lt;/p&gt;
&lt;p&gt;Moreover, I started getting messages, not only from tech-savvy developers who already know how to make websites but from people just getting started. I was ecstatic to see those because I feared I would write this &lt;em&gt;web book&lt;/em&gt; (as I call it), and it wouldn’t reach beyond my circle of developers.&lt;/p&gt;
&lt;p&gt;It has been a few weeks, so it’s time to formally introduce it on my blog and provide a little bit of director’s commentary.&lt;/p&gt;
&lt;h2 id=&quot;html-for-people-unaccustomed-to-coding&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#html-for-people-unaccustomed-to-coding&quot;&gt;HTML for people unaccustomed to coding&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have forgotten why the name popped into my head, but my notes show that I wrote down the idea in January. “HTML for people,” I wrote, “is an idea for a radically non-technical (as much as possible) guide for teaching regular people how to make their own websites from scratch and put them on the internet.”&lt;/p&gt;
&lt;p&gt;I introduce HTML not as a “coding language” but as a document format like Word. Then, I slowly teach about tags, structure, and semantic content (but without using words like “semantic”). Throughout the book, I guide the reader through building a personal website using HTML and &lt;a href=&quot;https://simplecss.org/&quot;&gt;Simple.css&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I intentionally avoid discussing CSS as much as possible, only really delving into it in an appendix that I call a bonus chapter. These bonus chapters go more in-depth on styling and introduce the PHP &lt;code&gt;include&lt;/code&gt; statement as a way of composing HTML.&lt;/p&gt;
&lt;p&gt;I published the book as a website and made it freely available. I licensed the code and content under &lt;a href=&quot;https://creativecommons.org/licenses/by-nc-sa/4.0/&quot;&gt;a Creative Commons license&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;motivation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#motivation&quot;&gt;Motivation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I &lt;a href=&quot;https://blakewatson.com/microblog/113267849389679928/&quot;&gt;joked on Mastodon&lt;/a&gt; that my selfish motivation was that, having &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/&quot;&gt;deleted my Facebook account in 2017&lt;/a&gt;, I now needed everyone to have a personal webpage. I was only half joking.&lt;/p&gt;
&lt;p&gt;I feel a strong sense of nostalgia when I think about my younger self learning HTML in the 2000s. It was a time of both frustration and limitless possibility. I developed an interest in making websites in high school. At the time, I was using whatever free WYSIWYG (“what you see is what you get”) editor I could get my hands on. But I quickly got fed up with being unable to implement the designs I had in my head. I knew I needed to learn how to make webpages &lt;em&gt;for real&lt;/em&gt;. Here is a screenshot of my freeware gaming site, which I converted from some free website editor to handwritten HTML.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2024/gameZone.webp&quot; alt=&quot;Screenshot of a plain looking website. Logo reads &#39;KBG&#39;s gameZone&#39; and the page is titled &#39;What&#39;s new?&#39; The single update there is dated April 20, 2005.&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;On the one hand, it was difficult because I was learning about something completely foreign—I had never done any coding or programming. As I was learning, my design abilities were extremely limited. But at the same time, I unlocked a newfound joy in creating something clean and fresh. My mind was blown by the realization that websites were just text files on a computer. Once I realized that, I couldn’t get enough of the make-a-change-and-hit-refresh positive feedback loop.&lt;/p&gt;
&lt;p&gt;My websites were mine. I had not joined any social networks when I was first learning HTML. I was never really interested in MySpace,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; and Facebook had yet to make it to my university (remember when it was universities only?). I knew about blogging, but now that I could write HTML directly, even a blog on Blogger felt somehow less &lt;em&gt;mine&lt;/em&gt;. It’s difficult to overstate how proud I was to publish on the internet, even if the content was silly or inconsequential.&lt;/p&gt;
&lt;p&gt;This mentality of ownership has aged better than I could have imagined. In a world where most people publish on the internet inside walled gardens that mine their inhabitants for profit, the humble personal website becomes even rarer a gem. I wanted to tap into that nostalgia of my early years. I wanted to expose more people to the fundamental, direct way of publishing on the web. I wanted to show that anyone could do it—not just professional developers.&lt;/p&gt;
&lt;h2 id=&quot;from-zero-to-internet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#from-zero-to-internet&quot;&gt;From zero to internet&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I was &lt;a href=&quot;https://social.lol/@bw/111903738658430162&quot;&gt;riffing with Sara on Mastodon&lt;/a&gt; when I first posted the phrase “HTML for people.” I wanted a practical guide to putting a page on the web in its simplest form. What is the fastest way to go from nothing to having a page on the internet that you created yourself?&lt;/p&gt;
&lt;p&gt;I was deeply inspired by this old CSS-Tricks post where Chris Coyier gives a straightforward, practical answer to &lt;a href=&quot;https://css-tricks.com/get-started-web-design/&quot;&gt;how to get started in web design&lt;/a&gt;. If you follow his steps, you end up with a webpage on the internet. You don’t get drowned in theory or concepts. I wanted that directness but for pure HTML. It wasn’t so much how to get started in web design as a profession, but thinking of HTML as a viable way for anyone with a passing interest to make a website.&lt;/p&gt;
&lt;p&gt;I wanted to approach HTML from the personal rather than the technical side, and I wanted it to be immediately valuable. That’s why, in the very first chapter, there isn’t a single HTML tag! We just write some text in an HTML file and publish it. It goes from file-on-your-computer to live webpage in as few steps as possible.&lt;/p&gt;
&lt;p&gt;Only after publishing the first plain webpage do I discuss adding HTML tags. But after making a few basic pages, I wanted to introduce styling &lt;em&gt;without&lt;/em&gt; teaching CSS.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; Fortunately, Simple.css exists. In fact, there are many &lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#what-are-classless-css-themes%3F&quot;&gt;classless frameworks&lt;/a&gt; out there, and I’ve been fascinated by them for quite some time.&lt;/p&gt;
&lt;p&gt;The book could be renamed &lt;em&gt;How to Build a Website with Simple.css&lt;/em&gt; and would still be accurate. That’s really what this book became. I’m grateful to &lt;a href=&quot;https://kevquirk.com/&quot;&gt;Kev Quirk&lt;/a&gt; and contributors for the Simple.css project. I believe it was the perfect framework for this scenario because it makes writing HTML fun.&lt;/p&gt;
&lt;h2 id=&quot;generating-hype&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#generating-hype&quot;&gt;Generating hype&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I usually don’t publicize things I am working on for better or worse (mostly for worse). I have been a “build it and they will come” kind of developer for years. But for this project, I just decided to throw up a landing page &lt;a href=&quot;https://neatnik.net/&quot;&gt;Adam Newbold&lt;/a&gt;-style with a title and description. I added an email signup, too. I was so sure that the interest would be minimal that I wrote a short PHP script to save the emails to a text file rather than use some kind of email list service. I figured I would just email each person individually.&lt;/p&gt;
&lt;p&gt;I posted about the idea on Mastodon and threw the landing page out there. To my surprise, more than a few people seemed interested. The number of subscribers crept up throughout the summer as I worked. Nearly 300 people had signed up to be notified of the book’s release.&lt;/p&gt;
&lt;p&gt;I find it scary to promise something I’m making. I don’t like the pressure. What if I fail to deliver? What if I decide I hate the project and don’t want to release it after all? What if everyone finds out I’m an &lt;em&gt;imposter&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;But it wasn’t so scary after all. People liked the idea. I found the early feedback motivating, and it helped me push through the…&lt;/p&gt;
&lt;h2 id=&quot;gruntwork&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#gruntwork&quot;&gt;Gruntwork&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I had the idea near the beginning of the year, but it was April or so before I started in earnest. The tricky bit was building the same site I was teaching &lt;em&gt;how&lt;/em&gt; to build and getting screenshots along the way. I tried keeping a Git repo with branches at each stage, but it got out of hand after a point.&lt;/p&gt;
&lt;p&gt;Along with that was the writing. I’m a slow typer because I mostly &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;use an onscreen keyboard&lt;/a&gt;. I spent just about every weekend during the summer writing.&lt;/p&gt;
&lt;p&gt;In September, I picked up a Grammarly subscription and proofread every chapter. This was eye-opening. I never realized how much I leaned on certain words or phrases as a crutch. Grammarly has some annoyances,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; but it &lt;em&gt;did&lt;/em&gt; improve my writing.&lt;/p&gt;
&lt;p&gt;After proofreading, I began processing the 70+ images I used in the book—most of them screenshots. I knew I was going to need to supply alt-text for these images, but I also knew that it would take me ages to type them out by hand (screenshots, in particular, are challenging to write alt-text for because I need to describe the same nuanced information I’m conveying to sighted readers—that is, how changes to the code result in changes to the rendered webpage).&lt;/p&gt;
&lt;p&gt;I used an AI tool that could look at an image and generate alt-text. It worked okay, and it got 80% of the typing done for me. I read and edited each one as necessary to avoid blindly throwing AI garbage into my content.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Finally, I scaled, crushed, and converted the hi-res PNG screenshots into smaller WebP images. This was my first time actively using WebP, and I was shocked at how small the file sizes were. I used the handy &lt;a href=&quot;https://www.realmacsoftware.com/squash/&quot;&gt;Squash&lt;/a&gt; app (also available on &lt;a href=&quot;https://go.setapp.com/invite/4e40affd-e4b9-49b7-ac73-d79e284dcf15&quot;&gt;Setapp&lt;/a&gt;—affiliate link) to process the images in batches.&lt;/p&gt;
&lt;p&gt;After proofing and processing images, I decided to “splurge” by commissioning some artwork. While I originally planned &lt;em&gt;not&lt;/em&gt; to spend much money on this project, I felt that some friendly artwork would go a long way toward softening the blow for beginners who might feel intimidated.&lt;/p&gt;
&lt;p&gt;I had previously been a customer of &lt;a href=&quot;https://www.andycarolan.com/&quot;&gt;Andy Carolan&lt;/a&gt;, known in the fediverse for his &lt;a href=&quot;https://ko-fi.com/andycarolan/commissions&quot;&gt;avatar commissions&lt;/a&gt;. But he also has an extensive portfolio of quality work. I commissioned the homepage illustration, the development of a mascot, and supporting assets like the open graph preview image.&lt;/p&gt;
&lt;p&gt;Even as I was procuring art, I failed to realize just how vital a good open graph preview image is. There’s a reason many YouTubers put so much effort into making thumbnails—they work. I attribute the book’s launch-day success primarily to the quality of the preview thumbnail. It enticed people into clicking. Yes, I had to back it up with content people enjoyed, but the thumbnail brought people through the door.&lt;/p&gt;
&lt;h2 id=&quot;building-the-site&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#building-the-site&quot;&gt;Building the site&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For me, this was the fun part. I revel in sweating the details of typography and page design. I built the site using &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, which has become my go-to for static websites. I chose typefaces from the excellent &lt;a href=&quot;https://mbtype.com/&quot;&gt;MB Type&lt;/a&gt;. I tweaked the typography relentlessly, even changing the heading font at the last minute before launching!&lt;/p&gt;
&lt;p&gt;I have come to loathe frontend build steps, so other than Eleventy, I didn’t use any bundler for assets. I used vanilla CSS and, in a few spots, vanilla JavaScript. What a breath of fresh air. Look, I’m not saying bundlers and tooling don’t have their place—sometimes they’re handy—but I believe they are vastly overused in modern web development. I have a lot of opinions about the maintainability, sustainability, and ergonomics of frontend tooling, but that’s a blog post for another day.&lt;/p&gt;
&lt;p&gt;After finalizing the site build (and adding some interactive Easter eggs to the artwork), I did one final &lt;em&gt;manual&lt;/em&gt; proofreading. On the morning of October 10, I hit the launch button and posted the link on Mastodon.&lt;/p&gt;
&lt;h2 id=&quot;launch-day-shenanigans&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#launch-day-shenanigans&quot;&gt;Launch-day shenanigans&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I initially deployed the site to Cloudflare Pages, which I’ve found to be the dead simplest way to deploy an Eleventy site from a Git repo. I set up the DNS, and everything seemed to work. Almost immediately, I started receiving reports that some of the chapters, when navigated to via the main menu, were downloading a file rather than displaying a webpage. &lt;em&gt;Wha?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I frantically re-deployed the site to my longtime, trusty &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;shared host&lt;/a&gt;, and it seemed to work normally. After screwing with the DNS, including a brief period where I caused an infinite redirect loop, I successfully pointed the domain back at my shared host with Cloudflare features disabled. Fortunately, static sites are resilient, and that setup got me through the launch-day traffic.&lt;/p&gt;
&lt;p&gt;I blamed Cloudflare at first, but—shocker—&lt;a href=&quot;https://www.youtube.com/watch?v=b1kbLwvqugk&quot;&gt;I’m the problem; it’s me&lt;/a&gt;. I misconfigured some of my Eleventy templates, causing them to output files without file extensions. Cloudflare, understandably, didn’t know what to do with those files. I was lucky that my shared host decided to serve them as HTML. Anyway, I’ve since fixed my configuration, and now I’ve moved everything back to Cloudflare Pages—I think that’s better for the international readers who might experience latency from my shared host.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;feedback%2C-discussion%2C-and-the-future&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#feedback%2C-discussion%2C-and-the-future&quot;&gt;Feedback, discussion, and the future&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I enjoyed reading the discussions happening at various places online, in particular, &lt;a href=&quot;https://www.metafilter.com/205847/HTML-For-People&quot;&gt;MetaFilter&lt;/a&gt; and &lt;a href=&quot;https://news.ycombinator.com/item?id=41801334&quot;&gt;Hacker News&lt;/a&gt;. And, of course, &lt;a href=&quot;https://social.lol/@bw/113283972108556527&quot;&gt;Mastodon&lt;/a&gt;. I’m grateful for all the feedback, suggestions, and corrections. A few people filed &lt;a href=&quot;https://github.com/blakewatson/htmlforpeople/issues&quot;&gt;issues on GitHub&lt;/a&gt; and even submitted PRs!&lt;/p&gt;
&lt;h3 id=&quot;internationalization&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#internationalization&quot;&gt;Internationalization&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve had many requests for translated versions of the book. I’m new at this and not sure how to proceed. I would love to have translated versions and am happy to host them. I need to update the repo’s readme with something about contributing translations, but in the meantime, if you are interested in contributing translations, please &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;email me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m thinking a translation could go into a subfolder, for example, &lt;code&gt;/es/&lt;/code&gt;. We could use the same images, or if someone wants to try to get language-specific screenshots, I’d be good with that as well. It’s a lot of work, though! I would be willing to list contributors on the translated pages and allow donation links.&lt;/p&gt;
&lt;h3 id=&quot;downloadable-pdf&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#downloadable-pdf&quot;&gt;Downloadable PDF&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;People also asked for a downloadable version. I put up a quick &lt;a href=&quot;https://htmlforpeople.com/printable/&quot;&gt;everything-on-one-page printable version&lt;/a&gt;, but I’d love to offer a nice PDF version and possibly an ePub version.&lt;/p&gt;
&lt;p&gt;It would take some work, and if I do it, it will probably be for sale on Gumroad or something.&lt;/p&gt;
&lt;h3 id=&quot;video-course&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#video-course&quot;&gt;Video course&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I nearly decided to tack on a video course at the last minute. My coworkers will tell you I tend to sabotage myself with scope creep.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fn6&quot; id=&quot;fnref6&quot;&gt;[6]&lt;/a&gt;&lt;/sup&gt; Fortunately, I talked myself out of delaying the web book.&lt;/p&gt;
&lt;p&gt;That said, I’m still considering a video series. If that sounds like something you’d be interested in, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;let me know&lt;/a&gt;. I do have difficulty typing, and I’m self-conscious about it when people are watching (because it’s slow, and I don’t want to bore people), so I’m not sure about the logistics of it. If I end up doing this, I’m leaning towards it being free on YouTube.&lt;/p&gt;
&lt;h3 id=&quot;will-you-write-more-for-people-books%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#will-you-write-more-for-people-books%3F&quot;&gt;Will you write more &lt;em&gt;For People&lt;/em&gt; books?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Maybe! I have a special, nostalgic place in my heart for JavaScript (not the complex FAANG kind, but the homemade, fun kind). But it’s not as easily approachable as HTML. I’m not sure I have much to offer beyond the many, &lt;em&gt;many&lt;/em&gt; JavaScript resources that are out there already. I &lt;em&gt;did&lt;/em&gt; &lt;a href=&quot;https://javascriptforpeople.com/&quot;&gt;buy the domain&lt;/a&gt;, though, because obviously I did.&lt;/p&gt;
&lt;p&gt;But keep your eyes on a few that are coming from some smart peeps I know!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cssforpeople.com/&quot;&gt;CSS for People&lt;/a&gt; by &lt;a href=&quot;https://anniegreens.lol/&quot;&gt;Annie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://phpforpeople.com/&quot;&gt;PHP for People&lt;/a&gt; by &lt;a href=&quot;https://neatnik.net/&quot;&gt;Neatnik&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;While I never joined MySpace, I appreciate what it did for HTML and CSS. MySpace didn’t hide away the fabric of the web from its members. It embraced experimentation and expression rather than forcing everyone into the same cookie-cutter profile. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I think CSS is great, and I have a bonus chapter at the end of the book that gives readers a taste. But CSS has a learning curve that’s much steeper than HTML’s. I didn’t want to bog people down. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It will sometimes offer these “beta” suggestions that seem to be using an LLM behind the scenes. But even if I accept one of those suggestions, the “normal” Grammarly tools will find problems with the result. I was better off ignoring those. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Just to be clear, the alt-text for images was the only prose written by AI. The rest of the book was written by me. I also used AI to generate some of the longform placeholder content for the demo sites—three fake blog posts and one contrived page about the planets of the solar system. This saved from needing to type all the fake content from scratch. As with the alt-text, I read over them and modified as needed. The rest of the demo content was made by me. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I know a bunch of &lt;a href=&quot;https://bunny.net/&quot;&gt;Bunny&lt;/a&gt; fans and it’s on my to-do list to check them out. Do they do static website hosting? Do they have anything similar to Cloudflare Pages? &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This whole thing was originally going to be like four posts on my blog. Scope creep is how it became a 10 chapter web book with an appendix in the first place. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-html-for-people/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Where I’m at with notetaking apps</title>
      <link href="https://blakewatson.com/journal/where-im-at-with-notetaking-apps/"/>
      <updated>2024-09-30T17:45:09Z</updated>
      <id>https://blakewatson.com/journal/where-im-at-with-notetaking-apps/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I switch notetaking apps constantly. It’s a problem I’ve had for a long time now. Unfortunately, I’ve probably spent more time hopping around notes apps than taking good notes. I’ve written about some of those times. There was that &lt;a href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/&quot;&gt;time I got into rich text&lt;/a&gt;, and the &lt;a href=&quot;https://blakewatson.com/journal/why-i-chose-simplenote-over-standard-notes-and-nvultra/&quot;&gt;time I picked Simplenote&lt;/a&gt; out of several options at the time.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; Here’s a quick list of notetaking apps I’ve used (the ones I remember anyway).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Evernote&lt;/li&gt;
&lt;li&gt;Notational Velocity (the OG)&lt;/li&gt;
&lt;li&gt;nvALT&lt;/li&gt;
&lt;li&gt;Apple Notes&lt;/li&gt;
&lt;li&gt;Simplenote&lt;/li&gt;
&lt;li&gt;iA Writer&lt;/li&gt;
&lt;li&gt;Vesper (RIP)&lt;/li&gt;
&lt;li&gt;Craft&lt;/li&gt;
&lt;li&gt;Bear&lt;/li&gt;
&lt;li&gt;Obsidian&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m trying to stop app-hopping. But I gotta be real with myself—sometimes I like using something different. It depends on the task or just my impulsive whims.&lt;/p&gt;
&lt;p&gt;So, I’ve devised a plan to give me the best of both worlds—the ability to use different apps with zero time spent migrating notes. Here’s the trick—&lt;strong&gt;I’m committing to storing my notes as a folder of files.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The folder of files pattern is nice and portable. It’s robust and future-proof.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; I can use Obsidian, The Archive, and iA Writer—three apps I adore for different reasons. All of them can act on a folder of files. Switching between these three apps is zero-friction. They all support hashtags, which I’ve used to categorize my notes for over a decade. All of them support linking notes with the double-bracket syntax (&lt;code&gt;[[Like this]]&lt;/code&gt;). It’s great. What a time to be alive!&lt;/p&gt;
&lt;p&gt;But seriously, I need to stick with it this time because migrating notes is a pain, and I never want to do it again. At a surface level, you’d think it would be simple enough to export and import markdown. However, slight differences among tools have introduced annoying artifacts into my notes (some old notes have duplicated h1s now, for example). The last time I migrated, I wrote a script to clean things up. I’m not looking to repeat that experience.&lt;/p&gt;
&lt;h2 id=&quot;folder-of-files%3A-the-benefits&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#folder-of-files%3A-the-benefits&quot;&gt;Folder of files: the benefits&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A significant benefit of using a folder of plain text files is its compatibility with multiple applications. A folder of files will always be readable. I’ll always have numerous options for reading and editing these files, and, as I’ve mentioned, the choices are not mutually exclusive. Any app that can read a folder of files can join or leave my rotation of apps as I see fit.&lt;/p&gt;
&lt;p&gt;And when I mention compatibility with multiple applications—it’s much more than that. In addition to notetaking apps, I can interact with my files via command line tools and scripts (I’ve already done this once, as I mentioned when I needed to clean up some of my notes after exporting from a cloud service). That opens up some pretty powerful options. Not everyone will care about this level of access to their notes. But as a programmer, I appreciate it.&lt;/p&gt;
&lt;p&gt;Backing up my notes is straightforward because, hey, it’s just a folder of files. Other apps, particularly those that use a SaaS model that stores all your notes in the cloud, are not as straightforward to back up. Sure, you can rely on the service provider to have backups—and they probably do—but you won’t get the warm and fuzzies from being able to create and retrieve backups yourself. If something happens to that service—say it gets acquired by EvilCorp—you may be given the chance to get your data out, but what that looks like will vary. At that point, you are really at the service provider’s mercy.&lt;/p&gt;
&lt;p&gt;Another benefit of the folder-of-files method of note storage is that your notes are locally available. Backing up your notes or syncing them is possible, but you aren’t reliant on a persistent connection to work on them. This has nice performance benefits. It may be a moot point, as most services will keep notes cached locally and usually support offline working. But it’s worth mentioning so we don’t take it for granted.&lt;/p&gt;
&lt;h2 id=&quot;folder-of-files%3A-the-drawbacks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#folder-of-files%3A-the-drawbacks&quot;&gt;Folder of files: the drawbacks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are few drawbacks to the folder-of-files method when it comes to notes. However, the ones I can think of fall into two categories: syncing and proprietary features.&lt;/p&gt;
&lt;p&gt;Suppose you require syncing your notes between multiple devices. In that case, this immediately becomes the first obstacle you will face with the folder of files method. Since you aren’t using a cloud service specifically for notes, you’ll need to sync your data another way. That could be a generic cloud drive like iCloud, Google Drive, Dropbox, etc. It could be a private cloud like ownCloud or a local syncing mechanism like Syncthing. This is a manageable problem, but you will have to do it yourself rather than getting it for free with a SaaS notes provider.&lt;/p&gt;
&lt;p&gt;The other drawback is proprietary features. Some apps do cool things you can’t do with plain markdown. For example, apps that use a block editor pattern or offer database-like storage and querying (I’m thinking about Notion and Anytype). These kinds of features require more complex data models, and understandably, they may use a bespoke data storage format—one that you don’t have direct access to in many cases.&lt;/p&gt;
&lt;p&gt;When it comes to fancy features, Obsidian plugins can fill the gap quite nicely. I don’t have many complex needs, so I haven’t used popular Obsidian plugins like &lt;a href=&quot;https://blacksmithgu.github.io/obsidian-dataview/&quot;&gt;Dataview&lt;/a&gt;. But if the hype is to be believed, you can do anything in Obsidian if you install enough plugins.&lt;/p&gt;
&lt;h2 id=&quot;my-three-favorite-folder-of-files-apps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#my-three-favorite-folder-of-files-apps&quot;&gt;My three favorite folder-of-files apps&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;ia-writer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#ia-writer&quot;&gt;iA Writer&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2024/ia-writer-window.png&quot; alt=&quot;A screenshot of a window displaying a minimalistic text editor with a split layout. The left pane shows a list of dated entries, while the right pane discusses &amp;quot;My three favorite folder-as-files apps,&amp;quot; which is this same article.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When I first purchased &lt;a href=&quot;https://ia.net/writer&quot;&gt;this app&lt;/a&gt;, it was only for editing a single file. However, as the years passed and the app became popular, the developers built a library into the sidebar. Personally, I didn’t think it was that great at first, but I shouldn’t have slept on iA because they ended up making a robust library system for managing your notes.&lt;/p&gt;
&lt;p&gt;This isn’t my favorite app for consuming notes, but when I need to do some honest-to-goodness, rubber-meets-the-road writing, iA Writer is my go-to.&lt;/p&gt;
&lt;h3 id=&quot;obsidian&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#obsidian&quot;&gt;Obsidian&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2024/obsidian-window.png&quot; alt=&quot;A screenshot of the Obsidian app window with a note titled &amp;quot;Default apps, 2023.&amp;quot; The note categorizes various apps under headings like Mail Client, Web Browser, Note-taking, To-do, Phone Management, Photos, Cloud Storage, RSS Reader, Bookmark Manager, and more.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I am a newcomer to &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt;. I’ve known about it for a while but couldn’t use it because the &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;onscreen keyboard&lt;/a&gt; I use didn’t work well with Electron-based apps.&lt;/p&gt;
&lt;p&gt;However, Apple has fixed those problems.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; I’ve used it for a few months now without issues.&lt;/p&gt;
&lt;p&gt;I love how customizable it is. In particular, I have opinions on what makes good typography, so I appreciate the ability to customize that deeply in Obsidian.&lt;/p&gt;
&lt;p&gt;Obsidian is my favorite app when I need to have back-and-forth interactions with my notes—reading something, write something down, cross-reference with another thing, etc. Obsidian is great for that because it makes markdown look great, and has many ways to reference your notes.&lt;/p&gt;
&lt;p&gt;This app has just about everything you need, plus more when it comes to a folder of markdown files.&lt;/p&gt;
&lt;h3 id=&quot;the-archive&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#the-archive&quot;&gt;The Archive&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2024/the-archive-window.png&quot; alt=&quot;Screenshot of The Archive app window displaying a list titled &amp;quot;100 ways to make a story idea.&amp;quot; The interface features a sidebar on the left with file names, while the main pane on the right lists various ideas. Some listed items include: &amp;quot;Steal the plot of another story,&amp;quot; and &amp;quot;Adopt a plot on the NaNo forums.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In my mind, &lt;a href=&quot;https://zettelkasten.de/the-archive/&quot;&gt;The Archive&lt;/a&gt; is the spiritual successor to the Notational Velocity and nvALT apps. It doesn’t pack as many features as nvUltra, but what it does, it does very well. Sometimes, I like to use it when I want something small and fast. When I just want to get a thought down. There’s no reason I couldn’t do that with iA Writer or Obsidian. It’s just the way the app feels to me. Sometimes I prefer it.&lt;/p&gt;
&lt;p&gt;As with the other two apps, it’s great at handling a folder of files and supports the things I need—tags and links between notes. I will also say that the forums are pretty interesting if you are into Zettelkasten or similar methodologies.&lt;/p&gt;
&lt;h2 id=&quot;the-notes-app-to-end-all-notes-apps%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#the-notes-app-to-end-all-notes-apps%3F&quot;&gt;The notes app to end all notes apps?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I told myself never again to write about what notetaking apps I use. I swap apps so often that it feels silly to write confidently about any of them.&lt;/p&gt;
&lt;p&gt;I’m pretty happy with my current setup, but I always keep an eye on what’s out there.&lt;/p&gt;
&lt;p&gt;Would love to hear what your favorite apps are. Let me know on Mastodon.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I previously had hidden this review because I felt it was unfair to nvUltra, which was in beta then. Well, nvUltra is &lt;em&gt;still&lt;/em&gt; in beta, so I’m opening it back up for posterity. &lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;As much as I am intrigued by things like Notion and, more recently, Anytype, I don’t feel comfortable getting invested in an app with a less compatible storage format than plain text. Databases are cool, and I use them in some of my &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;home-cooked apps&lt;/a&gt;. But they are in well-supported formats like SQLite, which I imagine will be readable forever. &lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;My biggest gripe was that word prediction would fall after about one sentence. I’m pretty sure it had something to do with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable&quot;&gt;contenteditable&lt;/a&gt;, which a bunch of these browser-based editors use. &lt;a href=&quot;https://blakewatson.com/journal/where-im-at-with-notetaking-apps/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>SMA Chat Discord server and other communities</title>
      <link href="https://blakewatson.com/journal/sma-chat-discord-server/"/>
      <updated>2024-08-05T21:28:45Z</updated>
      <id>https://blakewatson.com/journal/sma-chat-discord-server/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Spinal muscular atrophy is pretty rare. There aren’t many of us out there relative to other conditions. I always enjoy connecting with people that have SMA, so I thought it would be nice to list out a few of the communities that are available.&lt;/p&gt;
&lt;p&gt;I imagine that the biggest one is the Living with MD group on Facebook. I’m no longer in this group because I &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/&quot;&gt;deleted my Facebook account&lt;/a&gt; in 2017. Last I was in there it was invite only. But I know there were a ton of people with SMA there. This group is probably the only thing I miss from my Facebook days. But even then, it wasn’t an SMA &lt;em&gt;only&lt;/em&gt; community.&lt;/p&gt;
&lt;h2 id=&quot;sma-chat-on-discord&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-chat-discord-server/#sma-chat-on-discord&quot;&gt;SMA Chat on Discord&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m a moderator on the &lt;a href=&quot;https://discord.gg/KqadTr6rns&quot;&gt;SMA Chat&lt;/a&gt; server on Discord. The server is open to people with SMA as well as parents of children with SMA. We have channels for topical stuff like health and wellness, jobs and careers, assistive tech, dating and relationships, etc.&lt;/p&gt;
&lt;p&gt;At one point, we hosted a video meetup, just for getting to know each other. This is something I would like to do again in the future. I enjoy hanging out with people with SMA.&lt;/p&gt;
&lt;p&gt;I’m one of the handful of &lt;a href=&quot;https://www.urbandictionary.com/define.php?term=An+Old&quot;&gt;olds&lt;/a&gt; on the server, but a cool thing I see happen often is young adults with SMA coming to the server, sometimes in desperation to vent or get advice about struggles that are going on in their lives, only to find that there are people with SMA around their age going through similar things. It creates a bond between people that is different from the ones we form with non-disabled people (not better, just different).&lt;/p&gt;
&lt;p&gt;So if you have SMA and you just need to talk to people who get you, the SMA Chat server is a great place.&lt;/p&gt;
&lt;p&gt;It’s a quiet server (which is good in some ways) but would love to see many more people there, which is the motivation behind this post.&lt;/p&gt;
&lt;h2 id=&quot;r%2Fspinalmuscularatrophy-on-reddit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-chat-discord-server/#r%2Fspinalmuscularatrophy-on-reddit&quot;&gt;r/spinalmuscularatrophy on Reddit&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay, SMA Chat is technically the Discord server for the &lt;a href=&quot;https://www.reddit.com/r/spinalmuscularatrophy/&quot;&gt;SMA subreddit&lt;/a&gt;. I much prefer Discord to Reddit so I don’t participate much in this community. If you are interested, you should definitely check it out. If you have SMA, just join the Discord server already. :-)&lt;/p&gt;
&lt;h2 id=&quot;sma-news-today-forums&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-chat-discord-server/#sma-news-today-forums&quot;&gt;SMA News Today forums&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you aren’t familiar with it, &lt;a href=&quot;https://smanewstoday.com/&quot;&gt;SMA News Today&lt;/a&gt; is a site that publishes a ton of articles about SMA. My favorite thing about it is that there are &lt;a href=&quot;https://smanewstoday.com/category/columns/&quot;&gt;&lt;em&gt;multiple columnists with SMA&lt;/em&gt;&lt;/a&gt;. Check them out!&lt;/p&gt;
&lt;p&gt;They also have &lt;a href=&quot;https://smanewstoday.com/forums&quot;&gt;forums&lt;/a&gt;. This is another good place to meet others with SMA. There are a lot of topical discussions, especially around living with SMA as an adult. It’s not super active, but there is regular ongoing talk.&lt;/p&gt;
&lt;h2 id=&quot;spinalmuscularatrophy.net&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-chat-discord-server/#spinalmuscularatrophy.net&quot;&gt;&lt;a href=&quot;http://spinalmuscularatrophy.net/&quot;&gt;SpinalMuscularAtrophy.net&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I just found this community a few days after originally publishing this article. Similar to SMA News Today, &lt;a href=&quot;https://spinalmuscularatrophy.net/&quot;&gt;SpinalMuscularAtrophy.net&lt;/a&gt; has articles about SMA with many of them written by people who have SMA. They also have &lt;a href=&quot;https://spinalmuscularatrophy.net/forums&quot;&gt;forums&lt;/a&gt;, which I just joined.&lt;/p&gt;
&lt;h2 id=&quot;i-wish-there-were-more&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-chat-discord-server/#i-wish-there-were-more&quot;&gt;I wish there were more&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are the ones that I know of. If you know any that I didn’t mention please &lt;a href=&quot;https://blakewatson.com/about/#contact-me&quot;&gt;send them my way&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Monster of the Week: Game introduction and rules summary</title>
      <link href="https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/"/>
      <updated>2024-07-28T12:04:29Z</updated>
      <id>https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/</id>
      <content xml:lang="en" type="html">&lt;p&gt;The following is a modified version of a writeup I did for my players in a play-by-post game we’ve just started on Discord. I wrote it to give the players a brief summary of the game and also to help myself understand the game, as I am also learning it for the first time.&lt;/p&gt;
&lt;p&gt;When I finished it, I realized it might be useful for other folks, so I’m posting it here. It has absolutely nothing to do with the fact that I’m trying to keep up my post-every-month streak and I just realized July was passing me by.&lt;/p&gt;
&lt;p&gt;Some of it is lifted verbatim from the rules book, most of it is my own words.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you’ve never played a tabletop RPG, it’s kind of like playing pretend but with rules. It is a theater-of-the-mind style game where the game engine as it were is our collective imaginations. The players create characters to be heroes in a fictional world. One person plays as the gamemaster, or GM (Monster of the Week calls it &lt;em&gt;The Keeper&lt;/em&gt;). The GM describes the world and the scenes facing the characters and asks the characters how they react.&lt;/p&gt;
&lt;p&gt;The game plays out like a collaborative story that we write together (but you don’t have to be a writer!), with the characters driving the action and the GM describing the consequences of that action.&lt;/p&gt;
&lt;h2 id=&quot;monster-of-the-week&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#monster-of-the-week&quot;&gt;Monster of the Week&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://evilhat.com/product/monster-of-the-week/&quot;&gt;Monster of the Week&lt;/a&gt; (MotW) is modeled around action-horror media (think Buffy, Supernatural, X-Files, Stranger Things, Fringe, etc). If you’ve never seen those, don’t worry about it—I haven’t seen all of them—just imagine whatever monster-based media you’re familiar with.&lt;/p&gt;
&lt;p&gt;In MotW, the players play as monster hunters. You’re a group of badass elite monster killers. The best of the best. You use your skills to solve mysteries, find monsters, and kill them. We’ll create characters together and come up with a team concept of why you’re all together. Then we’ll play the first &lt;em&gt;mystery&lt;/em&gt; (this is what D&amp;amp;D calls an &lt;em&gt;adventure&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;How does it work? I’ll start off with a teaser to set the scene. I’ll explain the situation and tell you where you’re at. That could be as straightforward as putting you at the scene of an incident, a body, or some sort of destruction. Then you will use your various skills to investigate, figure out what caused the destruction, what killed the victim, what is terrorizing the town, etc.&lt;/p&gt;
&lt;p&gt;You’ll describe what you’re doing and how you’re doing it and I will describe how the world and its inhabitants react. Sometimes you’ll roll dice (in MotW it’s two regular d6 dice) because you’re using a specific &lt;em&gt;move&lt;/em&gt;. Unlike D&amp;amp;D we won’t be rolling dice constantly for every action. If you want to do something your character could do and no one or nothing is trying to stop you, then you’ll just do it. In MotW rolling dice happens less often, but should always result in something interesting happening.&lt;/p&gt;
&lt;p&gt;A tenet of Monster of the Week is &lt;strong&gt;to do it you have to actually do it&lt;/strong&gt;. You’re not saying “I attack the vampire.” You’re saying, “I pull out my revolver and fire three shots off. Then I fumble around my pockets looking for the silver bullet I brought for this very purpose.”&lt;/p&gt;
&lt;p&gt;You don’t need to be a great writer—I’m not—but you do have to describe what you’re doing and how (and maybe why) you’re doing it.&lt;/p&gt;
&lt;p&gt;The mystery is over when you kill the monster for good. What do I mean by, &lt;em&gt;for good&lt;/em&gt;? I mean that every monster has a weakness and, if you don’t exploit it, the monster might not really be dead!&lt;/p&gt;
&lt;h2 id=&quot;rules-summary&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#rules-summary&quot;&gt;Rules summary&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We’ll all be learning as we go and I will do my best to explain the rules when they are needed. Here are the basics, though. Make sure you grab the hunter reference sheet.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-hunter-agenda&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#the-hunter-agenda&quot;&gt;The hunter agenda&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you’re playing your hunter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Act like you’re the hero in this story (because you are).&lt;/li&gt;
&lt;li&gt;Make your own destiny.&lt;/li&gt;
&lt;li&gt;Find the damn monsters and stop them.&lt;/li&gt;
&lt;li&gt;Play your hunter like they’re a real person.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;moves&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#moves&quot;&gt;Moves&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Most of the time, you’ll be describing what your hunter says, where they go, or what they do without activating a move. That goes for everything that a normal person could do, in situations where failure would not be interesting and where there’s no particular danger. In circumstances where a normal person couldn’t do what you want to do, or the drama of the story requires it, or it’s dangerous, that’s when the moves come in and control how well you do.&lt;/p&gt;
&lt;p&gt;I won’t list them here because there’s already a good description of them on the reference sheet. There are the basic moves that every hunter has, and then your playbook will give you some moves that only &lt;em&gt;your&lt;/em&gt; hunter can do.&lt;/p&gt;
&lt;p&gt;When it’s time to do a move, you’ll roll your 2 d6 dice and add to it your…&lt;/p&gt;
&lt;h3 id=&quot;ratings&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#ratings&quot;&gt;Ratings&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are how we track what your hunters are good at. Each one will be a number &lt;code&gt;-1&lt;/code&gt; to &lt;code&gt;+3&lt;/code&gt;. You’ll add this number to the dice roll, depending on which rating your move requires.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cool&lt;/strong&gt; is how calm and collected you are. It is added to your die roll for the &lt;em&gt;act under pressure&lt;/em&gt; and &lt;em&gt;help out&lt;/em&gt; basic moves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tough&lt;/strong&gt; is how strong and mean you are in a fight. It is added to your die roll for the &lt;em&gt;kick some ass&lt;/em&gt; and &lt;em&gt;protect someone&lt;/em&gt; basic moves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Charm&lt;/strong&gt; is how pleasant and persuasive you are. It is added to your die roll for the &lt;em&gt;manipulate someone&lt;/em&gt; basic move.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sharp&lt;/strong&gt; is how observant you are. It is added to your die roll for the &lt;em&gt;investigate a mystery&lt;/em&gt; and &lt;em&gt;read a bad situation&lt;/em&gt; basic moves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weird&lt;/strong&gt; is how attuned to the supernatural you are. It is added to your die roll for the &lt;em&gt;use magic&lt;/em&gt; basic move.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These will boost (or hinder) the outcome of…&lt;/p&gt;
&lt;h3 id=&quot;dice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#dice&quot;&gt;Dice&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The dice rolls work like this.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10+ means you succeed at what your doing&lt;/li&gt;
&lt;li&gt;7-9 means you succeed but there’s a consequence&lt;/li&gt;
&lt;li&gt;6- means you fail and make things worse (but you get to mark experience!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even when you succeed it doesn’t mean nothing bad happens. For example, if you choose to &lt;strong&gt;kick some ass&lt;/strong&gt;, you will inflict harm on the enemy if you succeed, but the enemy will also inflict harm on you—it’s a fight and it’s dangerous.&lt;/p&gt;
&lt;p&gt;You’ll want to make use of your…&lt;/p&gt;
&lt;h3 id=&quot;gear&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#gear&quot;&gt;Gear&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Your playbook will give you some starting gear, like a weapon. If you need extra or specific gear, you can buy it, if it’s a commonly available thing. If it’s not, you’ll have to do something special to attain it (call in a favor, steal it, etc). Your gear, especially weapons, have…&lt;/p&gt;
&lt;h3 id=&quot;tags&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#tags&quot;&gt;Tags&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;These are descriptors of how your weapons work. Every weapon has at least a harm tag and a range tag. From the rules book:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example: Power drill (2-harm hand loud messy)&lt;/p&gt;
&lt;p&gt;“2-harm” “hand,” “loud,” and “messy” are the tags. “2-harm” is the harm tag,
“hand” is the range tag, and “loud” and “messy” are descriptive tags.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pages 126-127 of the rules book has a list of tags. But they kind of just mean what they say.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2-harm&lt;/strong&gt; is how much damage the weapon will do, &lt;strong&gt;hand&lt;/strong&gt; means it’s effective within arms’ reach, &lt;strong&gt;loud&lt;/strong&gt; means it draws attention, and &lt;strong&gt;messy&lt;/strong&gt; means it’s gonna spread a lot of blood and gore around.&lt;/p&gt;
&lt;p&gt;Speaking of weapons, they are particularly good at inflicting…&lt;/p&gt;
&lt;h3 id=&quot;harm&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#harm&quot;&gt;Harm&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can take 7 harm, then you’re dead. Rip, you. &lt;em&gt;Armor&lt;/em&gt; can help reduce harm by 1 or 2.  Injuries of 1-3 harm will clear up once you get some rest or first aid. Once your hunter has suffered 4-harm, your injuries become &lt;strong&gt;unstable&lt;/strong&gt;. That means that they will get worse unless properly treated (The Keeper will tell you when to mark off another point of harm).&lt;/p&gt;
&lt;p&gt;What counts as treatment depends on the wound, but it will usually be one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A hunter’s healing move.&lt;/li&gt;
&lt;li&gt;Time in an infirmary in someone’s haven.&lt;/li&gt;
&lt;li&gt;A visit to a doctor or emergency room.&lt;/li&gt;
&lt;li&gt;A magic spell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fortunately your hunter can avoid harm and missteps by making use of their…&lt;/p&gt;
&lt;h3 id=&quot;luck&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#luck&quot;&gt;Luck&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Need to get out of a tight spot? Mark off a luck box and you can avoid the harm you were about to take, or retroactively change a roll to 12! You only have so much, and it generally doesn’t refill, so make it count.&lt;/p&gt;
&lt;p&gt;When you run out of luck, you’re doomed, which means fate is about to kick your ass (and your hunter’s story is approaching its end).&lt;/p&gt;
&lt;p&gt;Your hunter’s story progresses by…&lt;/p&gt;
&lt;h3 id=&quot;leveling-up&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#leveling-up&quot;&gt;Leveling up&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you fail at stuff (by rolling 6-) you learn from your mistakes and receive an experience point. Once you get 5 of them, you level up and improve your hunter’s gear and or abilities. You also get experience at the end of a session (or in our play-by-post game, maybe a few days or just when the mystery ends). Level up 5 times and you unlock advanced improvements.&lt;/p&gt;
&lt;h2 id=&quot;that%E2%80%99s-the-gist-of-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#that%E2%80%99s-the-gist-of-it&quot;&gt;That’s the gist of it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay that’s my brain dump of the game as I understand it. I’m totally learning just like you. As the Keeper, my responsibility to you is to keep things dangerous and scary, make the world seem real, and play to see what happens. Let’s make a fun scary quirky action-packed story together!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;If you’re one of my players, get the one from the PDFs channel in Discord as I removed the Keeper-related stuff. Everyone else, you can grab it from the &lt;a href=&quot;https://evilhat.com/product/monster-of-the-week/&quot;&gt;official website&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/monster-of-the-week-game-introduction-and-rules-summary/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>My home-cooked app for online bookmarks</title>
      <link href="https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/"/>
      <updated>2024-06-24T01:21:00Z</updated>
      <id>https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/</id>
      <content xml:lang="en" type="html">&lt;figure&gt;
  &lt;img class=&quot;dim&quot; src=&quot;https://blakewatson.com/uploads/2024/bookmarks-home.png&quot; alt=&quot;A screenshot of the homepage of my DIY online bookmarking app. The page displays a search bar with the text &#39;font&#39; typed in and tags &#39;webdesign, css&#39; above it. Below the search bar, there are search results related to fonts, each with a title, URL, and tags. Examples include &#39;More than you ever wanted to know about font loading on the web&#39; and &#39;Web Font Specimen.&#39; To the right, there is a list of &#39;Top Tags&#39; including &#39;css (117)&#39;, &#39;webdesign (117)&#39;, &#39;framework (36)&#39;, &#39;dev (26)&#39;, and others. At the top, there is a button labeled &#39;Add Bookmark.&#39;&quot; width=&quot;1400&quot; height=&quot;1007&quot; /&gt;
  &lt;figcaption&gt;I did a bit of a design refresh&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Two years ago this month, I decided to make my own little app for keeping bookmarks. I’m a longtime customer of &lt;a href=&quot;https://pinboard.in/&quot;&gt;Pinboard&lt;/a&gt;, but I was becoming frustrated with errors in its archival functionally and, in general, it felt cumbersome to browse the way I wanted to. I decided I wanted to make something myself to fill this role.&lt;/p&gt;
&lt;p&gt;I didn’t originally plan to release the code to the public. It’s a &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;home-cooked app&lt;/a&gt; and I knew it was going to be a bit rough around the edges. But as I finished it, I figured it was good enough to offer the &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;code as-is on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve been using it ever since and over the last month or so, I’ve made some significant improvements. I think it is finally time for me to write about it.&lt;/p&gt;
&lt;p&gt;If you don’t care to read anymore about it but want to check it out, head over to the &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;blakewatson/bookmarks GitHub page&lt;/a&gt; and check out the readme. It has instructions for setting up the app.&lt;/p&gt;
&lt;p&gt;I cover the design and intention of the app in the readme, so some of this article will come straight from that.&lt;/p&gt;
&lt;h2 id=&quot;features-at-a-glance&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#features-at-a-glance&quot;&gt;Features at a glance&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Saves bookmarks — title, URL, description, and tags.&lt;/li&gt;
&lt;li&gt;You can filter your bookmarks by one or more tags.&lt;/li&gt;
&lt;li&gt;Has archival capabilities. Every bookmark is sent over to the &lt;a href=&quot;https://wayback-api.archive.org/&quot;&gt;Wayback Machine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Has basic search capability. Search within tags.&lt;/li&gt;
&lt;li&gt;Comes with a bookmarklet for quickly adding bookmarks.&lt;/li&gt;
&lt;li&gt;Also comes with an importer script that can convert a Pinboard export file into the format needed by Bookmarks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;based-on-pinboard-but-with-some-big-differences&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#based-on-pinboard-but-with-some-big-differences&quot;&gt;Based on Pinboard but with some big differences&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My app is somewhat modeled on Pinboard because despite wanting something of my own, I still think Pinboard is a good app. There are some pretty big differences, though.&lt;/p&gt;
&lt;p&gt;I don’t really care about sharing my bookmarks so that social aspect is totally missing from my app. I could see myself possibly adding a way to make public listings of bookmarks at some point, though.&lt;/p&gt;
&lt;p&gt;My app is not as robust as Pinboard. Pinboard is battle-tested and used by many. My app works for &lt;em&gt;me&lt;/em&gt;, but is missing some of the affordances that Pinboard offers for the real pack rats out there.&lt;/p&gt;
&lt;p&gt;For example, it just occurred to me that I don’t know what will happen if you try to add a tag with a really long name. I assume it will break the UI. Rip.&lt;/p&gt;
&lt;p&gt;If I remember correctly, Pinboard does some cool stuff with tag groups or parent tags or something. There is none of that here. It is a simplistic tag implementation.&lt;/p&gt;
&lt;p&gt;I have a few thousand bookmarks and the app runs fine on my admittedly high end machines. Pinboard is much more efficient at handling huge numbers of bookmarks whereas I do some inefficient things in the name of a fast frontend experience. This is something I could see myself improving over time as I accumulate more bookmarks.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#how-to-use-it&quot;&gt;How to use it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a NodeJS project so you will need to have a Node server. Other than that, there isn’t a lot of complicated architecture going on. It’s mostly just shuttling JSON back and forth between the server and the browser.&lt;/p&gt;
&lt;p&gt;I have &lt;a href=&quot;https://github.com/blakewatson/bookmarks?tab=readme-ov-file#setup&quot;&gt;setup instructions over on the GitHub page&lt;/a&gt;. I recently (yesterday) added an init script that you can run to make setup as easy as possible. If you don’t care about archiving bookmarks to the Wayback Machine, you don’t need to do any configuration beyond running &lt;code&gt;init&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The readme should cover it, so I won’t go into any further detail here. If you do happen to follow my instructions to set up the app, let me know if they were helpful and or how I can improve them.&lt;/p&gt;
&lt;h2 id=&quot;adding-bookmarks-quickly&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#adding-bookmarks-quickly&quot;&gt;Adding bookmarks quickly&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Being able to quickly add bookmarks is a must-have feature. Otherwise I would never use it and this whole endeavor would be pointless. With Pinboard, there were multiple bookmarklet and browser extension options and I knew I needed something to replace those.&lt;/p&gt;
&lt;p&gt;I decided to go with a bookmarklet. It passes info to the app via the query string. That pre-populates the create form.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2024/bookmarks-add-bookmark.png&quot; alt=&quot;Screenshot of the add-bookmark form. It is pre populated with a URL from the webcomic xkcd. The form includes fields for Title, URL, Description, and Tags. The Title field contains &#39;xkcd: Fluid Speech,&#39; the URL field contains &#39;https://xkcd.com/2942/&#39;, the Description field contains &#39;A funny comic about how people streamline the pronunciation of phrases,&#39; and the Tags field contains &#39;funny.&#39; There are two buttons at the bottom: &#39;Cancel&#39; and &#39;Save Bookmark.&#39;&quot; width=&quot;1200&quot; height=&quot;674&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The tags field will offer autocomplete suggestions that you can select using the mouse or keyboard.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2024/bookmarks-tag-autocomplete.png&quot; alt=&quot;A screenshot of the tags autocompletion menu of the app. The Tags field contains the letter &#39;f&#39;, and the dropdown menu shows five suggestions: &#39;font (81)&#39;, &#39;framework (66)&#39;, &#39;fun (62)&#39;, &#39;friends (19)&#39;, and &#39;funny (10)&#39;.&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;development-notes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#development-notes&quot;&gt;Development notes&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are probably a million different ways you could go about making something like this. As a person who enjoys the frontend more than the backend, my apps tend to have pretty simple backend architectures that are primarily trying to make data persistence as easy as possible. That’s the same for this one, with a little bit of added complexity in order to implement bookmark archival on Wayback Machine.&lt;/p&gt;
&lt;h3 id=&quot;backend&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#backend&quot;&gt;Backend&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I usually go with PHP because I have a bit more experience with it than other backend languages. But for whatever reason I chose NodeJS and Express for this one. I can’t even remember why at this point. I’m sure there was a reason. Probably.&lt;/p&gt;
&lt;p&gt;Mostly it’s a matter of saving everything to JSON. I didn’t really feel like passing searches to the backend, so I just pass the entire JSON data store to the frontend and perform searches on it there. I cache everything in &lt;code&gt;localStorage&lt;/code&gt; so that startup of the app is quick. There is a point at which this method is going to fail and I’m going to have to move some stuff to the backend. But until then, weeeeeeeeee.&lt;/p&gt;
&lt;h3 id=&quot;frontend&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#frontend&quot;&gt;Frontend&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’m using &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; for rendering the frontend app. But, notably, I didn’t want to have anything to do with a build step. So I’m just grabbing Vue (the ESM one) and using it directly via template strings. Thanks to browser support for modules, I can split every Vue component into its own file. And because there are ways to get VS Code to highlight HTML inside template strings, it’s kind of like I have single-file components! Kind of.&lt;/p&gt;
&lt;p&gt;This was my first real use of the &lt;a href=&quot;https://vuejs.org/guide/introduction.html#composition-api&quot;&gt;composition API&lt;/a&gt;. It was… &lt;em&gt;fine?&lt;/em&gt;. I’m so used to the options API, that I still organized my code that way, so I’m not sure I got the full benefit. It was still kind of neat, though.&lt;/p&gt;
&lt;p&gt;I experimented with using &lt;a href=&quot;https://jsdoc.app/&quot;&gt;JSDoc&lt;/a&gt; on this project to give myself better editor support—the kind I’m used to with TypeScript projects. I couldn’t use TS here because I was adamant about not having a build step. But JSDoc worked out pretty great. That probably deserves its own article.&lt;/p&gt;
&lt;p&gt;Over this past weekend, I updated the styling of the site. I switched over from using &lt;a href=&quot;https://purecss.io/&quot;&gt;Pure CSS&lt;/a&gt; to &lt;a href=&quot;https://jenil.github.io/chota/&quot;&gt;Chota&lt;/a&gt;. It’s a tiny framework that has just enough of the useful things you need.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;accessibility&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#accessibility&quot;&gt;Accessibility&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I still have some work to do here. When I was first building this, I didn’t even think I was going to release the code. It was just going to be my home-cooked app. As such, I fell into some lazy practices (such as using links as buttons in situations where I just wanted text without padding and such).&lt;/p&gt;
&lt;p&gt;I did make some improvements during this redesign, but I still have a good bit of work to do in this area. If you happen to use the app and run into a problem, please &lt;a href=&quot;https://github.com/blakewatson/bookmarks/issues&quot;&gt;create an issue&lt;/a&gt; and I will take a look.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Things I know about are the links-as-buttons issue I mentioned, but also things like the tag autocomplete—how it works (it or most probably doesn’t) with screen readers.&lt;/p&gt;
&lt;h2 id=&quot;still-home-cooked-at-heart&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#still-home-cooked-at-heart&quot;&gt;Still home-cooked at heart&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I decided to write about my bookmarks app and share the code. And even though I have made some recent efforts to make it better for everyone, it is still a home-cooked app at its core. And it is still designed with primarily me in mind. That means if there is a feature you want, while you are free to create an issue, I most likely won’t be incorporating it. Depending on what it is, I might be open to PRs. But really, this app will continue to grow in whatever direction my whims decide.&lt;/p&gt;
&lt;p&gt;That said, I would be really happy to know if someone else gets any use out of it. So if you do decide to use it, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;let me know&lt;/a&gt;!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m always on the market for easy CSS frameworks. I especially like the classless ones and, when I need to actually make a design, I like the simple ones that I can wrap my mind around and start using quickly without a build step. If you know of any, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;hit me up&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I realize that telling someone to create an issue if they have a problem is not a healthy long-term solution to accessibility. I just point it out because if something is actively blocking someone from using the app, I’d rather fix &lt;em&gt;that&lt;/em&gt; problem before I tackle theoretical ones. &lt;a href=&quot;https://blakewatson.com/journal/my-home-cooked-app-for-online-bookmarks/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Mimicking e-ink with macOS</title>
      <link href="https://blakewatson.com/journal/e-ink-mode/"/>
      <updated>2024-05-28T22:36:33Z</updated>
      <id>https://blakewatson.com/journal/e-ink-mode/</id>
      <content xml:lang="en" type="html">&lt;p&gt;For several years now I have been wondering how I might fit an e-ink display into my workflow. It’s not as simple as just getting one of the cool e-ink tablets that exist. For example the recently announced &lt;a href=&quot;https://daylightcomputer.com/product&quot;&gt;DC-1 from Daylight Computer&lt;/a&gt; looks amazing. Unfortunately, I do not possess the hand strength to handle a tablet. No, I’m stuck with &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/&quot;&gt;using a Mac with a single-button mouse&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I could purchase an e-ink display for use with my Mac, though there aren’t a lot of consumer-friendly choices out there that I could find. But even if I do, it’s not ideal because I can only view one display at a time (I can’t turn my head) and I don’t think I could commit to e-ink for periods long enough to justify moving monitors around. I don’t know. We’ll see.&lt;/p&gt;
&lt;p&gt;But I had a thought. I realized that with the right settings a Mac display could be made to &lt;em&gt;feel&lt;/em&gt; like an e-ink one. Obviously it is but a facsimile of one—we’re talking about two radically different display technologies after all. But the Mac has a few tricks up its sleeve.&lt;/p&gt;
&lt;h2 id=&quot;try-these-settings-to-micmic-an-e-ink-display&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/e-ink-mode/#try-these-settings-to-micmic-an-e-ink-display&quot;&gt;Try these settings to micmic an e-ink display&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Go to System Settings &amp;gt; Accessibility &amp;gt; Display.&lt;/li&gt;
&lt;li&gt;Turn on &lt;em&gt;Increase contrast&lt;/em&gt; and &lt;em&gt;Differentiate without color&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Scroll to the bottom and turn on &lt;em&gt;Color filters&lt;/em&gt;. It should already be on &lt;em&gt;Grayscale&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click the Control Center icon in the menubar and then click &lt;em&gt;Display&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Turn on True Tone if available. Turn on Night Shift.&lt;/li&gt;
&lt;li&gt;Reduce the brightness of the screen to the minimum needed to read text.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional:&lt;/strong&gt; I prefer leaving &lt;em&gt;Dark Mode&lt;/em&gt; off for this effect, but it works either way.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;it%E2%80%99s-not-e-ink%2C-but-it%E2%80%99s-something&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/e-ink-mode/#it%E2%80%99s-not-e-ink%2C-but-it%E2%80%99s-something&quot;&gt;It’s not e-ink, but it’s &lt;em&gt;something&lt;/em&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think the secret sauce to this effect is the &lt;em&gt;Increase contrast&lt;/em&gt; setting. In general, I’ve never cared for the high contrast effect (not that it’s bad, just not for me). But that’s because I was also using my display at a moderate brightness level and in full color.&lt;/p&gt;
&lt;p&gt;Something happens when you take all the color away and turn the brightness down. The high contrast style evokes the retro feeling of a Mac OS from a different time. There is a simple, even brutalist appeal. It may not be e-ink, but it definitely feels like &lt;em&gt;something&lt;/em&gt; different. Quieter. Slower.&lt;/p&gt;
&lt;p&gt;I’m writing this post in &lt;a href=&quot;https://ia.net/writer&quot;&gt;iA Writer&lt;/a&gt; and this app in particular excels in this environment. In fact, open a few apps, visit a few websites—the ones with great design will stand out even more now. Good composition and use of contrast win the day. Designs that overuse color get the rug pulled out from under them in this mode.&lt;/p&gt;
&lt;p&gt;I’m not intending to always use my computer this way&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/e-ink-mode/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; but I can imagine using this mode for reading and writing. It’s an interesting way to trick the brain into switching contexts. This is especially true for me. Being very disabled, I can’t just decide, “you know what, I think I will leave the desk and go work from the couch for a while.” This isn’t a replacement for that, necessarily, but a good option to have when I need to make a mental reset.&lt;/p&gt;
&lt;p&gt;Anyway, if you happen to try it out, let me know what you think (&lt;a href=&quot;https://social.lol/@bw&quot;&gt;@bw@social.lol&lt;/a&gt; or &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;blake@blakewatson.com&lt;/a&gt;). I’m also interested if you have alternative settings that do something similar.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I can’t use grayscale all the time because I use &lt;a href=&quot;https://www.cursorless.org/&quot;&gt;Cursorless&lt;/a&gt; for Talon and Visual Studio Code, which specifically relies on color to annotate tokens in the editor. &lt;a href=&quot;https://blakewatson.com/journal/e-ink-mode/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Rebuilding my website with Eleventy</title>
      <link href="https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/"/>
      <updated>2024-05-09T13:55:54Z</updated>
      <id>https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/</id>
      <content xml:lang="en" type="html">&lt;figure&gt;
  &lt;img id=&quot;home-dark&quot; src=&quot;https://blakewatson.com/uploads/2024/homepage-2024-dark.png&quot; alt=&quot;Screenshot of my homepage in dark mode inside of a Safari window. There are 5 journal articles listed in the widest column. A card with my avatar, a one-sentence bio, and some social links are in the sidebar. Below that are 3 microblog posts.&quot; width=&quot;1500&quot; height=&quot;1486&quot; /&gt;
  &lt;img id=&quot;home-light&quot; src=&quot;https://blakewatson.com/uploads/2024/homepage-2024-light.png&quot; alt=&quot;Screenshot of my homepage in light mode inside of a Safari window. There are 5 journal articles listed in the widest column. A card with my avatar, a one-sentence bio, and some social links are in the sidebar. Below that are 3 microblog posts.&quot; width=&quot;1500&quot; height=&quot;1486&quot; hidden=&quot;&quot; /&gt;
  &lt;figcaption&gt;Screenshot of the homepage for posterity. Try changing the color theme :-)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;script&gt;
  (function() {
    const theme = document.querySelector(&#39;html&#39;).getAttribute(&#39;data-theme&#39;);
    const lightImg = document.querySelector(&#39;#home-light&#39;);
    const darkImg = document.querySelector(&#39;#home-dark&#39;);

    setImg(theme);
    window.addEventListener(&#39;theme-change&#39;, (e) =&gt; setImg(e.detail));

    function setImg(theme) {
      if (theme === &#39;light&#39;) {
        darkImg.setAttribute(&#39;hidden&#39;, &#39;hidden&#39;);
        lightImg.removeAttribute(&#39;hidden&#39;);
        return;
      }
      lightImg.setAttribute(&#39;hidden&#39;, &#39;hidden&#39;);
      darkImg.removeAttribute(&#39;hidden&#39;);
    }
  })()
&lt;/script&gt;
&lt;p&gt;This website began life as a typical personal homepage in the mid-2000s. Having dabbled with WYSIWYG programs for a few years prior, I had finally started learning HTML and CSS. And it wasn’t long until I decided I needed my own domain name.&lt;/p&gt;
&lt;p&gt;It was a static website because most websites were. At least the personal homepages I knew about. I eventually moved on to a DIY database-driven website using PHP. Then WordPress not long after that. I used WordPress during my freelancing years until I got &lt;a href=&quot;https://madg.com/2017/04/10/behind-things-blake-watson/&quot;&gt;my first full-time job&lt;/a&gt; as an “interactive designer.” I then scrapped my freelancer site and turned it into a web developer’s blog, christening it with its first post, &lt;a href=&quot;https://blakewatson.com/journal/hard-refresh&quot;&gt;Hard refresh&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;As part of that site rebuild, I moved away from WordPress and used a &lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/&quot;&gt;static site generator called Wok&lt;/a&gt;. But the creator abandoned it and I was getting tired of using it for… &lt;em&gt;reasons&lt;/em&gt;. So, in 2019 I went &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019&quot;&gt;crawling back to WordPress&lt;/a&gt;—a move for which I was so ashamed that I labelled it an “unpopular opinion,” despite the fact that a large part of the web runs on WordPress.&lt;/p&gt;
&lt;p&gt;Well, um, &lt;a href=&quot;https://www.youtube.com/watch?v=CduA0TULnow&quot;&gt;I did it again&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;WordPress is gone. This site is static once again, generated by the amazing &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;. This is a bit of a long post so here’s a little outline if you want to jump to specific sections.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;table-of-contents&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#switching-to-static-again&quot;&gt;Switching to static again&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#speed&quot;&gt;Speed&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#ergonomics&quot;&gt;Ergonomics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#longevity&quot;&gt;Longevity&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#design&quot;&gt;Design&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#cool-uris-don%E2%80%99t-change&quot;&gt;Cool URIs don’t change&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#eleventy-buildout&quot;&gt;Eleventy buildout&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#search&quot;&gt;Search&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-form&quot;&gt;The search form&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-index&quot;&gt;The search index&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-endpoint&quot;&gt;The search endpoint&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#bringing-back-comments.-sort-of.&quot;&gt;Bringing back comments. Sort of.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#homemade-like-button&quot;&gt;Homemade like button&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#automatic-microblog-publishing&quot;&gt;Automatic microblog publishing&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#cloudflare-cdn&quot;&gt;Cloudflare CDN&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#personal-websites-for-the-win&quot;&gt;Personal websites for the win&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#appendix%3A-stuff-i-used-for-building-my-site&quot;&gt;Appendix: Stuff I used for building my site&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;h2 id=&quot;switching-to-static-again&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#switching-to-static-again&quot;&gt;Switching to static again&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I just want to take this opportunity to say that you should feel free to do whatever you want on your own website and you are in no way required to justify it to anyone. I just enjoy nerding out about the reasoning. But I’m not trying to set a precedent that you need to defend any decisions you make about your own website.&lt;/p&gt;
&lt;h3 id=&quot;speed&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#speed&quot;&gt;Speed&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Anyway, the single biggest reason for going static again is that my site was pretty slow when it was on WordPress. In particular, my &lt;a href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/&quot;&gt;web host&lt;/a&gt; is opinionated about how they set up their servers and they don’t make sacrifices to help WordPress run faster. There were things I could have done,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; but they would be working against the infrastructure.&lt;/p&gt;
&lt;p&gt;I didn’t want to switch hosts, and I certainly didn’t want to pay for specialized WordPress hosting. My server has lots of odds and ends on it and I like where it is and how it’s hosted now.&lt;/p&gt;
&lt;p&gt;But static sites are &lt;em&gt;fast&lt;/em&gt;. Instead of a bunch of running a bunch of PHP and database queries, all my server needs to do is send a file. Boom.&lt;/p&gt;
&lt;h3 id=&quot;ergonomics&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#ergonomics&quot;&gt;Ergonomics&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I was scarcely using any of WordPress’ features—I was using the classic editor instead of blocks, authoring everything in markdown, and mostly ignoring categories and tags.&lt;/p&gt;
&lt;p&gt;For a time, I did enjoy being able to easily make corrections to an article without needing a development setup. But these days I’m always with my development setup. Editing a markdown file feels right to me.&lt;/p&gt;
&lt;h3 id=&quot;longevity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#longevity&quot;&gt;Longevity&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I am a mere mortal. One day I will be gone. I would like to think that my website could outlive me. That would mean &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;someone&lt;/a&gt; else would have to keep it running. That job becomes much easier if my website is a pile of HTML files.&lt;/p&gt;
&lt;p&gt;Ok enough about the reasons.&lt;/p&gt;
&lt;h2 id=&quot;design&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#design&quot;&gt;Design&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I re-coded the website from scratch. It’s a &lt;em&gt;completely different website&lt;/em&gt;. But if I’ve done my job right, most people won’t notice. This was more a &lt;a href=&quot;https://alistapart.com/article/redesignrealign/&quot;&gt;realignment&lt;/a&gt; than a redesign. But there are a few noteworthy changes.&lt;/p&gt;
&lt;p&gt;I kept a &lt;a href=&quot;https://web.archive.org/web/20221107004654/https://blakewatson.com/&quot;&gt;super minimal homepage&lt;/a&gt; for years but I’m now experimenting with a busier design. I also rewrote my About page for the first time in years and added a sidebar with some silliness in it.&lt;/p&gt;
&lt;p&gt;This project was my first time using CSS grid extensively. It helped me make layout decisions without feeling like I was positioning things arbitrarily. Hopefully it makes things feel more cohesive.&lt;/p&gt;
&lt;p&gt;Writing more code-based tutorials is always a goal of mine (which I fail to meet often) so I wanted to make code samples extra nice this time around. Previously I used &lt;a href=&quot;https://highlightjs.org/&quot;&gt;Highlight.js&lt;/a&gt; for that. But now I’m trying &lt;a href=&quot;https://torchlight.dev/&quot;&gt;Torchlight&lt;/a&gt;, which highlights code when the site is built rather than in-browser. That’s a nice performance boost. Torchlight also results in more accurate highlighting and has annotation features.&lt;/p&gt;
&lt;p&gt;As an accessibility measure, I also made it possible to toggle highlighting off. That’s useful if readers want more contrast or don’t want to read light-on-dark code samples when the site is in light mode.&lt;/p&gt;
&lt;p&gt;I made a ton of tiny improvements. There were things that annoyed me previously—spacing around and in between elements, font-sizes in certain cases, color tweaks. Lots of things. It’s my favorite type of CSS to write. Tiny details that make things &lt;em&gt;feel&lt;/em&gt; right.&lt;/p&gt;
&lt;h2 id=&quot;cool-uris-don%E2%80%99t-change&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#cool-uris-don%E2%80%99t-change&quot;&gt;Cool URIs don’t change&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/Provider/Style/URI.html&quot;&gt;The W3C guilted me&lt;/a&gt; into making sure that all of my old WordPress permalinks worked on my new site. For journal articles that wasn’t a problem as I was using the format &lt;code&gt;/journal/post-slug&lt;/code&gt; for the permalink and that is also what I’m using on the new site. But for hard-to-explain WordPress reasons all of my individual microblog posts &lt;em&gt;also&lt;/em&gt; had the format &lt;code&gt;/journal/post-slug&lt;/code&gt;. But on the new site I wanted all individual microblog posts to live under the &lt;code&gt;/microblog&lt;/code&gt; path.&lt;/p&gt;
&lt;p&gt;To achieve this I ended up using PHP to query my WordPress database and programmatically generate a &lt;code&gt;.htaccess&lt;/code&gt; file that includes a 301 redirect for every single microblog post. After adding those and a handful of manual one-off redirects like my RSS feeds, I ended up with over 950 redirects. I have no idea if that is going to cause a problem for Apache but I guess we’ll find out.&lt;/p&gt;
&lt;h2 id=&quot;eleventy-buildout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#eleventy-buildout&quot;&gt;Eleventy buildout&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have a few sections on my site. My main blog is my Journal. That’s a folder of markdown, which is straightforward.&lt;/p&gt;
&lt;p&gt;I also have some one-off pages which are easy peasy to set up with Eleventy.&lt;/p&gt;
&lt;p&gt;On the other hand, I have a microblog that compiles posts from my Mastodon account, posts from &lt;a href=&quot;https://bw.status.lol/&quot;&gt;my Statuslog&lt;/a&gt;, and asides—untitled short posts—into one unified feed.  This took a bit of work but fortunately Eleventy has flexible features that make this kind of data wrangling possible.&lt;/p&gt;
&lt;p&gt;I’m using some Node scripts to hit the Mastodon and omg.lol APIs, then distilling that data down into a couple of JSON &lt;a href=&quot;https://www.11ty.dev/docs/data-global/&quot;&gt;data files&lt;/a&gt;. Eleventy’s ability to &lt;a href=&quot;https://www.11ty.dev/docs/pages-from-data/&quot;&gt;create pages out of any kind of data&lt;/a&gt; is a killer feature. And using its &lt;a href=&quot;https://www.11ty.dev/docs/collections/&quot;&gt;collections system&lt;/a&gt;, I’m able to put statuslogs, toots, and asides together into one collection I call my &lt;a href=&quot;https://blakewatson.com/microblog&quot;&gt;microblog&lt;/a&gt; and paginate through them.&lt;/p&gt;
&lt;h2 id=&quot;search&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#search&quot;&gt;Search&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One WordPress feature I lost was search. I had a few options for replacing it. My server still runs PHP so I considered doing some kind of &lt;a href=&quot;https://gomakethings.com/how-to-create-your-own-search-api-for-a-static-website-with-javascript-and-php/&quot;&gt;server-side search implementation&lt;/a&gt;. Another option was to use JavaScript to implement search functionality on the client-side.&lt;/p&gt;
&lt;p&gt;I ended up choosing a middle-ground approach. I discovered the little JS package &lt;a href=&quot;https://www.npmjs.com/package/minisearch&quot;&gt;MiniSearch&lt;/a&gt; via &lt;a href=&quot;https://coryd.dev/posts/2024/lightweight-search-in-eleventy/&quot;&gt;Cory’s excellent article&lt;/a&gt; about how he implemented search on his Eleventy site. I took that approach but instead of in-browser search, I’m exposing a search endpoint on a cloud function. &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-endpoint&quot;&gt;More on that in a bit&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-search-form&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-form&quot;&gt;The search form&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The search form is perfectly functional without JavaScript.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;form class=&amp;quot;search-form&amp;quot; action=&amp;quot;https://duckduckgo.com&amp;quot; method=&amp;quot;get&amp;quot;
  @submit.prevent=&amp;quot;search&amp;quot;&amp;gt;
  &amp;lt;label&amp;gt;
    &amp;lt;span class=&amp;quot;sr-only&amp;quot;&amp;gt;Search:&amp;lt;/span&amp;gt;
    &amp;lt;input type=&amp;quot;search&amp;quot; name=&amp;quot;q&amp;quot; placeholder=&amp;quot;Search&amp;quot;
      x-effect=&amp;quot;getDuckDuckGoFallback&amp;quot; x-model=&amp;quot;query&amp;quot;&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Search&amp;lt;/button&amp;gt;

  &amp;lt;input type=&amp;quot;hidden&amp;quot; placeholder=&amp;quot;Search&amp;quot;
    name=&amp;quot;sites&amp;quot; value=&amp;quot;blakewatson.com&amp;quot;&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we’re submitting to DuckDuckGo, users without JavaScript will get sent there to see results. If JavaScript is enabled, Alpine takes over. &lt;a href=&quot;https://alpinejs.dev/&quot;&gt;Alpine&lt;/a&gt; is a great alternative to frameworks like Vue and React in situations where you don’t want a build step. In this case it catches the submit event and handles search itself and uses &lt;code&gt;fetch&lt;/code&gt; to hit a custom endpoint.&lt;/p&gt;
&lt;h3 id=&quot;the-search-index&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-index&quot;&gt;The search index&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To search my site, regardless of whether it’s in-browser or on a custom endpoint, I need a search index.&lt;/p&gt;
&lt;p&gt;An Eleventy template is usually one input file (e.g., &lt;code&gt;my-page.md&lt;/code&gt;) that produces one or more output files (e.g., &lt;code&gt;my-page.html&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;But a killer feature of Eleventy is just how many different types of template formats it can process out of the box. One such template is a &lt;a href=&quot;https://www.11ty.dev/docs/languages/javascript/&quot;&gt;special JavaScript file&lt;/a&gt; ending in &lt;code&gt;.11ty.js&lt;/code&gt;. You export a class. You can specify frontmatter data by returning an object from a &lt;code&gt;data&lt;/code&gt; method. Then you specify the output by returning a string from a &lt;code&gt;render&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;I used it to create a search index of any content I wanted searchable. Here is the code with some of the minutia redacted.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;class SearchIndex {
  data() {
    return {
      permalink: &#39;/search-index.json&#39;,
    };
  }

  render(data) {
    const journal = data.collections.journal;
    const microblog = data.collections.microblog;
    const pages = data.collections.page;
    const project = data.collections.project;
    const work = data.collections.work;

    const index = [...journal, ...microblog, ...pages, ...project, ...work].map(
      (post, idx) =&amp;gt; {

        // REDACTED logic stuff for brevity

        // object with all the fields I want to search on
        // along with fields I want to come back in the results
        return {
          id: post.id || post.fileSlug,
          title: post.data.title,
          url:
            type === &#39;microblog&#39;
              ? `/microblog/${post.data.microblogId}`
              : post.url,
          date: post.date,
          dateDisplay: post.data.dateDisplay || &#39;&#39;,
          text: post.content,
          microblogText: type === &#39;microblog&#39; ? post.content : &#39;&#39;,
          summary: post.data.summary || &#39;&#39;,
          emoji: post.emoji || &#39;&#39;,
          type,
        };
      },
    );

    return JSON.stringify(index);
  }
}

module.exports = SearchIndex;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In short, I’m grabbing all the different collections I have and smushing them into one big array. Then I am returning that whole thing as a JSON string. This will write the file &lt;code&gt;search-index.json&lt;/code&gt; which is hosted alongside the rest of my website.&lt;/p&gt;
&lt;h3 id=&quot;the-search-endpoint&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#the-search-endpoint&quot;&gt;The search endpoint&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then I implemented a search endpoint on a &lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt; function. If the visitor has JavaScript enabled, I use &lt;code&gt;fetch&lt;/code&gt; to hit the worker, passing the search term as a query parameter. If JavaScript isn’t available, the search form falls back to POSTing to DuckDuckGo, where it will perform a search against my website for the given query.&lt;/p&gt;
&lt;p&gt;Back to the cloud function. This won’t be a full tutorial on Workers,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; but just to give you an idea of what I’m doing I will show you a few relevant pieces. This bit of code involves retrieving the search index.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;let searchIndex = await env.STORAGE.get(&#39;search-index&#39;);
let data = [];

if (!searchIndex) {
  const resp = await fetch(indexUrl, {method: &#39;GET&#39;});
  data = await resp.json();
  await env.STORAGE.put(&#39;search-index&#39;, JSON.stringify(data), { expirationTtl: 60 * 60 * 24 });
} else {
  data = JSON.parse(searchIndex);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, I attempt to retrieve the search index from my worker’s &lt;a href=&quot;https://developers.cloudflare.com/kv/&quot;&gt;KV storage&lt;/a&gt;, which is roughly equivalent to the browser’s &lt;code&gt;localStorage&lt;/code&gt;. If it isn’t available I fetch it from my website. In that case, I also store the index and set it to expire in one day. This is a little nicety to speed up searches since it eliminates an extra network request that would otherwise be required.&lt;/p&gt;
&lt;p&gt;Next, I set things up for searching by creating an instance of &lt;code&gt;MiniSearch&lt;/code&gt;. I specify which fields I want to search on, and which fields I would like to be returned back to me in the such results. Then I give it the search index data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const minisearch = new MiniSearch({
  // fields to search
  fields: [
    &#39;title&#39;, &#39;url&#39;, &#39;date&#39;, &#39;text&#39;, &#39;summary&#39;, &#39;type&#39;
  ],
  // fields to return
  storeFields: [
    &#39;title&#39;, &#39;url&#39;, &#39;date&#39;, &#39;dateDisplay&#39;, &#39;emoji&#39;, &#39;microblogText&#39;, &#39;summary&#39;, &#39;type&#39;
  ],
});

minisearch.addAll(data);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, I execute the search, get the results, and return them.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const results = minisearch.search(query);

return new Response(JSON.stringify(results), {
  headers: {
    &amp;quot;Content-Type&amp;quot;: &amp;quot;application/json&amp;quot;,
    &#39;Access-Control-Allow-Origin&#39;: allowedOrigin(env)
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Back on my website, I display the results. I wanted to be able to filter results by collection (journal, microblog, page, etc) so I include a series of checkboxes above the search results. To wire that up I used Alpine to re-render the results based on what collections are checked.&lt;/p&gt;
&lt;h2 id=&quot;bringing-back-comments.-sort-of.&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#bringing-back-comments.-sort-of.&quot;&gt;Bringing back comments. Sort of.&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s been about a decade since I ran a blog with comments. I never got many of them and most discussion, if any occurred at all, would happen on social media. I dropped support for comments happily and haven’t really thought about it since.&lt;/p&gt;
&lt;p&gt;But lately I miss having a bit of interaction. So this time around I decided to implement two ways for people to interact with my articles. A “like” button, and a link to a corresponding post on Mastodon.&lt;/p&gt;
&lt;p&gt;As a way to make the link to Mastodon more interesting, I’m showing a stylized preview of the post at the end of my article by using the &lt;a href=&quot;https://daviddarnes.github.io/mastodon-post/&quot;&gt;mastodon-post&lt;/a&gt; web component from &lt;a href=&quot;https://daviddarnes.github.io/&quot;&gt;David Darnes&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2024/mastodon-post-preview-dark.png&quot; width=&quot;1706&quot; height=&quot;730&quot; alt=&quot;Screenshot of a Mastodon post on my site that says &#39;Use your Mac the way I do: a thought experiment&#39; along with the URL of the article on my website. It shows the stats below it. Reposts: 26. Replies: 4. Favorites: 28.&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;homemade-like-button&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#homemade-like-button&quot;&gt;Homemade like button&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I feel like I’ve seen a bunch of these bespoke like buttons recently and I thought it would be fun to implement one.&lt;/p&gt;
&lt;p&gt;Since I already had a Workers function that I was using for search—and it was already using KV storage—I decided to use the same function to handle the backend aspect of the like button functionality.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;&amp;lt;like-button&amp;gt;&lt;/code&gt; is a custom &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_components&quot;&gt;web component&lt;/a&gt;. Once it’s loaded on the page it uses the article’s slug and fetches the number of likes from the worker function. Just to show a quick snippet, here is the code in my worker that gets the likes from KV storage.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;async function getLikes(env, key) {
  let val = await env.STORAGE.get(`likes-${key}`);
  val = val ? parseInt(val) : 0;
  
  return new Response(val, {
    status: 200, headers: { &#39;Access-Control-Allow-Origin&#39;: allowedOrigin(env) }
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As I said, Workers KV is similar to &lt;code&gt;localStorage&lt;/code&gt; in the browser. So it is just a matter of storing the number of likes for each article and retrieving them when requested. If I don’t find a value, I use zero. If there are any likes on an article, I display a count next to the like button itself.&lt;/p&gt;
&lt;p&gt;When someone clicks the like button, I fetch the current number of likes (if any exist), increment that number, and put it back in storage.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;async function handleLike(env, key) {
  let val = await env.STORAGE.get(`likes-${key}`);

  val = val ? parseInt(val) + 1 : 1;
  await env.STORAGE.put(`likes-${key}`, val);

  return new Response(val, {
    status: 200, headers: { &#39;Access-Control-Allow-Origin&#39;: allowedOrigin(env) }
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the frontend I put a little value in &lt;code&gt;localStorage&lt;/code&gt; to track whether the user has liked the given article. Sadly this means you can’t spam the like button to inflate my ego. Well, I guess you can if you use a private window or clear &lt;code&gt;localStorage&lt;/code&gt;. If you’re willing to do all that then you deserve to smash that like button as much as you want.&lt;/p&gt;
&lt;h2 id=&quot;automatic-microblog-publishing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#automatic-microblog-publishing&quot;&gt;Automatic microblog publishing&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I said, the microblog consists partially of posts from Mastodon and my omg.lol Statuslog. I’ve set up a workflow that automatically catches new posts from those sources and publishes them to my site.&lt;/p&gt;
&lt;p&gt;The magic that makes this possible is good ol’ RSS. I’m using the fancy new service, &lt;a href=&quot;https://echofeed.app/&quot;&gt;EchoFeed&lt;/a&gt; from &lt;a href=&quot;https://rknight.me/blog/echofeed/&quot;&gt;Robb Knight&lt;/a&gt;, to monitor my Mastodon and Statuslog feeds. When a new post appears on one of them, EchoFeed sends a request to a webhook I set up.&lt;/p&gt;
&lt;p&gt;The webhook parses the data in the request and extracts the URL of the social posts. Leaving out error-checking for brevity, it looks something like this.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// Get the JSON input from the request body
$json_input = file_get_contents(&#39;php://input&#39;);

// Decode the JSON data
$data = json_decode($json_input, true);

// get the post url
$link = $data[&#39;link&#39;] ?? null;

// save the url to a text file to be processed later
file_put_contents(PATH_TO_QUEUE, $link . PHP_EOL, FILE_APPEND);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The URLs end up in a text file with one URL per line. Meanwhile, I have a cron task that runs every hour that checks that text file. A Node script runs and finds new posts using the &lt;a href=&quot;https://docs.joinmastodon.org/api/&quot;&gt;Mastodon API&lt;/a&gt; and the &lt;a href=&quot;https://api.omg.lol/#statuslog&quot;&gt;Statuslog API&lt;/a&gt;. It extracts the data I want from them and then it updates two &lt;a href=&quot;https://www.11ty.dev/docs/data-global/&quot;&gt;global data files&lt;/a&gt; I’m using, &lt;code&gt;toots.json&lt;/code&gt; and &lt;code&gt;statuslogs.json&lt;/code&gt;. The script commits and pushes the changes.&lt;/p&gt;
&lt;p&gt;When a new commit is pushed to &lt;code&gt;main&lt;/code&gt; branch, it gets picked up by &lt;a href=&quot;https://www.deployhq.com/r/6ask19&quot;&gt;DeployHQ&lt;/a&gt; (referral link), the service I use for website deployments. DeployHQ will run my Eleventy build, which processes those JSON data files and adds the posts to my site. Finally DeployHQ grabs the output of the build and transfers it to my server.&lt;/p&gt;
&lt;h2 id=&quot;cloudflare-cdn&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#cloudflare-cdn&quot;&gt;Cloudflare CDN&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Moving from WordPress to a static site improved the speed of my website by an order of magnitude (at least when it comes to uncached pages&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fn2&quot; id=&quot;fnref2:1&quot;&gt;[2:1]&lt;/a&gt;&lt;/sup&gt;). But I knew anyone not located in the US might have a slow connection to my US-based server. I decided to experiment with putting my site behind Cloudflare CDN.&lt;/p&gt;
&lt;p&gt;It was a rocky start but once I figured things out I was happy with the results. My site feels pretty speedy even if I connect to VPN on the other side of the world. I’m also interested in playing with &lt;a href=&quot;https://bunny.net/&quot;&gt;Bunny CDN&lt;/a&gt; but it seems the integration process is a bit less straightforward than Cloudflare, so I need some time to research.&lt;/p&gt;
&lt;h2 id=&quot;personal-websites-for-the-win&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#personal-websites-for-the-win&quot;&gt;Personal websites for the win&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That’s the whirlwind tour of my site rebuild. I love working on my website. This quote from &lt;a href=&quot;https://jamesg.blog/&quot;&gt;James’ Coffee Blog&lt;/a&gt; comes to mind:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One of my favourite things to do in my free time is to tinker with this website. Indeed, this website is the culmination of years of tinkering. I have added features like coffee shop maps that I can share with friends, a way for me to share my bio in two languages, a sitemap.xml file to help search engines find pages on my website, and more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is from his article &lt;a href=&quot;https://jamesg.blog/2024/02/19/personal-website-ideas/&quot;&gt;100 things you can do on your personal website&lt;/a&gt;. I enjoy tinkering and I enjoy reading about everyone else’s tinkering. Every personal website is a win for the web and proof that we don’t need large corporate content silos to connect with each other.&lt;/p&gt;
&lt;p&gt;So if you’ve written about your website, let me know! And thank you for reading about mine. Long live &lt;a href=&quot;https://web1.land/&quot;&gt;web1&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;appendix%3A-stuff-i-used-for-building-my-site&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#appendix%3A-stuff-i-used-for-building-my-site&quot;&gt;Appendix: Stuff I used for building my site&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt;&lt;/strong&gt; - old school pay-as-you-go web host&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;&lt;/strong&gt; - static site generator&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.npmjs.com/package/markdown-it-anchor&quot;&gt;markdown-it-anchor&lt;/a&gt;&lt;/strong&gt; - on-page heading links&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.npmjs.com/package/markdown-it-table-of-contents&quot;&gt;markdown-it-table-of-contents&lt;/a&gt;&lt;/strong&gt; - shortcode for auto-generating a table of contents based on heading structure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt;&lt;/strong&gt; - JavaScript cloud functions. I also use &lt;a href=&quot;https://developers.cloudflare.com/kv/&quot;&gt;Workers KV&lt;/a&gt; for storage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.cloudflare.com/application-services/products/cdn/&quot;&gt;Cloudflare CDN&lt;/a&gt;&lt;/strong&gt; - CDN to speed up requests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.backblaze.com/cloud-storage&quot;&gt;Backblaze B2&lt;/a&gt;&lt;/strong&gt; - site backup&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://alpinejs.dev/&quot;&gt;Alpine.js&lt;/a&gt;&lt;/strong&gt; - reactive UI library&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.deployhq.com/r/6ask19&quot;&gt;DeployHQ&lt;/a&gt;&lt;/strong&gt; (referral link) - site deployment SaaS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://torchlight.dev/&quot;&gt;Torchlight&lt;/a&gt;&lt;/strong&gt; - code syntax highlighting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.typography.com/&quot;&gt;Hoefler&amp;amp;Co&lt;/a&gt;&lt;/strong&gt; - webfonts &lt;a href=&quot;https://www.typography.com/fonts/ringside/overview&quot;&gt;Ringside Regular&lt;/a&gt;, &lt;a href=&quot;https://www.typography.com/fonts/ringside/styles/ringsideextrawide&quot;&gt;Ringside Extra Wide&lt;/a&gt;, and &lt;a href=&quot;https://www.typography.com/fonts/operator/styles/operatormono&quot;&gt;Operator Mono&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://fontawesome.com/&quot;&gt;Font Awesome&lt;/a&gt;&lt;/strong&gt; - I’m using a few icons here and there&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I have screenshots of all of my old designs in that post. In many ways, learning about design has made my website more boring over the years. Where is the creative experimentation? The &lt;em&gt;whimsy&lt;/em&gt;? &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I did use caching. The excellent &lt;a href=&quot;https://wordpress.org/plugins/hyper-cache/&quot;&gt;HyperCache&lt;/a&gt; plugin is the only reason my site was navigable. Page loads on non-cached pages could take several seconds to load. You don’t need to email me about how my host was definitely doing something wrong. It’s all about tradeoffs. You can run WordPress fast, but you have to make tradeoffs to get there. &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fnref2:1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Although I do want to write a tutorial now that I’ve used Workers for a handful of projects. &lt;a href=&quot;https://blakewatson.com/journal/rebuilding-my-website-with-eleventy/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Song Swap: Kayama by Karl Jenkins</title>
      <link href="https://blakewatson.com/journal/song-swap-kayama/"/>
      <updated>2024-04-25T18:21:00Z</updated>
      <id>https://blakewatson.com/journal/song-swap-kayama/</id>
      <content xml:lang="en" type="html">&lt;p&gt;My brother, &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt&lt;/a&gt;, and I decided to explore our fairly different musical tastes and do a song swap. What follows is my reaction to a song of his choice from his collection.&lt;/p&gt;
&lt;p&gt;Go check out &lt;a href=&quot;https://www.mattwatson.org/blog/20240425-song-swap-lilac-wine/&quot;&gt;Matt’s reaction to Lilac Wine&lt;/a&gt; by Jeff Buckley.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Song:&lt;/strong&gt; Kayama&lt;br /&gt;
&lt;strong&gt;Artists:&lt;/strong&gt; Karl Jenkins, Adiemus, et al&lt;br /&gt;
&lt;strong&gt;Album:&lt;/strong&gt; Adiemus&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://song.link/i/1447107151&quot;&gt;https://song.link/i/1447107151&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This track exudes 90s new age, which makes sense as it was released in 1995. I can get down with a bit of Enya or Enigma so there were things about this I liked even if it isn’t my normal jam. I like vocal harmonies. The harmonies in this track sounded tribal in nature which is kind of cool.&lt;/p&gt;
&lt;p&gt;The language is made up which is another interesting aspect as it makes me think of the song from the movie Gladiator, &lt;a href=&quot;https://www.youtube.com/watch?v=mQQKZ5cgybU&quot;&gt;Now We Are Free&lt;/a&gt;, which I discovered, years after seeing the film, used an invented language of sorts.&lt;/p&gt;
&lt;p&gt;The whole thing had a cinematic feel and a gradual build-up that I liked. I thought the beginning and middle were kind of same-y or went on too long. But at some point midway a cool sounding flute joined in and the following build-up of strings and other instruments was kind of neat.&lt;/p&gt;
&lt;p&gt;It has a pretty long runtime of 7:56. Apparently this is the non-radio-edit version. Matt said he gave me this one instead because it had more of the flute. Fair enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Would you listen to it again?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I kind of enjoyed it as a novelty but I can’t say I will be adding this to any playlists or seeking it out again. I could see looking for various other “invented language” music to listen to while working since sometimes lyrics can be distracting to me.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Use your Mac the way I do: a thought experiment</title>
      <link href="https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/"/>
      <updated>2024-03-16T17:33:00Z</updated>
      <id>https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/</id>
      <content xml:lang="en" type="html">&lt;p&gt;No one is ever going to invent a Blake’s Life Simulator. Well, &lt;em&gt;probably&lt;/em&gt; not. I can imagine some quantum computer of the future that allows you to simulate any person given known details of their life and AI-powered estimations.&lt;/p&gt;
&lt;p&gt;Short of that, this blog post will have to suffice. I’m now going to transport you to a place of wonder. A place of limitless creative possibility. A place to hang with friends. A place to work. A place to write. That place is my most important technological possession—my Mac.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;one-peripheral-to-rule-them-all&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#one-peripheral-to-rule-them-all&quot;&gt;One peripheral to rule them all&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To start this thought experiment, imagine that you’re only allowed to use one input peripheral with your Mac. That peripheral is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hockey_puck_mouse&quot;&gt;Apple hockey puck mouse&lt;/a&gt;. Its groovy, semi-transparent tinted plastic oozes 90s whimsy and transports you to a carefree time of tech optimism that has long since faded.  It’s got one glorious button for you to press. Alas, I don’t actually use one of those but it’s a good placeholder for my actual setup because I can only use a mouse and I can only left click.&lt;/p&gt;
&lt;p&gt;Now, in a real day-in-the-Mac-life-of-Blake, you would only be able to move your mouse about half an inch in any direction. You’ll need to turn those mouse sensitivity settings all the way up—but even that won’t be good enough. You’ll need &lt;a href=&quot;https://plentycom.jp/en/steermouse/&quot;&gt;SteerMouse&lt;/a&gt; or something similar to turn up the sensitivity even further.&lt;/p&gt;
&lt;p&gt;But I’m going to let you forgo that limitation to make the thought experiment simpler. Now let’s begin.&lt;/p&gt;
&lt;h2 id=&quot;blake-mode-activated&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#blake-mode-activated&quot;&gt;Blake mode activated&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here you are, sat at your desk, armed with the hockey puck and ready to get things done on your Mac. You click around and get quite far that way but a point comes when you need to type something. You instinctively go for your keyboard when my omnipresent voice enters the chat Mufasa-style and reminds you that in this thought experiment you don’t have a keyboard. You have but the hockey puck.&lt;/p&gt;
&lt;p&gt;What to do? The Mac comes with a tool called the &lt;a href=&quot;https://support.apple.com/guide/mac-help/use-the-accessibility-keyboard-mchlc74c1c9f/mac&quot;&gt;Accessibility Keyboard&lt;/a&gt;. It’s an onscreen keyboard that lets you type by clicking keys on the screen—not too different than the one on a phone or tablet.&lt;/p&gt;
&lt;h2 id=&quot;scrolling&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#scrolling&quot;&gt;Scrolling&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So you enable the keyboard and now you’ve unlocked a lot of possibility. You pop over to Safari where you can now type a web search! You submit to your intrusive thought that demands to know &lt;em&gt;right now&lt;/em&gt; how long it will take Voyager 1 to pass by Proxima Centauri.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; You’ve discovered a bit of a problem though. You’ve landed on a Wikipedia page, but you don’t know how to scroll down. Your hockey puck doesn’t have a scroll wheel. That’s when you remember that the up and down arrow keys can scroll a webpage.&lt;/p&gt;
&lt;p&gt;This works but is mildly annoying at times. Fortunately, there is an option in macOS’ Appearance settings to always make scrollbars visible.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; With this setting enabled, the scrollbar on the page is visible and you can scroll by interacting with it (dragging it or clicking on the track).&lt;/p&gt;
&lt;p&gt;You don’t love it, but it works. Until it doesn’t. Turns out quite a few native apps seem to &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;ignore this setting altogether and hide scrollbars from you&lt;/a&gt;. You’re left to find weird hacks—turns out resizing the window can trigger scrollbars to appear in some cases—or use further assistive technologies to get by.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;right-clicking&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#right-clicking&quot;&gt;Right-clicking&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You do the best you can. Some apps work great; others you give up on. You find that web apps are often better than native ones when it comes to predictable UI behavior.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The one-button mouse is nice and minimal but you eventually get to a point where you need to right-click something. What now? Longtime Mac users will probably know the answer to this one—Control+Click in macOS will act as a right-click in most cases and summon the context menu.&lt;/p&gt;
&lt;p&gt;Fortunately, the Accessibility Keyboard is aware of the need to press modifier keys. Clicking the Control key puts it in an active state—this is the same thing as if you tap Shift on your iPhone’s keyboard. You can then click on whatever your target is and macOS will execute a Control+Click action. This “sticky” behavior works for all the modifier keys.&lt;/p&gt;
&lt;h2 id=&quot;typing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#typing&quot;&gt;Typing&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Thanks to the Accessibility Keyboard you are able to type, but you quickly discover that the standard QWERTY keyboard is &lt;em&gt;not&lt;/em&gt; fun to point and click on. You spend a lot of time jumping around the keyboard as you peck out letters one-by-one. The typing suggestions toolbar helps a lot with this. Often times, typing the first two or three letters is enough to get the right suggestion, which you can click on to type out the rest of the word—just like on your iPhone.&lt;/p&gt;
&lt;p&gt;You’ve heard of people changing their keyboard layouts and you remember one called Dvorak that people seem to nerd out about. You decide to investigate and you come across the &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/&quot;&gt;Chubon keyboard layout&lt;/a&gt;, which seems to be optimized for your very situation—it places common letters toward a center grouping where they’re easy to click with less pointer travel.&lt;/p&gt;
&lt;p&gt;The Accessibility Keyboard allows you to have multiple “panels” which you can switch to as needed. The QWERTY keyboard is one such panel. The built-in &lt;a href=&quot;https://support.apple.com/guide/mac-help/set-panel-editor-options-switch-control-mchlf55dbb46/14.0/mac/14.0&quot;&gt;Panel Editor&lt;/a&gt; gives you the ability to edit the panel or create new ones. This means you can create your very own keyboard layout! The Panel Editor is powerful. You can add not only the basic keys but also buttons which execute key combos, invoke system actions, input strings of text, and more.&lt;/p&gt;
&lt;p&gt;You build yourself an &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;optimized keyboard panel&lt;/a&gt; with all sorts of fancy buttons for copying, pasting, invoking app shortcuts, and more.&lt;/p&gt;
&lt;h2 id=&quot;apps-that-help&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#apps-that-help&quot;&gt;Apps that help&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Built-in macOS tools have taken you a long way but you discover you can save time and make your life easier with a variety of third-party apps and browser extensions. Most of these are well-known productivity tools, and as much as they might help the average user,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn6&quot; id=&quot;fnref6&quot;&gt;[6]&lt;/a&gt;&lt;/sup&gt; they help you even more.&lt;/p&gt;
&lt;p&gt;Tools like &lt;a href=&quot;https://textexpander.com/&quot;&gt;TextExpander&lt;/a&gt; and &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt; help reduce the amount of typing needed, which is an ongoing pursuit of yours. Typing is tedious, as we’ve learned, and any shortcut or way to avoid it is preferable. &lt;a href=&quot;https://1password.com/&quot;&gt;1Password&lt;/a&gt; auto-fill is a must (and its handling of passkeys eliminates all typing involved in authentication).&lt;/p&gt;
&lt;p&gt;Note-taking apps like &lt;a href=&quot;https://bear.app/&quot;&gt;Bear&lt;/a&gt; that use &lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; for formatting are great because you can avoid using keyboard shortcuts or UI controls for formatting—and you added dedicated punctuation buttons to your keyboard so that you don’t need to press Shift to access characters like the asterisk or underscore.&lt;/p&gt;
&lt;p&gt;The browser extension &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt; lets you click and drag on webpages to scroll them—much like you would on a mobile touchscreen.&lt;/p&gt;
&lt;h2 id=&quot;speech-to-text-and-ai&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#speech-to-text-and-ai&quot;&gt;Speech to text and AI&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You don’t always feel like using your voice to control your Mac, but when you do, you have found the ultimate tool for doing it called &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fn7&quot; id=&quot;fnref7&quot;&gt;[7]&lt;/a&gt;&lt;/sup&gt; Talon takes a bit of technical know-how and has a learning curve, but investing in learning it is worth it because it gives you powerful ways to not only write prose, but also—and possibly more importantly—write code. Your mind is blown when you start to see what’s possible in &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt; with the &lt;a href=&quot;https://www.cursorless.org/&quot;&gt;Cursorless&lt;/a&gt; extension.&lt;/p&gt;
&lt;p&gt;Since Talon gives you the ability to verbalize keypresses, your mouse pointer is freed from typing duty. This is important for being able to play games that require camera control via the mouse.&lt;/p&gt;
&lt;p&gt;And when it comes to code, you find that the AI tool &lt;a href=&quot;https://www.tabnine.com/&quot;&gt;Tabnine&lt;/a&gt; is useful for autocompleting lines of code—this saves you tons of time as it eliminates many keystrokes.&lt;/p&gt;
&lt;h2 id=&quot;if-it-doesn%E2%80%99t-exist%2C-build-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#if-it-doesn%E2%80%99t-exist%2C-build-it&quot;&gt;If it doesn’t exist, build it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You’re really cooking with grease now! Sometimes there’s an app or a feature you need that doesn’t exist. Fortunately, you’re well-versed in web-based programming and that gives you the ability to build your own &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt; home-cooked apps and tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You may or may not sometimes build completely unnecessary tools just for the fun of it.&lt;/p&gt;
&lt;h2 id=&quot;thank-you-for-taking-this-journey-with-me&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#thank-you-for-taking-this-journey-with-me&quot;&gt;Thank you for taking this journey with me&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You’ve come a long way. You started with nothing more than a one-button mouse. But from there you expanded the capabilities of that humble device, giving yourself keyboard access, shortcuts and macros, assistive tech tools, and powerful voice input capability.&lt;/p&gt;
&lt;p&gt;This concludes the thought experiment. You are transported back into your normal state, feeling refreshed and just a bit more appreciative of technology than you were before.&lt;/p&gt;
&lt;p&gt;If you’ve read (or skimmed) this far, I appreciate it. I take for granted that I’m using such a customized setup. I just wanted to put it out into the world. I’d love for software developers to consider edge-cases like mine when they build their wares. Challenge assumptions. Be flexible. As a web developer, I also need to do this in my own work. It’s an ongoing personal struggle that I’m trying to improve at. It’s easy to assume, and it’s challenging to progressively enhance. But we need to do the work so that the things we build benefit everyone.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;And this coming from someone who uses a highly customized power wheelchair. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Ok turns out it’s not even headed that direction. If it were, it would take about 70k years to get there. It is moving at about 17km &lt;em&gt;per second&lt;/em&gt;, which is mind boggling to even think about. Even at that speed it would take about six hours for it to travel the distance between the earth and the moon. The scale of the universe breaks my brain but I &lt;a href=&quot;https://www.youtube.com/watch?v=Z_1Q0XB4X0Y&quot;&gt;can’t get enough of it&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Technically this setting would be set to the &lt;em&gt;Automatically based on mouse or trackpad&lt;/em&gt; option. Since your mouse, the hockey puck, doesn’t have a scroll wheel, the system would automatically show scrollbars. I have purposely overlooked this fact for simplicity. Unfortunately, many native apps and an alarming number of websites take a &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;heavy-handed approach to scrollbars&lt;/a&gt; which hides them regardless of the system setting. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I did recently discover a way to access a scroll-on-hover control as part of &lt;a href=&quot;https://support.apple.com/guide/mac-help/control-the-pointer-using-dwell-mchl437b47b0/mac&quot;&gt;Accessibility Keyboard’s dwell feature&lt;/a&gt;, which allows you to perform certain actions after leaving the mouse pointer at rest for a specified amount of time. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I love &lt;a href=&quot;https://inessential.com/2020/03/19/proxyman.html&quot;&gt;Mac-assed Mac apps&lt;/a&gt; but even those seem to have unpredictable scrollbar behavior or interaction with the Accessibility Keyboard. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Just remember that the average user doesn’t exist. Everyone is edge case in some way or other. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;macOS also has built-in &lt;a href=&quot;https://support.apple.com/guide/mac-help/use-voice-control-commands-mh40719/14.0/mac/14.0&quot;&gt;Voice Control&lt;/a&gt; but it doesn’t work well for programming. Talon, on the other hand, excels at producing code and is infinitely configurable (mostly by writing Python). I do use Voice Control for iOS and it works well enough for my purposes. &lt;a href=&quot;https://blakewatson.com/journal/use-your-mac-the-way-i-do-a-thought-experiment/#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Things I miss</title>
      <link href="https://blakewatson.com/journal/things-i-miss/"/>
      <updated>2024-02-13T07:09:17Z</updated>
      <id>https://blakewatson.com/journal/things-i-miss/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I don’t link to it often but I do have an &lt;a href=&quot;https://blakewatson.com/ihs/&quot;&gt;archive of my old disability blog&lt;/a&gt;. It used to have its own domain and everything. I did my best to make sure that old domain and any URLs still work and redirect to this static archive—because &lt;a href=&quot;https://www.w3.org/Provider/Style/URI.html&quot;&gt;cool URIs don’t change&lt;/a&gt;. But I don’t link to them much anymore because the posts are old and I am slightly embarrassed by some of them.&lt;/p&gt;
&lt;p&gt;But every now and then I poke around in the archives myself and reminisce about times past.&lt;/p&gt;
&lt;p&gt;The other day I was reminded of a &lt;a href=&quot;https://blakewatson.com/ihs/fourth-quarter/index.html&quot;&gt;post I wrote about SMA&lt;/a&gt;. I wrote it soon after I discovered I had grown too weak to handle a PlayStation controller and play the new edition of Madden I had just received as a gift. In that post I said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But SMA took football from me. And it took writing (by making it slow and tedious).&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; It keeps taking and taking. Its hunger is never filled nor its thirst quenched.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote that in 2009. &lt;em&gt;Fifteen years ago.&lt;/em&gt; I’ve lost even more abilities since then. Sometimes I think about the things I used to be able to do. Some of them I miss dearly. So in this somewhat downer of a blog post, I thought I would make a list of things that I miss being able to do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I told myself I wasn’t going put one of these in here, but what if this is the only blog post of mine that someone sees? I feel I need to mention that I am living a good life. I have fun &lt;a href=&quot;https://blakewatson.com/my-apps/&quot;&gt;making things&lt;/a&gt;, I have a job doing &lt;a href=&quot;https://blakewatson.com/work&quot;&gt;meaningful work&lt;/a&gt;, and I’ve gotten pretty good at &lt;a href=&quot;https://blakewatson.com/assistive-tech-gear/&quot;&gt;adapting to my disability&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Okay, with that out of the way, here we go—in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Handwriting&lt;/li&gt;
&lt;li&gt;Drawing&lt;/li&gt;
&lt;li&gt;Typing on a keyboard&lt;/li&gt;
&lt;li&gt;Using a video game controller&lt;/li&gt;
&lt;li&gt;Playing video games using a keyboard&lt;/li&gt;
&lt;li&gt;The ability to right-click a mouse&lt;/li&gt;
&lt;li&gt;Catching a football&lt;/li&gt;
&lt;li&gt;Walking (okay more like hopping) around a swimming pool&lt;/li&gt;
&lt;li&gt;Playing with/handling physical objects&lt;/li&gt;
&lt;li&gt;Painting ceramics&lt;/li&gt;
&lt;li&gt;Using &lt;a href=&quot;https://fieldnotesbrand.com/&quot;&gt;Field Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using a pen tablet mouse&lt;/li&gt;
&lt;li&gt;Playing action games with quick reaction times&lt;/li&gt;
&lt;li&gt;Moving chess pieces&lt;/li&gt;
&lt;li&gt;Swallowing easily&lt;/li&gt;
&lt;li&gt;Holding a hockey stick&lt;/li&gt;
&lt;li&gt;Calligraphy&lt;/li&gt;
&lt;li&gt;Clicking a retractable pen&lt;/li&gt;
&lt;li&gt;Using a mechanical pencil&lt;/li&gt;
&lt;li&gt;Playing games on my iPhone&lt;/li&gt;
&lt;li&gt;Writing on my iPhone&lt;/li&gt;
&lt;li&gt;Drawing on my iPhone&lt;/li&gt;
&lt;li&gt;Playing music on a Cassio keyboard &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Holding a book&lt;/li&gt;
&lt;li&gt;Turning pages&lt;/li&gt;
&lt;li&gt;Holding a Kindle&lt;/li&gt;
&lt;li&gt;Holding a sandwich&lt;/li&gt;
&lt;li&gt;Feeding myself&lt;/li&gt;
&lt;li&gt;Scratching my face&lt;/li&gt;
&lt;li&gt;Turning my head&lt;/li&gt;
&lt;li&gt;Sleeping on my stomach&lt;/li&gt;
&lt;li&gt;Playing with a bouncing ball&lt;/li&gt;
&lt;li&gt;Using a trackpad&lt;/li&gt;
&lt;li&gt;Using a calculator&lt;/li&gt;
&lt;li&gt;Doodling&lt;/li&gt;
&lt;li&gt;Playing with Legos&lt;/li&gt;
&lt;li&gt;Holding a drink&lt;/li&gt;
&lt;li&gt;Eating an ice cream cone&lt;/li&gt;
&lt;li&gt;Eating popcorn &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Holding playing cards&lt;/li&gt;
&lt;li&gt;Driving with a standard wheelchair joystick&lt;/li&gt;
&lt;li&gt;Playing with GarageBand on an iPad&lt;/li&gt;
&lt;li&gt;Picking at my fingernails&lt;/li&gt;
&lt;li&gt;Tapping a pen&lt;/li&gt;
&lt;li&gt;Playing a GameBoy&lt;/li&gt;
&lt;li&gt;Playing Duck Hunt&lt;/li&gt;
&lt;li&gt;Rolling dice&lt;/li&gt;
&lt;li&gt;Handling dominoes&lt;/li&gt;
&lt;li&gt;Putting a cassette in a Sony Walkman&lt;/li&gt;
&lt;li&gt;Thumb war&lt;/li&gt;
&lt;li&gt;Coloring&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m sure there are way more but now that I’ve gotten to this point in the list I haven’t been able to think of anything else for a few minutes. So I guess I’m calling this done.&lt;/p&gt;
&lt;p&gt;Let’s pour one out for where we’ve been and turn our attention back to where we’re going.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;SMA didn’t take writing away. Through a combination of an &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/&quot;&gt;optimized onscreen keyboard&lt;/a&gt; and a &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/&quot;&gt;voice input tool&lt;/a&gt;, I continue to write blog posts, code, and &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;very bad fiction&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This is one of the last times I was able to play music. I was using an iPad mini. I wore a glove so that I could rest my hand on the screen. My elbow sat on an armrest that swivelled, which gave me the range of motion to move my arm around. &lt;a href=&quot;https://www.youtube.com/watch?v=-uhcCow3M8Q&quot;&gt;https://www.youtube.com/watch?v=-uhcCow3M8Q&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;With my difficulty swallowing, it is too easy for me to get choked up on the husks. &lt;a href=&quot;https://blakewatson.com/journal/things-i-miss/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Building our own private Discord knockoff</title>
      <link href="https://blakewatson.com/journal/building-our-own-private-discord-knockoff/"/>
      <updated>2024-01-28T19:46:54Z</updated>
      <id>https://blakewatson.com/journal/building-our-own-private-discord-knockoff/</id>
      <content xml:lang="en" type="html">&lt;p&gt;For two years in a row I’ve taken some time off at the end of the year to rest and relax and, most importantly, to work on personal projects. I’ve begun calling it my annual holiday sprint. This past year I ended up building two apps. One is a &lt;a href=&quot;https://write.omg.lol/&quot;&gt;writing app built on omg.lol&lt;/a&gt;. It deserves its own blog post, but that’ll be another time.&lt;/p&gt;
&lt;p&gt;The other thing I built was a &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;home-cooked&lt;/a&gt; collaboration with my brother, &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt&lt;/a&gt;. On a whim, we decided to build our own real-time chat application—a Discord knockoff we call BrainWave Chat.&lt;/p&gt;
&lt;p&gt;The name, BrainWave Chat, isn’t going to appeal or make sense to most of you. And it shouldn’t, because it’s based on an inside reference. That in itself should give you some insight about the application. The name as well as the functionality of this app is specific to me and Matt. We created the app just for us; our own dedicated chat tool.&lt;/p&gt;
&lt;p&gt;If you just want the TL;DR, &lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#features&quot;&gt;jump to the list of features&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2024/01/brainwavechat-screenshot.png&quot; alt=&quot;Screenshot of BrainWave Chat. Several test messages are shown along with emoji reactions. One message is a meme gif that says &amp;quot;nerd alert.&amp;quot; The last message is the shrug emoticon.&quot; width=&quot;1400&quot; height=&quot;990&quot; class=&quot;alignnone size-full wp-image-1547&quot; /&gt;
&lt;figcaption&gt;The BrainWave Chat user interface in dark mode&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;why-build-yet-another-chat-app-in-2024%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#why-build-yet-another-chat-app-in-2024%3F&quot;&gt;Why build yet another chat app in 2024?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may be thinking, &lt;em&gt;what’s the point in building a chat app when so many good options already exist?&lt;/em&gt; We certainly thought this at the project’s outset, though admittedly not for very long. It’s true, though. There’s SMS, iMessage, Facebook Messages, Snapchat, WeChat, Discord, WhatsApp, Telegram, Signal, and Slack—and that’s just the stuff I thought of off the top of my head without any research. I’m sure ChatGPT could vomit out a list of a hundred more options.&lt;/p&gt;
&lt;p&gt;I don’t know if these are &lt;em&gt;good&lt;/em&gt; reasons, but here are the factors that pushed us to go ahead with the project.&lt;/p&gt;
&lt;h3 id=&quot;privacy-and-the-small-web&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#privacy-and-the-small-web&quot;&gt;Privacy and the small web&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Matt and I bounced around a few apps, but the latest one was Discord. We love its UI. But we don’t love that it doesn’t offer much privacy. I recently saw this &lt;a href=&quot;https://www.youtube.com/watch?v=uvNkdAggUGU&quot;&gt;video that levels some pretty big accusations&lt;/a&gt; against Discord. Specifically, the idea that the Chinese government has access to our data by way of Tencent, the China-based company that invests in Discord.&lt;/p&gt;
&lt;p&gt;I didn’t do much to fact-check that accusation but it’s not like believing that &lt;a href=&quot;https://en.wikipedia.org/wiki/PRISM&quot;&gt;big companies are harvesting data and sharing it with governments&lt;/a&gt; is a &lt;a href=&quot;https://www.youtube.com/watch?v=urglg3WimHA&quot;&gt;tin-foil-hat-level idea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We were inspired by &lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;home-cooked&lt;/a&gt; apps and &lt;a href=&quot;https://benhoyt.com/writings/the-small-web-is-beautiful/&quot;&gt;small web&lt;/a&gt; ideas. It’s fine to make your own thing just for you. And you can absolutely build software without pulling in a ton of dependencies and wiring up complex infrastructure. We’re so used to reading about the software practices of large companies that it’s easy to forget that a lot of (most?) software projects don’t need to be built at that scale.&lt;/p&gt;
&lt;h3 id=&quot;accessibility&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#accessibility&quot;&gt;Accessibility&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://daverupert.com/2024/01/what-can-a-website-do/&quot;&gt;What can a website do?&lt;/a&gt; Turns out, a lot. In my &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;MagnoliaJS talk about home-cooked apps&lt;/a&gt; I discussed several websites that I made just for me in order to make something that was more accessible and usable for me. This was another motivation for us. As much as we like the Discord UI, it has some browser inconsistencies and other issues that don’t work well for how we use our computers. More on that later.&lt;/p&gt;
&lt;h3 id=&quot;features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#features&quot;&gt;Features&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you build something for yourself it means that you can make it do whatever you want. There were some specific features we wanted that Discord didn’t have. Also more on this later.&lt;/p&gt;
&lt;h3 id=&quot;practice-and-fun&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#practice-and-fun&quot;&gt;Practice and fun&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lastly, we had time off and we wanted to build something together. We had some &lt;a href=&quot;https://alpinejs.dev/&quot;&gt;tools we wanted to use&lt;/a&gt; and an &lt;a href=&quot;https://gomakethings.com/php-islands-architecture/&quot;&gt;architecture&lt;/a&gt; we wanted to push to the limit. Sometimes you do something just to do it.&lt;/p&gt;
&lt;h2 id=&quot;what-makes-a-good-chat-app-for-us&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#what-makes-a-good-chat-app-for-us&quot;&gt;What makes a good chat app for us&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve already said a couple of times that we like a lot of things about Discord.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nice-looking. I really don’t care for chat bubbles and fortunately there are none to be found in Discord.&lt;/li&gt;
&lt;li&gt;Doesn’t presume you have a phone. It’s hard for me to use phones because of my disability. I’m a desktop native and anything that forces me to use my phone for initial setup is annoying to me.&lt;/li&gt;
&lt;li&gt;Discord really nails the fun factor. It has lots of goodies and delightful interactions.&lt;/li&gt;
&lt;li&gt;Speaking of which, reactions are fun. Especially when you go beyond standard emoji and use the custom or animated ones. They’re a great way to micro dose memes.&lt;/li&gt;
&lt;li&gt;GIFs, or as they are correctly called, GIFs, are a must-have feature of a chat app at this point. Though I prefer that they be collapsible.&lt;/li&gt;
&lt;li&gt;Toggle-able desktop notifications for new messages. No-brainer.&lt;/li&gt;
&lt;li&gt;Easy to share images and video. I share a &lt;em&gt;lot&lt;/em&gt; of screenshots. I need this feature or it’s a dealbreaker.&lt;/li&gt;
&lt;li&gt;I use different computers in different lighting environments so being able to switch between dark and light modes as needed is a must. Discord also has multiple themes now which I think is kinda fun.&lt;/li&gt;
&lt;li&gt;Video calls. This feature always works pretty well for us and we’ll probably stick with Discord for video chat for the time being.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But there are things we don’t like about Discord that we knew we could address with our own bespoke app.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Privacy. This is a big one. We can host our app on an affordable VPS&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; using &lt;a href=&quot;https://boringtechnology.club/&quot;&gt;boring old&lt;/a&gt; PHP and MySQL. Now we control our data. Boom.&lt;/li&gt;
&lt;li&gt;The desktop version of Discord &lt;em&gt;really&lt;/em&gt; wants to be used in its downloadable desktop app form. It will run in the browser, but can be finicky compared to the desktop app. But I don’t love having another always-on &lt;a href=&quot;https://www.electronjs.org/&quot;&gt;Electron&lt;/a&gt; app&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; running as it hogs a fair amount of resources.&lt;/li&gt;
&lt;li&gt;I mentioned browser inconsistencies. What I found was that it works best in Chromium-based browsers. I ran into more glitchiness when using it in Firefox. I haven’t tried Safari much so I can’t comment on that.&lt;/li&gt;
&lt;li&gt;Scrolling. This is a big one. Matt and I have to scroll by clicking and dragging scroll bars. Discord shrinks its scrollbars down and they’re hard for us to use. We counteract this on most websites by using a browser extension called &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt;. Unfortunately, it struggles with Discord’s infinite scrolling—a UI pattern I despise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also like the idea of adding weirdly specific features in the future. We haven’t yet added too many of these, but I can brainstorm a few right now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We type mostly using onscreen keyboards because we’re mouse-centric. We could make our app more mouse-friendly by adding any number of shortcut buttons: canned messages, go-to reactions or GIFs, a Morse code sender!&lt;/li&gt;
&lt;li&gt;Some kind of advanced text-prediction that saves us some keystrokes (err, mouse clicks).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;building-the-app&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#building-the-app&quot;&gt;Building the app&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay now we’re to the fun part! Matt is a &lt;a href=&quot;https://www.mattwatson.org/blog/20230716-let-me-live-dangerously-php/&quot;&gt;PHP curmudgeon&lt;/a&gt; so he was tasked with building the backend of the application whilst I would build out the frontend simultaneously.&lt;/p&gt;
&lt;h3 id=&quot;php-islands&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#php-islands&quot;&gt;PHP Islands&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We decided to build an API out of plain PHP. But not even a reasonable one that directs all requests to a single entry point and employs a routing mechanism—you know, like every single backend framework ever. No. Every endpoint is just a PHP file. You want to create a message? “Right this way,” I say as I direct you to &lt;code&gt;/api/create-message.php&lt;/code&gt;. It imports a handful of shared functions from elsewhere and does one thing, you can probably guess what that is.&lt;/p&gt;
&lt;p&gt;We started calling it &lt;a href=&quot;https://gomakethings.com/php-islands-architecture/&quot;&gt;PHP Islands Architecture&lt;/a&gt; because we had just read Chris Ferdinandi’s article of the same name. But this is not that. Chris described it thusly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The tl;dr: the site is nearly entirely static, pre-rendered HTML. Rather than using JavaScript to render the interactive and dynamic bits, I use islands of server-powered PHP.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What we were doing was smashing tons of loosely related islands together to form a monstrous archipelago. And our app’s frontend; well it &lt;em&gt;is&lt;/em&gt; technically pre-rendered HTML, but it makes heavy use of JavaScript to hide and show things. So I’m not sure why we hijacked that name or why I’ve prattled on about it for this long. Sorry.&lt;/p&gt;
&lt;h3 id=&quot;polling-versus-websockets&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#polling-versus-websockets&quot;&gt;Polling versus websockets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; In March 2024, we refactored the app to use the websockets service, &lt;a href=&quot;https://pusher.com/&quot;&gt;Pusher&lt;/a&gt;. The app performs much better. The integration process wasn’t as hard as I thought it would be, and our everyday usage is still well below the limits of the free tier.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Pretty much every article about writing a real-time chat app will tell you that you need websockets. They are all correct. Polling is a terrible way to keep a chat client up-to-date.&lt;/p&gt;
&lt;p&gt;We chose polling. Why? Because we didn’t immediately know how to latch websockets onto PHP, we didn’t have much time to learn, and we had already decided we didn’t want to use NodeJS (the only other server-side language either of us are any good at). And anyway it’s built for two users. How bad could it be?&lt;/p&gt;
&lt;p&gt;Real bad. I probably spent more time fixing the polling function than anything else. It would have been nice to know if a message was sent or a previous one was updated (or reacted to, etc) instead of continually asking the server, “What’s new home skillet?” and having to sort through the resulting pile of shit.&lt;/p&gt;
&lt;p&gt;But we got there and it’s working pretty well now. I’m guessing this could scale up to about a dozen people but I feel like it might get weird beyond that. That’s my un-researched wild-ass guess.&lt;/p&gt;
&lt;h3 id=&quot;ain%E2%80%99t-nobody-got-time-for-%5Ba-build-step%5D&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#ain%E2%80%99t-nobody-got-time-for-%5Ba-build-step%5D&quot;&gt;Ain’t nobody got time for [a build step]&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We were in a hurry because we had about one week of free time to get this thing usable before it was time to go back to our day jobs. We weren’t going to have a ton of time to maintain this thing and we wanted it to be able to run by itself for a long time without intervention. That meant using as few dependencies as possible. We didn’t even bother with &lt;a href=&quot;https://getcomposer.org/&quot;&gt;Composer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the front-end, we skipped having a bundler. The handful of libraries and utils I used—I just downloaded their minified versions from a CDN and checked them right into git. &lt;em&gt;Dusts hands.&lt;/em&gt; The only thing I used npm for was to install &lt;a href=&quot;https://prettier.io/&quot;&gt;prettier&lt;/a&gt;, the code formatter.&lt;/p&gt;
&lt;h3 id=&quot;single-page-app-with-alpine.js&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#single-page-app-with-alpine.js&quot;&gt;Single page app with Alpine.js&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The frontend is found at &lt;code&gt;/chat.php&lt;/code&gt; (which I keep accidentally pronouncing as ChatGPT 😩). We use PHP to generate most of the HTML then we drop Alpine on top of it to provide all the interactivity.&lt;/p&gt;
&lt;p&gt;Alpine deserves its own article, and I plan to write one at some point. It’s refreshing in many ways but also kind of odd—it encourages writing JavaScript expressions, or sometimes whole code blocks, directly inside of HTML attributes. It’s similar to the &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt; philosophy. And I love hating on Tailwind so it’s hard to justify why I enjoy Alpine.&lt;/p&gt;
&lt;p&gt;Alpine can quickly add functionality &lt;em&gt;anywhere&lt;/em&gt; which means I often end up with random JS code &lt;em&gt;everywhere&lt;/em&gt;. But it gets you moving quickly and doesn’t require an annoying build step. So it was the perfect tool for this project.&lt;/p&gt;
&lt;h3 id=&quot;iteration-and-dogfooding&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#iteration-and-dogfooding&quot;&gt;Iteration and dogfooding&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We did little planning and a lot of iteration. The beginning was the hardest because the frontend and backend couldn’t work without each other and we were building them simultaneously. But as soon as we reached critical mass of functionality, our duties split up nicely. Eventually both of us worked on both sides, which was a nice change of pace.&lt;/p&gt;
&lt;p&gt;We forced ourselves to use the app as soon as we could feasibly do it. That gave us immediate feedback and pointed us, quite painfully at times, toward what we should tackle next. It was a whirlwind but it was a ton of fun.&lt;/p&gt;
&lt;h3 id=&quot;the-long-tail-of-fixes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#the-long-tail-of-fixes&quot;&gt;The long tail of fixes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After our vacation was over, we had a functioning app. I’m proud of that accomplishment for sure. But we also had a huge list of stuff left over that we still wanted to do. Fortunately, it is much easier to accomplish a quick win on a functioning system than to build the system in the first place. I have found this to be true with most of my side projects. Build the MVP in a mad dash, then slowly improve it over time.&lt;/p&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;p&gt;Here is a snapshot of the app’s features as of press time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time text chat with &lt;a href=&quot;https://marked.js.org/&quot;&gt;markdown&lt;/a&gt; support&lt;/li&gt;
&lt;li&gt;Light and dark mode&lt;/li&gt;
&lt;li&gt;Emoji support (including custom/animated) via &lt;a href=&quot;https://nolanlawson.github.io/emoji-picker-element/&quot;&gt;shortcode and picker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GIF support via &lt;a href=&quot;https://tenor.com/gifapi&quot;&gt;Tenor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Message editing&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://highlightjs.org/&quot;&gt;Syntax highlighted&lt;/a&gt; code blocks&lt;/li&gt;
&lt;li&gt;Image and video embedded attachments (stored on &lt;a href=&quot;https://www.backblaze.com/cloud-storage&quot;&gt;Backblaze B2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Downloadable file attachments protected behind login&lt;/li&gt;
&lt;li&gt;Reactions (standard emoji and custom)&lt;/li&gt;
&lt;li&gt;Inline (Discord-style) replies&lt;/li&gt;
&lt;li&gt;Open graph previews&lt;/li&gt;
&lt;li&gt;Message notifications/sound&lt;/li&gt;
&lt;li&gt;Unread message favicon status&lt;/li&gt;
&lt;li&gt;Active user indicator&lt;/li&gt;
&lt;li&gt;User-is-typing indicator&lt;/li&gt;
&lt;li&gt;Pinned messages&lt;/li&gt;
&lt;li&gt;Message search&lt;/li&gt;
&lt;li&gt;The OG Discord font, &lt;a href=&quot;https://en.wikipedia.org/wiki/Whitney_%28typeface%29&quot;&gt;Whitney&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Can render &lt;code&gt;¯&#92;_(ツ)_/¯&lt;/code&gt; properly&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;roadmap&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#roadmap&quot;&gt;Roadmap&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, we have shipped most of the features that we really wanted. Most of the leftover stuff are small UI tweaks. The biggest thing left is giving each message a permalink.  I would love to be able to link to specific messages.&lt;/p&gt;
&lt;p&gt;We’ve already started using pinned messages as a way to have shared “notes.” I wouldn’t be surprised if the next phase is to bolt on another application that lets us have collaborative notes.&lt;/p&gt;
&lt;p&gt;We designed the app for us, but it does technically support &lt;em&gt;n&lt;/em&gt; users and we coded things in such a way that they could potentially be open sourced. Maybe we’ll do that at some point. If anyone is actually interested in this, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;shoot me an email&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lessons-learned&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#lessons-learned&quot;&gt;Lessons learned&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This project went mostly better than I thought it would. Most of my lessons learned were good things—like confirming that a project with few dependencies and no build step could succeed. I learned that Matt and I can work together quickly and efficiently and to make a lot of progress in a short amount of time. And have fun doing it!&lt;/p&gt;
&lt;p&gt;My biggest lesson learned in terms of what &lt;em&gt;not&lt;/em&gt; to do is not to use polling for a realtime application. I mean it is working fine for this use case. But it is painfully clear that websockets are a much better fit for something like this. But even then, I am better at polling now. The next time I need to do it, hopefully I can avoid some of the pitfalls.&lt;/p&gt;
&lt;p&gt;Sometimes I do stop and wonder whether these kinds of endeavors are worth it. Shouldn’t I have been working on something more important? Like a SaaS or something that can make some money. Or an open source project that would benefit society. Or perhaps something that doesn’t involve computers at all.&lt;/p&gt;
&lt;p&gt;I don’t have a good answer. All I know is that it sure was fun and I love using it.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you would like to comment on this article, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;send me an email&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;We opted for the managed VPS, &lt;a href=&quot;https://vrlps.co/m73z9kk/cp&quot;&gt;Cloudways&lt;/a&gt; (referral link). It gives us the old and reliable LAMP stack we’re using without needing to do much server maintenance. &lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I say this as a person who sells an Electron app for possibly the most overkill use case possible—&lt;a href=&quot;https://d20app.me/&quot;&gt;rolling dice&lt;/a&gt;. All I can say is I’m sorry and I will try to do better next time. &lt;a href=&quot;https://blakewatson.com/journal/building-our-own-private-discord-knockoff/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>2023: my year in review</title>
      <link href="https://blakewatson.com/journal/2023-my-year-in-review/"/>
      <updated>2024-01-01T22:07:18Z</updated>
      <id>https://blakewatson.com/journal/2023-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I always feel like nothing much happened during the year. I’m not a super active person in terms of getting out and doing things so when I try to think back over the year it all feels kind of same-y. Work, eat, sleep, repeat.&lt;/p&gt;
&lt;p&gt;But when I push myself to come up with a list of accomplishments I end up pleasantly surprised. I believe it’s helpful to take stock of how you’re doing in life and write it down. Annually is probably too infrequent but it’s better than nothing.&lt;/p&gt;
&lt;p&gt;Let’s dive in.&lt;/p&gt;
&lt;h2 id=&quot;2023-goals&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#2023-goals&quot;&gt;2023 Goals&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/&quot;&gt;last year’s review&lt;/a&gt; I gave myself a list of seven goals for 2023. Let’s see how I did and grade each one.&lt;/p&gt;
&lt;h3 id=&quot;read-5-books&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#read-5-books&quot;&gt;Read 5 books&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I did it! Thanks to the bookclub at work, I met my reading goals, limited as they were. I relied on a mix of audiobook and ebooks as it really just depends on my mood and the context. I read:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Rainmaker by John Grisham&lt;/li&gt;
&lt;li&gt;Tress of the Emerald Sea by Brandon Sanderson&lt;/li&gt;
&lt;li&gt;We Are Legion (We are Bob): Bobiverse, Book 1 by Dennis E. Taylor&lt;/li&gt;
&lt;li&gt;For We Are Many: Bobiverse, Book 2 by Dennis E. Taylor&lt;/li&gt;
&lt;li&gt;All These Worlds: Bobiverse, Book 3 by Dennis E. Taylor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I particularly enjoyed the Bobiverse series as it’s the sort of nerdy space stuff that pushes all the right buttons for me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: B+&lt;/strong&gt;, I met my goal but leaned heavily on one series.&lt;/p&gt;
&lt;h3 id=&quot;write-5-articles&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#write-5-articles&quot;&gt;Write 5 articles&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For years now I’ve written a handful of articles a year on my website (I call it &lt;a href=&quot;http://blakewatson.com/journal&quot;&gt;Journal&lt;/a&gt; for whatever reason). I wanted to nudge that up to five in 2023. I got off to a good start when, in March, I realized I had written one article each month in 2023. Right then and there I amended my goal to one article per month. And I did it! Plus two extra for a total of 14 articles in 2023.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: A+&lt;/strong&gt;, goal shattered!&lt;/p&gt;
&lt;h3 id=&quot;make-one-game&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#make-one-game&quot;&gt;Make one game&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the spring I discovered Zachtronics’ &lt;a href=&quot;https://www.zachtronics.com/last-call-bbs/&quot;&gt;Last Call BBS&lt;/a&gt;. True to form it’s another game about programming along with interesting mini-games. One of those was a version of solitaire with some interesting rules that made it feel more strategic than regular Klondike. I enjoyed it so much that I made my own &lt;a href=&quot;https://blakewatson.com/journal/i-made-a-web-based-version-of-sawayama-solitaire/&quot;&gt;web-based version of it&lt;/a&gt;. You can play my version of &lt;a href=&quot;https://www.watsonbrosgames.com/solitaire/&quot;&gt;Sawayama Solitaire here&lt;/a&gt; along with the rest of me and &lt;a href=&quot;https://www.mattwatson.org/&quot;&gt;Matt’s&lt;/a&gt; &lt;a href=&quot;https://www.watsonbrosgames.com/&quot;&gt;collection of web games&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/05/sawayama-solitaire-1024x709.png&quot; alt=&quot;Screenshot of my version of Sawayama Solitaire. The cards are dealt similar to Klondike but all of them are face up.&quot; width=&quot;1024&quot; height=&quot;709&quot; class=&quot;alignnone size-large wp-image-1047&quot; /&gt;
&lt;figcaption&gt;Screenshot of my version of Sawayama Solitaire.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;keep-a-journal&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#keep-a-journal&quot;&gt;Keep a journal&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve bounced around journaling solutions for years but nothing ever sticks. I tried really hard this past year but journaling (the private kind, not to be what I confusingly call Journal on this website) always feels like a chore and writing them is rarely enjoyable to me.&lt;/p&gt;
&lt;p&gt;I managed to write 68 entries this year. It was heavier at the beginning of the year but I ran out of steam by the end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: C&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;write-one-work-of-fiction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#write-one-work-of-fiction&quot;&gt;Write one work of fiction&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I stuck with my yearly tradition of participating in &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;. But like last year, I lowered my writing goal to 20k words (a novella I guess). This year I wrote my first attempt at fan fiction, The Emergent—a story that takes place in the world of the Matrix.&lt;/p&gt;
&lt;p&gt;I’m not publishing it or anything but it was fun to write and to make my brother read it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: A&lt;/strong&gt;, because I completed the goal. Not because the story is good.&lt;/p&gt;
&lt;h3 id=&quot;make-(or-start)-a-new-app-for-profit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#make-(or-start)-a-new-app-for-profit&quot;&gt;Make (or start) a new app for profit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My &lt;a href=&quot;https://afinestart.me/&quot;&gt;main side hustle&lt;/a&gt; chugs along (more about that in a bit) but I wanted to branch out and start something new this year.&lt;/p&gt;
&lt;p&gt;Unfortunately the ideas just never came to me. I spent my free time on various other side projects, home-cooked apps, and writing. I never got around to this one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: F&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;be-more-social&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#be-more-social&quot;&gt;Be more social&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I made small advancements here. The easy ones were being more active in online discussions (because I’m hopelessly extremely online). But I also mailed one personal letter (yes an actual physical letter delivered by the postal service). I didn’t manage to get out and do much. Nor did I get back into D&amp;amp;D or board games with friends. I’d say I made small victories but I need to do more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grade: C-&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;final-grade&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#final-grade&quot;&gt;Final grade&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ll give myself a B. I surprised myself in some areas while others went about as expected. On the whole I’m glad I set these goals and I did better than I thought I would.&lt;/p&gt;
&lt;h2 id=&quot;four-years-of-building-software-for-nasa&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#four-years-of-building-software-for-nasa&quot;&gt;Four years of building software for NASA&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It doesn’t feel like it but I’ve been with &lt;a href=&quot;https://www.mricompany.com/&quot;&gt;MRI Technologies&lt;/a&gt; for over four years now, building web apps for NASA and Collins Aerospace. It’s been great. I’d say I had my hand in more big features and decisions this past year than I have previously. I feel more confident and I’m still having fun doing the work (well, you know, most of it).&lt;/p&gt;
&lt;p&gt;Our frontend team grew and that trend may be continuing, so follow me if you’re interested in building web apps for NASA. I’ll share open positions when and if they become available.&lt;/p&gt;
&lt;h2 id=&quot;speaking&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#speaking&quot;&gt;Speaking&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/blake-magnoliajs2023-1024x576.jpg&quot; alt=&quot;Photo of me at MagnoliaJS. I’m sitting in my wheelchair at a small table by the podium. My laptop is open and off to the side behind me is my presentation slideshow. The cover slide reads &amp;quot;The joys of home-cooked apps. Blake Watson.&amp;quot;&quot; width=&quot;1024&quot; height=&quot;576&quot; class=&quot;alignnone size-large wp-image-1384&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;I gave a talk in October at &lt;a href=&quot;https://www.magnoliajs.com/&quot;&gt;MagnoliaJS&lt;/a&gt; called &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;&lt;em&gt;The joys of home-cooked apps&lt;/em&gt;&lt;/a&gt;. This was my third appearance as a speaker at MagnoliaJS and the first one in person since Magnolia’s inaugural conference in 2019. It was a good experience and I think I’m getting a little better at public speaking every time I do it.&lt;/p&gt;
&lt;h2 id=&quot;new-wheelchair&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#new-wheelchair&quot;&gt;New wheelchair&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you don’t already know, I have a condition called spinal muscular atrophy (SMA). As such, I use a power wheelchair. At the tail end of summer, the joystick on my wheelchair shorted out and for months I had to use a backup which had its own problems but worked enough for me to get by.&lt;/p&gt;
&lt;p&gt;Fortunately, I was at my 5-year mark with my old chair. Here in the United States that is usually how often insurance will pay for a new wheelchair. I got my new chair and I’ve been using it for two weeks and while it takes an adjustment period, I’m happy to have a working joystick again.&lt;/p&gt;
&lt;h2 id=&quot;the-side-hustle-keeps-hustling&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#the-side-hustle-keeps-hustling&quot;&gt;The side hustle keeps hustling&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;During last year’s holiday I took some time to add an annual subscription option (in addition to the monthly one) to my new tab page browser extension, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;. Annual subs turned out to be even more popular than I thought. Most of my customers are now annual subscribers.&lt;/p&gt;
&lt;p&gt;Speaking of which, as this year comes to a close I have more subscribers than I ever have at 44. A Fine Start has about 1,370 users across all three extensions (Chrome, Firefox, Edge). There is also a web version but because I don’t use any analytics in the app itself I don’t know how many web users I have. After hosting costs and sparse advertising, this project doesn’t really turn a profit. But it does continue to tick upward year-over-year and I’m still proud of it.&lt;/p&gt;
&lt;h2 id=&quot;blake%3A-across-the-fediverse&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#blake%3A-across-the-fediverse&quot;&gt;Blake: across the Fediverse&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/&quot;&gt;deleted my Facebook account&lt;/a&gt; years ago now. I was somewhat active on Twitter until January of 2023 when Elon Musk broke third-party Twitter clients. That was enough to send me packing, and it just so happened I had recently joined a Mastodon instance when I signed up for a little service called &lt;a href=&quot;https://home.omg.lol/referred-by/bw&quot;&gt;omg.lol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This service transformed my social media experience and brought back, for me, some of the fun and joy of the old internet. You can read all about it on &lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/&quot;&gt;my article about omg.lol that went viral&lt;/a&gt; on Hacker News!&lt;/p&gt;
&lt;h2 id=&quot;music&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#music&quot;&gt;Music&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I gave up on Apple Music two years ago because its macOS app kept glitching out on me and &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;hiding scrollbars&lt;/a&gt;. I’ve been using Spotify ever since and it’s just better.&lt;/p&gt;
&lt;p&gt;I also started using &lt;a href=&quot;https://www.last.fm/&quot;&gt;Last.fm&lt;/a&gt; this year. It’s been fun to see all the in-depth stats. You can have a look at the &lt;a href=&quot;https://www.last.fm/user/blakewatson/listening-report/year/2023&quot;&gt;fancy report&lt;/a&gt; if you want! But for the TL;DR here’s my Spotify Wrapped.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2024/01/IMG_0030-2-576x1024.jpg&quot; alt=&quot;Spotify Wrapped. Top Artists: Falling Up, Death Cab for Cutie, Band of Horses, Beach House, Tycho. Minutes Listened: 19,942. Top Songs: Levitation, FAST LAND, Sparks, Space Song, EASY PREY. Top Genre: Indietronica.&quot; width=&quot;576&quot; height=&quot;1024&quot; class=&quot;alignnone size-large wp-image-1511&quot; /&gt;
&lt;h2 id=&quot;holiday-coding-sprint&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#holiday-coding-sprint&quot;&gt;Holiday coding sprint&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I had two weeks off from work this holiday and spent some time on personal projects. I thought I was going to be tackling the backlog of stuff I have on existing projects but instead I ended up building two new apps. Each of these deserves its own post but here’s a little preview.&lt;/p&gt;
&lt;h3 id=&quot;write.omg.lol&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#write.omg.lol&quot;&gt;write.omg.lol&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I snatched up the &lt;em&gt;write&lt;/em&gt; subdomain on omg.lol and decided to use it to build a writing app. I’ve had &lt;a href=&quot;https://blakewatson.com/scratchpad/&quot;&gt;this super minimalist scratchpad&lt;/a&gt; on my site for several years but wanted to expand on it to allow for multiple notes. What I ended up with was a minimalist writing app built on top of omg.lol’s web infrastructure that uses its API to store and retrieve notes.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2024/01/9075ef3ad22da9a3-1024x696.png&quot; alt=&quot;Screenshot of write.omg.lol&amp;#039;s app interface in Safari. A sidebar lists the notes and the writing area is a minimalist textarea with generous padding an a larg font size.&quot; width=&quot;1024&quot; height=&quot;696&quot; class=&quot;alignnone size-large wp-image-1512&quot; /&gt;
&lt;figcaption&gt;My thanks to Adam for this &lt;a href=&quot;https://social.lol/@prami/111619479833689788&quot;&gt;nice callout&lt;/a&gt; and screenshot.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;brainwave-chat&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#brainwave-chat&quot;&gt;BrainWave Chat&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My brother and I use Discord fairly heavily and used it to chat with each other. But we wanted something a bit more private. And we had our own little list of niceties we thought a chat app ought to have (big &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/&quot;&gt;scrollbars&lt;/a&gt; for starters). We ended up building a fairly usable Discord knock-off in about a week!&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2024/01/CleanShot-2024-01-01-at-10.13.01@2x-1024x782.png&quot; alt=&quot;Screenshot of BrainWave Chat. It looks a lot like Discord except simplified. Depicted here is a conversation between me and my brother. In said conversation we made use of replies, reactions, custom emoji, and GIF search.&quot; width=&quot;1024&quot; height=&quot;782&quot; class=&quot;alignnone size-large wp-image-1513&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;It already has these features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discord-style replies&lt;/li&gt;
&lt;li&gt;GIF search&lt;/li&gt;
&lt;li&gt;Reactions&lt;/li&gt;
&lt;li&gt;Custom emoji&lt;/li&gt;
&lt;li&gt;Notifications / sound&lt;/li&gt;
&lt;li&gt;Dark/light themes&lt;/li&gt;
&lt;li&gt;Message search&lt;/li&gt;
&lt;li&gt;User active status&lt;/li&gt;
&lt;li&gt;User is-typing status&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;miscellaneous-projects&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#miscellaneous-projects&quot;&gt;Miscellaneous projects&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Quick updates on my other projects…&lt;/p&gt;
&lt;h3 id=&quot;synthwave.live&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#synthwave.live&quot;&gt;synthwave.live&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My YouTube-powered &lt;a href=&quot;https://synthwave.live/&quot;&gt;music mix site&lt;/a&gt; just keeps trucking along. I thought it would get more traffic than it does but it’s pretty sparse. So I’ve been neglecting the backlog of minor fixes and improvements. I continue running the update script weekly to keep content fresh. Props to &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt; for making that process easy.&lt;/p&gt;
&lt;h3 id=&quot;d20&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#d20&quot;&gt;d20&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My &lt;a href=&quot;https://d20app.me/&quot;&gt;RPG dice-rolling app&lt;/a&gt; still works but is in an unfortunate state. I have some minor updates I’d like to push to the Mac App Store but I’ve run into technical difficulties related to code signing.&lt;/p&gt;
&lt;p&gt;There’s also a problem of Intel vs. Apple Silicon. The only way to support both chipsets is to compile what’s called a &lt;em&gt;universal&lt;/em&gt; app. That’s nothing fancy, it’s just an Intel app and an Apple Silicon app smushed into one. But my app, being built on &lt;a href=&quot;https://www.electronjs.org/&quot;&gt;Electron&lt;/a&gt;, is already huge. Doubling the app size is just ridiculous. So not sure how I want to proceed yet.&lt;/p&gt;
&lt;h2 id=&quot;goals-for-2024&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2023-my-year-in-review/#goals-for-2024&quot;&gt;Goals for 2024&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Phew. This was a long one. If you’re still here thanks for reading. And if you just skimmed to the end that’s cool too!&lt;/p&gt;
&lt;p&gt;I’ll wrap this up with goals for 2024. I’m keeping most of them from last year.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read 5 books (again)&lt;/li&gt;
&lt;li&gt;Write one article/blog post every month&lt;/li&gt;
&lt;li&gt;Write a novella (bonus: not sci-fi)&lt;/li&gt;
&lt;li&gt;Make one game&lt;/li&gt;
&lt;li&gt;Watch at least some of the video courses I bought in 2023&lt;/li&gt;
&lt;li&gt;Spend more time with friends&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>omg.lol: an oasis on the internet</title>
      <link href="https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/"/>
      <updated>2023-12-10T20:25:03Z</updated>
      <id>https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/</id>
      <content xml:lang="en" type="html">&lt;p&gt;In the fall of 2022, I started using Twitter more. I don’t know why; probably a curious desire to see how bad Elon Musk would screw it up. To make it bearable from a user interface perspective I alternated between the Twitterrific&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; and Tweetbot macOS apps. It was fun at first—getting back into Twitter and using a chronological timeline rather than an algorithmically generated one.&lt;/p&gt;
&lt;p&gt;But the fun died when both apps suddenly lost access to Twitter on January 12, 2023. At first we third-party app fans hoped for an announcement of a temporary glitch along with reinstated access. But it turned out to be what, deep down, we knew it was all along—&lt;a href=&quot;https://techcrunch.com/2023/01/16/twitters-third-party-client-issue-is-seemingly-a-deliberate-suspension/&quot;&gt;Elon Musk shut down third-party API access with no warning&lt;/a&gt;. It was a sad day, and it’s the day that, for me, Twitter died.&lt;/p&gt;
&lt;p&gt;Over the course of 2023, Twitter fractured, with many people leaving to join Threads, Bluesky, or Mastodon/fediverse. I ultimately made the jump to Mastodon—but it was an accident.&lt;/p&gt;
&lt;h2 id=&quot;how-i-accidentally-joined-mastodon&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#how-i-accidentally-joined-mastodon&quot;&gt;How I accidentally joined Mastodon&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;About a week before Elon killed third-party Twitter clients, I had signed up for this quirky link-in-bio-plus-more service called &lt;a href=&quot;https://home.omg.lol/referred-by/bw&quot;&gt;omg.lol&lt;/a&gt; (this is a referral link, if you sign up I get 3 months of free time). I discovered it during what I later found out was a &lt;a href=&quot;https://omglol.news/2023/01/07/wildest-36-hours-ever&quot;&gt;big wave of new users coming from Hacker News&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I joined omg.lol because of the quirky, fun vibes. I didn’t even pay attention to the fact that there was an optional Mastodon instance. Mastodon, the concept, interested me but like many others I had no idea how to sign up, what instance I should pick, etc.&lt;/p&gt;
&lt;p&gt;But all of the sudden the decision was made for me—I had easy access to a smallish Mastodon instance with a lot of interesting people who, like me, had a fondness for the weird, fun internet of yore. And since it’s a paid service, I could feel like I wasn’t freeloading on some poor admin. And a paywall offers a little bit of spam protection (I’m assuming $20/yr is enough to prevent some spammy accounts from signing up).&lt;/p&gt;
&lt;p&gt;I ended up trying it out and then just a week later, Elon broke Twitter. At that point I went all-in on Mastodon and haven’t looked back. I have a third as many followers as I did on Twitter but five times the engagement on my posts.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; I have the choice of dozens of native and web clients. It’s awesome. I settled on &lt;a href=&quot;https://tapbots.com/ivory/mac/&quot;&gt;Ivory for macOS&lt;/a&gt; and it’s been pretty great.&lt;/p&gt;
&lt;p&gt;The instance over at &lt;a href=&quot;https://social.lol/&quot;&gt;social.lol&lt;/a&gt; is full of interesting, friendly, folks. More on that in a bit.&lt;/p&gt;
&lt;h2 id=&quot;cool-stuff-you-get-with-omg.lol&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#cool-stuff-you-get-with-omg.lol&quot;&gt;Cool stuff you get with omg.lol&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/12/CleanShot-2023-12-09-at-17.38.33@2x-1024x970.png&quot; alt=&quot;Screenshot of my omg.lol dashboard for the bw address. It&amp;#039;s colorful and friendly and has links to all of the services I’m about to describe.&quot; width=&quot;1024&quot; height=&quot;970&quot; class=&quot;alignnone size-large wp-image-1456&quot; /&gt;
  &lt;figcaption&gt;The omg.lol dashboard for my bw address&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The main thing you are getting with omg.lol is one or more subdomains, which are referred to as addresses. For example, my primary one is &lt;a href=&quot;https://bw.omg.lol/&quot;&gt;bw.omg.lol&lt;/a&gt;. Each one of your addresses comes with a slew of stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Email forwarding&lt;/strong&gt;: You get an email address, &lt;code&gt;you@omg.lol&lt;/code&gt;, which you can forward to any email address.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web Page&lt;/strong&gt;: This is your link-in-bio one-pager to do whatever you want with. By default this is where your main address (eg, &lt;code&gt;you.omg.lol&lt;/code&gt;) points. It’s the flagship feature of omg.lol. It comes with a markdown editor that has some &lt;a href=&quot;https://home.omg.lol/info/editor&quot;&gt;fancy features&lt;/a&gt; baked into it. You get a selection of built-in themes but you also have the freedom to go wild with your own CSS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DNS&lt;/strong&gt;: You have the ability to use your omg.lol subdomain however you wish by way of a friendly DNS panel.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Now Page&lt;/strong&gt;: This is a &lt;a href=&quot;https://nownownow.com/about&quot;&gt;type of page&lt;/a&gt; you can use to let people know what’s going on in your life. It’s broader than a social media post but more immediately relevant than an about page. It comes with the same fancy markdown editor and you can optionally appear in omg.lol’s &lt;a href=&quot;https://now.garden/&quot;&gt;Now Garden&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Statuslog&lt;/strong&gt;: This is a place to post &lt;a href=&quot;https://status.lol/&quot;&gt;statuses&lt;/a&gt;. It’s really just a fun, silly alternative to other social media platforms but without follows and likes and such. These can cross-post to Mastodon if you want.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weblog&lt;/strong&gt;: A full-fledge blogging platform. I’m not aware of all its features but it’s pretty powerful. It comes with fancy markdown support and has all the bloggy things you need like tags and RSS. A good example of a very custom blog on omg.lol is &lt;a href=&quot;https://weblog.anniegreens.lol/&quot;&gt;Apple Annie’s Weblog&lt;/a&gt;. But it’s worth noting you use it right out of the box without design customization if you want.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pastebin&lt;/strong&gt;: It’s just a pastebin for storing text snippets. Super simple and friendly like all of the omg.lol services.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pics&lt;/strong&gt;: It’s an image hosting service labeled as being “super-beta” as of the time of this writing. But it does what it says on the tin. You can host images there and they also show up on the &lt;a href=&quot;https://some.pics/&quot;&gt;some.pics&lt;/a&gt; image feed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PURLs&lt;/strong&gt;: Persistent uniform resource locators. This is a URL redirection service. You get &lt;code&gt;you.omg.lol/whatever&lt;/code&gt; and &lt;code&gt;you.url.lol/whatever&lt;/code&gt;. You can use these the way you would use similar services and they come with a basic hit counter and way to preview the URL before following it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Switchboard&lt;/strong&gt;: This is a powerful routing system that lets you point the variants of your address wherever you want, be it a destination on the omg.lol platform or an external website. Most omg.lol services have their own domain so you end up with a variety of options. Just as an example, you get a tilde address (ie, &lt;code&gt;omg.lol/~you&lt;/code&gt;). Mine points to my &lt;a href=&quot;https://tilde.club/&quot;&gt;tilde.club&lt;/a&gt; &lt;a href=&quot;https://omg.lol/~bw&quot;&gt;webpage&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keys&lt;/strong&gt;: A place to store public keys—SSH, PGP, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proofs&lt;/strong&gt;: A service for verifying ownership or control of a particular web property at a particular moment in time. For example, here is &lt;a href=&quot;https://proven.lol/f6874d&quot;&gt;proof that I controlled blakewatson.com as of December 10, 2023&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API access&lt;/strong&gt;: Most, if not all, omg.lol services have an API you can use to interact with them. Total nerd freedom. 🤯&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Phew, we made it! Thing is, omg.lol is constantly expanding and improving its offerings—this list will probably be outdated weeks or months after I publish it.&lt;/p&gt;
&lt;h2 id=&quot;a-cool-community&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#a-cool-community&quot;&gt;A cool community&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I can’t explain it but when you join omg.lol you join a &lt;a href=&quot;https://home.omg.lol/directory&quot;&gt;community&lt;/a&gt; of the nicest, most interesting people. This service just seems to bring the old-internet lovers together and, I don’t know, it’s just fun and pleasant.&lt;/p&gt;
&lt;p&gt;If Mastodon is not your thing, that’s cool! There’s also an IRC with a bridge to Discord so you can chat with other members. I’m a lurker most of the time, but I will say that when I do participate in chat I feel immediately welcomed.&lt;/p&gt;
&lt;h2 id=&quot;harnessing-the-power-of-the-adam&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#harnessing-the-power-of-the-adam&quot;&gt;Harnessing the power of the Adam&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The mastermind and architect behind omg.lol is &lt;a href=&quot;https://adam.omg.lol/&quot;&gt;Adam Newbold&lt;/a&gt;. I can’t say enough nice things about him. Adam is extremely active in this community. I’ve seen him build entire features in an afternoon just because someone in chat said “it would be cool if…” Heck, I &lt;em&gt;was&lt;/em&gt; that person in at least one instance.&lt;/p&gt;
&lt;p&gt;Adam is just so good at listening to feedback and is always gracious about it, even if the answer is &lt;em&gt;no&lt;/em&gt; or even if the person asking is being a little belligerent (not that this happens often). Adam’s positive energy is contagious. I think it spreads into the community and is a big reason that everyone seems so cool here.&lt;/p&gt;
&lt;p&gt;Also can we talk about what a prolific creator he is? He’s always got tons of neat (&lt;a href=&quot;https://neatnik.net/&quot;&gt;-nik&lt;/a&gt; 😄) stuff in the oven—&lt;a href=&quot;https://terminal.land/&quot;&gt;a multiplayer RPG in the shell&lt;/a&gt;, &lt;a href=&quot;https://web1.land/&quot;&gt;a service dedicated to web 1&lt;/a&gt;, and &lt;a href=&quot;https://dns.kitchen/&quot;&gt;a friendly DNS service&lt;/a&gt;, just to name a few.&lt;/p&gt;
&lt;p&gt;Okay, okay. Nerd crush over.&lt;/p&gt;
&lt;h2 id=&quot;the-small-web&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#the-small-web&quot;&gt;The small web&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve been enjoying a &lt;a href=&quot;https://neustadt.fr/essays/the-small-web/&quot;&gt;different kind of internet&lt;/a&gt; lately—the kind filled with &lt;a href=&quot;https://personalsit.es/&quot;&gt;personal&lt;/a&gt; &lt;a href=&quot;https://caramiki.com/&quot;&gt;websites&lt;/a&gt;, &lt;a href=&quot;https://chriscoyier.net/&quot;&gt;blogs&lt;/a&gt; that aren’t cookie-cutter marketing machines, and &lt;a href=&quot;https://satyrs.eu/index.html&quot;&gt;hypertext oddities&lt;/a&gt; you can only find by clicking around. And &lt;a href=&quot;https://kayserifserif.place/work/proseplay/&quot;&gt;so many&lt;/a&gt; &lt;a href=&quot;https://rknight.me/projects/&quot;&gt;personal&lt;/a&gt; &lt;a href=&quot;https://neal.fun/&quot;&gt;projects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This internet is a breath of fresh air if you’ve only been visiting what Google gives you on its first few pages of &lt;del&gt;results&lt;/del&gt; ads. I, of course, &lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/&quot;&gt;think everyone should have a personal site&lt;/a&gt;. And if you’re worried no one will want read your stuff, just remember that &lt;a href=&quot;https://andy-bell.co.uk/just-post/&quot;&gt;Andy will&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Making your own website is rewarding in a way that a corporate social media profile never will be.&lt;/p&gt;
&lt;p&gt;Need help getting started? These services, tools, and tutorials can help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://home.omg.lol/referred-by/bw&quot;&gt;omg.lol&lt;/a&gt; (obviously)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bearblog.dev/&quot;&gt;Bear Blog&lt;/a&gt; - a minimalist blogging service&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blot.im/&quot;&gt;Blot&lt;/a&gt; - turn a folder into a website&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for People&lt;/a&gt; - a web book I wrote for absolute beginners&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://able-dev.com/your-first-webpage-with-html-and-netlify/&quot;&gt;Your first webpage with HTML and Netlify&lt;/a&gt; - a tutorial by yours truly&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.htmldog.com/guides/html/beginner/&quot;&gt;HTML Dog beginner HTML tutorial&lt;/a&gt; - learn how to make a webpage with HTML&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jgthms.com/web-design-in-4-minutes/&quot;&gt;Web design in 4 minutes&lt;/a&gt; - quick tips for making a website look nice&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/get-started-web-design/&quot;&gt;How To Get Started in Web Design&lt;/a&gt; - Chris Coyier shows you how to put a website on the internet&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Twitterrific has especially historic relevance to Twitter as it is responsible for associating a bird as a mascot. Previously, Twitter sported an uninspired Web 2.0 text logo. Twitterrific introduced us to &lt;a href=&quot;http://gedblog.com/2007/05/11/twitter-identity-transference-syndrome-twits/&quot;&gt;Ollie&lt;/a&gt;, the cute little blue bird that many people probably think Twitter itself created. Twitter would go on to incorporate a little blue bird as its logo mark. &lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;87.5% of statistics are made up on the spot. &lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Default apps, 2023</title>
      <link href="https://blakewatson.com/journal/default-apps-2023/"/>
      <updated>2023-11-16T02:31:58Z</updated>
      <id>https://blakewatson.com/journal/default-apps-2023/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m supposed to be frantically writing a story for &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;. But I also have a streak of posting to my blog every month this year and I want to keep it going.&lt;/p&gt;
&lt;p&gt;To that end, I’m taking &lt;a href=&quot;https://rknight.me/app-defaults/&quot;&gt;inspiration from Robb Knight&lt;/a&gt; and the &lt;a href=&quot;https://listen.hemisphericviews.com/097&quot;&gt;Hemispheric Views podcast&lt;/a&gt; and posting a list of default apps I use for various purposes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mail Client:&lt;/strong&gt; Mail.app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mail Server:&lt;/strong&gt; &lt;a href=&quot;https://www.pobox.com/&quot;&gt;Pobox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Notes:&lt;/strong&gt; Bear, Tot, Bike, iA Writer 😅&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;To-Do:&lt;/strong&gt; Things&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iPhone Photo Shooting:&lt;/strong&gt; n/a&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Photo Management:&lt;/strong&gt; Photos.app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calendar:&lt;/strong&gt; Fantastical&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud file storage:&lt;/strong&gt; Dropbox, iCloud Drive&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RSS:&lt;/strong&gt; Feedbin web&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contacts:&lt;/strong&gt; Cardhop&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser:&lt;/strong&gt; Arc&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chat:&lt;/strong&gt; Discord&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bookmarks:&lt;/strong&gt; &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;My DIY bookmarks app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read It Later:&lt;/strong&gt; n/a&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Word Processing:&lt;/strong&gt; Pages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spreadsheets:&lt;/strong&gt; Numbers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presentations:&lt;/strong&gt; &lt;a href=&quot;https://ia.net/presenter&quot;&gt;iA Presenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shopping Lists:&lt;/strong&gt; &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/&quot;&gt;My DIY groceries app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meal Planning:&lt;/strong&gt; n/a&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Budgeting &amp;amp; Personal Finance:&lt;/strong&gt; Numbers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;News:&lt;/strong&gt; Mastodon (Ivory), Hacker News&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music:&lt;/strong&gt; Spotify&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Podcasts:&lt;/strong&gt; no dedicated podcast app, just a web browser&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password Management:&lt;/strong&gt; 1Password&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bonus stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code:&lt;/strong&gt; Visual Studio Code (Rainier theme)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terminal:&lt;/strong&gt; iTerm2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search:&lt;/strong&gt; &lt;a href=&quot;https://kagi.com/&quot;&gt;Kagi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;See others’ default apps&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;additional-comments&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#additional-comments&quot;&gt;Additional comments&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m very macOS-centric. I know for a lot of people their phone is their most personal device. For me that’s macOS via my Mac Studio and MacBook Pro. I have an iPhone but can’t physically operate it. I use just enough &lt;a href=&quot;https://support.apple.com/en-us/HT210417&quot;&gt;Voice Control&lt;/a&gt; to get by and I use macOS for everything else.&lt;/p&gt;
&lt;p&gt;Phone calls? &lt;a href=&quot;https://support.apple.com/en-us/102405&quot;&gt;macOS&lt;/a&gt;. Messages? &lt;a href=&quot;https://support.apple.com/guide/messages/get-sms-texts-from-iphone-on-your-mac-icht8a28bb9a/mac&quot;&gt;macOS&lt;/a&gt;. Writing? macOS. Notes? macOS. Fun and games? macOS. Social media? macOS. Reading? macOS. Art? macOS.&lt;/p&gt;
&lt;p&gt;For more on the assistive technology angle of my software, check out my &lt;a href=&quot;https://blakewatson.com/assistive-tech-gear/&quot;&gt;assistive tech gear page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;mail-server&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#mail-server&quot;&gt;Mail Server&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I signed up with Pobox a decade ago. Since then Pobox was acquired by Fastmail. They still operate somewhat separately, as there are separate dashboards and settings and such. But for webmail they both use Fastmail (I’m assuming there’s a lot of shared infrastructure behind the scenes). If I were signing up now, I’d just get Fastmail.&lt;/p&gt;
&lt;p&gt;As for why a paid mail provider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’m using my own domain so that I can switch mail providers in the future without changing my email address.&lt;/li&gt;
&lt;li&gt;I’ve read too many horror stories of people getting locked out of their Google (and even iCloud) account. If you’re not paying for it you’re the product.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;notes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#notes&quot;&gt;Notes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I switch notes apps all the time, but I’m pretty happy with &lt;a href=&quot;https://blog.bear.app/2023/07/bear-2-is-here/&quot;&gt;Bear 2&lt;/a&gt; for my general note-taking and blog-drafting needs. I use &lt;a href=&quot;https://tot.rocks/&quot;&gt;Tot for Mac&lt;/a&gt; for transient text, &lt;a href=&quot;https://www.hogbaysoftware.com/bike/&quot;&gt;Bike Outliner&lt;/a&gt; for outlining and long-form writing, and iA Writer for markdown writing and editing.&lt;/p&gt;
&lt;p&gt;Obsidian appeals to me but unfortunately my onscreen keyboard’s predictive text feature doesn’t work well in browsers or Electron-based apps, so it’s a non-starter.&lt;/p&gt;
&lt;p&gt;In the past I’ve used Craft, Simplenote, nvALT, Notational Velocity, and Evernote.&lt;/p&gt;
&lt;h3 id=&quot;cloud-file-storage&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#cloud-file-storage&quot;&gt;Cloud file storage&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Dropbox seems to increasingly do more things than just keeping a folder synced on all my computers. There is also a &lt;a href=&quot;https://help.dropbox.com/installs/dropbox-for-macos-support&quot;&gt;pretty big change with Dropbox on macOS due to low-level APIs&lt;/a&gt; for opening online-only files. Anyway, I’m not really interested in Dropbox’s other services or online-only files. I longed for the simpler Dropbox of yore, so I switched to using the Dropbox client, &lt;a href=&quot;https://maestral.app/&quot;&gt;Maestral&lt;/a&gt;, a few months ago and it’s been pretty great. It turns Dropbox back into what it used to be. I’ve seen a slight uptick in sync conflicts but not enough to dissuade me from using it.&lt;/p&gt;
&lt;h3 id=&quot;browser&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#browser&quot;&gt;Browser&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not too long ago I wrote about my &lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/&quot;&gt;multi-browser workflow&lt;/a&gt;. I’ve since decided to experiment with &lt;a href=&quot;https://arc.net/&quot;&gt;Arc&lt;/a&gt;. It has a feature called &lt;em&gt;Air Traffic Control&lt;/em&gt; that lets me open certain URL patterns in one workspace versus the other. With that, I’m able to have separate work and personal spaces/profiles and have links open in the correct one.&lt;/p&gt;
&lt;h3 id=&quot;presentations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#presentations&quot;&gt;Presentations&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I recently gave a conference talk using &lt;a href=&quot;https://ia.net/presenter&quot;&gt;iA Presenter&lt;/a&gt; and it really changed the way I think about public speaking. That could be a whole blog post of its own but, in short, it not-so-gently pushed me toward writing a good talk first and sprucing up the slides second.&lt;/p&gt;
&lt;h3 id=&quot;spreadsheets&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#spreadsheets&quot;&gt;Spreadsheets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I like Apple Numbers for one reason: you can put multiple tables on a page. This is a hill I will die on, probably alone.&lt;/p&gt;
&lt;h3 id=&quot;music&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/default-apps-2023/#music&quot;&gt;Music&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve been using Spotify exclusively for almost two years only because the Apple Music desktop app is just awful. It’s a shame because iTunes in the early days is responsible for me switching from Windows to Mac in 2006. I was about to purchase another Dell, then I got to thinking about how awesome my iPod was and how iTunes was my favorite program on my PC. I decided to see what kind of computers Apple sold and &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/&quot;&gt;the rest is history&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>MagnoliaJS 2023: The joys of home-cooked apps</title>
      <link href="https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/"/>
      <updated>2023-10-15T17:21:08Z</updated>
      <id>https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/</id>
      <content xml:lang="en" type="html">&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/kqxx1VNE_5s&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;h2 id=&quot;links-and-stuff&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#links-and-stuff&quot;&gt;Links and stuff&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s quick list of links to the stuff I mention in the talk. Scroll down for the full text. This page is also accessible at .&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/uploads/2023/10/The-joys-of-home-cooked-apps-MagnoliaJS.pdf&quot;&gt;PDF slides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;An app can be a home-cooked meal by Robin Sloan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://start.blakewatson.com/&quot;&gt;Start&lt;/a&gt; (no longer maintained)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; - my side hustle&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;My DIY bookmarks app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://writeremergency.com/&quot;&gt;Writer Emergency Pack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/finishing-side-projects/&quot;&gt;Finishing side projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Home-cooked app submissions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://scout.gaston.wtf/&quot;&gt;Scout’s dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/simonhildebrandt/tobuy&quot;&gt;tobuy GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/spencerc99/status/1447013977024651265&quot;&gt;Spencer’s siri shortcut tweet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dynamic-profiterole-188619.netlify.app/&quot;&gt;Breastfeeding tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/f11xter/celebrate&quot;&gt;Celebrate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rgwood/burninator&quot;&gt;Burninator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;text-version-of-the-talk&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#text-version-of-the-talk&quot;&gt;Text version of the talk&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/blake-magnoliajs2023-1024x576.jpg&quot; alt=&quot;Photo of me at MagnoliaJS. I’m sitting in my wheelchair at a small table by the podium. My laptop is open and off to the side behind me is my presentation slideshow. The cover slide reads &amp;quot;The joys of home-cooked apps. Blake Watson.&amp;quot;&quot; width=&quot;1024&quot; height=&quot;576&quot; class=&quot;alignnone size-large wp-image-1384&quot; /&gt;
&lt;figcaption&gt;Me at MagnoliaJS 2023 in Jackson, MS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Hey everyone. Welcome to &lt;em&gt;The joys of home-cooked apps&lt;/em&gt;. I’m Blake Watson. I’m a frontend developer and side-project enthusiast. I have a disability called spinal muscular atrophy. It basically means my muscle tone is in the trash. I will never be a gymnast. But I could plausibly turn out to be a supervillain.&lt;/p&gt;
&lt;p&gt;I use &lt;em&gt;a lot&lt;/em&gt; of technology to adapt and thrive, including some home-cooked apps I’m going to talk about in a bit. The state of technology, with all its faults, is pretty amazing right now. I basically get paid to sit in my house, click a mouse, and watch photons emanating out of a glass rectangle. What a time to be alive.&lt;/p&gt;
&lt;p&gt;I work remotely with MRI Technologies out of Houston, TX, working on projects for NASA and Collins Aerospace. I primarily work on a suite of internal web applications called COSMIC, which NASA uses for tracking and managing hardware related to the spacesuit.&lt;/p&gt;
&lt;p&gt;Before that I worked at Mad Genius, shoutout to the best ad agency in Mississippi. Before that I was a web dev enthusiast with no job for several years. So if you find yourself in that situation, don’t give up. Probably follow Taylor’s advice.&lt;/p&gt;
&lt;p&gt;I’m excited to be back at MagnoliaJS. Although, apologies to the other speakers—I’m mostly here to watch Kenneth LaFrance.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://afinestart.me/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/magnoliajs-1024x683.png&quot; alt=&quot;A Fine Start promo image. afinestart.me. Shows a new tab page in a web browser with three columns of plain text links.&quot; width=&quot;1024&quot; height=&quot;683&quot; class=&quot;alignnone size-large wp-image-1336&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p&gt;I’m also a community sponsor of MagnoliaJS again this year. A Fine Start is my main side-project. It’s a new-tab page browser extension. And I’ll be talking more about that in a bit.&lt;/p&gt;
&lt;p&gt;I have difficulty traveling but I had a lot of FOMO seeing all these great tech conferences around the country that I couldn’t get to. Frustrated with my options, I wrote a post on my blog in 2010 titled “&lt;a href=&quot;https://blakewatson.com/ihs/mississippi-needs-a-web-conference/index.html&quot;&gt;Mississippi needs a Web conference&lt;/a&gt;.” So this is personal for me and I’m very happy to support MagnoliaJS. Also go download my browser extension.&lt;/p&gt;
&lt;h2 id=&quot;home-cooked-apps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#home-cooked-apps&quot;&gt;Home-cooked apps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what am I talking about? What is a home-cooked app? It’s the kind of app that you make for yourself, to solve your own problem or for your own entertainment. Much like a home-cooked meal, it can be shared with friends or family. But it’s not designed for mass consumption.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/7nk8wf.jpg&quot; alt=&quot;Drake meme. Top: Best practices, ROI, KPIs, Scaling, Clean code. Bottom: Just get it working.&quot; width=&quot;500&quot; height=&quot;500&quot; class=&quot;alignnone size-full wp-image-1340&quot; /&gt;
&lt;p&gt;Home-cooked apps aren’t optimized for shareholders. There are no sales funnels. No user stories. No scrums. And they don’t scale. They don’t have to. They aren’t designed for thousands or millions of users. These are the kinds of apps that you make for a handful of people. Or maybe just for you.&lt;/p&gt;
&lt;h2 id=&quot;robin-sloan-%E2%80%94-author-%26-home-cook&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#robin-sloan-%E2%80%94-author-%26-home-cook&quot;&gt;Robin Sloan — author &amp;amp; home cook&lt;/a&gt;&lt;/h2&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/sloan-473x1024.png&quot; alt=&quot;Screenshot of a video app in mobile portrait orientation. Shows Sloan smiling with his dog. A red record button is at the bottom.&quot; width=&quot;473&quot; height=&quot;1024&quot; class=&quot;alignnone size-large wp-image-1342&quot; /&gt;
&lt;p&gt;Now I didn’t invent the term, &lt;em&gt;home-cooked app&lt;/em&gt;. A couple of years ago I read an &lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;article by Robin Sloan&lt;/a&gt;. He’s a New York Times best-selling author and calls himself the “programming equivalent of a home cook.” In this article he described making this sort of short form video messaging service just for use in his household.&lt;/p&gt;
&lt;p&gt;It was super simple. You basically hit record, send the video, and the receiver views it, after which it disappears.&lt;/p&gt;
&lt;p&gt;That’s it. He built it because the proprietary app they had been using was discontinued.&lt;/p&gt;
&lt;p&gt;The important bit here is that he didn’t make this app to be a product for the general public. He didn’t even design it to be a shared open source project. It’s literally an app built just for their own use. And that’s what makes it home-cooked.&lt;/p&gt;
&lt;p&gt;I’ve been making these kinds of apps for myself for years. It’s one of the things that drew me into programming. But I didn’t have a term for apps like this or even a context for thinking about them until I read Sloan’s article. I was thrilled to have a word for this idea—the idea that you can make useful things and they don’t need to be packaged for mass adoption to be successful.&lt;/p&gt;
&lt;h2 id=&quot;making-a-home-cooked-app-is-about-redefining-what-success-looks-like&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#making-a-home-cooked-app-is-about-redefining-what-success-looks-like&quot;&gt;Making a home-cooked app is about redefining what success looks like&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I love this. It’s a powerful idea. And maybe developers do this all the time—build things for themselves. But Sloan’s article was the first time I had heard it expressed this way and it smacked me right in the face—like of course we can make stuff just for ourselves. This is a thing we can do.&lt;/p&gt;
&lt;p&gt;Now, that’s not to say you should &lt;em&gt;never&lt;/em&gt; generalize a solution to make it more useful for more people. If you’re working on website or app meant to be used by others, you should be as inclusive as possible. I’m just saying not every idea needs to be a product or a package to be distributed.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/papaw-1024x800.jpg&quot; alt=&quot;Black and white photo of my grandfather sitting at a work desk in a shop. Looking fly because it was the sixties or seventies.&quot; width=&quot;1024&quot; height=&quot;800&quot; class=&quot;alignnone size-large wp-image-1345&quot; /&gt;
  &lt;figcaption&gt;My grandfather at bottom right&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I think back to my late grandfather who would often take to his shop to make custom things for himself and his family—a cabinet for his wife, toys for the grandkids, and even a custom-made wheelchair lock down system designed specifically for the van and wheelchairs me and my brother had at the time. As a kid I was mesmerized with his craftsmanship. Watching him, the idea of building things for oneself was ingrained in me at a young age.&lt;/p&gt;
&lt;p&gt;Okay, enough backstory. Let’s get into it.&lt;/p&gt;
&lt;h2 id=&quot;why%3F-how%3F-what%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#why%3F-how%3F-what%3F&quot;&gt;Why? How? What?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My job here today is to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Convince you that you should make your own home-cooked apps&lt;/li&gt;
&lt;li&gt;Show you a bunch examples of home-cooked apps&lt;/li&gt;
&lt;li&gt;Give you a little recipe to help you get started&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;but-why-tho%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#but-why-tho%3F&quot;&gt;But why tho?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are several good reasons you should make your own home-cooked apps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You can make exactly what you want. Have you ever used an app and thought to yourself, “Man, this app would be dope if it just did this &lt;em&gt;one thing&lt;/em&gt;?” &lt;em&gt;Guess I’ll have to make a feature request and wait around for months until the developer says they’re not going to do it.&lt;/em&gt; No, guess what? When you make it yourself, you can make it do that thing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you build with the idea that you are only serving yourself or a few people, you can skip over many of the challenging problems of software development: compatibility, extensibility, standards, best practices, scaling, etc. In the land of home-cooked apps, the only important benchmark is, &lt;strong&gt;does it work for you&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Another reason is privacy. You have some control over your data, depending on how you build your app. You have an opportunity to keep it out of the hands of big companies who will harvest it and use it for its own purposes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lastly, it’s fun. Building what you want and then using it is a rewarding experience. It’s magic to me. It’s what pulled me into web dev and why I still get excited about it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And with that let’s take a look at some examples. They’re gonna start off more general and get increasingly weirdly specific.&lt;/p&gt;
&lt;h2 id=&quot;start-(this-became-an-actual-product.-oops.)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#start-(this-became-an-actual-product.-oops.)&quot;&gt;Start (This became an actual product. Oops.)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay I’m going to start (heh) the tour of examples by breaking one of my own rules. I made &lt;a href=&quot;https://start.blakewatson.com/&quot;&gt;this new tab page&lt;/a&gt; called Start for myself but ended up packaging it up for other people to use. It ultimately became my main side project, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/start.png&quot; alt=&quot;Browser window showing a minimal page with two columns of plain text links.&quot; width=&quot;875&quot; height=&quot;643&quot; class=&quot;alignnone size-full wp-image-1348&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The idea here was to have a single HTML file as a new tab page that would allow you to add and organize text links directly on the page. At the time I created it, built-in new tab pages were using gratuitous visual effects, ugly screenshots of webpages, and had very poor user experience in my opinion. I just wanted a new tab page with plain text links that I could add, edit, and arrange.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/AFS_Screen_02-1024x705.png&quot; alt=&quot;Browser window showing a minimal page with three columns of plain text links.&quot; width=&quot;1024&quot; height=&quot;705&quot; class=&quot;alignnone size-large wp-image-1349&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;I made it for me but after a few years I ended up packaging it up into a browser extension called A Fine Start and found out others liked it too. That’s cool that it worked out that way, but it’s not required in the world of home-cooked apps.&lt;/p&gt;
&lt;h2 id=&quot;my-diy-pinboard-replacement&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#my-diy-pinboard-replacement&quot;&gt;My DIY Pinboard replacement&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you’ve never heard of Pinboard, it’s a web app for keeping web bookmarks. So it keeps the URL, title, description, and you can add tags for organization. I’ve been a longtime user and this app met my needs adequately for a long time.&lt;/p&gt;
&lt;p&gt;But it was also becoming the place where my bookmarks went to die. I felt like retrieving things from it wasn’t very easy. I also paid for an optional archival account. This means that every link I add gets cached by Pinboard so that if that URL goes bad (which so many of them do) I would still have a copy.&lt;/p&gt;
&lt;p&gt;But I noticed my archival account was often failing to capture pages. And the whole thing was becoming unenjoyable.&lt;/p&gt;
&lt;p&gt;What to do?&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2022/12/bookmarks-screenshot-1024x741.png&quot; alt=&quot;Browser window in dark mode. Shows a simple interface with a search bar followed by a main column of bookmark entries. The search bar contains the text, &amp;#039;#WebDesign #css font.&amp;#039; Each entry has a title, URL, description, and associated tags. A sidebar on the right shows a list of all tags that are part of the search result set.&quot; width=&quot;1024&quot; height=&quot;741&quot; class=&quot;alignnone size-large wp-image-808&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;You will be shocked to hear that I created my own solution. It’s a NodeJS app that saves URLs along with metadata like descriptions and tags. It automatically sends the URL to Wayback Machine via an API and it saves the cached URL that Wayback returns, so that I always have access to a cached copy.&lt;/p&gt;
&lt;p&gt;Now just to be clear, this is an app I host myself for just me. It doesn’t have users or sign ups or anything like that. I did break my own rule and &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;open sourced this app&lt;/a&gt; with instructions for setting it up. But it comes with the &lt;em&gt;huge&lt;/em&gt; caveat that I designed this for me and didn’t take any other people into account.&lt;/p&gt;
&lt;h2 id=&quot;paymenow&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#paymenow&quot;&gt;PayMeNow&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/Capture-2023-10-15-100504-1024x898.png&quot; alt=&quot;Screenshot of the PayMeNow settle up screen. Dropdown inputs show that Blake and Matt are selected. Below that a card says &amp;quot;Blake owes Matt a total of $155&amp;quot; along with a button to copy the URL and a primary button to complete all payments. A couple of tables below list out what is owed to whom and what for—things like food, gas, and stuff from Amazon.&quot; width=&quot;1024&quot; height=&quot;898&quot; class=&quot;alignnone size-large wp-image-1351&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;My family is constantly getting mixed up about what money we owe each other.&lt;/p&gt;
&lt;p&gt;So a couple of weeks ago I made this little app called PayMeNow to help my family keep track of what we owe each other. In this screenshot we’re looking at what I called the settle up screen. You select two people (me and my brother in this case) and you get a list of everything owed between us, which gets boiled down to one number.&lt;/p&gt;
&lt;p&gt;We’ll use Cash App or something separately to make the actual payment then we can hit the &lt;em&gt;Complete all payments&lt;/em&gt; button to mark all the items as completed&lt;/p&gt;
&lt;h2 id=&quot;writer-emergency-pack-card-viewer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#writer-emergency-pack-card-viewer&quot;&gt;Writer Emergency Pack card viewer&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/CleanShot-2023-10-14-at-14.58.10@2x-1024x716.png&quot; alt=&quot;Screenshot showing two cards from the Writer Emergency Pack XL. The first card has an illustration of an owl delivering a package. Text below says &amp;quot;Mysterious Package: Special delivery!&amp;quot; The second card has an illustration depicting two warriors confronting a fake dragon whilst the real dragon is hiding behind it. Text below says, &amp;quot;That&amp;#039;s not the dragon: You thought that was the enemy? Nope. The real danger lies ahead. The first card has a UI overlay indicating that you can cycle through the cards, flip the card over, zoom the card, etc.&quot; width=&quot;1024&quot; height=&quot;716&quot; class=&quot;alignnone size-large wp-image-1354&quot; /&gt;
  &lt;figcaption&gt;I&#39;m not allowed to link to this project because of copyrights.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;So I enjoy doing a bit of creative writing. Every year I participate in a marathon event called  &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;. (Just curious show of hands if you have ever attempted it)&lt;/p&gt;
&lt;p&gt;It’s a wild 30-day challenge to write a 50-thousand word novel during November. It often means I’m scrambling to invent my story on the fly.&lt;/p&gt;
&lt;p&gt;So I ordered this deck of cards called  &lt;a href=&quot;https://writeremergency.com/&quot;&gt;Writer Emergency Pack&lt;/a&gt;. It’s a thing for storytelling. Every card has advice on how to get your story unstuck, giving you new ways to think about your characters and plot. They’re awesome, but I’m not able to physically handle a deck of cards, so I had my assistant help me scan them all in and I created a web viewer that lets me flip through the cards, draw them at random, flip them over to read the back, and generally use them as you might the physical deck.&lt;/p&gt;
&lt;p&gt;There’s a link in my notes to their website but I’m not allowed to share the web viewer because of copyright.&lt;/p&gt;
&lt;h2 id=&quot;a-home-cooked-language&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#a-home-cooked-language&quot;&gt;A home-cooked language&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My brother and I have a team of caregivers that work various day and night shifts. At the end of each pay period they need to turn in detailed timesheets. Sometimes these timesheets are difficult and error-prone.&lt;/p&gt;
&lt;p&gt;I wanted a way to keep my own records and also help my caregivers complete the timesheets accurately. I toyed around briefly with a spreadsheet. I know they’re powerful, but man I hate them. After being annoyed with that, I decided that what I really needed was something that worked like Markdown. I wanted a plaintext entry system. It works like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# This is a comment. It is ignored.

1 Day
Johnny Appleseed

1-2 Night
Jane Doe

# Johnny left early
2 Day (7:00am-3:00pm)
Johnny Appleseed

2-3 Night *
Jane Doe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each shift that is worked, I make an entry. Entries are separated by a line break. Each entry is two lines. The top line is the date followed by the type of shift that was worked (Day/Night). The next line is the name of the person who worked.&lt;/p&gt;
&lt;p&gt;Most shifts follow a standard time range so I don’t specify the start and end time. But if, for some reason, someone works a different time schedule than normal, I can specify that in parentheses.&lt;/p&gt;
&lt;p&gt;That last piece of metadata is represented by an asterisk and it means my bother and I were together for the whole shift and the caregiver worked with both of us. That means they’ll need to do a timesheet for each of us and split the hours.&lt;/p&gt;
&lt;p&gt;I don’t specify the month and the year because that info will be used at compile time, which we’ll see in a second.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/parser.png&quot; alt=&quot;Small screenshot showing an empty textarea with the placeholder text &amp;quot;Paste in shorthand notes.&amp;quot; Below is a text input for the year, a dropdown for the month, and a submit button.&quot; width=&quot;704&quot; height=&quot;852&quot; class=&quot;alignnone size-full wp-image-1358&quot; /&gt;
&lt;p&gt;I wrote a little frontend tool that can process this syntax and spit out a table of dates and times that I can print out for my caregivers to help them complete their timesheets.&lt;/p&gt;
&lt;p&gt;This is where I paste in the plaintext data and provide the month and year.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/10/timesheet-1024x625.png&quot; alt=&quot;Screenshot of multiple tables that meticulously list clock-in, clock-out times over the course of a few weeks.&quot; width=&quot;1024&quot; height=&quot;625&quot; class=&quot;alignnone size-large wp-image-1359&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;This is an example printout. It’s hard to tell what’s going on here—and that’s why I made this tool to figure it out. The timesheets we have to use were terribly designed.&lt;/p&gt;
&lt;p&gt;The agency requires that the timesheets be completed by hand so what my tool does is output something that my caregivers can use as a reference while they are filling out the timesheets.&lt;/p&gt;
&lt;h2 id=&quot;domain-specific-language&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#domain-specific-language&quot;&gt;Domain-specific language&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I didn’t know it at the time, but this kind of thing has a name—it’s called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-specific_language&quot;&gt;domain-specific language&lt;/a&gt;. In this case, a human-readable computer language designed specifically for tracking caregiver hours between two people. My frontend tool is the compiler so to speak, which produces the final output—HTML tables I can print. I store all of my records in my note-taking app of choice as what you could think of as &lt;em&gt;source code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This year marks one decade since I first made this app. I’m sure I would do it much differently now, but even with its idiosyncrasies (and a lot of jQuery), it gets the job done and it’s held up longer than many other things I’ve made.&lt;/p&gt;
&lt;h2 id=&quot;crowd-sourced-examples&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#crowd-sourced-examples&quot;&gt;Crowd-sourced examples&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I put out a form and took submissions from people on social media, specifically asking for examples of home-cooked apps. I got some great examples back.&lt;/p&gt;
&lt;h3 id=&quot;scout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#scout&quot;&gt;Scout&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is &lt;a href=&quot;https://scout.gaston.wtf/&quot;&gt;Scout’s dashboard&lt;/a&gt;. Scout is a dog who has epilepsy so her owner, Gaston, made this page that keeps track of her seizures and he shares it with friends and family who want to know how she’s doing.&lt;/p&gt;
&lt;p&gt;It has some nice charts and graphs with things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scout’s seizures broken down by time of day, day of the week, and even phase of the moon.&lt;/li&gt;
&lt;li&gt;It categorizes her seizures into three types so all the breakdowns are further split into those.&lt;/li&gt;
&lt;li&gt;And it has descriptions of what her symptoms and behavior are like.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s just a sweet personal thing that’s incredibly useful to the people who need it.&lt;/p&gt;
&lt;h3 id=&quot;i-love-living&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#i-love-living&quot;&gt;I love living&lt;/a&gt;&lt;/h3&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/10/love-life-951x1024.jpg&quot; alt=&quot;Two mobile screenshots. One shows the construction of the Siri shortcut in iOS. The other shows the resulting note that says &amp;quot;i love living&amp;quot; and has the address and the time and date.&quot; width=&quot;951&quot; height=&quot;1024&quot; class=&quot;alignnone size-large wp-image-1361&quot; /&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/spencerc99/status/1447013977024651265&quot;&gt;Spencer said&lt;/a&gt; “[I] have started keeping a note in my phone where I had a timestamp every time I am intimate with the feeling of an indomitable joy of / gratitude for life. It’s a Siri shortcut now.”&lt;/p&gt;
&lt;p&gt;What I love about this is that it’s an app made with the no-code tools that were available. You might not think of it as an app at first, but tools like this can enable even more people to create software specific to them.&lt;/p&gt;
&lt;h3 id=&quot;other-submissions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#other-submissions&quot;&gt;Other submissions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;David made a breast feeding tracker for his partner that only asks which side and when you hit the button it records the time in &lt;code&gt;localStorage&lt;/code&gt; until the next time. That’s it. A two-button app.&lt;/p&gt;
&lt;p&gt;Felix struggled with being lonely after starting his degree so he made an app where you list out your achievements and, after a short loading sequence, it gives you a compliment.&lt;/p&gt;
&lt;p&gt;Simon submitted a grocery list app he created for him and his wife. I love this because he said “No” to the million-and-one list apps out there and made his own. Now there’s a million-and-two.&lt;/p&gt;
&lt;p&gt;Reilly’s friend had a laptop where the screen would flicker if the GPU dropped below a certain temperature so they made an app that keeps the GPU warm—literal cooking in this case.&lt;/p&gt;
&lt;h2 id=&quot;recipe&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#recipe&quot;&gt;Recipe&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These apps were made for me or their respective creators, so I’m not expecting you to think, “Oh I could use that,” necessarily. I just want to get your creative juices flowing about how you could address some of your own specific wants and needs.&lt;/p&gt;
&lt;h2 id=&quot;the-what&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#the-what&quot;&gt;The What&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is just a little recipe to get you started. There is really no right or wrong way to go about it. If it works for you, then do it.&lt;/p&gt;
&lt;p&gt;Think of a problem of yours that you could solve. For example, some tedious work that you wish you had an app for but don’t. Or something you and your friends would like to use that isn’t readily available. It could be something a popular app does but in a way that is much simpler and straightforward or specific to you.&lt;/p&gt;
&lt;h2 id=&quot;the-what%2C-exactly&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#the-what%2C-exactly&quot;&gt;The What, &lt;em&gt;exactly&lt;/em&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you have a general idea, give yourself some rough requirements. Make a list. If it has UI, do little napkin sketch. I like to go into my notes app of choice and type out a list of the features I need and jot down a few notes about the behavior of the app.&lt;/p&gt;
&lt;p&gt;It’s important at this stage to explore ideas but don’t be tempted to add a million features. You don’t want to get overwhelmed and kill the project on the vine.&lt;/p&gt;
&lt;p&gt;You may have heard the term, MVP, or &lt;em&gt;minimum viable product&lt;/em&gt;. It’s the idea that you define the least amount of features that accomplish the main goal of the app. That’s close to what we’re doing here, but even easier! Because remember, we’re not making a &lt;em&gt;product&lt;/em&gt; per se. It’s something simpler and rougher. It’s home-cooked. Let’s call it a &lt;em&gt;minimum viable meal&lt;/em&gt;. That’s your job as a home cook to figure out at this stage.&lt;/p&gt;
&lt;p&gt;The main thing is to solve &lt;em&gt;your&lt;/em&gt; problem, not some abstract user’s problem. That may sound obvious, but it’s easier said than done. All of your developer instincts are gonna push back and throw little red flags up. Ignore them.&lt;/p&gt;
&lt;h2 id=&quot;the-how&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#the-how&quot;&gt;The How&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Determine the easiest way to get to your goal. No need to over-complicate things—unless you enjoy that sort of thing! We are developers after all.&lt;/p&gt;
&lt;p&gt;My advice here is to use what you know. But really you can use whatever technology you want. I don’t care if it’s new and shiny or old and boring. Use jQuery if you want. Or no JavaScript at all. This thing you’re building just needs to work for you so feel free to adopt whatever technical debt you want.&lt;/p&gt;
&lt;p&gt;What’s important is that all decisions are in service of getting the thing to work.&lt;/p&gt;
&lt;h2 id=&quot;build-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#build-it&quot;&gt;Build it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Even if it’s a larger project, just make small progress toward it. I’ve written some tips about &lt;a href=&quot;https://blakewatson.com/journal/finishing-side-projects/&quot;&gt;finishing side projects&lt;/a&gt;. Check out the written version of this talk for a link to that.&lt;/p&gt;
&lt;p&gt;But TL;DR, small progress adds up. Use your commit history for motivation—it’s an automatic list of everything you have accomplished. If you’ve kept things simple, then hopefully it won’t take too long to knock out the rough draft.&lt;/p&gt;
&lt;p&gt;Once you start using it you can take note of any enhancements or bug fixes you need to make.&lt;/p&gt;
&lt;h2 id=&quot;go-cook-up-your-own-apps!&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/#go-cook-up-your-own-apps!&quot;&gt;Go cook up your own apps!&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most of the home-cooked apps I’ve made took me a weekend or two. When you strip an app down to its essentials and the only requirements are yours, you have the freedom to hack things together however you see fit.&lt;/p&gt;
&lt;p&gt;I think the time investment on these projects was totally worth it. The example of the timesheet system, in particular, has saved me probably &lt;em&gt;days&lt;/em&gt; of time pouring over timesheets.&lt;/p&gt;
&lt;p&gt;Hopefully this has you thinking of how to tackle a problem of your own or make a fun thing just for friends or family. Home-cooked apps are fun, useful, and a breath of fresh air.&lt;/p&gt;
&lt;p&gt;So, go forth cook up some of your own.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Fancy forEach with functional programming in JavaScript</title>
      <link href="https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/"/>
      <updated>2023-09-19T04:56:38Z</updated>
      <id>https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’m not a functional programming guru by any means, but I have a passing curiosity and I’ve been trying to learn more about it. I recently dealt with some annoying, repetitive code at work&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; by applying some functional programming concepts.&lt;/p&gt;
&lt;p&gt;Here’s a boiled down example that’s similar to what I ran into.&lt;/p&gt;
&lt;p&gt;First, suppose you have an API that gives you a list of TV shows. We’ll store them in an array like this.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const tvShows = [
  { id: 100, name: &#39;Better Call Saul&#39; },
  { id: 101, name: &#39;Fringe&#39; },
  { id: 102, name: &#39;Stargate SG-1&#39; },
  { id: 103, name: &#39;Ted Lasso&#39; },
  { id: 104, name: &#39;The Office&#39; }
];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now assume that a separate API call gives us a user’s watch list. It’s an array of IDs corresponding to TV shows they would like to watch at some point.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const watchList = [101, 102, 104, 105];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is just an array of numbers. But look again and you may notice a problem. We received the ID &lt;code&gt;105&lt;/code&gt; in our &lt;code&gt;watchList&lt;/code&gt;, but we don’t have a TV show in our dataset with that ID.&lt;/p&gt;
&lt;p&gt;Now, in a real world app you would probably need to deal with this discrepancy in some kind of nice way. For our purposes, however, we’re following the rule that if we receive an ID that our program doesn’t know about, we can just ignore it.&lt;/p&gt;
&lt;p&gt;With that in mind, let’s think about how we would retrieve a list of TV show names, based on the user’s watch list. Here’s one way we could do it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const names = [];

for (const id of watchList) {
  const show = tvShows.find(s =&amp;gt; s.id === id);
  
  if (show) {
    names.push(show.name);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’re given the ID, so we can do a lookup based on that, then add the name of the show to the list.&lt;/p&gt;
&lt;p&gt;This isn’t terrible, but because we have to deal with potentially nonexistent IDs, we have to check the result of the lookup to make sure it exists before trying to add its name to our list.&lt;/p&gt;
&lt;p&gt;We can tighten this up a bit by chaining together a few of JavaScript’s array methods. This results in more concise and FP-friendly code.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const names = watchList
  .map(id =&amp;gt; tvShows.find(s =&amp;gt; s.id === id)?.name)
  .filter(s =&amp;gt; s);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Array&lt;/code&gt; object’s &lt;code&gt;map&lt;/code&gt; method&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; returns a new array based on the original. The difference is that it lets us run a function on each item in the array. Whatever we return from that function ends up in the new array.&lt;/p&gt;
&lt;p&gt;We’re first mapping the watch list. For each ID, we do a lookup with &lt;code&gt;find&lt;/code&gt; and return the name of the show. We’re taking advantage of JavaScript’s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining&quot;&gt;optional chaining&lt;/a&gt; feature (notice the &lt;code&gt;?.&lt;/code&gt;). If the show doesn’t exist, this causes the expression to short circuit and return &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, we add a quick filter on the end to throw out any &lt;code&gt;undefined&lt;/code&gt; items in our list of names.&lt;/p&gt;
&lt;p&gt;This is better. But if we need to do this often, it’s kind of annoying that we have to do the lookup and the filter &lt;em&gt;every time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There are multiple ways to solve this, of course. For example, it would probably be smart to run this loop one time and store the results in an array for future usage. Let’s assume that there’s an external reason preventing us from doing that.&lt;/p&gt;
&lt;p&gt;Instead, let’s make a new function that does the work for us.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const mapWatchList = fn =&amp;gt; watchList
  .map(id =&amp;gt; tvShows.find(s =&amp;gt; s.id === id))
  .filter(s =&amp;gt; s)
  .map(fn);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we’ve created a function called &lt;code&gt;mapWatchList&lt;/code&gt;. It receives a function as its only parameter. It then maps the watch list, returning the corresponding show for each ID. It then filters out any instances where the show doesn’t exist. Finally, it maps over the new list of shows using the callback function it received.&lt;/p&gt;
&lt;p&gt;This means that we can now access the watch list, not as IDs, but as TV show objects.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const names = mapWatchList(show =&amp;gt; show.name);
console.log(names)
// [ &#39;Fringe&#39;, &#39;Stargate SG-1&#39;, &#39;The Office&#39; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is one problem, though. While our code does work, it is a bit inefficient. It must loop over all of the TV shows, then loop over the results in order to filter out nonexistent shows. Then, finally, loop over the results of &lt;em&gt;that&lt;/em&gt;, invoking the callback function for each item. That’s three loops. Ideally, we’d only loop through the TV show list one time.&lt;/p&gt;
&lt;p&gt;Let’s refactor our &lt;code&gt;mapWatchList&lt;/code&gt; function so that it works the same way but only performs one loop over the list. For this, we will be returning to our performant friend,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; the &lt;code&gt;for...of&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const mapWatchList = fn =&amp;gt; {
  const mappedShows = [];
  
  for (const id of watchList) {
    const show = tvShows.find(s =&amp;gt; s.id === id);
    
    if (show) {
      mappedShows.push(fn(show));
    }
  }
  
  return mappedShows;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again we are accepting a function as the only parameter. Remember, the goal of this function is to use it like a map. That means it should invoke our callback function on each item of the watch list and use the return value of the callback as an item in the new array.&lt;/p&gt;
&lt;p&gt;We create an empty array that will hold all of our mapped shows. Then we iterate through the &lt;code&gt;watchList&lt;/code&gt;. For each ID, we do a lookup to get the full show object. If we find one, we invoke the callback function and store the result in the &lt;code&gt;mappedShows&lt;/code&gt; array.&lt;/p&gt;
&lt;p&gt;After the loop is complete, we return the results.&lt;/p&gt;
&lt;p&gt;This works great, and we could stop here.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But…&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It’s kind of not great that we are accessing variables that live outside our function (&lt;code&gt;tvShows&lt;/code&gt; and &lt;code&gt;watchList&lt;/code&gt;). And what if our application needs to do the same thing but for other entities besides TV shows?&lt;/p&gt;
&lt;p&gt;For our final trick, let’s go up one more level and make a function that can make the &lt;code&gt;mapWatchList&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;To do this, we need to think generically. Instead of a list of TV shows and list of TV show IDs, let’s think of it as being a &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;ids&lt;/code&gt;. Now in our case we are matching based on &lt;code&gt;&#39;id&#39;&lt;/code&gt;, but let’s make it such that you can match on whatever primitive value you want. We will call that the &lt;code&gt;identifier&lt;/code&gt;, and the consumer of our function will need to pass that in.&lt;/p&gt;
&lt;p&gt;So we’ll ask for these three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;list&lt;/code&gt;: this is the full array of objects&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ids&lt;/code&gt;: this is an array of &lt;em&gt;identifiers&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;identifier&lt;/code&gt;: this is a string, such as &lt;code&gt;&#39;id&#39;&lt;/code&gt;, that we will use for the lookup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here we goooooo (Mario voice):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const mapThingsWithIds = (list, ids, identifier) =&amp;gt; fn =&amp;gt; {
  const mappedThings = [];
  
  for (const id of ids) {
    const thing = list.find(s =&amp;gt; s[identifier] === id);
    
    if (thing) {
      mappedThings.push(fn(thing));
    }
  }
  
  return mappedThings;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s go from the inside out. We are still returning a function that loops over a list of IDs, does a lookup from a list of objects, then invokes a callback for each item it finds. But rather than access specific arrays, we wrap our function inside &lt;em&gt;another function&lt;/em&gt; that accepts the information we need.&lt;/p&gt;
&lt;p&gt;We use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const mapWatchList = mapThingsWithIds(tvShows, watchList, &#39;id&#39;);
const names = mapWatchList(show =&amp;gt; show.name);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If this is breaking your brain, I get it. Creating a function that returns a function that returns a function can get a little trippy to think about. But what we’ve done is make our work reusable and flexible. We are no longer limited to TV shows.&lt;/p&gt;
&lt;p&gt;We can use our new function with any other kind of entity, and match using a property other than &lt;code&gt;&#39;id&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;const mapReadingList = mapThingsWithIds(books, readingList, &#39;isbn&#39;);
const titles = mapReadingList(book =&amp;gt; book.title);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See? Nice, efficient, and reusable!&lt;/p&gt;
&lt;p&gt;But I have a confession to make. In my case, I didn’t go this far. I stopped after making the first helper function. The point of this little tutorial is just to show you what you &lt;em&gt;can&lt;/em&gt; do. Even turning a little bit of procedural code into more declarative, functional code can be helpful. This only scratches the surface of interesting things you can do with a functional programming style. If you want more on this, check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/playlist?list=PL0zVEGEvSaeEd9hlmCXrk5yUyqUag-n84&quot;&gt;Functional programming in JavaScript&lt;/a&gt;: A video series on YouTube by Fun Fun Function.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://leanpub.com/fljs&quot;&gt;Functional-Light JavaScript&lt;/a&gt;: an ebook by Kyle Simpson. “A uniquely pragmatic approach to explaining core functional programming concepts WITHOUT wading through mathematical notation or heavy terminology.”&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Code that I wrote, just to be clear. 😅 &lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;code&gt;for&lt;/code&gt; loops are faster than JavaScript’s array methods. &lt;a href=&quot;https://leanylabs.com/blog/js-forEach-map-reduce-vs-for-for_of/&quot;&gt;https://leanylabs.com/blog/js-forEach-map-reduce-vs-for-for_of/&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/fancy-foreach-with-functional-programming-in-javascript/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>100 ways to generate a story idea</title>
      <link href="https://blakewatson.com/journal/100-ways-to-generate-a-story-idea/"/>
      <updated>2023-08-19T21:09:30Z</updated>
      <id>https://blakewatson.com/journal/100-ways-to-generate-a-story-idea/</id>
      <content xml:lang="en" type="html">&lt;p&gt;In late October 2019, I desperately scoured the NaNoWriMo forums searching for creative inspiration ahead of November’s big writing event.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/100-ways-to-generate-a-story-idea/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; At some point, I decided to write down as many ways to generate a story as I could think of. This was the result, which I just rediscovered in my notes.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Steal the plot of another story&lt;/li&gt;
&lt;li&gt;Adopt a plot on the NaNo forums&lt;/li&gt;
&lt;li&gt;Combine a fairy tale with a different genre or time period&lt;/li&gt;
&lt;li&gt;Use the titles of an album or playlist as plot points/chapter titles&lt;/li&gt;
&lt;li&gt;Snowflake method&lt;/li&gt;
&lt;li&gt;Free write&lt;/li&gt;
&lt;li&gt;Fanfiction&lt;/li&gt;
&lt;li&gt;Based on real events&lt;/li&gt;
&lt;li&gt;Based on an interesting person you know in real life&lt;/li&gt;
&lt;li&gt;Use an alternative history&lt;/li&gt;
&lt;li&gt;Use a list of random words as plot points&lt;/li&gt;
&lt;li&gt;Write a sequel to an existing story&lt;/li&gt;
&lt;li&gt;Write a Coen brothers-esque story&lt;/li&gt;
&lt;li&gt;Take inspiration from a particular time period&lt;/li&gt;
&lt;li&gt;Take an existing story and change its style or genre&lt;/li&gt;
&lt;li&gt;Take an existing conflict from current events and switch up its details/style/genre&lt;/li&gt;
&lt;li&gt;Ask a series of what if questions&lt;/li&gt;
&lt;li&gt;Write a prequel or origin story to an existing story&lt;/li&gt;
&lt;li&gt;Use characters and events from previous, unfinished stories&lt;/li&gt;
&lt;li&gt;Write what you know&lt;/li&gt;
&lt;li&gt;Write what you don’t know&lt;/li&gt;
&lt;li&gt;Write what you wish you knew&lt;/li&gt;
&lt;li&gt;Based on a board game&lt;/li&gt;
&lt;li&gt;Based on D&amp;amp;D&lt;/li&gt;
&lt;li&gt;Use a writing prompt&lt;/li&gt;
&lt;li&gt;Make a list of 100 plot ideas&lt;/li&gt;
&lt;li&gt;Rewrite an existing story (original or otherwise)&lt;/li&gt;
&lt;li&gt;Write a Stanley Kubrick-esque story&lt;/li&gt;
&lt;li&gt;Write from the perspective of a dead historical figure&lt;/li&gt;
&lt;li&gt;Write about a character who’s traveling through different existing stories like the Energizer bunny&lt;/li&gt;
&lt;li&gt;Use the &lt;a href=&quot;https://writeremergency.com/&quot;&gt;Writer Emergency Pack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use story dice (or whatever they’re called)&lt;/li&gt;
&lt;li&gt;Make up some different characters and then see how you can relate them to each other&lt;/li&gt;
&lt;li&gt;Turn a movie or TV show into a novel&lt;/li&gt;
&lt;li&gt;Write an original story story that takes place in an existing story’s world&lt;/li&gt;
&lt;li&gt;Look through old plot idea notes&lt;/li&gt;
&lt;li&gt;Turn your friends into characters in a story&lt;/li&gt;
&lt;li&gt;Turn a poem into a full story&lt;/li&gt;
&lt;li&gt;Turn a short film (like the ones from Dust on YT) into a story&lt;/li&gt;
&lt;li&gt;Based on a video game&lt;/li&gt;
&lt;li&gt;Based on an obscure/odd profession&lt;/li&gt;
&lt;li&gt;Based on a fictional profession&lt;/li&gt;
&lt;li&gt;Based on a fictional sport&lt;/li&gt;
&lt;li&gt;Imagine the villain is suing the hero or vice-versa&lt;/li&gt;
&lt;li&gt;Make up one-sentence story ideas&lt;/li&gt;
&lt;li&gt;Ask someone else what kind of story they would like to read&lt;/li&gt;
&lt;li&gt;Based on a particular aesthetic&lt;/li&gt;
&lt;li&gt;Based on Biblical stories or characters&lt;/li&gt;
&lt;li&gt;Write a fictional religious text&lt;/li&gt;
&lt;li&gt;Write a manifesto&lt;/li&gt;
&lt;li&gt;Write non-fiction&lt;/li&gt;
&lt;li&gt;Based on a comic book&lt;/li&gt;
&lt;li&gt;Based on a TV show&lt;/li&gt;
&lt;li&gt;Take the problems of one historical character and have a different historical character experience them&lt;/li&gt;
&lt;li&gt;Based on a web comic (eg, xkcd)&lt;/li&gt;
&lt;li&gt;Based on characters from popular toy franchises (eg, GI Joe)&lt;/li&gt;
&lt;li&gt;Write from the perspective of a journalist chasing a story&lt;/li&gt;
&lt;li&gt;Interview with hero&lt;/li&gt;
&lt;li&gt;Interview with the villain&lt;/li&gt;
&lt;li&gt;Based on a rare medical condition&lt;/li&gt;
&lt;li&gt;Based on a major catastrophe&lt;/li&gt;
&lt;li&gt;Take the villain (or hero) from one story and insert them into another&lt;/li&gt;
&lt;li&gt;Write about Donald Trump if he were in a different profession (eg, private investigator)&lt;/li&gt;
&lt;li&gt;Turn a Greek epic into a contemporary story&lt;/li&gt;
&lt;li&gt;Use a plot generator&lt;/li&gt;
&lt;li&gt;Use a character generator&lt;/li&gt;
&lt;li&gt;Draw a storyboard&lt;/li&gt;
&lt;li&gt;Pick different stock photos and relate them together&lt;/li&gt;
&lt;li&gt;What if a fact or assumption everyone agreed on turned out to be wrong?&lt;/li&gt;
&lt;li&gt;Write about an industry as if it were a different industry (eg, what if Apple and Microsoft were hospitals?)&lt;/li&gt;
&lt;li&gt;Use a selection of tropes as storytelling mechanisms&lt;/li&gt;
&lt;li&gt;Write about a weird or scary time in your own life&lt;/li&gt;
&lt;li&gt;Build a world first, then add the characters&lt;/li&gt;
&lt;li&gt;Build a detailed character first and then develop the plot&lt;/li&gt;
&lt;li&gt;Write about online communities as if they were IRL institutions (eg, Redditors Guild)&lt;/li&gt;
&lt;li&gt;Start with a visceral scene or concept and work outward from there&lt;/li&gt;
&lt;li&gt;Start with the ending and work backward&lt;/li&gt;
&lt;li&gt;Write some dialog between two characters with opposing wants and see if an idea is born out of that&lt;/li&gt;
&lt;li&gt;Start with a main idea/character/setting and mindmap out from there&lt;/li&gt;
&lt;li&gt;Use the life of an animal as inspiration for a story (eg, ants are like militant colonists)&lt;/li&gt;
&lt;li&gt;Start with a question and ask more questions&lt;/li&gt;
&lt;li&gt;Write about something you wish would happen&lt;/li&gt;
&lt;li&gt;Based on song lyrics&lt;/li&gt;
&lt;li&gt;Based on a sidekick to a popular hero&lt;/li&gt;
&lt;li&gt;Write about possible near-future events&lt;/li&gt;
&lt;li&gt;Write a short story first, then turn it into a novel&lt;/li&gt;
&lt;li&gt;Turn a play into a novel&lt;/li&gt;
&lt;li&gt;Create a story from a mad-lib-style template&lt;/li&gt;
&lt;li&gt;Create random characters from a generator and try to make a story with them&lt;/li&gt;
&lt;li&gt;Roll a D&amp;amp;D character (or two) and make a story out of them&lt;/li&gt;
&lt;li&gt;Write a story based on a published D&amp;amp;D adventure&lt;/li&gt;
&lt;li&gt;Write the plot of a Western into a modern day story&lt;/li&gt;
&lt;li&gt;Take the plot of a sci-fi and turn it into a Western&lt;/li&gt;
&lt;li&gt;Sit outside and see where your mind takes you&lt;/li&gt;
&lt;li&gt;Create a magic system or game mechanic and then build a story out of it&lt;/li&gt;
&lt;li&gt;Write a story where each chapter is based on a joke&lt;/li&gt;
&lt;li&gt;Create a character that has an obscure phobia&lt;/li&gt;
&lt;li&gt;What’s the scariest thing you can possibly imagine? Create a story about that&lt;/li&gt;
&lt;li&gt;Create a story that’s preachy about a particular religious or political point&lt;/li&gt;
&lt;li&gt;Create a series of short stories that are tied together by theme or setting or something else (eg, they all take place in the same world)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;NaNoWriMo (or &lt;a href=&quot;https://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt;) is a writing event that happens every November. Writers all over the world scramble to write a 50k-word novel by the end of the month. &lt;a href=&quot;https://blakewatson.com/journal/100-ways-to-generate-a-story-idea/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Multi-browser workflow on macOS with Choosy</title>
      <link href="https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/"/>
      <updated>2023-08-14T03:24:20Z</updated>
      <id>https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/</id>
      <content xml:lang="en" type="html">&lt;p&gt;One web browser is plenty for most folks but you might find yourself needing more for various reasons. For instance, here is a handful of activities I can think of that you might want to perform in separate browsers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Work activity.&lt;/strong&gt; Maybe you have a time-tracking extension for work. Or you are logged into your work Google account. Etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Development.&lt;/strong&gt; Maybe you love to develop in a particular browser because of its devtools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Social media.&lt;/strong&gt; Maybe you want to contain your social media activity to one browser as a way to mitigate tracking and targeted ads.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Picky apps.&lt;/strong&gt; it shouldn’t be this way but sometimes you need Chrome for that one app that refuses to work in Firefox or Safari.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay that’s all I can think of off the top of my head but there are probably other reasons.&lt;/p&gt;
&lt;p&gt;Much of this could probably be done with browser profiles. That’s cool too!&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#the-problem&quot;&gt;The problem&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are using multiple browsers, you’ve probably hit the classic multi-browser annoyance—opening a link in the wrong browser.&lt;/p&gt;
&lt;p&gt;This is super annoying. But this problem can be mitigated by using a specialized browser made for opening &lt;em&gt;other&lt;/em&gt; browsers.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#the-solution&quot;&gt;The solution&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are several of these browser-opening browsers but the one I’ve landed on is &lt;a href=&quot;https://choosy.app/&quot;&gt;Choosy&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; Make Choosy your default browser and it will do the work of opening your links in the right browser or profile.&lt;/p&gt;
&lt;p&gt;There are a ton of features and different ways you can use Choosy. Check out the website for all the details, but at a high level, there are two ways Choosy picks which browser to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompting you with a choice&lt;/li&gt;
&lt;li&gt;Choosing automatically based on rules you have provided&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The second item is where the magic is at for me. I’m able to set up rules to open links in my work browser&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; profile if any of the following are true:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The URL matches my work’s GitLab instance&lt;/li&gt;
&lt;li&gt;The URL includes the name of our cloud platform&lt;/li&gt;
&lt;li&gt;The URL matches one of the handful of URLs we use when serving our app locally for development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And I just want to reiterate, the links not only open in the specified browser, but also the &lt;em&gt;specified profile&lt;/em&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Anything not matching the work rules I set up will fallback to my preferred default browser, Firefox.&lt;/p&gt;
&lt;p&gt;I’m so used to it—because it operates so smoothly—that I take Choosy for granted. And that’s why I decided to write about it. If you’re dealing with multiple browsers, Choosy can make it a much nicer experience.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Another one I’ve tried is &lt;a href=&quot;https://apps.apple.com/us/app/lincastor-browser/id1037256618&quot;&gt;LinCastor Browser&lt;/a&gt;. It works a bit differently but ultimately can open a browser according to specified rules. It’s serviceable, but I find Choosy to be easier to use and understand. &lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Previously Google Chrome, but recently trying out Microsoft Edge. &lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’ve done it with Chromium-based browsers that have profiles. I haven’t tried it with Firefox profiles, as that browser does profiles a bit differently. From what I can tell, this feature only works with Chromium-based browsers. &lt;a href=&quot;https://blakewatson.com/journal/multi-browser-workflow-on-macos-with-choosy/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Homebrew package for setting specified audio input device</title>
      <link href="https://blakewatson.com/journal/homebrew-package-for-setting-specified-audio-input-device/"/>
      <updated>2023-07-18T17:10:30Z</updated>
      <id>https://blakewatson.com/journal/homebrew-package-for-setting-specified-audio-input-device/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I had an annoying situation where, when my AirPods connected to my Mac, they would take over as the active input device (ie, microphone). I didn’t want that because I already have a nice microphone setup. So I set out to find a way to prevent that behavior.&lt;/p&gt;
&lt;p&gt;I failed.&lt;/p&gt;
&lt;p&gt;The only solution I’ve been able to find is to change the input device back to my good microphone after AirPods connect. The easiest way to automate this is to use a package called &lt;code&gt;switchaudio-osx&lt;/code&gt; and the &lt;a href=&quot;https://c-command.com/toothfairy/&quot;&gt;ToothFairy&lt;/a&gt; app (also available via Setapp).&lt;/p&gt;
&lt;p&gt;Install &lt;code&gt;switchaudio-osx&lt;/code&gt; with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install switchaudio-osx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ToothFairy can &lt;a href=&quot;https://c-command.com/toothfairy/manual#run-shell-script-after&quot;&gt;run a shell script after AirPods connect&lt;/a&gt;. So I’m using that to run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;SwitchAudioSource -t input -s &amp;quot;MICROPHONE NAME HERE&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
</content>
    </entry>
    <entry>
      <title>My journey with the Chubon keyboard layout</title>
      <link href="https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/"/>
      <updated>2023-07-15T23:06:07Z</updated>
      <id>https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/</id>
      <content xml:lang="en" type="html">&lt;p&gt;In high school, I still had the ability to handwrite, albeit with some difficulty. Toward the end of high school in the early aughts, I was given use of an ancient computer for completing some of my assignments. At that time, typing on a keyboard was easier than handwriting.&lt;/p&gt;
&lt;p&gt;After starting college in fall 2003, I continued to experience muscular atrophy in my hands. I was still able to type, but it was slow. I needed a laptop-sized keyboard because full sized ones were too difficult.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Over the course of the late 2000s, SMA swallowed the remaining strength in my hands. After a &lt;a href=&quot;https://www.youtube.com/watch?v=YNyqCmk4X6M&quot;&gt;creative-but-doomed last ditch effort&lt;/a&gt;, I was forced to transition to alternate forms of input. I played around with dictation but was frustrated by it. My main form of input became the onscreen keyboard (abbreviated OSK).&lt;/p&gt;
&lt;p&gt;Windows has a built-in onscreen keyboard:&lt;/p&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://blakewatson.com/uploads/2023/07/osk-1.png&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2023/07/osk-1-1024x576.png&quot; alt=&quot;Screenshot of the default onscreen keyboard in Windows. Standard QWERTY keyboard layout.&quot; width=&quot;1024&quot; height=&quot;576&quot; class=&quot;alignnone size-large wp-image-1154&quot; /&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p&gt;Macs come with an &lt;a href=&quot;https://support.apple.com/guide/mac-help/use-the-accessibility-keyboard-mchlc74c1c9f/mac&quot;&gt;extremely powerful onscreen keyboard&lt;/a&gt; &lt;em&gt;now&lt;/em&gt;, but they didn’t until the mid-2010s. Prior to that, they had something called the &lt;a href=&quot;https://blakewatson.com/ihs/onscreen-keyboard-fail-why-macs-keyboard-viewer-is-utter-atrocity/index.html&quot;&gt;Keyboard Viewer&lt;/a&gt; which was a barely functional onscreen keyboard that was originally designed (I’m assuming) for displaying the alternate functions of keys when various modifiers are held down.&lt;/p&gt;
&lt;p&gt;Fortunately, Mac users at the time had a good third party option.&lt;/p&gt;
&lt;h2 id=&quot;assistiveware-keystrokes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#assistiveware-keystrokes&quot;&gt;AssistiveWare KeyStrokes&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/07/keystrokes_animation.gif&quot; alt=&quot;Animated GIF of KeyStrokes, the onscreen keyboard. It depicts a mouse typing by clicking on keys and predictive text suggestions. It’s a standard QWERTY layout with some extra keys for common actions like copy and paste.&quot; width=&quot;481&quot; height=&quot;350&quot; class=&quot;alignnone size-full wp-image-1156&quot; /&gt;
  &lt;figcaption&gt;This was the marketing image on the KeyStrokes product page for years.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://www.assistiveware.com/legacy-apps&quot;&gt;KeyStrokes&lt;/a&gt; was a third party onscreen keyboard for Mac. It had a number of huge improvements over the Keyboard Viewer and even Windows’ OSK.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Word and phrase prediction (the Windows OSK has this now)&lt;/li&gt;
&lt;li&gt;Custom keyboard layouts&lt;/li&gt;
&lt;li&gt;Custom buttons, which could emulate other keys or even run complex macros&lt;/li&gt;
&lt;li&gt;Dwelling, an input mode that lets you activate a key by hovering the mouse pointer over it for a specified amount of time&lt;/li&gt;
&lt;li&gt;Fully resizable&lt;/li&gt;
&lt;li&gt;Honestly, all sorts of other things I can’t remember&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While I still loathed typing on an OSK, I was glad to have it.&lt;/p&gt;
&lt;p&gt;But my average words-per-minute plummeted. There was something so slow and tedious about typing with a mouse. The most annoying part was the jumping around the keyboard. Why couldn’t all of the common letters be in one spot?&lt;/p&gt;
&lt;p&gt;Then I noticed one of the custom keyboard layouts that KeyStrokes came with: Chubon.&lt;/p&gt;
&lt;p&gt;I had no idea what that word meant, &lt;em&gt;Chubon&lt;/em&gt;. It would be sometime before I realized it was a name.&lt;/p&gt;
&lt;p&gt;It was strange, having been used to QWERTY. But being a nerd and a programmer, I had often heard of people changing their keyboard layout to Dvorak. This was the same thing. Not the same layout, but a layout made to be more efficient than QWERTY.&lt;/p&gt;
&lt;p&gt;The difference was that it was optimized for people typing with a single finger or a typing stick. This was exactly what I needed. A mouse pointer may as well be a finger.&lt;/p&gt;
&lt;p&gt;I made the switch and taught myself the new layout by playing typing games on the web.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/07/keystrokes_chubon-1024x589.png&quot; alt=&quot;My custom KeyStrokes keyboard panel. It’s the Chubon keyboard layout and has many custom buttons for text navigation, common actions like copy, paste, and undo, and buttons especially for web development, such as a browser refresh button.&quot; width=&quot;1024&quot; height=&quot;589&quot; class=&quot;alignnone size-large wp-image-1160&quot; /&gt;
  &lt;figcaption&gt;My custom KeyStrokes panel&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-chubon-layout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#the-chubon-layout&quot;&gt;The Chubon layout&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I became obsessed with this keyboard layout. I wanted to know more about it. Where did it come from? Was Chubon a person? If so, who were they?&lt;/p&gt;
&lt;p&gt;It turns out that my beloved keyboard layout was designed during a research project in the eighties by Dr. Robert Chubon. He was interested in optimizing a layout for single-digit entry because he typed using a typing stick.&lt;/p&gt;
&lt;p&gt;Dr. Chubon (Bob) was paralyzed as a high schooler during a trampoline accident. In the mid-eighties, while working as a professor at the University of South Carolina, he had so much typing work that needed to be done that he was becoming overwhelmed. He sought a way to increase his words per minute. This is what he came up with.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/07/chubon_keyboard-1024x361.png&quot; alt=&quot;Photo of Dr. Chubon&amp;#039;s keyboard. It’s using his layout on a hardware keyboard that has been remapped. The number keys and alpha keys are color-coded.&quot; width=&quot;1024&quot; height=&quot;361&quot; class=&quot;alignnone size-large wp-image-1161&quot; /&gt;
  &lt;figcaption&gt;Photo of Dr. Chubon&#39;s personal keyboard, as seen in his self-published autobiography&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You can read all about it in his &lt;a href=&quot;https://blakewatson.com/uploads/2023/07/chubon.pdf&quot;&gt;journal article&lt;/a&gt; if you are so inclined, but I will give you the quick rundown.&lt;/p&gt;
&lt;p&gt;It’s based on letter frequencies and is arranged in a target-like layout with the most common letters being clustered in the center. The &lt;em&gt;E&lt;/em&gt; serves as the bullseye (he even color coded the &lt;em&gt;E&lt;/em&gt; key red). Lesser used characters are pushed to the periphery.&lt;/p&gt;
&lt;p&gt;The Chubon layout reduces the amount of movement the typist needs to make in order to bounce around the keyboard spelling words. This might seem like a minor improvement, but I can say from experience that the difference is huge. It’s quantifiably better in terms of typing speed but it is also qualitatively better in terms of reducing tedium and making typing more enjoyable.&lt;/p&gt;
&lt;p&gt;Writing had become such a chore, but once I got the hang of this keyboard layout, I could see the light at the end of the tunnel—typing wouldn’t always be a terrible slog.&lt;/p&gt;
&lt;p&gt;I would soon be using a form of &lt;em&gt;single-digit entry&lt;/em&gt; that wasn’t a mouse pointer. It was a method of typing much more mainstream than an OSK. It was called &lt;em&gt;iPhone&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;bringing-the-chubon-layout-to-iphone&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#bringing-the-chubon-layout-to-iphone&quot;&gt;Bringing the Chubon layout to iPhone&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I had been spoiled by using the Chubon layout on my Mac. I was not taking very kindly to having to use QWERTY again on my iPhone.&lt;/p&gt;
&lt;p&gt;Specifically, I found that a good way to type on my computer was to use the iPhone as an external keyboard. This was possible thanks to a category of apps than I call “remote apps.” There were a handful of these at the time. But the one I was using most was called HippoRemote.&lt;/p&gt;
&lt;p&gt;Remote apps let you use your phone as an external keyboard and mouse for your computer. This was of particular interest to me because at the time I had plenty of hand strength to type rather quickly on a phone. The ability to transfer that to my computer was a huge win in my continual search for a better way to type.&lt;/p&gt;
&lt;p&gt;At the time, there was no way to change out the standard iOS keyboard.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; But HippoRemote had a concept of custom panels, typically used for controlling media playback. As a result, it had an interesting feature that would let you create your own custom key panel.&lt;/p&gt;
&lt;p&gt;It was a bit clumsy, due to some limitations with the feature, but I managed to put together a &lt;a href=&quot;https://blakewatson.com/ihs/more-efficient-typing-with-the-chubon-keyboard-layout/&quot;&gt;Chubon keyboard panel for HippoRemote&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/Fz0W7DNtVm4&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;After a couple of years of using this serviceable but awkward keyboard panel, I set out to make a &lt;em&gt;real&lt;/em&gt; remote Chubon keyboard. One that didn’t need a whole extra set of keys just for capital letters. One that behaved more like an iPhone keyboard.&lt;/p&gt;
&lt;p&gt;I put together a little app&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; that had a proper Chubon layout&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; and behaved more like a remote keyboard. It ran as a homescreen app on my iPhone and enabled me to use the Chubon layout on the phone to type on the Mac.&lt;/p&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/Pre6EQGIuKY&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;It was my greatest typing achievement since my transition away from physical keyboards. But it wouldn’t last. As &lt;a href=&quot;https://blakewatson.com/ihs/fourth-quarter/&quot;&gt;I once said&lt;/a&gt; of SMA:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It keeps taking and taking. Its hunger is never filled nor its thirst quenched.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My hand weakened to the point where I could no longer use my creation. I transitioned to using KeyStrokes full-time. But there was a problem. KeyStrokes was aging software. The developer couldn’t justify a large overhaul because he was focused on other, more popular accessibility apps. KeyStrokes was on life support, in danger of breaking down completely with each new release of macOS.&lt;/p&gt;
&lt;p&gt;But Apple worked with AssistiveWare and something incredible happened.&lt;/p&gt;
&lt;h2 id=&quot;the-macos-accessibility-keyboard&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#the-macos-accessibility-keyboard&quot;&gt;The macOS Accessibility Keyboard&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Apple recreated much of KeyStrokes’ capabilities in the form of a new built-in OSK called the Accessibility Keyboard. The first iteration was a bit janky, but after a few releases it was capable enough for me to jump ship from KeyStrokes, which ceased to work not long after.&lt;/p&gt;
&lt;p&gt;The essential features of the Accessibility Keyboard were, for me, the ability to create a custom layout and the ability to add custom buttons to execute key combo presses. I was able to create the Chubon layout and use the Accessibility Keyboard full-time.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/07/mak_chubon-1024x702.png&quot; alt=&quot;Screenshot of the current iteration of my Chubon panel for the macOS Accessibility Keyboard. It features the Chubon layout with an adjacent number pad. There is an entire row dedicated to special characters and about 42 custom buttons that support everything from text navigation to app-specific shortcuts.&quot; width=&quot;1024&quot; height=&quot;702&quot; class=&quot;alignnone size-large wp-image-1162&quot; /&gt;
  &lt;figcaption&gt;I kept the red coloring of the &quot;E&quot; key as homage to the original hardware design.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;bob&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#bob&quot;&gt;Bob&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I corresponded with Dr. Chubon several times in the 2010s (he signed his name, Bob, in emails to me). He seemed delighted that his work from the eighties lived on, coming to new platforms he could have never imagined in the eighties.&lt;/p&gt;
&lt;p&gt;Dr. Chubon impressed me. I consider him as a sort of disability &lt;a href=&quot;https://simple.wikipedia.org/wiki/Renaissance_man&quot;&gt;renaissance man&lt;/a&gt;. His academic field was rehabilitation counseling, but he also picked up programming and playwriting. All of this while facing the challenges of a twentieth-century society that had only just begun to be more accepting of people with disabilities.&lt;/p&gt;
&lt;p&gt;Dr. Chubon &lt;a href=&quot;http://www.chubon.org/bob/ab%202011-7-11.pdf&quot;&gt;self-published an autobiography&lt;/a&gt; in 2010 and it’s a delightful little read. As a fellow disabled person I can relate to much of his story. We hate to use the &lt;em&gt;i-word&lt;/em&gt; but I was nonetheless inspired by what he accomplished and how he used his skills and abilities to help others.&lt;/p&gt;
&lt;p&gt;I was feeling overwhelmed with gratitude and nostalgia late one night this week and decided to email him again to express my thanks and appreciation for his work on the Chubon layout. I was saddened to discover that he had died in April of 2022, and his wife had died in May of this year.&lt;/p&gt;
&lt;p&gt;I left a note on his obituary page and watched a video his family had made of spreading his ashes on family land.&lt;/p&gt;
&lt;p&gt;I didn’t know him closely, but he affected my life greatly. It’s hard to imagine that I would have accomplished what I have if not for his keyboard layout. That sounds like hyperbole—and maybe it is—but it’s how I feel.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#resources&quot;&gt;Resources&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I hope to put up a one-page site on all things Chubon layout&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt;, but until then I can offer some links to existing stuff.&lt;/p&gt;
&lt;p&gt;I don’t know if Dr. Chubon’s website will remain online so I’m going to link to documents that I’m hosting myself. But if it still works, you can visit his webpage here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.chubon.org/bob/&quot;&gt;http://www.chubon.org/bob/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;dr.-chubon%E2%80%99s-work&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#dr.-chubon%E2%80%99s-work&quot;&gt;Dr. Chubon’s work&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/uploads/2023/07/chubon.pdf&quot;&gt;The Chubon paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/uploads/2023/07/ab-2011-7-11.pdf&quot;&gt;Bob Chubon: Just an Innocent Kid (An Autobiography)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;stuff-i%E2%80%99ve-written-about-the-chubon-layout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#stuff-i%E2%80%99ve-written-about-the-chubon-layout&quot;&gt;Stuff I’ve written about the Chubon layout&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;Writing and coding with the macOS Accessibility Keyboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blakewatson.com/ihs/more-efficient-typing-with-the-chubon-keyboard-layout/&quot;&gt;More efficient typing with the Chubon keyboard layout&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;further-research&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#further-research&quot;&gt;Further research&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Chubon layout was developed for hardware keyboards. In particular, it was intended to be implemented by remapping the keys of off-the-shelf keyboards, so as to be practical and affordable for people with disabilities.&lt;/p&gt;
&lt;p&gt;It was also primarily developed around typing-stick typing, which introduces some different variables that aren’t present on virtual keyboards—keys on the bottom row being easier to physically access, for example.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blakewatson.com/uploads/2023/07/Performance_Optimization_of_Virtual_Keyboards.pdf&quot;&gt;Further research&lt;/a&gt; has been done and hypothetically faster layouts have been developed. I’m not sure if I’ll be switching to something else anytime soon but I love that work being done in this area.&lt;/p&gt;
&lt;h3 id=&quot;speech-recognition&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#speech-recognition&quot;&gt;Speech recognition&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you can’t use a physical keyboard, another typing option is speech recognition. There have been big developments in this area and I’ve covered one of them, &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;, &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/&quot;&gt;times&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’m not always in an environment where I can use speech recognition and sometimes I just prefer the onscreen keyboard. But I mention it here because it can be a powerful tool for people who need it.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Part of the appeal of compact, laptop keyboards was the fact that the keys were usually flatter and flush, allowing my fingers to slide across them without lifting them up. &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It wasn’t even called iOS at the time. It was called iPhone OS. &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;For the dev nerds, I made a tiny desktop app in Python using Tkinter. It’s only purpose was to give me a button that would fire up a PHP server that served a single-page app over the local network. That app passed encoded key commands over the wire where the PHP server would parse them and execute them with AppleScript. Yes, I realize how ridiculous that sounds. &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Ok I actually used a variant of the Chubon layout that moved the “J” key to the end of the top row. I also have never used his numbers layout as I prefer a numpad layout for those. &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’ve already secured the domain name, which means 90% of the work is done and there’s no excuse for the near-certain procrastination of this project, which will cause me shame and regret annually when the domain comes up for renewal. &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>The fragile nature of my life’s work</title>
      <link href="https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/"/>
      <updated>2023-06-23T04:59:45Z</updated>
      <id>https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/</id>
      <content xml:lang="en" type="html">&lt;p&gt;On June 16, 2023 a storm rolled through Mississippi. Violent straight-line winds and, possibly, a tornado caused several telephone poles in my subdivision to snap and fall, knocking out the power and blocking the only way in and out of the subdivision.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2023/06/IMG_1422.jpeg&quot; alt=&quot;A photograph depicting a telephone poll that has apparently snapped in half, the transformer having shattered to pieces and the power lines having been brought down.&quot; width=&quot;768&quot; height=&quot;1024&quot; class=&quot;alignnone size-full wp-image-1121&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Unfortunately, whole swathes of Mississippi’s power grid failed, overwhelming repair crews and leaving many residents without air conditioning during a Mississippi summer.&lt;/p&gt;
&lt;p&gt;I’m somewhat prepared for short power outages—those lasting less than a day. I charge my wheelchair every night. My patient lift—a thing I use to transfer to and from my wheelchair and bed—is usually charging when not in use. My MacBook Pro is usually charged and is a newer model with great battery life. My desktop Mac is attached to an uninterruptible power supply (UPS) so that I have time to save my work and shut down properly. My modem and router are also connected to that UPS. That keeps my internet connection powered for several hours.&lt;/p&gt;
&lt;p&gt;But this was not a short outage. The June 16 outage lasted (for me) four grueling days until the evening of June 19. My internet connection held up long enough to communicate with my fellow remote coworkers to let them know what was going on. I submitted my end-of-pay-period timecard form just before my UPS died.&lt;/p&gt;
&lt;p&gt;After my UPS died, taking with it my internet connection, I tried to switch to my phone’s personal hotspot. I couldn’t get it to work and wouldn’t discover until after the fact that the problem was that my particular wireless plan didn’t include the feature. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I’m much more capable using a Mac than a mobile device. My hands aren’t strong enough to use a touch screen. So I try to maintain internet access on the Mac as long as I can. But after fighting with the hotspot and also learning that the outage was gonna be a bad one, I decided that I needed to shut down the MacBook Pro and use it as a power bank for our phones. I’m extremely limited on what I can accomplish on a phone, but I’m not totally helpless thanks to Apple’s &lt;a href=&quot;https://support.apple.com/en-us/HT210417&quot;&gt;Voice Control&lt;/a&gt; feature.&lt;/p&gt;
&lt;p&gt;More on technology later.&lt;/p&gt;
&lt;p&gt;The harsh realities of a power outage began to set in after about 12 hours—the house warmed to an uncomfortable temperature, food in the fridge was no longer being properly cooled, the house was dark.&lt;/p&gt;
&lt;p&gt;Mississippi has hot, humid summers. We jumped back and forth on whether opening the windows helped or harmed us. I had to sleep without my BiPAP, which meant I had trouble breathing at night. That prevented my body from resting like it needed to.&lt;/p&gt;
&lt;p&gt;As we rolled into Saturday morning it became apparent that repair crews were busy elsewhere. And there was another problem. Those downed telephone poles were blocking the only way in or out of our subdivision. Ours and our neighbors’ only way to get out of the subdivision was going offroad through an uneven patch of land belonging to a neighbor.&lt;/p&gt;
&lt;p&gt;For all intents and purposes, we were stuck at home. Dealing with power outages is already difficult. Having a significant physical disability makes it even tougher. It was hard on me and my brother, but also on our mother and caregivers.&lt;/p&gt;
&lt;p&gt;Overall we did okay. We were never really in physical danger. Had the power outage continued further, we would have had more significant problems—batteries in our durable medical equipment would have eventually died. At a certain point, we would have been forced to set up a generator or either figure out how to stay in a hotel (which is a tricky accessibility problem).&lt;/p&gt;
&lt;p&gt;But that four days without power gave me time to think. There wasn’t much else I &lt;em&gt;could&lt;/em&gt; do. As SMA has continually weakened my muscles, my interface with the world around me is increasingly computer-based.&lt;/p&gt;
&lt;p&gt;I’m a web developer by trade. I make websites. Websites are just computer files. If the world was suddenly without power, websites would more or less cease to exist. The things that I have spent the majority of my adult life learning how to build would be nonexistent and meaningless. All the skills I’ve developed in programming and digital graphic design would become useless.&lt;/p&gt;
&lt;p&gt;When the power is on, I’m worth a competitive web developer’s salary, despite only being able to move a few fingers. When the power is off, there is nothing productive I can offer the world on my own.&lt;/p&gt;
&lt;p&gt;Many people have this problem. Not just me. What does it mean that the livelihoods of so many people rely on an intangible world of our creation?&lt;/p&gt;
&lt;p&gt;But it goes beyond just working. All of my hobbies and interests are either computer-based inherently, or either I interface with them via a computer. I am a &lt;a href=&quot;https://blakewatson.com/journal/finishing-side-projects/&quot;&gt;side project enthusiast&lt;/a&gt; and I run several &lt;a href=&quot;https://blakewatson.com/my-apps/&quot;&gt;websites and apps&lt;/a&gt;. Without power, I can’t work on those at all.&lt;/p&gt;
&lt;p&gt;I’m also a writer. I write for this website, but I also write fiction as a hobby and have participated in &lt;a href=&quot;https://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt; for many years. There was a time when I had enough strength in my hand to write with pen and paper. But that time has long since passed. I require a computer to be able to write. I’m writing this very article on two different computers—a Mac Studio on which I’m using an &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;onscreen keyboard&lt;/a&gt;, and a MacBook Pro on which I’m using &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/&quot;&gt;voice recognition software&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My life has become increasingly screen-based, but as a generally optimistic technologist, I’ve embraced it.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; But being without power for the better part of a week made me acutely aware of how detached from the physical world I have become.&lt;/p&gt;
&lt;p&gt;During the power outage I started listening to &lt;a href=&quot;https://www.amazon.com/We-Are-Legion-We-Are-Bob-audiobook/dp/B01L082SCI&quot;&gt;We Are Legion (We Are Bob)&lt;/a&gt;, the current read that my book club at work is on. Hilariously, it is about a man who has his mind uploaded into a self-replicating spacecraft. That is about as reliant on technology, and detached from the physical world, as it gets. So I still have a ways to go.&lt;/p&gt;
&lt;p&gt;I guess what I’m saying is I need to &lt;em&gt;get out more&lt;/em&gt;, as soon as I figure out what that means.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I don’t understand why this requires a separate charge. I’m already paying for the data. My iPhone supports personal hotspots. What is justifying the extra cost from the carrier. Feels like a sleazy cash grab. &lt;a href=&quot;https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I don’t mean “optimistic technologist” in the technology-as-a-god futurism sense. Just that I go easy on myself when it comes to screen time and using technology. For me, computers and the internet have a huge upside. It’s by no means the only way I could live, but it’s the way I choose to, given my interests and level of physical ability. &lt;a href=&quot;https://blakewatson.com/journal/the-fragile-nature-of-my-lifes-work/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>I made a web-based version of Sawayama Solitaire</title>
      <link href="https://blakewatson.com/journal/i-made-a-web-based-version-of-sawayama-solitaire/"/>
      <updated>2023-05-18T04:10:22Z</updated>
      <id>https://blakewatson.com/journal/i-made-a-web-based-version-of-sawayama-solitaire/</id>
      <content xml:lang="en" type="html">&lt;p&gt;One of my favorite game developers, Zachtronics, released their final game, &lt;a href=&quot;https://www.zachtronics.com/last-call-bbs/&quot;&gt;Last Call BBS&lt;/a&gt;, a little while back. And in true Zachtronics fashion it fuses programming, retro futurism, and nostalgia to great effect, resulting in a fun, educational, and visually enticing game.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/EdU-ABucIjk&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Last Call BBS is interesting because it’s a set of mini-games. The game boots up like a retro computer and you dial in to a bulletin board system (that’s the &lt;em&gt;BBS&lt;/em&gt;) to download several games.&lt;/p&gt;
&lt;p&gt;I’ve played about half of the games and they are pretty fun. In particular, a programming game about recreating 20th century food court food for people in the far future pushed all the right buttons for me.&lt;/p&gt;
&lt;p&gt;But, in my opinion, one game stole the show. And it wasn’t even one of the mini games. It’s really a mini-mini game. Your Sawayama computer system does have one game pre-installed—Sawayama Solitaire.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/05/Screenshot-2023-05-17-at-10.33.11-PM-1024x600.jpg&quot; alt=&quot;A screenshot of Sawayama Solitaire in its beginning state. It looks like a retro OS desktop. The graphics are low resolution. The cards are dealt similar to Klondike but all of them are face up. The entire screenshot is slightly warped said that it looks like a CRT monitor.&quot; width=&quot;1024&quot; height=&quot;600&quot; class=&quot;alignnone size-large wp-image-1045&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;It’s a variant of Klondike with a few rules changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The tableau is face-up but, like Klondike, only cards on top or cards in a sequence can be moved.&lt;/li&gt;
&lt;li&gt;Any card (not just kings) can go into an open cell.&lt;/li&gt;
&lt;li&gt;The deck can only be drawn through once. After all cards have been drawn, it does not reset.&lt;/li&gt;
&lt;li&gt;After all the cards in the deck are gone, the spot where the deck sat becomes a free cell.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These changes have an exciting effect on the game. It suddenly becomes a lot more strategical than before. Since you can see all the cards, you can start thinking several moves ahead—and you are going to need to because you only get to go through the deck once. There is much less luck involved (but still a good amount). They claim that their variant of solitaire is often more winnable than Klondike and, anecdotally, I have found that to be true.&lt;/p&gt;
&lt;p&gt;Aside from the rules, the execution of the game—the graphics, the sound effects, the music—is flawless. If you have childhood memories of playing solitaire on an old computer than you will appreciate the game design on this one.&lt;/p&gt;
&lt;p&gt;I lost a bunch at first. But then I started winning. And then I became hooked. I would catch a few minutes of downtime during my day and want to play a few rounds, but I didn’t want to have to open Steam every time. I just wanted to be able to pop a browser tab open and play a little.&lt;/p&gt;
&lt;p&gt;I’m no Zachtronics, but I’ve been slowly learning game development with &lt;a href=&quot;https://pixijs.com/&quot;&gt;PixiJS&lt;/a&gt;. So I set out to create a web-based variant of Sawayama Solitaire. I wasn’t trying to copy the retro vibe or anything else about the game other than the ruleset. I’m certainly not trying to take any business away from Zachtronics. I hope I bring more attention to their amazing game, if anything.&lt;/p&gt;
&lt;h2 id=&quot;some-notes-about-my-version-of-the-game&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-made-a-web-based-version-of-sawayama-solitaire/#some-notes-about-my-version-of-the-game&quot;&gt;Some notes about my version of the game&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the most interaction-heavy PixiJS game I’ve made so far. I’m sure I did a lot of things very badly code-wise. But it works. For the most part.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/05/sawayama-solitaire-1024x709.png&quot; alt=&quot;My version of the game look similar but not as cool.&quot; width=&quot;1024&quot; height=&quot;709&quot; class=&quot;alignnone size-large wp-image-1047&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Once I had a playable alpha version of the game I started passing it around to a few people. Immediately, the most prominent feedback was that I needed to make a bouncy card animation after winning a game. Multiple people told me that this was &lt;em&gt;required&lt;/em&gt; in a solitaire game and I agreed.&lt;/p&gt;
&lt;p&gt;I was going to embed a video here of the animation, but I think it would be more fun if I challenge you to win the game and unlock the animation yourself. That’s your reward.&lt;/p&gt;
&lt;p&gt;I’m not going to win any awards here, but I’m proud of how this one came out. For what it’s worth, the &lt;a href=&quot;https://github.com/blakewatson/sawayama-solitaire&quot;&gt;source code&lt;/a&gt; is on GitHub. Feel free to use it for learning purposes, but probably don’t follow my example too closely because I’m very much a beginner at this.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.watsonbrosgames.com/solitaire/&quot;&gt;game is published&lt;/a&gt; on me and my brother’s little &lt;a href=&quot;https://www.watsonbrosgames.com/&quot;&gt;web game site&lt;/a&gt;. I decided I’m not going to put it on Itch because Zachtronics already has their solitare collection for sell there and I don’t want to cause any confusion.&lt;/p&gt;
&lt;h2 id=&quot;links-and-stuff&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/i-made-a-web-based-version-of-sawayama-solitaire/#links-and-stuff&quot;&gt;Links and stuff&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zachtronics.com/last-call-bbs/&quot;&gt;Last Call BBS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.zachtronics.com/solitaire-collection/&quot;&gt;Zachtronics Solitaire Collection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.watsonbrosgames.com/solitaire/&quot;&gt;My version of Sawayama Solitaire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/blakewatson/sawayama-solitaire&quot;&gt;The source code for my version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pixijs.com/&quot;&gt;PixiJS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>A home-cooked app for hiring personal caregivers</title>
      <link href="https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/"/>
      <updated>2023-04-27T03:33:49Z</updated>
      <id>https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I don’t talk about this often, but I use a team of caregivers to help with all of my daily personal care needs. I’m fortunate enough to be on a program in the state of Mississippi that provides me (and my brother, Matt) with a certain amount of hours of personal care assistance per day. The program requires that I find my own caregivers, which is great in one sense because I have control of who works with me. But it also means I bare the burden of recruiting.&lt;/p&gt;
&lt;p&gt;Recruiting personal care assistants (PCAs) is tough. There has been a nationwide caregiver shortage since at least the 2020 pandemic, if not before. Add to that the fact that the economy has seen rising inflation and increased prices for just about everything. In response, many hospitals and healthcare agencies have risen the pay rate for CNAs and PCAs,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; some going as far as to offer sign on bonuses.&lt;/p&gt;
&lt;p&gt;Unfortunately, the program I’m on doesn’t pay its workers very much. I’m not going to provide numbers here but for the area I live in, the hourly rate is below average, anecdotally speaking.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; The program is also somewhat slow to onboard people, which means it can take a week or more from when we find someone until they can start—and another two weeks until they get their first paycheck.&lt;/p&gt;
&lt;p&gt;All of this means hiring a caregiver is challenging for me and and my brother. We typically approach this problem by paying for an ad on Indeed and processing applications to find people to interview and ultimately hire. This is a high turnover industry so we’re typically going through at least one round of hiring every year.&lt;/p&gt;
&lt;p&gt;Despite the caregiver shortage we get a lot of applications, albeit many low quality ones. Processing these is its own problem and it’s one that, as developers, we could actually solve.&lt;/p&gt;
&lt;h2 id=&quot;in-which-we-reinvent-the-wheel-because-other-wheels-weren%E2%80%99t-quite-right&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#in-which-we-reinvent-the-wheel-because-other-wheels-weren%E2%80%99t-quite-right&quot;&gt;In which we reinvent the wheel because other wheels weren’t quite right&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After years of using form providers like Google Forms (Matt) and Wufoo (me), we started using a self-hosted form made with WordPress and &lt;a href=&quot;https://www.gravityforms.com/&quot;&gt;Gravity Forms&lt;/a&gt;. I was tired of paying so much for Wufoo and didn’t like reading Google Forms entries in a big spreadsheet. So the Gravity Forms setup was meant to save us money and give us more control.&lt;/p&gt;
&lt;p&gt;It worked well enough but viewing Gravity Forms entries in the backend of WordPress left such a sour taste in my mouth that I finally got sick of it. And as full-featured as Gravity Forms is, posting new job forms proved to be tedious work. Here’s a short list of my grievances with the Gravity Forms setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything about it was slow&lt;/li&gt;
&lt;li&gt;Viewing entries was slow&lt;/li&gt;
&lt;li&gt;In some spots, leaving form instructions meant typing HTML into a tiny box.&lt;/li&gt;
&lt;li&gt;Did I mention it was slow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, I’d had enough. Surely two professional web developers could do better. We could make a &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/&quot;&gt;home-cooked app&lt;/a&gt;, just for us. So like developers are wont to do, we threw out all the perfectly adequate ready-made solutions and set out to build our own.&lt;/p&gt;
&lt;h2 id=&quot;boring-is-best&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#boring-is-best&quot;&gt;Boring is best&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We turned to tried and true tech for this project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PHP (&lt;a href=&quot;https://fatfreeframework.com/&quot;&gt;Fat Free Framework&lt;/a&gt; a small one we’re both familiar with)&lt;/li&gt;
&lt;li&gt;HTML forms&lt;/li&gt;
&lt;li&gt;Classless CSS (awsm, but looks like that repo went private)&lt;/li&gt;
&lt;li&gt;As little JavaScript as possible&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;A basic VPS&lt;/li&gt;
&lt;li&gt;Postmark for transactional email&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal here was to build something that would require little maintenance, be fast, and make reviewing applications easy.&lt;/p&gt;
&lt;p&gt;Because of these choices, we were able to build the app in a weekend, with another weekend for fixes and enhancements.&lt;/p&gt;
&lt;h2 id=&quot;job-ads-and-application-forms&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#job-ads-and-application-forms&quot;&gt;Job ads and application forms&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For privacy reasons, I’m not going to link to the site here. It’s not hard to find though. But it’s not super interesting. It’s mostly just description of the job and what we’re looking for in a PCA.&lt;/p&gt;
&lt;p&gt;The homepage shouldn’t be hit much but, if it is, visitors will see our current hiring status.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/Screenshot-2023-05-09-at-8.39.17-PM-1024x753.jpg&quot; alt=&quot;Screenshot of the homepage. It indicates that we are currently hiring and briefly explains who we are.&quot; width=&quot;1024&quot; height=&quot;753&quot; class=&quot;alignnone size-large wp-image-1036&quot; /&gt;
&lt;p&gt;Click through to the job ad/description shows details about the job. Here’s a partial screenshot of an ad we’re running at the time of this writing.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/job_ad-1024x903.png&quot; alt=&quot;Partial screenshot of the job description. It tells who we are and lists the shifts we’re looking to cover and describes some basic info about the job, such as the pay rate (redacted), and the program that provides the job, the Mississippi Department of Rehabilitation Services&quot; width=&quot;1024&quot; height=&quot;903&quot; class=&quot;alignnone size-large wp-image-1011&quot; /&gt;
&lt;p&gt;The ad contains a few callouts to “Apply Now” which sends visitors to the main part of the app, the application form. Most people will land directly on this form because they are coming from our ad on Indeed.&lt;/p&gt;
&lt;p&gt;For this page, we coded up an HTML form. The awsm CSS stylesheet has pretty good form styling. It looks something like this:&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/form_1-1024x985.png&quot; alt=&quot;Screenshot showing a few basic text fields (name, email, phone) and a radio button question about a valid driver’s license.&quot; width=&quot;1024&quot; height=&quot;985&quot; class=&quot;alignnone size-large wp-image-1012&quot; /&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/form_2-1024x795.png&quot; alt=&quot;Screenshot shows two text areas asking about previous experience and professional references.&quot; width=&quot;1024&quot; height=&quot;795&quot; class=&quot;alignnone size-large wp-image-1013&quot; /&gt;
&lt;p&gt;There are a few more questions, a resume upload, then a submit button. Applications get submitted and saved to a SQLite database.&lt;/p&gt;
&lt;p&gt;Matt and I get an email notification of the application and the applicant gets a confirmation email containing a copy of their responses.&lt;/p&gt;
&lt;h2 id=&quot;reviewing-applications&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#reviewing-applications&quot;&gt;Reviewing applications&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now the fun part. Each job we post has an ID associated with it. That lets us sort applications into what we call “campaigns.” Our admin area presents a list of campaigns. Clicking through to one of those shows a table of applications.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/applications-1024x625.png&quot; alt=&quot;A table showing applications. Personal details have been redacted. Columns are Status, Notes, Name, Email, City, Date&quot; width=&quot;1024&quot; height=&quot;625&quot; class=&quot;alignnone size-large wp-image-1014&quot; /&gt;
&lt;p&gt;This is a simple table view. It provides high-level info, most importantly the status. Matt and I will log in and review applications, marking the ones that we’d like to contact for an interview.&lt;/p&gt;
&lt;p&gt;As an aside, I can see how the status “Nope” can come off as a little harsh. But look, I didn’t set out to be a PCA recruiter. It’s just something I have to do. I use a little humor to cope with it sometimes. This app isn’t for public consumption so the only audience the admin area targets is me and Matt. Applicants never see their status.&lt;/p&gt;
&lt;p&gt;Clicking through to an application gives us a view of all the responses, plus a few editable fields like Status and contact info.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/entry_1-977x1024.png&quot; alt=&quot;Screenshot of a single application, Test Person, with a status of Unreviewed (in a dropdown) and a few fake responses.&quot; width=&quot;977&quot; height=&quot;1024&quot; class=&quot;alignnone size-large wp-image-1015&quot; /&gt;
&lt;p&gt;We also have the ability to leave internal notes on applications. We use for recording how an interview went or reasoning behind rejecting an application.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2023/04/entry_3-818x1024.png&quot; alt=&quot;Screenshot of the bottom of an application showing a textarea where a note can be left.&quot; width=&quot;818&quot; height=&quot;1024&quot; class=&quot;alignnone size-large wp-image-1016&quot; /&gt;
&lt;h2 id=&quot;homemade-is-a-feature&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#homemade-is-a-feature&quot;&gt;Homemade is a feature&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There really isn’t anything interesting about the architecture of the application I spent a whole article writing about. It performs a fairly simple task that I suspect many systems perform similarly—and probably do it better.&lt;/p&gt;
&lt;p&gt;But ours it does it in the &lt;em&gt;exact way we want&lt;/em&gt;. That’s the magic part. If we want to change it, we can. If we want it to stay the same for years, we can keep it that way. This is the best kept secret about being a developer—making your own stuff, just for you (okay it’s a poorly kept secret because developers are always blogging about their stuff).&lt;/p&gt;
&lt;p&gt;It never gets old.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A Certified Nursing Assistant (CNA) is a caregiver who has had a certain amount of training and has a license. For the program I’m on, PCAs can have a CNA license, but it’s not required. CNA’s typically make more than PCAs, generally speaking (but the program I’m on pays the same either way). &lt;a href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I think PCAs are underpaid as it is. They often don’t get the same work benefits that other jobs in the health industry do. But that’s a topic for another day. &lt;a href=&quot;https://blakewatson.com/journal/a-home-cooked-app-for-hiring-personal-caregivers/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Surveying the landscape of CSS micro-frameworks</title>
      <link href="https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/"/>
      <updated>2023-03-13T01:26:53Z</updated>
      <id>https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Pretty soon after learning CSS and building my first few websites without table layouts (yes I’m old) I stumbled across the world of CSS frameworks. The oldest one I can remember using was the &lt;a href=&quot;https://960.gs/&quot;&gt;960 Grid System&lt;/a&gt;. I guess calling it a framework is a stretch. It’s just a grid really. But at the time it was a breath of fresh air. I was trying to learn about design and grid systems and the 960 grid was so easy to use.&lt;/p&gt;
&lt;p&gt;Then at some point Boostrap took over the world. A number of comprehensive frontend frameworks were born—CSS (probably Sass) and JavaScript included. And nowadays we have JavaScript libraries that people build frontend frameworks around, complete with fully-functional components—building blocks for making websites and web apps of any sort.&lt;/p&gt;
&lt;p&gt;But with that kind of power comes complexity, bloat, performance issues, and dependency hell. So when beginning a new project, I like start by thinking about the bare minimum needed to get going. It’s also an excuse to waste time scouring the web for goodies as I am wont to do.&lt;/p&gt;
&lt;p&gt;I’ve done everything from building with &lt;a href=&quot;https://vuetifyjs.com/&quot;&gt;Vuetify&lt;/a&gt; to exclusively using my own CSS. But lately I’ve been enjoying the world of CSS micro-frameworks and classless CSS themes.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-css-micro-framework%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#what-is-a-css-micro-framework%3F&quot;&gt;What is a CSS micro-framework?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don’t know.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; So I’m defining it myself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;May include classes for building grids, components, etc. Typically limited, though, because of the next rule.&lt;/li&gt;
&lt;li&gt;Under 10kb minified and gzipped. I feel like you can’t claim “micro” or “lightweight” beyond 10kb.&lt;/li&gt;
&lt;li&gt;JavaScript is optional and is not supplied by the framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Under this definition, classless CSS themes also count as micro-frameworks, but I prefer to think of them separately because they have different goals. More on those later.&lt;/p&gt;
&lt;p&gt;Here are a few of the micro-frameworks I could find. I’ve used Spectre, Chota, and Pure recently, but haven’t used the others. I’d like to try Pico in the future.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pico: &lt;a href=&quot;https://picocss.com/&quot;&gt;https://picocss.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Spectre: &lt;a href=&quot;https://picturepan2.github.io/spectre&quot;&gt;https://picturepan2.github.io/spectre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Milligram: &lt;a href=&quot;https://milligram.io/&quot;&gt;https://milligram.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Skeleton: &lt;a href=&quot;http://getskeleton.com/&quot;&gt;http://getskeleton.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Picnic: &lt;a href=&quot;https://picnicss.com/&quot;&gt;https://picnicss.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pure: &lt;a href=&quot;https://purecss.io/&quot;&gt;https://purecss.io/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing I’ve noticed is that many of these appear to be somewhat dated, past their prime of peak activity. If I were to speculate, I’d say it’s because CSS is very good now and if you aren’t using one of the big players in the CSS framework space, you might just be writing your own styles. That’s just a guess, though.&lt;/p&gt;
&lt;p&gt;Personally I would like to see a lot more of these. And I was a little bit surprised to see that the same half dozen frameworks kept popping up everywhere (which is a problem I suppose I’m contributing to now).&lt;/p&gt;
&lt;h2 id=&quot;why-use-a-css-micro-framework-over-a-regular-one-like-bootstrap%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#why-use-a-css-micro-framework-over-a-regular-one-like-bootstrap%3F&quot;&gt;Why use a CSS micro-framework over a regular one like Bootstrap?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There could be many reasons, but here are reasons &lt;em&gt;I’ve&lt;/em&gt; used them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I would go for a micro-framework if I want to skip having a build step. They are usually easy to pull in and get started with.&lt;/li&gt;
&lt;li&gt;I want to reduce complexity. I want fewer options and less documentation to have to wade through.&lt;/li&gt;
&lt;li&gt;Performance. If it is a small project, maybe I can’t justify the larger sizes of other frameworks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just for fun, here is a size comparison of CSS micro-frameworks versus two larger ones, Bootstrap and Bulma. I came up with these numbers by starting with the minified version of each one and gzip-ing them from the command line.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Framework&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bootstrap 5&lt;/td&gt;
&lt;td&gt;26.89kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulma&lt;/td&gt;
&lt;td&gt;26.95kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pico&lt;/td&gt;
&lt;td&gt;9.94kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spectre&lt;/td&gt;
&lt;td&gt;9.54kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Picnic&lt;/td&gt;
&lt;td&gt;7.26kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chota&lt;/td&gt;
&lt;td&gt;3.56kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure&lt;/td&gt;
&lt;td&gt;3.51kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Milligram&lt;/td&gt;
&lt;td&gt;2.24kb&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skeleton&lt;/td&gt;
&lt;td&gt;1.64kb&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;But what if you could go even more micro than micro-frameworks? Enter classless CSS themes.&lt;/p&gt;
&lt;h2 id=&quot;what-are-classless-css-themes%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#what-are-classless-css-themes%3F&quot;&gt;What are classless CSS themes?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;They are kind of like micro-frameworks except that they don’t provide classes for styling. Instead they aim to make regular semantic HTML look and work nicely by default. This typically means adding a max-width to the body (or &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; tag), implementing some good typography, and styling most or all of the default HTML elements.&lt;/p&gt;
&lt;p&gt;Classless CSS themes differ from other CSS frameworks because they aren’t generally meant as a jumping off point for a full blown design. Frameworks are meant to be used to build something—a particular layout or multiple templates for a larger website. Classless CSS themes, while happy to be extended, represent something closer to the end result. These themes aren’t generally made to build multiple templates or layouts of a website. They often begin and end with a centered column of content, and that’s all they ever intend to be.&lt;/p&gt;
&lt;p&gt;This is why I like to call them “themes” rather than “frameworks.” Because they aren’t really made for building so much as they are made for viewing.&lt;/p&gt;
&lt;p&gt;Here are a few I have collected recently. I’ve used awsm, Water, and Holiday but I would like to try the others out soon.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pico: &lt;a href=&quot;https://picocss.com/&quot;&gt;https://picocss.com/&lt;/a&gt; (they have a classless version)&lt;/li&gt;
&lt;li&gt;Simple.css &lt;a href=&quot;https://simplecss.org/&quot;&gt;https://simplecss.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Water.css &lt;a href=&quot;https://watercss.kognise.dev/&quot;&gt;https://watercss.kognise.dev/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;awsm.css &lt;a href=&quot;https://igoradamenko.github.io/awsm.css/&quot;&gt;https://igoradamenko.github.io/awsm.css/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;holiday.css &lt;a href=&quot;https://holidaycss.js.org/usage/&quot;&gt;https://holidaycss.js.org/usage/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GDCSS &lt;a href=&quot;https://gdcss.netlify.app/&quot;&gt;https://gdcss.netlify.app/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Neat &lt;a href=&quot;https://neat.joeldare.com/&quot;&gt;https://neat.joeldare.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Typesafe &lt;a href=&quot;https://github.com/bradleytaunt/typesafe-css&quot;&gt;https://github.com/bradleytaunt/typesafe-css&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to call out two of these. &lt;a href=&quot;https://watercss.kognise.dev/&quot;&gt;Water.css&lt;/a&gt; made waves (heh) on Hacker News a few years ago and introduced me to the concept of classless themes. It’s still one of my favorites.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gdcss.netlify.app/&quot;&gt;GDCSS&lt;/a&gt; is modeled after &lt;a href=&quot;https://www.gov.uk/&quot;&gt;GOV.UK&lt;/a&gt;, which I admire for putting simplicity and accessibility front and center. US government (especially local) could learn a thing or two from the UK here (although &lt;a href=&quot;https://designsystem.digital.gov/&quot;&gt;this looks like progress&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Some of these and more can be found at &lt;a href=&quot;https://www.cssbed.com/&quot;&gt;CSS Bed&lt;/a&gt; and this &lt;a href=&quot;https://github.com/dohliam/dropin-minimal-css&quot;&gt;huge list of classless themes on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;i-love-these-classless-css-themes-and-it-is-hard-to-say-why-exactly&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#i-love-these-classless-css-themes-and-it-is-hard-to-say-why-exactly&quot;&gt;I love these classless CSS themes and it is hard to say why exactly&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The biggest appeal is that they are drop-in, meaning it doesn’t take any special coding or design thought to make it happen (other than including it). Just create some HTML and include the stylesheet and you are done. You have a styled webpage.&lt;/p&gt;
&lt;p&gt;I remember the first time I stumbled across this concept. It was in the mid-2000s when I found the &lt;a href=&quot;https://www.w3.org/StyleSheets/Core/&quot;&gt;W3C Core Styles&lt;/a&gt;. These were meant to be (I believe) drop-in CSS styles that you could use immediately with mostly no addition of classes or anything else. This idea intrigued me.&lt;/p&gt;
&lt;p&gt;In the years following my discovery of the Core Styles, the idea of reusable themes would be hammered into my psyche in the form of WordPress themes. And once I dove into WordPress, the idea of publishing my own theme became a years-long white whale that I never did capture.&lt;/p&gt;
&lt;p&gt;Fast-forward to the present. I no longer find myself deep in WordPress work. My website still does use WordPress (as of the time of this writing), but I no longer think of WordPress themes as the dominant way to make a webpage (&lt;a href=&quot;https://w3techs.com/technologies/overview/content_management&quot;&gt;even if it still is&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I’m now thinking in terms of static sites made with generators like &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt;. So “theme” means something different to me now. A good CSS theme should not presuppose too much boilerplate, so as to be easier to apply to different sites with different markup.&lt;/p&gt;
&lt;p&gt;That brings us back to the W3C Core Styles. We want some good default styles that don’t assume you are using any particular markup scheme beyond regular, semantic HTML. You &lt;em&gt;can&lt;/em&gt; if you want, but you will need to add custom styles as needed.&lt;/p&gt;
&lt;p&gt;The W3C Core Styles are a bit dated and they don’t style many of the newer elements that came with HTML5.&lt;/p&gt;
&lt;p&gt;That’s where modern, classless CSS themes come in. They add just enough styling over the top of browser defaults to provide a fantastic base look without the need for specialized markup. There’s just something satisfying about the idea that I can write some HTML and then grab a nice pre-made theme that Just Works™. It’s hard to describe why I like this so much. In a way I suppose it’s nostalgic—these themes take me back to a time when I had first discovered HTML and CSS and learned to make simple webpages by hand (as opposed to using a site builder).&lt;/p&gt;
&lt;p&gt;It gives me warm fuzzies to get back to the “bare metal” of the web. It’s the digital equivalent of cleaning your desk and having only the essential items at your fingertips. These classless themes feel fresh and exciting despite their minimalistic nature. They make content look great, which makes me want to write more content. We &lt;em&gt;should&lt;/em&gt; be excited about writing content. It’s never been easier or cheaper or to write and publish to a worldwide audience.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-framework-less-framework&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#the-framework-less-framework&quot;&gt;The framework-less framework&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As we go deeper down the path of minimal CSS starters we end up at the logical conclusion—you might not need a framework at all. CSS has come a long way over the past decade. Many frameworks aren’t taking advantage of the cool stuff CSS can do now (eg, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries&quot;&gt;container queries&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units#relative_length_units&quot;&gt;new sizing units&lt;/a&gt;, etc.).&lt;/p&gt;
&lt;p&gt;Things that used to be difficult are much easier now. If all you need is a sidebar and a main content area, look no further than:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;.with-sidebar {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.sidebar {
  /* ↓ The width when the sidebar _is_ a sidebar */
  flex-basis: 20rem;
  flex-grow: 1;
}

.not-sidebar {
  /* ↓ Grow from nothing */
  flex-basis: 0;
  flex-grow: 999;
  /* ↓ Wrap when the elements are of equal width */
  min-inline-size: 50%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://every-layout.dev/layouts/sidebar/&quot;&gt;Every Layout&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-takeaway&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#the-takeaway&quot;&gt;The takeaway&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Less code is desirable and, for content on the web, simpler design is often better than complex design.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; Micro-frameworks and classless themes are great for getting up and running quickly without adding file size bloat, build steps, or reams of documentation to peruse. Classless CSS themes in particular look great by default and make for a handy go-to when you just need some HTML to be presentable.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I asked ChatGPT what a micro CSS framework was and it was hilariously wrong, citing Bootstrap as its first example. &lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I realize that putting something on the web doesn’t automatically mean you have an audience, but this grandiose idea that you can write anything and publish it is part of the thrill of these classless themes to me so just let me pretend. &lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A good litmus test to know if your design is too complex is if your users are hitting the browsers &lt;a href=&quot;https://www.maketecheasier.com/enable-browser-reader-mode/&quot;&gt;reader mode&lt;/a&gt; (or using an extension that does something similar). &lt;a href=&quot;https://blakewatson.com/journal/surveying-the-landscape-of-css-micro-frameworks/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Neglecting the scrollbar: a costly trend in UI design</title>
      <link href="https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/"/>
      <updated>2023-02-17T23:13:50Z</updated>
      <id>https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’ve noticed an alarming UI trend over the last five years or so. Apps are neglecting, misusing, or outright omitting the scrollbar from their interfaces. Notice isn’t the right word. I’ve been &lt;em&gt;living&lt;/em&gt; this trend.&lt;/p&gt;
&lt;p&gt;I have a &lt;a href=&quot;https://rebelwheelsblog.wordpress.com/2020/10/03/spinal-muscular-atrophy&quot;&gt;physical disability&lt;/a&gt; that, among other things, makes it difficult for me to scroll by using a typical scroll wheel or touch surface. That means I often scroll by clicking and dragging the scrollbar.&lt;/p&gt;
&lt;p&gt;It’s likely you haven’t thought about scrolling this way. Maybe you think of it as an old, outdated way of doing it. Or maybe you didn’t even know the scrollbar is draggable. But some people actually scroll that way! And it’s becoming more difficult than it used to be.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-the-scrollbar&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#benefits-of-the-scrollbar&quot;&gt;Benefits of the scrollbar&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The scrollbar has been around for decades now and is an effective, &lt;em&gt;interactive&lt;/em&gt; UI control. It gives you quite a bit of immediate visual feedback:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That the area is in fact scrollable.&lt;/li&gt;
&lt;li&gt;About how long a given page of content is.&lt;/li&gt;
&lt;li&gt;How much of that content you’re viewing &lt;em&gt;right now&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Your current location on the page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The scrollbar is a versatile control. It appears anywhere you might have a long area of content embedded in a window. That could be a single document—like a webpage—or something smaller like a menu of items. One window might have multiple embedded content areas and all of them could use a scrollbar.&lt;/p&gt;
&lt;p&gt;It also provides some functionality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can click and drag a scrollbar to move long distances in a single motion.&lt;/li&gt;
&lt;li&gt;You can click within the scroll track to either page up and down, or to jump to a specific point (depending on how the the scrollbar is implemented).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You might very well know what a scrollbar is and wonder why I’m rambling on about it. The point I’m trying to make is that this control is a useful, battle-tested one that is everywhere. We need to remind ourselves of that so that we know what we’re losing when we neglect it.&lt;/p&gt;
&lt;h2 id=&quot;the-cost-of-neglecting-the-scrollbar&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#the-cost-of-neglecting-the-scrollbar&quot;&gt;The cost of neglecting the scrollbar&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With the proliferation of touch-based scrolling, the role of the scrollbar in modern interfaces has changed. Some might say it has &lt;em&gt;evolved&lt;/em&gt;, but I think of it as &lt;em&gt;neglect&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The scrollbar is often relegated to serving as a mere visual indicator. And in some UI patterns, like infinite scrolling, the scrollbar effectively loses all meaning or utility. As a result, they are typically styled to be thin, semitransparent, and sometimes auto-hiding. They’re optimized for being seen when the context is right (e.g., when the user is scrolling). But that comes at a cost.&lt;/p&gt;
&lt;p&gt;The interactivity of the scrollbar is diminished when it’s made to be a visual indicator only.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thin scrollbars are difficult to click.&lt;/li&gt;
&lt;li&gt;Auto-hiding scrollbars can actively prevent scrolling if the only way to reveal them is to scroll the content.&lt;/li&gt;
&lt;li&gt;Non-clickable scrollbars cause confusion because some users might expect them to be clickable.&lt;/li&gt;
&lt;li&gt;Neglecting the interactivity of scrollbars takes away multiple methods of navigating a content area.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;example%3A-the-bad-one&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#example%3A-the-bad-one&quot;&gt;Example: the bad one&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I want to offer a real world example of the struggle&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I go through. One of the worst offenders in my world is the &lt;a href=&quot;https://setapp.com/&quot;&gt;Setapp&lt;/a&gt; app explorer (I don’t mean any ill will here—I &lt;em&gt;love&lt;/em&gt; Setapp).&lt;/p&gt;
&lt;p&gt;Here’s a quick video where I demonstrate the problem.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/rKqNG1Rk7Q4&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Here’s what’s happening in the video. I’m looking at the Setapp app’s main view. I’m an onscreen keyboard user so I have my &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;heavily modified macOS Accessibility Keyboard&lt;/a&gt; in the frame so you can see it.&lt;/p&gt;
&lt;p&gt;Notice that there’s no scrollbar control visible. Hovering my mouse over the rightmost area of the screen doesn’t reveal a scrollbar. I’m able to get the scrollbar to appear by pressing the &lt;em&gt;down&lt;/em&gt; arrow key, which scrolls a few lines and causes the scrollbar to become visible. At that point, clicking and dragging works like it normally would.&lt;/p&gt;
&lt;p&gt;After a few seconds, the scrollbar disappears. I’m back where I started.&lt;/p&gt;
&lt;p&gt;If it wasn’t for that workaround using the arrow key, I’d be physically unable to scroll that view. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;example%3A-the-good-one&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#example%3A-the-good-one&quot;&gt;Example: the good one&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the best scrolling experiences I have is with &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;. As soon as you mouseover the code editor pane you can see the scrollbar. That’s a win right there—you get immediate visual feedback. You can click and drag it as you would expect. And because it’s a code editor, you get a code &lt;em&gt;mini map&lt;/em&gt; which also functions as a scrollbar.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/O_jPLrhycxg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;The best part is that the size of the scrollbar is configurable. In the video, I set the vertical scrollbar width to a nice, eminently clickable 28 pixels.&lt;/p&gt;
&lt;h2 id=&quot;example%3A-the-best-one&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#example%3A-the-best-one&quot;&gt;Example: the best one&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One thing I &lt;em&gt;adore&lt;/em&gt; about the web is its near infinite ability to be customized. It’s a foundational concept on the web and it enables &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/&quot;&gt;powerful accessibility wins&lt;/a&gt; for users.&lt;/p&gt;
&lt;p&gt;I use the incredible browser extension, &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt;. It allows me to scroll webpages mobile-style by clicking and dragging &lt;em&gt;anywhere&lt;/em&gt; on the page. This extension is a life saver for me. I want ScrollAnywhere &lt;em&gt;everywhere&lt;/em&gt; now. It’s so good.&lt;/p&gt;
&lt;h2 id=&quot;considerations-for-developers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#considerations-for-developers&quot;&gt;Considerations for developers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My pitch is simple. Scrollbars are awesome. Use them! I’ll wrap this up with a list of considerations to keep in mind when working with scrollbars, in no particular order.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remember that scrollbars are interactive, not just visual indicators.&lt;/li&gt;
&lt;li&gt;Don’t hide them without an obvious way to summon them.&lt;/li&gt;
&lt;li&gt;On macOS, if the user has checked the global setting for always showing scrollbars (Settings &amp;gt; Appearance) don’t hide them &lt;em&gt;at all&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Avoid thin scrollbars if you can help it.&lt;/li&gt;
&lt;li&gt;If you’re customizing the look of a scrollbar, give it enough contrast to be visible.&lt;/li&gt;
&lt;li&gt;Try clicking and dragging your scrollbar. If it’s difficult for you, the developer, it’s probably difficult for your users.&lt;/li&gt;
&lt;li&gt;Try not to hijack the scroll. Yes scrolling hijacks make for cool Awwwards websites, but they can be quite difficult to deal with.&lt;/li&gt;
&lt;li&gt;Don’t be afraid to make the scrollbar bigger!&lt;/li&gt;
&lt;li&gt;Provide a way to scroll with the keyboard (e.g., up/down arrows). It’s often the expected behavior and can be a safety net for the user in case you screw up the scrollbar for whatever reason (but please don’t screw it up).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;There are a lot of struggles that are a much bigger deal than this one. I realize that. But we’re talking about UI here. So take it in context. &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Well, almost. I’d probably launch &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;, for which I have set up a voice command for scrolling. &lt;a href=&quot;https://blakewatson.com/journal/neglecting-the-scrollbar-a-costly-trend-in-ui-design/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>2022: my year in review</title>
      <link href="https://blakewatson.com/journal/2022-my-year-in-review/"/>
      <updated>2023-01-02T02:24:50Z</updated>
      <id>https://blakewatson.com/journal/2022-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I live a fairly boring dorky, life, often spending my non-working hours engaged in various projects. In 2022, I had a relatively prolific creative spurt. I made some new apps, a couple of video games, and even wrote a novella! Here’s a rundown of stuff from 2022.&lt;/p&gt;
&lt;h2 id=&quot;to-infinity-and-beyond&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#to-infinity-and-beyond&quot;&gt;To infinity and beyond&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The MRI dev team had a pretty prolific year too. The &lt;a href=&quot;https://blakewatson.com/work/cosmic/&quot;&gt;COSMIC&lt;/a&gt; team created two new applications supporting our customers’ spacesuit logistics needs. We are a part of several NASA contracts that were awarded in 2022, which means 2023 should be packed with new work. We’ll likely be hiring new team members to cope with the amount of work coming our way. 2022 was a big year for space (James Webb and Artemis I to name a few successes) and it’s exciting to see how I’ll get to be a part of it going forward.&lt;/p&gt;
&lt;h2 id=&quot;books&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#books&quot;&gt;Books&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m not much of a reader, I regret to say. I wanted to make a conscious effort to read more in 2022 and though I didn’t read a ton, I did make it through a handful of novels, thanks in part to the book club at work. I read a cyberpunk classic, Neuromancer, a grimdark fantasy trilogy, The First Law, and a YA rom-com about a teen with SMA—a book I was so thrilled to read that I &lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/&quot;&gt;wrote about it&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;writing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#writing&quot;&gt;Writing&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I wrote a handful of articles on my website in 2022. One of them—&lt;a href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/&quot;&gt;a love letter to writing fonts&lt;/a&gt;—made it to the top of Hacker News for a day. In November, as part of &lt;a href=&quot;http://nanowrimo.org/&quot;&gt;NaNoWriMo&lt;/a&gt;, I wrote a sci-fi novella called The Signal, about a group of astronauts stranded in deep space after they fail to prevent an asteroid from crashing into earth.&lt;/p&gt;
&lt;h2 id=&quot;spotify-instead-of-apple-music&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#spotify-instead-of-apple-music&quot;&gt;Spotify instead of Apple Music&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I spent 2022 using Spotify almost exclusively for music instead of Apple Music. This topic really deserves its own article, but the gist is that the Apple Music app on macOS is terrible. It’s clunky and glitchy. The  last straw happened toward the end of 2021. I was typing in the search input and my text somehow got deleted three times in a row without producing search results. I was so angry that it was making me retype my query over and over that I rage quit and opened Spotify. I used it the whole year and it was great.&lt;/p&gt;
&lt;h2 id=&quot;the-side-hustle&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#the-side-hustle&quot;&gt;The side hustle&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My biggest side project is my browser extension, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;. I spent the holiday season redesigning my marketing site and adding some new features to the app. The big one is that I &lt;em&gt;finally&lt;/em&gt; added an annual premium subscription that offers a discount over the monthly one. I also added a power-user feature that allows you to fold and unfold groups—handy if you have a lot of links on your new tab page. I also did some longstanding housekeeping that was needed, reducing the permissions needed by the extension and updating to Manifest V3, which is a behind-the-scenes technical thing that Chrome had been yelling at me about.&lt;/p&gt;
&lt;h2 id=&quot;that-time-i-got-really-into-synthwave&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#that-time-i-got-really-into-synthwave&quot;&gt;That time I got really into synthwave&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A few year ago I got really into synthwave music mixes on YouTube. I ended up &lt;a href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/&quot;&gt;making a site&lt;/a&gt; dedicated to listening to these mixes. I continue to update it weekly, automatically pulling in videos from a variety of handpicked creators.&lt;/p&gt;
&lt;h2 id=&quot;home-cooked-apps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#home-cooked-apps&quot;&gt;Home-cooked apps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A while back I read a fantastic post about how &lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;apps can be a home-cooked meal&lt;/a&gt;. I made a few of these for myself and my family and began referring to them as home-cooked apps. One of them was a grocery list app for my family to use and one of them was a digital bookmark repository. For more on that, see the article I wrote about &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/&quot;&gt;the joys of home-cooked apps&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;games&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#games&quot;&gt;Games&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve been slowly achieving and ol goal of mine since childhood—to make video games. My brother and I have a growing collection of &lt;a href=&quot;https://www.watsonbrosgames.com/&quot;&gt;silly little gaming experiments&lt;/a&gt;. This year, I created my first-ever game on &lt;a href=&quot;http://itch.io/&quot;&gt;Itch.io&lt;/a&gt;, &lt;a href=&quot;https://blakewatson.itch.io/chain&quot;&gt;Chain&lt;/a&gt;. I also made a tiny dungeon game called &lt;a href=&quot;https://www.watsonbrosgames.com/tiny-terror-tower/&quot;&gt;Tiny Terror Tower&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;pawpaw%E2%80%99s-stories&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#pawpaw%E2%80%99s-stories&quot;&gt;Pawpaw’s stories&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My brother and I finally got around to publishing our collection of stories by our late grandfather, Roy Charles Watson. He used to tell them often and usually over and over to anyone who would listen. He also typed up many of them as part of a family newsletter he used to send out. Matt, our mother, and I compiled them into a little website. &lt;a href=&quot;https://www.roycharleswatson.com/&quot;&gt;https://www.roycharleswatson.com&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;goals-for-2023&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2022-my-year-in-review/#goals-for-2023&quot;&gt;Goals for 2023&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m glad I wrote this because before listing it out, it didn’t feel like I accomplished that much. But looking back, I did alright. I hope to continue some of the successes of 2022 as well as add some new ones. I better list them out so I have something to go by.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read 5 books&lt;/li&gt;
&lt;li&gt;Write 5 articles&lt;/li&gt;
&lt;li&gt;Make one game&lt;/li&gt;
&lt;li&gt;Keep a journal&lt;/li&gt;
&lt;li&gt;Write one work of fiction&lt;/li&gt;
&lt;li&gt;Make (or start) a new app for money&lt;/li&gt;
&lt;li&gt;Be more social&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    <entry>
      <title>The joys of home-cooked apps</title>
      <link href="https://blakewatson.com/journal/the-joys-of-home-cooked-apps/"/>
      <updated>2022-12-11T23:06:53Z</updated>
      <id>https://blakewatson.com/journal/the-joys-of-home-cooked-apps/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;em&gt;Update: I gave a &lt;a href=&quot;https://blakewatson.com/journal/magnoliajs-2023-the-joys-of-home-cooked-apps/&quot;&gt;talk about this at MagnoliaJS 2023&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Home-cooked apps are the kind you make for yourself that solve your own problems. Much like a home-cooked meal, they can be shared with friends or family. They don’t have ROI, KPIs, or sales funnels. They don’t scale. They don’t have to.&lt;/p&gt;
&lt;p&gt;I’ve been making these kinds of apps for myself for years but I didn’t have a term for them or even a context for thinking about them until I read Robin Sloan’s &lt;a href=&quot;https://www.robinsloan.com/notes/home-cooked-app/&quot;&gt;An app can be a home-cooked meal&lt;/a&gt;. I was thrilled to read this because it spoke to ideas I held but hadn’t thought about actively—the idea that you can make useful things and they don’t need to be packaged for mass adoption to be successful.&lt;/p&gt;
&lt;p&gt;I love solving my own specific problems in the specific ways I want without concern for how other people would want to solve their similar problems. Now, that’s not to say you should &lt;em&gt;never&lt;/em&gt; generalize a solution to make it more useful for more people. I’m just saying you don’t &lt;em&gt;have&lt;/em&gt; to. Not every idea needs to be a product or a package.&lt;/p&gt;
&lt;p&gt;I think back to my late grandfather who would often take to his shop to make custom things for himself and his family—a cabinet for his wife, toys for the grandkids, and even a bespoke wheelchair lock down system custom made for my specific van and wheelchair. As a kid I was impressed with his craftsmanship. I would go on to learn that having a disability often means coming up with creative solutions to your problems. And so the idea of building things for yourself was ingrained in me from a young age.&lt;/p&gt;
&lt;p&gt;In this article I will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Discuss why you should make your own home-cooked apps&lt;/li&gt;
&lt;li&gt;Give you a little recipe to help you get started&lt;/li&gt;
&lt;li&gt;Show you some of my home-cooked apps&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;why-would-i-want-to-make-my-own-home-cooked-apps%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#why-would-i-want-to-make-my-own-home-cooked-apps%3F&quot;&gt;Why would I want to make my own home-cooked apps?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are several good reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can make exactly what you want. No settling for or compromising with what other apps offer.&lt;/li&gt;
&lt;li&gt;If you build with the idea that you are only serving yourself or a few people, you can skip over many of the challenging problems of software development: compatibility, extensibility, standards, best practices, scaling, etc.&lt;/li&gt;
&lt;li&gt;You can control your data. You don’t have to worry about a big company tracking everything you do.&lt;/li&gt;
&lt;li&gt;It’s fun. Building what you want and then using it is a rewarding experience. This is one of the things that got me into web development in the first place.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-to-build-a-home-cooked-app&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#how-to-build-a-home-cooked-app&quot;&gt;How to build a home-cooked app&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is just a little recipe to get you started. There is really no right or wrong way to go about it. If it works for you, then do it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The what.&lt;/strong&gt; Think of a problem of yours that you could solve. For example, some tedious work that you wish you had an app for but don’t. Or something you and your friends would like to use that isn’t readily available. It could be something a popular app does but in a way that is much simpler and straightforward.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The what, exactly.&lt;/strong&gt; Decide what, exactly, you want to build. Give yourself some rough requirements. Make a list. If it has UI, do little napkin sketch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The how.&lt;/strong&gt; Determine the easiest way to get to your goal. No need to over-complicate things—unless you enjoy that sort of thing! Main thing is to solve &lt;em&gt;your&lt;/em&gt; problem, not some abstract user’s problem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The how, part 2.&lt;/strong&gt; Use whatever technology you want. I don’t care if it’s new and shiny or old and boring. Use jQuery if you want. Or no JavaScript at all. This thing you’re building just needs to work for you so feel free to adopt whatever technical debt you want.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build it.&lt;/strong&gt; Even if it’s a larger project, just make small progress toward it. Check out these tips for &lt;a href=&quot;https://blakewatson.com/journal/finishing-side-projects/&quot;&gt;finishing side projects&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;start---a-new-tab-page&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#start---a-new-tab-page&quot;&gt;Start - a new tab page&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay I’m going to start (heh) the tour of examples by breaking one of my own rules. I made &lt;a href=&quot;https://start.blakewatson.com/&quot;&gt;this new tab page&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; for myself but ended up packaging it up for other people to use. It ultimately became my main side project, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea here was to have a single HTML file as a new tab page that would allow you to add and organize text links directly on the page. I realize this might seem trivial compared to all the fancy frontend apps out their but at the time I was manually editing HTML to add links and Start was one of my first experiences with local storage.&lt;/p&gt;
&lt;p&gt;I made it for me and, as it happened, others liked it too. That’s cool, but it’s not required!&lt;/p&gt;
&lt;h2 id=&quot;my-diy-pinboard-replacement&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#my-diy-pinboard-replacement&quot;&gt;My DIY Pinboard replacement&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve been a long time user of Pinboard, the popular bookmarking app, but I noticed my archival account—a feature of Pinboard that caches a snapshot of URLs you save—was often failing to capture pages. And I also felt the searching and browsing experience wasn’t great for me.&lt;/p&gt;
&lt;p&gt;My solution to this was a Node-backed JavaScript app that saves URLs along with metadata like descriptions and tags. It automatically sends the URL to Wayback Machine and saves the resulting cached URL along with the rest of the bookmark metadata.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/12/bookmarks-screenshot.png&quot; alt=&quot;Screenshot of the Bookmarks app. There is an Add Bookmark button at the top followed by a search input followed by a list of saved bookmarks.&quot; title=&quot;bookmarks-screenshot.png&quot; border=&quot;0&quot; width=&quot;1106&quot; height=&quot;800&quot; /&gt;
&lt;figcaption&gt;Screenshot of the Bookmarks app&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I &lt;a href=&quot;https://github.com/blakewatson/bookmarks&quot;&gt;open sourced this app&lt;/a&gt; with instructions for setting it up but with the caveat that I designed this for me and didn’t take other users into account.&lt;/p&gt;
&lt;h2 id=&quot;groceries&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#groceries&quot;&gt;Groceries&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s a fun one that was made for family. My brother and I have &lt;a href=&quot;https://rebelwheelsblog.wordpress.com/2020/10/03/spinal-muscular-atrophy/&quot;&gt;SMA&lt;/a&gt; and live at home with our mother. We needed a way to have a shared grocery list. There are numerous existing apps for list sharing but they all have cruft that a non-tech-savvy user (ie, my mom) would find confusing.&lt;/p&gt;
&lt;p&gt;So my brother and I teamed up to build a home screen web app that Mom could use on her phone and that we could use on the web (because mobile devices are difficult for us to handle).&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/12/groceries-screenshot.png&quot; alt=&quot;Screenshot of the groceries app. Header is Grocery List. Below that is a list of four grocery items with a checkbox by each one. Each item has 3 action buttons to the right of it: top emoji, pencil emoji, and red ex emoji. Underneath the list is a text box for adding a new item.&quot; title=&quot;groceries-screenshot.png&quot; border=&quot;0&quot; width=&quot;935&quot; height=&quot;676&quot; /&gt;
&lt;figcaption&gt;Screenshot of the Groceries app with admittedly strange items ¯&#92;_(ツ)_/¯&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The design is as dead simple as possible, using large emoji buttons for basic actions. You can add things, check them off, edit them, or delete them. Even drag-and-drop sort was too much UI complication, we decided, so the app offers minimal sorting functionality by way of a move-to-top button.&lt;/p&gt;
&lt;p&gt;The best part is the list is synced (via an admittedly hacky system) so that any of us can add things to the list.&lt;/p&gt;
&lt;p&gt;There’s not even a concept of multiple lists. That would introduce more UI. Instead, the same list is reused. There’s a button that unchecks everything and one that deletes everything.&lt;/p&gt;
&lt;p&gt;That’s it. That’s the app. It’s silly, really, but works great for us.&lt;/p&gt;
&lt;h2 id=&quot;the-time-i-accidentally-created-a-domain-specific-language&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#the-time-i-accidentally-created-a-domain-specific-language&quot;&gt;The time I accidentally created a domain-specific language&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My brother and I have a team of caregivers that work various day and night shifts. At the end of the pay period they need to turn in detailed timesheets. Sometimes these timesheets are difficult and error-prone.&lt;/p&gt;
&lt;p&gt;I wanted a way to keep my own records and also help my caregivers complete the timesheets accurately. After being annoyed with keeping records in a spreadsheet, I decided to create a plain text syntax. It works like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;# This is a comment. It is ignored.

# Each entry is two lines. First line has the date and which
# shift was worked. The second line is the name of the caregiver.
# The month and year are in the title of the document so not
# specified in the entry.

1 Day
Johnny Appleseed

1-2 Night
Jane Doe

# The following indicates a non-standard in/out time.

2 Day (7:00am-3:00pm)
Johnny Appleseed

# The asterisk means my bother and I were together the whole
# shift, meaning the caregiver will complete a timesheet
# for each of us.

2-3 Night *
Jane Doe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wrote a little frontend tool that can process this syntax and spit out a table of dates and times to print out that caregivers can reference when they are working on their timesheets. Here’s an example printout, albeit with less entries than normal. It’s made to match the way the timesheets are laid out, which are kind of awkwardly designed.&lt;/p&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/12/Screenshot-2022-12-11-at-4.06.40-PM.png&quot; alt=&quot;Heading, Johnny Appleseed. Following that is a table with 2 columns titled 1 and 2. Each column has a start time, end time, and total hours.&quot; title=&quot;Screenshot 2022-12-11 at 4.06.40 PM.png&quot; border=&quot;0&quot; width=&quot;497&quot; height=&quot;303&quot; /&gt;
&lt;p&gt;It works by convention. I have a normal day shift and night shift, so most of the time there’s no need to specify the start and end times. But I can always override the times by specifying them in parentheses.&lt;/p&gt;
&lt;p&gt;To speed up the record keeping process even further, I set up a little &lt;a href=&quot;https://textexpander.com/learn/using/snippets/advanced-snippet-elements/advanced-fill-ins&quot;&gt;TextExpander form&lt;/a&gt; that lets me type the date then choose the caregiver from a dropdown. This lets me quickly output the above syntax with minimal typing—something that’s difficult for me to do.&lt;/p&gt;
&lt;p&gt;I didn’t know it at the time, but this kind of thing has a name—&lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-specific_language&quot;&gt;domain-specific language&lt;/a&gt;. What I created was essentially a human-readable computer language designed for tracking caregiver hours. My frontend tool is the compiler, which produces the final output—HTML tables I can print. I store all of my records in my note-taking app of choice as &lt;em&gt;source code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I’m sure I would do it much differently now, but even with my limited knowledge at the time&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; I was able to process the above syntax using JavaScript. I’m not doing anything fancy, just splitting it apart into strings and reading it piece-by-piece.&lt;/p&gt;
&lt;h2 id=&quot;go-cook-up-your-own-apps&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#go-cook-up-your-own-apps&quot;&gt;Go cook up your own apps&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These apps were made for me so I’m not expecting you to think, “Oh I could use that.” But I &lt;em&gt;am&lt;/em&gt; expecting you to think about how you could address some of your own specific problems. Most of these apps took me a weekend or two. When you strip an app down to its essentials and the only requirements are yours, you have the freedom to hack things together however you see fit. I think the time investment on these projects was totally worth it. The last example, in particular, has saved me probably &lt;em&gt;days&lt;/em&gt; of time helping caregivers with timesheets.&lt;/p&gt;
&lt;p&gt;Hopefully this has you thinking of how to tackle a problem of your own or make a fun thing just for friends or family. Home-cooked apps are fun, useful, and a breath of fresh air.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Start is no longer maintained but if you like what it’s doing, check out &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://blakewatson.com/ihs/a-system-for-tracking-personal-care-hours/&quot;&gt;2013&lt;/a&gt; 🤯 &lt;a href=&quot;https://blakewatson.com/journal/the-joys-of-home-cooked-apps/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>SMA in fiction: The First Thing About You</title>
      <link href="https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/"/>
      <updated>2022-12-04T03:08:13Z</updated>
      <id>https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/</id>
      <content xml:lang="en" type="html"> &lt;figure&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/OsJKpe9tfzg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
 &lt;/figure&gt;
&lt;p&gt;I’ve never read a novel in which the main character was someone with SMA. As a person with SMA, I’ve always wanted to, though. &lt;a href=&quot;https://www.chazhayden.com/the-first-thing-about-you&quot;&gt;The First Thing About You&lt;/a&gt; is the debut novel by Chaz Hayden. It’s not my usual genre, being a YA rom-com, but I enjoyed the departure from fantasy and sci-fi and honestly I’ll read about a character with SMA in any genre.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This isn’t so much a review as it is me capturing my thoughts while they are fresh. There will be some spoilers, but I will warn you. But, really, you should read it if you’d like a fun, cute rom-com about quirky kids trying to figure out themselves while dealing with some tough real life stuff. The disability insight is a bonus.&lt;/p&gt;
&lt;h2 id=&quot;disability-logistics&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#disability-logistics&quot;&gt;Disability logistics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m a hobbyist writer of fiction with little to no ambition of publishing. I enjoy the creative challenge of &lt;a href=&quot;https://nanowrimo.org/&quot;&gt;National Novel Writing Month&lt;/a&gt; and I get satisfaction from making my brother read whatever mess I end up with at the end of the month.&lt;/p&gt;
&lt;p&gt;I’ve tried to write about a character with SMA but I found it difficult for the same reasons having SMA is difficult—it’s hard to make a character do stuff when they can’t do stuff. Many people with SMA need help with &lt;em&gt;everything.&lt;/em&gt; That means your character needs help to do just about &lt;em&gt;anything&lt;/em&gt;. My FBI analyst with SMA was really struggling.&lt;/p&gt;
&lt;p&gt;I was curious how Chaz would handle this and I must say he pulled if off well. In fact this assistance is central to the story—as it is central in our lives. The assistance that Harris, the main character, receives from various people—his family, school friends, his nurse, and his love interest—&lt;em&gt;is&lt;/em&gt; the story. It’s how those relationships function that makes the story happen.&lt;/p&gt;
&lt;h2 id=&quot;sma-accuracy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#sma-accuracy&quot;&gt;SMA accuracy&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I wasn’t sure going in how realistic the character’s disability was going to be, partially because of the logistics concern I just described. SMA feels like something of a spectrum so the severity of muscle weakness can vary, sometimes wildly, case-by-case.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; I would have been happy with any level of SMA severity but I was especially happy to see that it was something close to my own. The struggles Harris works through were that much more relatable to me.&lt;/p&gt;
&lt;p&gt;Chaz didn’t cut corners. We got showers, bathroom problems, respiratory issues—hello cough assist, old friend—and many more. This stuff is part of having SMA and I was happy to see it in the story as part of the plot.&lt;/p&gt;
&lt;h2 id=&quot;the-family-relationships&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#the-family-relationships&quot;&gt;The family relationships&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All I can say here is… accurate. I saw more than a few similarities between Harris’ mother and my own legendary mom.&lt;/p&gt;
&lt;h2 id=&quot;the-pca-relationship-(spoilers)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#the-pca-relationship-(spoilers)&quot;&gt;The PCA relationship (spoilers)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A character named Miranda becomes Harris’ nurse (or what I would call a personal care assistant or PCA). She helps Harris come out of his shell and navigate new people in a new town. The nurse who helps the disabled individual grow as a person is something of a trope in disability stories but this one had redeeming qualities that I enjoyed.&lt;/p&gt;
&lt;p&gt;First off, it’s a two-way thing. At first Miranda is the cool 20-something who treats Harris like a person and pushes him like an outgoing friend would a quiet one. But as the story continues, we see that Miranda gets a lot in return from Harris, who helps her work through some of her own problems.&lt;/p&gt;
&lt;p&gt;It might be cliché but in my experience it can be like this sometimes. If you spend many hours a day with someone through some of your most intimate daily activities it’s easy to become close friends eventually. And if things go well, in any friendship, both people should get something out of it.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;SPOILER: I would’ve liked to see Miranda’s arc end a little differently because, in the end, I think Harris was a bit too hard on her. Minor gripe.&lt;/p&gt;
&lt;h2 id=&quot;the-friend-relationship&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#the-friend-relationship&quot;&gt;The friend relationship&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Harris had one main friend in school in the story (aside from the love interest). This isn’t to say everyone with SMA will have the same experience, but I definitely had a few quality friends rather than a quantity of them. Disability may or may not have anything to do with that—it really depends on your personality—but this was another relatable thing for me.&lt;/p&gt;
&lt;h2 id=&quot;the-love-interest-relationship-(spoilers)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#the-love-interest-relationship-(spoilers)&quot;&gt;The love interest relationship (spoilers)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I enjoyed this arc. I felt like it had just the right mix of regular relationship stuff and some of the &lt;em&gt;disability logistics&lt;/em&gt; I mentioned earlier (i.e., I know we are on a date but, surprise, you have to feed me! 😬😅). Nory, the love interest, had an interesting backstory that made Harris more relatable to her and made their connection feel more real, whereas it would have been easy for the love story arc to feel totally contrived in a novel like this.&lt;/p&gt;
&lt;p&gt;I haven’t found my own Nory Fischer yet, &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; but many people with disabilities have and I appreciate this representation of dating with a disability. It’s the same as with anyone else, and also different. And both sides of that coin are present here, and really make the story for me.&lt;/p&gt;
&lt;h2 id=&quot;sma-in-fiction&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#sma-in-fiction&quot;&gt;SMA in fiction&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spinal muscular atrophy is a very specific and rare disability and it’s not like I expect to see it everywhere. But it was nice to have a deep dive into the mind of another person with SMA. I can tell that many of Harris’ experiences were pulled from real life (in a good way!) and after two days of reading I feel like I have known Chaz Hayden forever. I probably have an incredible bias when it comes to this novel so I am interested in what readers without SMA think. If anyone knows of good reviews, especially non-formal, bloggy ones, &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;send them my way&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I have read a draft of a friend’s novel that had a really great side character with SMA. I don’t think it has been published yet so I can’t really talk about it. But it was so so good! &lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;SMA is usually categorized into types (I have type 2, and most likely so does Harris in the story) but many people with SMA, including myself, feel the type system isn’t all that helpful, as there are always differences from person to person. &lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It’s important for everyone to remember that it is still a job, though. It starts off as being work friends but the line between work friends and &lt;em&gt;friend&lt;/em&gt; friends blurs the longer the relationship lasts. I believe it is just a reality of the nature of the job. This is a tough thing to balance for both parties but if done right can be rewarding for both parties. &lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Hello ladies. What I lack in muscle tone I feel I more than make up for with my collection of commercial fonts. &lt;a href=&quot;https://blakewatson.com/journal/sma-in-fiction-the-first-thing-about-you/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Almost monospaced: the perfect fonts for writing</title>
      <link href="https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/"/>
      <updated>2022-11-06T23:29:06Z</updated>
      <id>https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Monospaced fonts are the kind that most folks probably associate with a typewriter. It just &lt;em&gt;looks&lt;/em&gt; like typewriter text. Programmers often use monospaced fonts in their code editors, which gives monospaced fonts an association of being computer-y text.&lt;/p&gt;
&lt;p&gt;A monospaced font is one where each character takes up the same amount of horizontal space, even punctuation and spaces. The effect of this sameness is that multiple lines of characters are automatically aligned in neat columns. That means you can reliably line up text. If you’ve ever tried lining up text with “regular” fonts, then you will know it’s frustratingly impossible without using the appropriate tools. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; For example, check this out:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Name         Ability
====================
Superman     Flight
Batman       Money
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything lined up nicely.&lt;/p&gt;
&lt;p&gt;But there is a reason we don’t use monospaced fonts everywhere. They are somewhat hard to read because some characters need less space (eg, lowercase &lt;em&gt;i&lt;/em&gt;) and some characters need more (eg, uppercase &lt;em&gt;W&lt;/em&gt;). So in most instances, a &lt;em&gt;proportional&lt;/em&gt; font is used. The body text of this article is a proportional font. Most fonts are, and in professional documents they should be.&lt;/p&gt;
&lt;p&gt;Proportional fonts use just enough space for each character, making them easier to read and avoiding the awkwardness that some characters in monospaced fonts have (look at the poor little lowercase &lt;em&gt;m&lt;/em&gt; in the sample above—it appears smushed in order to fit into one character space).&lt;/p&gt;
&lt;h2 id=&quot;so-why-use-monospaced-fonts%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#so-why-use-monospaced-fonts%3F&quot;&gt;So why use monospaced fonts?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are a few good reasons. One is that many folks, myself included, love the writerly aesthetic of monospaced fonts. As a result, many writing apps allow you to write in a monospaced font and then export your document using proportional fonts. One such app is &lt;a href=&quot;https://ia.net/writer&quot;&gt;iA Writer&lt;/a&gt;, which I’ll discuss more in a bit.&lt;/p&gt;
&lt;p&gt;Another good use for monospaced fonts is computer code. The reason many software developers use them is because code requires specific syntax that is often full of abbreviated text, punctuation, and numbers. A monospaced font can make it easier to distinguish individual characters and avoid mistakes.&lt;/p&gt;
&lt;p&gt;Lastly, they are sometimes used as a design choice. You have to be careful with it because you can certainly ruin a design by tossing monospaced fonts in there. But if done well, you can draw on the informal, rough-around-the-edges aesthetic and add depth to a design.&lt;/p&gt;
&lt;h2 id=&quot;monospaced-meets-proportional&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#monospaced-meets-proportional&quot;&gt;Monospaced meets proportional&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have recently become obsessed with this in between category of fonts—those which combine aspects of monospaced &lt;em&gt;and&lt;/em&gt; proportional fonts to create interesting hybrids. Let’s look at some examples.&lt;/p&gt;
&lt;h3 id=&quot;ia-writer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#ia-writer&quot;&gt;iA Writer&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first are a set of fonts used in iA Writer.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/11/ia-writer-fonts.jpg&quot; alt=&quot;A sample of iA Writer Mono, Duo, and Quattro that shows the spacing differences between them.&quot; width=&quot;1388&quot; height=&quot;1098&quot; class=&quot;alignnone size-full wp-image-764&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The first sample up top is monospaced. The second sample, iA Writer Duo, is interesting because all the characters are the same width &lt;em&gt;except&lt;/em&gt; a few of the larger characters that need more space—they are set at one and a half width. That means any given character will be one of two possible widths, thus the name &lt;em&gt;Duo.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The third sample above takes this idea even further. Yes, some characters like uppercase &lt;em&gt;W&lt;/em&gt; need more space. But some characters, like lowercase &lt;em&gt;i&lt;/em&gt;, need &lt;em&gt;less&lt;/em&gt;. As the name &lt;em&gt;Quattro&lt;/em&gt; suggests, every character can be one of four possible widths—half, three-fourths, one, or one and a half.&lt;/p&gt;
&lt;p&gt;You might be thinking, “Okay, but now characters won’t line up neatly.” Thats true, but the upside of this sizing means you still retain the typewriter aesthetic with a bit more legibility. Notice the difference?&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/11/ia-writer-quattro-comparison.jpg&quot; alt=&quot;A sample sentence in both iA Writer Mono and Quattro. Quattro takes up less space and appears less rigid, thanks to its proportional spacing.&quot; width=&quot;1388&quot; height=&quot;584&quot; class=&quot;alignnone size-full wp-image-767&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;input&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#input&quot;&gt;Input&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://input.djr.com/&quot;&gt;Input&lt;/a&gt; font family by DJR &amp;amp; Font Bureau is another great example of monospaced meets proportional. This one may be of interest to programmers as the slogan of Input is &lt;em&gt;fonts for code&lt;/em&gt;. Similar to the iA Writer fonts, Input comes with monospaced &lt;em&gt;and&lt;/em&gt; proportional versions.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2022/11/input-comparison.png&quot; alt=&quot;JavaScript code sample comparison between Input Mono and Input Sans side by side.&quot; width=&quot;1327&quot; height=&quot;427&quot; class=&quot;alignnone size-full wp-image-769&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The difference is subtle but notice that the sample on the right gives letters like lowercase “m” a little leg room, improving the readability of the code. Even though Input Sans is technically a proportional font, it still gives plenty of attention to numbers and symbols, ensuring that they stand out and are easily distinguishable from each other.&lt;/p&gt;
&lt;p&gt;This family has Mono, Sans, and Serif variations that come in multiple weights, as well as narrow and compressed variations.&lt;/p&gt;
&lt;h3 id=&quot;triplicate-poly&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#triplicate-poly&quot;&gt;Triplicate Poly&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Edit 2023/07/16: I’m updating this article to include Triplicate Poly, a font that I originally omitted only because I forgot about it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mbtype.com/fonts/triplicate/&quot;&gt;Triplicate&lt;/a&gt; is monospaced font from &lt;a href=&quot;https://mbtype.com/&quot;&gt;Matthew Butterick&lt;/a&gt; that inherits its style from typewriter faces of yore. It has a number of notable features—true itallics, three weights, small caps, and more. Relevant to us is its gorgeous poly version that retains the classic typewriter feel but offers nicers spacing and pleasing proportions on the usual troublesome supects.&lt;/p&gt;
&lt;figure&gt;
  &lt;a href=&quot;https://blakewatson.com/uploads/2022/11/triplicate_poly.png&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2022/11/triplicate_poly-1024x638.png&quot; alt=&quot;Image of a page from Triplicate&amp;#039;s PDF specimen. It shows three paragraphs at increasing point sizes, each one rendered twice—once in mono and once in poly. Both styles look great to me but this comparison shows how the poly version has more natural spacing and proportions. Text at the bottom of the image says “Available only at MBType.com.”&quot; width=&quot;1024&quot; height=&quot;638&quot; class=&quot;alignnone size-large wp-image-1177&quot; /&gt;&lt;/a&gt;
  &lt;figcaption&gt;Mono and poly comparison from Triplicate&#39;s &lt;a href=&quot;https://mbtype.com/pdf/triplicate-type-specimen.pdf&quot;&gt;PDF specimen&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Triplacate Poly makes for a fantastic writing font, especially if you want that old typewriter feel. And its multiple weights and other features make it nice and flexible—and pretty comfy for reading too.&lt;/p&gt;
&lt;p&gt;Triplicate (all styles, poly and mono, included) costs $119 at the time of this writing, but it’s worth mentioning that you can get the entire &lt;a href=&quot;https://mbtype.com/fonts/buy-all.html&quot;&gt;MB Type library&lt;/a&gt; of eight families (and a &lt;a href=&quot;https://mbtype.com/license/&quot;&gt;generous license&lt;/a&gt;) for $499, which probably makes it the best professional font starter pack available.&lt;/p&gt;
&lt;h2 id=&quot;why-and-how-to-use-almost-monospaced-fonts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#why-and-how-to-use-almost-monospaced-fonts&quot;&gt;Why and how to use &lt;em&gt;almost&lt;/em&gt; monospaced fonts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I enjoy using them for both writing and coding. I’m already obsessed with the style of monospaced fonts and these in-betweeners take the style to the next level for me. You get the readability of a proportional font with the rough draft feel of a monospaced one. When coding, you get easily distinguishable characters &lt;em&gt;and&lt;/em&gt; just the right amount of space for characters that need more or less.&lt;/p&gt;
&lt;p&gt;You can use these fonts in writing or coding apps or wherever you like. iA Writer fonts are open source. Note that Input is free for personal and unpublished usage only—if you want to use it on a website or in a publication, you’ll need to purchase the appropriate license.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get the &lt;a href=&quot;https://github.com/iaolo/iA-Fonts&quot;&gt;iA Writer fonts from GitHub&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Get &lt;a href=&quot;https://input.djr.com/&quot;&gt;Input from its website&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want some more background on these fonts, here is some recommended reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iA Writer: &lt;a href=&quot;https://ia.net/topics/a-typographic-christmas&quot;&gt;Writing Fonts: A Typographic Christmas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Input: &lt;a href=&quot;https://input.djr.com/info/&quot;&gt;See what makes Input a different coding typeface&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Never attempt to line up text by using spaces. The only exception is if you are using a monospaced font. But in word processing applications, there are appropriate tools available for lining up text, like &lt;a href=&quot;https://practicaltypography.com/tables.html&quot;&gt;tables&lt;/a&gt; and &lt;a href=&quot;https://practicaltypography.com/tabs-and-tab-stops.html&quot;&gt;tab stops&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;There is an unfortunate metadata problem with iA Writer Quattro. If, when you are using it, you run into situations where bold and/or itallic isn’t working properly, see this page for more and to get repaired files. &lt;a href=&quot;https://blakewatson.com/ia-writer-quattro/&quot;&gt;/ia-writer-quattro/&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/almost-monospaced-the-perfect-fonts-for-writing/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Thinking in rich text</title>
      <link href="https://blakewatson.com/journal/thinking-in-rich-text/"/>
      <updated>2022-03-09T18:15:49Z</updated>
      <id>https://blakewatson.com/journal/thinking-in-rich-text/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’ve been using plain text notetaking applications for over a decade now. Before that I used &lt;a href=&quot;https://evernote.com/&quot;&gt;Evernote&lt;/a&gt;, and before &lt;em&gt;that&lt;/em&gt; I didn’t really keep any digital notes. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I have written previously about notetaking, but that writing doesn’t remain relevant today. Some part of me always felt a little hypocritical for having such sharp opinions about notetaking applications whilst most of the notes I do keep are stupid and unhelpful.&lt;/p&gt;
&lt;p&gt;My real problem wasn’t a lack of a good application. My problem was not knowing how to make good use of notes. This is still my problem—I haven’t figured it out. But ever since I started using &lt;a href=&quot;https://www.craft.do/&quot;&gt;Craft&lt;/a&gt; last year I have made a discovery.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;think&lt;/em&gt; much better in rich text.&lt;/p&gt;
&lt;p&gt;My rich text notes have been much more helpful to me in actually being productive. I was surprised by this finding. But now that I have been doing it for a little while, I’m starting to understand why.&lt;/p&gt;
&lt;p&gt;First let me say that I’m a huge nerd and I love everything about plain text. I’m pretty much right there with all the hype—portable, future proof, elegant, interoperable—all of that good stuff.&lt;/p&gt;
&lt;p&gt;But, plain text nerds, hear me out. Rich text is actually kind of… &lt;em&gt;neat&lt;/em&gt;. You can organize your documents with nice headings, you can drop in media, you can make nice clickable hyperlinks (and they even hide away the ugly URLs!), you can highlight things and make block quotes and other types of visual callouts, you can add lists and even clickable checkboxes.&lt;/p&gt;
&lt;p&gt;I’m finding out what every non-nerd computer user already knows—computers are powerful document creation tools. They offer a ton of formatting and design options and these features have been around for decades. If I push back my bias toward plain text for just a second, I can see that there is a lot of flexibility and power that I am missing out on by limiting myself to plain text.&lt;/p&gt;
&lt;p&gt;Now I hear what you’re saying… “You can do all of this with plain text! It’s called Markdown! It’s amazing! And future proof, and portable, and interoperable, and—“ I hear you. I really do. I love Markdown. But it is not, and was never meant to be, a rich, what-you-see-is-what-you-get editing experience.&lt;/p&gt;
&lt;p&gt;I’m defining rich text as any kind of what-you-see-is-what-you-get (WYSIWYG) editing experience and not strictly &lt;code&gt;.rtf&lt;/code&gt; format. Craft fits squarely in that category, as does Evernote.&lt;/p&gt;
&lt;p&gt;Lately I’ve been using notes in Craft to outline my thinking before starting a coding problem and to describe solutions, outline tasks, and collect relevant links to documentation. I know that you can do all this with Markdown, but WYSIWYG is so much nicer. Lets look at a few things that are nice about WYSIWYGs but kind of annoying with plain text and/or Markdown.&lt;/p&gt;
&lt;h2 id=&quot;reading-and-writing-simultaneously&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#reading-and-writing-simultaneously&quot;&gt;Reading and writing simultaneously&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the benefits of a what-you-see-is-what-you-get editing experience is, well, just that. I can write my thoughts and mark them up visually as needed. And I can immediately read them as they are intended to appear. There’s no context switching involved. With many Markdown editors, the only way to write and immediately see it in a more reading-friendly format is to open up a preview pane.&lt;/p&gt;
&lt;p&gt;These kind of previews make sense from a technical perspective. You are basically writing source code and live-previewing the compiled version of it. &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But I’m not writing code. I’m writing my thoughts, plans, reference material. I don’t want to see the same document twice. I don’t have room on my monitor for that. I have come to enjoy the quick feedback loop of creating and consuming my notes simultaneously. Many apps try to make Markdown feel like rich text by doing some fancy parsing of your source code and doing some inline formatting. But that can be clunky and never feels quite right to me.&lt;/p&gt;
&lt;h2 id=&quot;speaking-of-source-code%2C-there-are-too-many-flavors-of-markdown&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#speaking-of-source-code%2C-there-are-too-many-flavors-of-markdown&quot;&gt;Speaking of source code, there are too many flavors of Markdown&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are &lt;a href=&quot;https://xkcd.com/927/&quot;&gt;quite a few implementations&lt;/a&gt; of Markdown floating around out there. I’m tired of never knowing exactly which version of Markdown I’m using. Every app seems to use a different one. Quick, how do you do italics in Markdown?&lt;/p&gt;
&lt;h2 id=&quot;visual-elements-are-nice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#visual-elements-are-nice&quot;&gt;Visual elements are nice&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is easy to think you don’t really need any of these superfluous features. That’s certainly what I thought. Who needs highlighting? But I have found visual elements to be useful. Highlighting bits of information is something I did back when I still had the ability to handwrite. Same for calling out bits of text or sketching little images. WYSIWYG editors like Craft make adding these elements a primary feature. It’s easy, it’s smooth, and it looks nice.&lt;/p&gt;
&lt;p&gt;Some Markdown apps to a pretty good job of adding inline visuals, I concede. But even then they are limited to the small subset of formatting options that Markdown (or more accurately, some Markdown variant) supports.&lt;/p&gt;
&lt;h2 id=&quot;giving-rich-text-a-try&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#giving-rich-text-a-try&quot;&gt;Giving rich text a try&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As much as I love the philosophy and utility of plain text notes, it hasn’t really worked out for me in practice. I’m starting to think that my anxiety about using WYSIWYGs with proprietary formats is perhaps not totally justified.&lt;/p&gt;
&lt;p&gt;For example, even though Craft uses its own format, the company has some pretty strong &lt;a href=&quot;https://www.craft.do/s/5EYqvXdOUIrNu5&quot;&gt;pro-privacy and pro-data-ownership positions&lt;/a&gt;. They have impressive export capability, which helps to prevent lock-in and future proof-ness. Knowing my track record, it’s possible (probable even) that I will switch notetaking apps on a whim in the future. But my point stands. Rich text is nice to work in.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Before I started using digital notes in the mid to late 2000s, I wrote and doodled a lot in physical notebooks. When I was younger I had a bit of a problem collecting pens. If it wasn’t for the fact that I have spinal muscular atrophy, and that SMA is a progressive condition which has since deprived me of the ability to handwrite, I would still be keeping a physical notebook to this day. &lt;a href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m going to keep calling Markdown source code because that is what it is. It is meant to be ”compiled” into HTML. Some apps will attempt some formatting inline, but the only way to see what a document written in Markdown actually looks like is to render it in HTML and CSS. &lt;a href=&quot;https://blakewatson.com/journal/thinking-in-rich-text/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>The powerful accessibility of the customizable web</title>
      <link href="https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/"/>
      <updated>2021-12-29T02:09:05Z</updated>
      <id>https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Scrolling is hard. I can’t quite use the scroll wheel on my mouse&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; so my options for scrolling are either the keyboard (arrow keys or page up/down) or clicking and dragging the scroll bar.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; Dragging the scroll bar is a tedious way to scroll (but I’m glad it’s an option—app developers, please stop killing scroll bars in your apps). Try it for the next few minutes if you dare and you will see what I mean. This method of scrolling gets unwieldy if the page or app is using infinite scroll.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But a few months ago my brother introduced me to a cool browser extension, &lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt;. This extension has a &lt;em&gt;lot&lt;/em&gt; of options but I like to configure it where clicking and dragging a webpage scrolls similar to how mobile devices work—with inertia and everything. You can disable this behavior when clicking and dragging over text, which means you can still select text normally. Scrolling this way feels natural and is far less tedious than grabbing the scrollbar.&lt;/p&gt;
&lt;p&gt;I wanted the same ability in my own browser extension, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;, which is an addon that replaces your browser’s new-tab page. But the way browser extensions are isolated from each other means that ScrollAnywhere can’t interact with A Fine Start’s new-tab page. So I ended up implementing my own, somewhat hacky, drag scroll functionality and added it as a secret setting.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But this whole thing got me to thinking about how cool it is that users can so easily customize webpages and web apps. It’s something you can’t really do with native desktop and mobile apps. Native apps are only as customizable as the app developer allows. But webpages are rendered based on the wants of the developer &lt;em&gt;and&lt;/em&gt; the user. Indeed part of the challenge of web design is designing with flexibility, knowing that you can’t guarantee the page will appear how you envision it. There are variables that change depending on the user and their device—screen size, text size, contrast, color, and more.&lt;/p&gt;
&lt;p&gt;Imagine if your whole computer was as customizable as a webpage. Linux users have been shouting this for years. But still, you have to be fairly technologically proficient to customize your OS. And customizing individual apps is even more difficult—unless an app has a plugin architecture of some sort you would need to modify the source code and build your own executable. Customizing web pages via browser extensions is something the average person can do easily.&lt;/p&gt;
&lt;p&gt;Web apps sometimes face (valid) &lt;a href=&quot;https://daringfireball.net/2014/11/native_apps_are_part_of_the_web&quot;&gt;criticism&lt;/a&gt; for being slower or clunkier than their native app counterparts, but a web app’s super power is the ability to customize it &lt;em&gt;without needing any support from the app developer&lt;/em&gt;. That gives web app users some control that native app users don’t have. Let me give you an example.&lt;/p&gt;
&lt;p&gt;I’ve trying to get back into RSS for the first time since &lt;a href=&quot;https://en.wikipedia.org/wiki/Google_Reader&quot;&gt;Google killed its Reader app&lt;/a&gt;. I downloaded the venerable &lt;a href=&quot;https://netnewswire.com/&quot;&gt;NetNewsWire&lt;/a&gt;, the native RSS reader for Mac. NetNewsWire is able to connect to &lt;a href=&quot;https://feedbin.com/home&quot;&gt;Feedbin&lt;/a&gt;, which is a web app that you can use to store all your RSS subs in a central location (I have two Macs so this is helpful to me). But for the same reasons I mentioned previously, scrolling is a little cumbersome for me and that combined with some &lt;a href=&quot;https://github.com/Ranchero-Software/NetNewsWire/issues/1119&quot;&gt;compatibility issues between NetNewsWire and the macOS Accessibility Keyboard&lt;/a&gt; meant that scrolling articles in NetNewsWire was tedious.&lt;/p&gt;
&lt;p&gt;But Feedbin is an RSS reader in its own right—it doesn’t require a native client to access it. And because Feedbin is a web app, it’s customizable by browser extensions. That means I can use ScrollAnywhere just like on any other webpage.&lt;/p&gt;
&lt;p&gt;My browser extension, A Fine Start, began as an accessibility tool of sorts that I created for myself to reduce the amount of typing needed to surf the web.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt; As apps go, web browsers are among the most customizable I can think of.&lt;/p&gt;
&lt;p&gt;Here are a few extensions I use that make the web more usable for me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fastaddons.com/#scroll_anywhere&quot;&gt;ScrollAnywhere&lt;/a&gt;, as I mentioned.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://add0n.com/stylus.html&quot;&gt;Stylus&lt;/a&gt;, an extension for adding users styles. I use this for my own custom CSS but it’s possible to browse/add public styles from others so knowing how to write CSS isn’t required. And if you’re really just wanting dark mode everywhere you could try something like the popular &lt;a href=&quot;https://darkreader.org/&quot;&gt;Dark Reader&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://1password.com/&quot;&gt;1Password&lt;/a&gt;, a password manager that autofills login forms. You can substitute your favorite password manager here but the point is this saves me a ton of typing by logging me into websites.&lt;/li&gt;
&lt;li&gt;Ad blockers. You know what, I’m calling these accessibility tools as well. It’s perhaps a stretch but on some sites with visually loud, distracting ads an ad blocker is almost necessary to read the content of the page. I use and recommend both &lt;a href=&quot;https://ublockorigin.com/&quot;&gt;uBlock Origin&lt;/a&gt; and &lt;a href=&quot;https://duckduckgo.com/app&quot;&gt;DuckDuckGo Privacy Essentials&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have a habit of conflating accessibility tools with productivity tools—⁠look no further than my &lt;a href=&quot;https://blakewatson.com/assistive-tech-gear/&quot;&gt;assistive tech gear&lt;/a&gt; page—⁠but when you are as disabled as I am they are one and the same.&lt;/p&gt;
&lt;p&gt;Accessibility is going to mean different things to different people. I’m not saying web apps are universally more accessible than native ones. Depending on the situation, native apps can be a lot more accessible. That said, the user-customizability of web apps (and websites) is a powerful boon to accessibility and can mean the difference between being able to use an app or not.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I kind of can but it’s difficult so I only do it as a last resort. &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Scrollbars usually have a behavior that allows you to click inside the scroll track to move up or down one viewport—essentially the same behavior as Page Up/Down. Something that annoys me about both of those is that they move &lt;em&gt;exactly&lt;/em&gt; one whole viewport. That makes reading jarring because it’s easy to lose your place. I wish this was configurable at the OS level such that paging up or down would move half or 75% of a viewport instead of a whole one. Linux peeps can let me know if this is something I am missing out on by sticking with macOS. 🙂 &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In my opinion, infinite scroll is a dark pattern. One of its most popular uses is keeping users hooked in the dopamine slot machine of the social media news feed. Not to mention it makes getting at footer links nearly impossible. &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The drag scroll feature is hidden because it was intended for only me and my brother. As such it’s experimental and doesn’t meet my standard of quality for being widely available (it’s also kind of random). But if you want to use it—at your own risk—you may find the secret settings by clicking the Settings button and then holding the mouse button down on the heading, &lt;em&gt;Settings&lt;/em&gt;, for five seconds, after which the secret settings will appear. &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Do people still use the phrase, &lt;em&gt;surf the web&lt;/em&gt;? &lt;a href=&quot;https://blakewatson.com/journal/the-powerful-accessibility-of-the-customizable-web/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Introducing synthwave.live, a nostalgic musical odyssey</title>
      <link href="https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/"/>
      <updated>2021-12-13T04:39:11Z</updated>
      <id>https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I stumbled upon the synthwave genre&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; when a friend of mine sent me a link to The Midnight’s &lt;a href=&quot;https://www.youtube.com/watch?v=Xzex-nN2yM0&quot;&gt;America Online&lt;/a&gt; track on YouTube. I became a little obsessed with the synth-y nostalgia of it all and ended up diving into several artists’ discographies and bookmarking compilations I would find on YouTube.&lt;/p&gt;
&lt;p&gt;In particular I enjoyed working to the sound of (mostly) instrumental synthwave mixes. I was making my own playlist of mixes at first but what I really wanted was “YouTube but it’s just synthwave mixes.” I started looking into it and it turns out &lt;a href=&quot;https://developers.google.com/youtube/v3/&quot;&gt;YouTube’s Data API&lt;/a&gt; could support what I wanted.&lt;/p&gt;
&lt;p&gt;The idea was to grab all the videos I had been finding and add them to a website that was more appropriate for music playback. That meant more advanced playback controls and behavior—ability to navigate track lists, now-playing notifications, and other features. I’m not gonna lie it was also fun to put a synthwave-y aesthetic on the whole thing—add some &lt;a href=&quot;https://www.typography.com/fonts/forza/overview&quot;&gt;sweet fonts&lt;/a&gt;, throw in some pinks and purples.&lt;/p&gt;
&lt;p&gt;I started searching for domain names—the obligatory first step of any new project—and settled on &lt;em&gt;synthwave.live&lt;/em&gt; (I also nabbed &lt;em&gt;chillwave.live&lt;/em&gt; and &lt;em&gt;retrowave.live&lt;/em&gt; while I was there). Never mind I wasn’t planning on posting live music. Just notice how pristine the domains are!&lt;/p&gt;
&lt;p&gt;I designed a quick logo and paid an illustrator on Fiverr to make a &lt;a href=&quot;https://blakewatson.com/journal/09-20-2020/&quot;&gt;favicon&lt;/a&gt;. It was off to the races.&lt;/p&gt;
&lt;p&gt;Oh yeah, that was in May 2020. Turns out I built it and quietly ran it for over a year before deciding to write about it. What can I say, I’m lazy and also I wanted to make sure I could keep it updated. Well, I did. So now I’m officially introducing &lt;a href=&quot;https://synthwave.live/&quot;&gt;synthwave.live&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://blakewatson.com/uploads/2021/12/homepage_view.png&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2021/12/homepage_view-1024x594.png&quot; alt=&quot;Screenshot of homepage showing a listing of video thumbnails in a grid.&quot; width=&quot;1024&quot; height=&quot;594&quot; class=&quot;size-large wp-image-621&quot; /&gt;&lt;/a&gt;
&lt;figcaption&gt;The homepage&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;concerns&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#concerns&quot;&gt;Concerns&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I had a few reservations about the project but nothing that ultimately deterred me from building it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I didn’t love being totally reliant on the YouTube API but displaying YouTube videos was the whole point so it is what it is.&lt;/li&gt;
&lt;li&gt;I feel a little guilty making something that’s just a conglomeration of stuff other people made. Technically these mixes are already curated collections of other folks’ work. Now I’m curating the curations. In an attempt to counteract this feeling, I have taken steps to link back to channels and their videos. I also show full video descriptions that aren’t collapsed, so it’s easy to see all the credits or click through to merch shops, Bandcamp pages, etc.&lt;br /&gt;&lt;br /&gt;
And just to be clear, these videos are ordinary YouTube embeds. I’m not ripping videos and rehosting them or any such funny business.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;overview-of-features&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#overview-of-features&quot;&gt;Overview of features&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;listing-view&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#listing-view&quot;&gt;Listing view&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The homepage is a listing of all videos on the site sorted by date. You can also sort the list by views on YouTube. This keeps the homepage fresh.&lt;/p&gt;
&lt;h3 id=&quot;single-video-view%2Fplayer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#single-video-view%2Fplayer&quot;&gt;Single video view/player&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is the bread and butter of the site and one of the main reasons for the project existing. It’s laid out similar to a single video page on YouTube with some key differences.&lt;/p&gt;
&lt;figure&gt;
&lt;a href=&quot;https://blakewatson.com/uploads/2021/12/single_player_view.png&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2021/12/single_player_view-1024x593.png&quot; alt=&quot;Screenshot of single view. Shows an embedded YouTube video with some metadata below.&quot; width=&quot;1024&quot; height=&quot;593&quot; class=&quot;size-large wp-image-623&quot; /&gt;&lt;/a&gt; &lt;figcaption&gt;Single view&lt;/figcaption&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Track parsing.&lt;/strong&gt; If a track list is present in the video description, it gets parsed and enables some interesting features—the ability to skip tracks, ability to immediately play any track, OS notification of current track, and ability to link to the currently playing track, to name a handful.[^track parsing]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mini player.&lt;/strong&gt; This is a fixed section at the bottom of the page that has playback controls and information about the currently playing track (thanks to track parsing) including a progress bar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Popout player.&lt;/strong&gt; It’s similar to the mini player but opens in a small, separate window. Good for positioning on your desktop for quick access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autoplay.&lt;/strong&gt; If this setting is enabled, a random mix will automatically start playing after the current one finishes. Optionally, it’ll autoplay only from your &lt;em&gt;favorites&lt;/em&gt;. More on that in a moment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metadata.&lt;/strong&gt; Title, full description, publish date, and links back to YouTube are all provided on this view.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;user-accounts-and-favorites&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#user-accounts-and-favorites&quot;&gt;User accounts and favorites&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I wanted to bookmark my favorite mixes for easy reference later so I added user accounts. Once signed in, an &lt;em&gt;Add to Favorites&lt;/em&gt; button appears on the player page. Clicking &lt;em&gt;Favorites&lt;/em&gt; in the menu bar will take you to a listing view of all your favorite videos.&lt;/p&gt;
&lt;p&gt;The only purpose of user accounts at the moment is for keeping track of Favorites. I don’t have any other immediate plans for accounts.&lt;/p&gt;
&lt;h3 id=&quot;search&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#search&quot;&gt;Search&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A basic search view exists that lets you perform searches against the full titles and descriptions of videos or titles only. The search is pretty basic but serviceable. It’s all frontend-powered so it first has to download an index file which is a bit large.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;developer-notes&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#developer-notes&quot;&gt;Developer notes&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here I’ll cover some of the technical details of how the site works. The birds-eye view is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A script gets video data from YouTube.&lt;/li&gt;
&lt;li&gt;That data is used to generate a static website.&lt;/li&gt;
&lt;li&gt;The built site is deployed to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;youtube-data-api&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#youtube-data-api&quot;&gt;YouTube Data API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I mentioned previously, synthwave.live is made possible because of YouTube’s Data API. I’m keeping a manually curated list of channel IDs and playlist IDs. If the whole channel is nothing but synthwave mixes I grab all the videos from the channel. Otherwise I grab playlists that fit the theme of the site. I prefer using the whole channel if possible because people sometimes forget to update their playlists.&lt;/p&gt;
&lt;p&gt;Using those IDs I run a NodeJS script that makes a series of requests to the API and the result is a big JSON file of video information. I do a bit of filtering after the fact. For example, I don’t want single-track videos on the site so I enforce a minimum duration of ten minutes.&lt;/p&gt;
&lt;h3 id=&quot;static-site-generation-with-eleventy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#static-site-generation-with-eleventy&quot;&gt;Static site generation with Eleventy&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This was my first project on which I used &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; and it’s definitely a tool I’d use again. Its most appealing feature in this case is its ability to use various data sources as input. My particular setup is a little complicated but, in short, I take the big JSON data dump and use it to generate all the different pages needed—paginated listing views, single views, and one-off pages like the one that lists every YouTube channel used on the site. I’m even using Eleventy to generate a small JSON file for each video (I call it a &lt;em&gt;fragment&lt;/em&gt;) that I can request when I need information about a particular video.&lt;/p&gt;
&lt;p&gt;All the pages get built by Eleventy and those, along with styles and scripts, get deployed to the server.&lt;/p&gt;
&lt;h3 id=&quot;vue-for-interactivity-and-userbase-for-persistent-user-data&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#vue-for-interactivity-and-userbase-for-persistent-user-data&quot;&gt;Vue for interactivity and Userbase for persistent user data&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For frontend interaction I’m using &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; 2. I take advantage of Vue’s reactivity system to sync up various parts of the UI, primarily the moving parts on the single view like the mini player, but also on the search page and user authentication pages.&lt;/p&gt;
&lt;p&gt;Since the app is all frontend I’m using a service called &lt;a href=&quot;https://userbase.com/&quot;&gt;Userbase&lt;/a&gt; to handle authenticating users and storing and retrieving their favorites. It’s a neat service that was fairly straightforward to integrate and kept me from needing to implement a backend. It costs $89/year for the standard plan which is a great value for what you get.&lt;/p&gt;
&lt;p&gt;I’m sure I could do a better job with the asynchronous nature of the whole thing but it works well enough for how I’m using it.&lt;/p&gt;
&lt;h3 id=&quot;track-list-parsing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#track-list-parsing&quot;&gt;Track list parsing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before making the site, I was listening to mixes directly on YouTube using an extension called &lt;a href=&quot;https://github.com/XavierDuthil/youtube-tracklist-control&quot;&gt;YouTube Tracklist Control&lt;/a&gt;. I thought it was really cool how it parsed tracks using the description text (if the publisher provided timestamps). As the code for that extension is public domain, I was able to use the parsing code with a little modification to support all the track-based features on the site. There are times when either track lists aren’t provided or they’re provided in such a way that the parser doesn’t recognize. In those cases, the video still plays but playback information and controls are limited.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&quot;https://blakewatson.com/uploads/2021/12/single_player_view_details.png&quot;&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2021/12/single_player_view_details-1024x594.png&quot; alt=&quot;Screenshot of single view scrolled down past the video. Showing video title, published date, links back to YouTube, full text description, sidebar with interactive tracklist.&quot; width=&quot;1024&quot; height=&quot;594&quot; class=&quot;size-large wp-image-622&quot; /&gt;&lt;/a&gt; &lt;figcaption&gt;Single view details&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;popout-player&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#popout-player&quot;&gt;Popout Player&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I had never tried interacting with a new browser window before so it was a learning experience. I ended up using an event system to communicate state between the windows as needed. I wish it was possible to set a window to be a &lt;em&gt;floating&lt;/em&gt; window (always on top of other windows) but I can see where that would be terrible for security.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2021/12/popout_player-1024x463.png&quot; alt=&quot;Screenshot of the popout player. It’s a small window showing playback controls, the track title, the video title, the channel name, and a playback progress bar.&quot; width=&quot;1024&quot; height=&quot;463&quot; class=&quot;alignnone size-large wp-image-630&quot; /&gt; &lt;figcaption&gt;Popout player&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id=&quot;infrastructure&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#infrastructure&quot;&gt;Infrastructure&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That’s a silly term to use in this case but here’s my setup.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A locally run script talks to YouTube and dumps some JSON video data in the project.&lt;/li&gt;
&lt;li&gt;I commit and push to a (private for now) repo on GitHub.&lt;/li&gt;
&lt;li&gt;When I push, it triggers a deployment on &lt;a href=&quot;https://www.deployhq.com/&quot;&gt;DeployHQ&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;DeployHQ builds the site and deploys the built files to my static server on &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NFSN&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m aware GitHub can deploy this for me now but I already have it set up this way. If you’re thinking it would be better to deploy to Netlify or some other fancy service I say to you… yeah you’re probably right. I’m a curmudgeon &lt;a href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/&quot;&gt;stuck in my ways&lt;/a&gt;. Get off my lawn.&lt;/p&gt;
&lt;h2 id=&quot;roadmap-and-closing-thoughts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#roadmap-and-closing-thoughts&quot;&gt;Roadmap and closing thoughts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m mostly letting it hum along as-is, just running the update script every week to grab new videos and occasionally adding new content sources. That said, there are some features on my radar.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Actual livestreams.&lt;/strong&gt; It’s kind of silly that a site with the &lt;code&gt;.live&lt;/code&gt; TLD doesn’t have any livestreams. Would be cool to have a page featuring some. For example, &lt;a href=&quot;https://www.youtube.com/watch?v=xxgxkjV70Vc&quot;&gt;ChillSynth FM&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open-sourcing some or all of the code.&lt;/strong&gt; One reason I put off writing this is because I had planned to publish the source code at some point. But I never got around to cleaning it up. It’s kind of messy and I haven’t felt like making it presentable. I may do it in the future, especially if there’s any expressed interest. It would be pretty cool for this same type of site to be made for other genres of music like lofi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Other data sources.&lt;/strong&gt; I don’t love being fully dependent on YouTube for content. Might be cool to look into SoundCloud or some other source. I must admit this is a very low priority given the amount of work it would require.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tasteful advertising.&lt;/strong&gt; This site was not created to make money. I mostly made it for myself to use and it doesn’t get a lot of traffic currently. That said, I could see selling a featured video spot on the homepage that I rotate out every week. Or something like that. I don’t know. I’ll reexamine this idea if and when the site has enough traffic to warrant it. But automated or tracker-infested ads will ever be on the site.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It was a fun project to build. I think it took me about three or four weekends for the initial build and then a little work here and there to fix things. The weekly maintenance is very easy. I run one script that gets the data from YouTube and builds a preview of the site for me to inspect. If I like what I see I can run another script to automatically commit and push it, which triggers the deployment.&lt;/p&gt;
&lt;p&gt;I use the site as my own personal audio player almost every day, especially during working hours. If you like synthwave or just like to listen to instrumental background music, give it a try and let me know what you think.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://synthwave.live/&quot;&gt;Go to synthwave.live →&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[^track parsing]: I realize technically YouTube can do most (all?) of this but it isn’t as straightforward. On synthwave.live I’m leaning heavily on track list parsing so that it feels like you’re viewing a real list of individual tracks, not a video with timestamp links.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;When I say synthwave, I usually also mean chillwave, retrowave, outrun, darksynth, and other sub-genres. &lt;a href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The index file is about 460kb gzipped at the time of this article and growing every week. “Index” is probably a misnomer since this file includes full descriptions of videos. But it &lt;em&gt;is&lt;/em&gt; a stripped down version compared to the all the data I get back from YouTube. &lt;a href=&quot;https://blakewatson.com/journal/introducing-synthwave-live-a-nostalgic-musical-odyssey/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Speaking in code: hands-free input with Talon</title>
      <link href="https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/"/>
      <updated>2021-05-23T21:00:30Z</updated>
      <id>https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;em&gt;This is an article version of my &lt;a href=&quot;https://www.magnoliajs.com/&quot;&gt;MagnoliaJS&lt;/a&gt; 2021 talk. You can &lt;a href=&quot;https://blakewatson.com/uploads/2021/05/Speaking-In-Code.pdf&quot;&gt;download the slides&lt;/a&gt; here.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;block-embed block-embed-service-youtube&quot;&gt;&lt;iframe type=&quot;text/html&quot; src=&quot;https://www.youtube.com/embed/S6zZNE9U6YI&quot; frameborder=&quot;0&quot; width=&quot;640&quot; height=&quot;390&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;I often use the phrase “coding by voice” to quickly describe Talon and what it’s for, but that phrase isn’t fully accurate. “Coding by voice” is just a stand-in for the more broad idea of “hands-free input.” The technology I’m talking about isn’t limited to coding, even though that’s a common use for it. If you are coding a website, for example, you are likely switching between writing code in an editor, testing your site and reading documentation in a web browser, and using any number of supplemental tools and applications. Hands-free input aims to help you with all of those tasks and more.&lt;/p&gt;
&lt;p&gt;That said, Talon is often used as a tool for programmers to code by voice. At the time of this writing, you all but need to be a programmer to use Talon. It has a setup and configuration process that’s a bit technical, so I would guess its current user base is mostly programmers or technically proficient users. I imagine that will change over time as Talon becomes easier to set up and configure.&lt;/p&gt;
&lt;h2 id=&quot;why-would-anyone-want-to-code-by-voice%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#why-would-anyone-want-to-code-by-voice%3F&quot;&gt;Why would anyone want to code by voice?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For me, personally, it’s accessibility. I have a condition called spinal muscular atrophy which, among other things, causes me to have extremely weak muscles—to the point where typing on a physical keyboard is impossible. I require alternate forms of input and speech recognition one of them.&lt;/p&gt;
&lt;p&gt;Another big reason people might want to code by voice is if they have repetitive strain injury (RSI). RSI tends to cause pain in the hands, arms, neck, and more. If you do a web search “RSI in programmers” you will find countless stories of RSI affecting people’s work and personal lives. If ignored, RSI symptoms can be severe. Using voice input can help here by giving your hands and arms a rest and break up some of the repetitiveness of typing&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;For years I’ve mostly adapted to the problem of not being able to type by &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;using an onscreen keyboard&lt;/a&gt;, which is software that allows you to use a mouse to type by clicking on a virtual keyboard. I’ve optimized my onscreen keyboard setup but typing with a mouse is still tedious and, at times, frustratingly slow.&lt;/p&gt;
&lt;p&gt;A couple of years ago I came across Talon. I’ve since started using Talon for about a third of my daily computer usage, sometimes more. Others use Talon as their primary means of input. It’s an effective tool, but it takes a shift in the way you think about computer input.&lt;/p&gt;
&lt;h2 id=&quot;misconceptions-and-the-current-state-of-voice-controlled-productivity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#misconceptions-and-the-current-state-of-voice-controlled-productivity&quot;&gt;Misconceptions and the current state of voice-controlled productivity&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most well-known type of speech recognition software at this point is probably the digital assistants found in our smart devices. These are normally used in short bursts for quick actions or used to request bite-sized pieces of information.&lt;/p&gt;
&lt;p&gt;For long-form usage a popular option is Dragon, which is available for Windows but was discontinued on the Mac in 2018. Both macOS and iOS have built-in dictation available as well as Voice Control, Apple’s voice-controlled accessibility software.&lt;/p&gt;
&lt;p&gt;That said, none of these options are great for programming, as seen in this hilarious video of a guy trying to write code using Windows Vista’s speech recognition feature.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/MzJ0CytAsec&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;I’d wager that this is what most people imagine when they hear “code by voice.”&lt;/p&gt;
&lt;p&gt;There are some alternatives specifically for programming. &lt;a href=&quot;https://serenade.ai/&quot;&gt;Serenade&lt;/a&gt; is one option, though it only supports certain editors and languages (and so isn’t a system-wide alternative). Window users have &lt;a href=&quot;https://github.com/synkarius/caster&quot;&gt;Dragonfly/Caster&lt;/a&gt; as an option, although I don’t know a lot about it.&lt;/p&gt;
&lt;p&gt;Bup we’ll be looking at Talon.&lt;/p&gt;
&lt;h2 id=&quot;cross-platform%2C-hands-free-input-with-talon&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#cross-platform%2C-hands-free-input-with-talon&quot;&gt;Cross-platform, hands-free input with Talon&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Talon is powerful, cross-platform software created by developer Ryan Hileman. It is available for free (though the developer has a &lt;a href=&quot;https://www.patreon.com/lunixbochs/posts&quot;&gt;Patreon&lt;/a&gt;). It enables hands-free input via speech recognition, noise recognition, and eye tracking. I’ll be limiting this presentation to speech recognition because I don’t have experience with the others yet. But, in short, eye tracking lets you move the cursor around using the movement of your eyes and head, and noise recognition enables you to script certain actions in response to particular noises (a hissing sound, for example).&lt;/p&gt;
&lt;p&gt;Talon’s speech recognition capability is powerful and getting better all the time. Talon’s superpower is its scriptability. It has its own declarative syntax for defining commands and behavior and beyond that it can be extended with Python, which we’ll see some examples of shortly.&lt;/p&gt;
&lt;h3 id=&quot;setup-and-configuration&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#setup-and-configuration&quot;&gt;Setup and configuration&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Talon &lt;em&gt;does&lt;/em&gt; require a bit of setup to use. It needs a speech engine (which you can get from its website) &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;. Out the box, Talon doesn’t do anything in response to spoken word. It needs configuration files and/or scripts to tell it what to do. There is a community maintained repo, &lt;a href=&quot;https://github.com/knausj85/knausj_talon&quot;&gt;&lt;code&gt;knausj_talon&lt;/code&gt;&lt;/a&gt;, that you can use to be productive immediately. This is a comprehensive command set that is essentially considered the standard or default configuration. It must be downloaded separately but the Talon website has &lt;a href=&quot;https://talonvoice.com/docs/&quot;&gt;instructions for setting it up&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In time, you will likely want to modify your configuration or write your own command set. More about this shortly.&lt;/p&gt;
&lt;h2 id=&quot;code-by-voice-concepts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#code-by-voice-concepts&quot;&gt;Code-by-voice concepts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Coding by voice introduces a new way of thinking about how you type your code. Just as you can optimize code input from a keyboard—learning keyboard shortcuts, configuring your editor, etc—you can do the same for inputting code by voice. We’ll look at some concepts and techniques for dictating code and managing the workflow around it.&lt;/p&gt;
&lt;h3 id=&quot;nothing-by-default&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#nothing-by-default&quot;&gt;Nothing by default&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Conventional speech recognition software works by listening for your speech and then transcribing whatever you say. Talon, on the other hand, does no transcribing by default. You need scripts to tell it what it should listen for and what it should do when it hears a command.&lt;/p&gt;
&lt;p&gt;That might not seem like a big difference on the surface, but it is. When you’re writing natural language it makes sense to speak it out loud and let the computer transcribe it. But you can’t speak code out loud in the way you speak natural language. So you need a way to express code out loud that a computer can understand. Talon’s command set acts as the interpreter between what you’re saying and what you want the computer to do. Operating in this sort of “command mode” makes it easier to use your system, navigate your code, and enter precise syntax&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;. And since it’s customizable, the sky’s the limit on what you can accomplish.&lt;/p&gt;
&lt;h3 id=&quot;scripts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#scripts&quot;&gt;Scripts&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes I call them scripts, sometimes I call them a command set but I’m referring to the same thing—it’s the collection of files you put in your Talon user folder, usually a mix of &lt;code&gt;.talon&lt;/code&gt; and &lt;code&gt;.py&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;If you’re just starting out you’ll probably want to use the &lt;a href=&quot;https://github.com/knausj85/knausj_talon&quot;&gt;&lt;code&gt;knausj_talon&lt;/code&gt; &lt;/a&gt; scripts that I mentioned before. It’t fully featured and has help menus and such that can give you an idea of what you can say in different situations.&lt;/p&gt;
&lt;p&gt;I chose to write my own command set, although I used &lt;code&gt;knausj_talon&lt;/code&gt; as a reference. I wanted to learn how Talon scripts work and I preferred to start with a smaller set of commands and grow from there. I also have a little bit of difficulty enunciating certain words so I continually tweak my commands to choose words that are easier for me to say.&lt;/p&gt;
&lt;p&gt;Scripting Talon could be a whole article unto itself, but I’ll show you two quick examples.&lt;/p&gt;
&lt;p&gt;Consider this file, &lt;code&gt;whatever.talon&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintxt&quot;&gt;enter: key(enter)

next: key(space)

arrow function:
  insert(&#39;() =&amp;gt; {}&#39;)
  key(left)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells Talon about three commands:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When I say “enter,” press the enter/return key.&lt;/li&gt;
&lt;li&gt;When I say “next,” press the spacebar.&lt;/li&gt;
&lt;li&gt;When I say “arrow function,” insert a JavaScript arrow function template, then press the left arrow key so that my cursor is inside the body of the function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s a more complex exanple using Python. Consider this &lt;code&gt;code.py&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-py&quot;&gt;from talon import Module

mod = Module()

@mod.capture(rule=&#39;runner &amp;lt;word&amp;gt;&#39;)
def npm_script(m) -&amp;gt; str:
  &#39;Run an npm script.&#39;
  return &#39;npm run &#39; + m.word.lower()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is defining what Talon calls a &lt;a href=&quot;https://talon.wiki/unofficial_talon_docs/#captures&quot;&gt;capture&lt;/a&gt;. In this example I want to capture the pattern &lt;code&gt;runner &amp;lt;word&amp;gt;&lt;/code&gt; and return the form &lt;span style=&quot;white-space:nowrap&quot;&gt;&lt;code&gt;npm run &amp;lt;word&amp;gt;&lt;/code&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is just the definition of the behavior. We need to enable it in a &lt;code&gt;.talon&lt;/code&gt; file. Let’s make a file, &lt;code&gt;code.talon&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintxt&quot;&gt;&amp;lt;user.npm_script&amp;gt;: insert(npm_script)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells Talon to listen for the capture we defined and, when it occurs, insert the value it returns.&lt;/p&gt;
&lt;h3 id=&quot;the-phonetic-alphabet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#the-phonetic-alphabet&quot;&gt;The phonetic alphabet&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Computers aren’t as good at understanding spoken word as humans are, so we need to avoid ambiguity when dictating to them. When it comes to dictating individual letters, simply saying the name of letter won’t work. Too many characters sound the same. Consider the “e” sound. “b,” “c,” “d,” “t,” and more sound very similar. This problem isn’t limited to speech recognition software. Military and other organizations need clarity when spelling over radio and telephone where sound quality is degraded. The most common solution is the NATO phonetic alphabet. It substitutes words for alphabet characters (e.g., “Charlie” for “C” and “November” for “N”).&lt;/p&gt;
&lt;p&gt;We can use this same technique for code dictation. But we need speed too—not just clarity—and the NATO alphabet becomes cumbersome when you’re trying to dictate quickly. Most Talon users will have a phonetic alphabet with shorter words and fewer syllables so as to speed up dictation and make it easier. Below is a table that shows the words used for the NATO phonetic alphabet, &lt;code&gt;knausj_talon&lt;/code&gt;’s alphabet, and the one I use.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Character&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;NATO&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;&lt;code&gt;knausj_talon&lt;/code&gt;&lt;/th&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Blake&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;A&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Alfa&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Air&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Air&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;B&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Bravo&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Bat&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Bill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;C&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Charlie&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Cap&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Cap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;D&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Delta&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Drum&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Drum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;E&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Echo&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Each&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Each&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;F&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Foxtrot&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Fine&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Faint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;G&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Golf&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Gust&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Gust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;H&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Hotel&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Harp&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Ham&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;I&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;India&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Sit&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Sit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;J&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Juliett&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Jury&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Jury&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;K&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Kilo&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Crunch&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Crunch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;L&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Lima&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Look&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Little&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;M&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Mike&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Made&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Made&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;N&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;November&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Near&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Near&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Oscar&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Odd&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Orange&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;P&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Papa&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Pit&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Pink&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Q&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Quebec&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Quench&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Queen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;R&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Romeo&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Red&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;S&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Sierra&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Sun&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Sun&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;T&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Tango&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Trap&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Trap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;U&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Uniform&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Urge&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Urge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;V&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Victor&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Vest&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Vest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;W&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Whiskey&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Whale&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Wet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Xray&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Plex&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Plex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Y&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Yankee&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Yank&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Yank&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Z&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Zulu&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Zip&lt;/td&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Zoo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This technique of using short, distinguishable commands is used throughout most user’s Talon config files and scripts. I’ve modified my commands over time as I come across words with which, in my voice, the speech engine struggles. Getting good accuracy with Talon is a mix of factors—the specific speech engine, your configuration, your microphone, your environment’s background noise, and your dictation style. Generally speaking, you should notice Talon’s accuracy improve as better speech models become available, you weed out problematic words, and you improve your dictation technique. Your microphone is a big piece of it as well and we’ll cover that shortly.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/wgm4zH1qS2s&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;h3 id=&quot;precise-key-input&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#precise-key-input&quot;&gt;Precise key input&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Mainstream speech recognition software doesn’t work well for coding because it’s designed for natural language input. Dragon’s features like automatic word spacing and auto-capitalizing sentences and proper nouns are great for dictating prose. But programing languages follow a much different syntax than natural language and programming languages can be significantly different from each other as well. Punctuation and symbols that aren’t found as often in prose are everywhere in code, so we need a quick and precise way of dictating them.&lt;/p&gt;
&lt;p&gt;Keyboards have limited space so they make efficient use of it by reusing keys to input punctuation and symbols. We don’t have the same limitation when using speech recognition so we’ll avoid using modifiers for punctuation. You can use whatever commands work for you, but you’ll want to include all the symbols and punctuation normally found in the programming languages. Here’s a demo of that in action:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/xNK2Kbzsykw&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;h3 id=&quot;text-formatting&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#text-formatting&quot;&gt;Text formatting&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Code often has special formatting that’s strange looking compared to natural language so we’ll need a way to specify the format of certain pieces of text. Formatting commands often work by starting with a trigger word and then following that up with the text to be formatted. So a command like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;camel hello world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…would produce output like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;helloWorld
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;camel&lt;/code&gt; in this case is just an arbitrary word we’re choosing to signal that we want some text to be &lt;a href=&quot;https://en.wikipedia.org/wiki/Camel_case&quot;&gt;camel cased&lt;/a&gt;. Here’s a demo of the various formatters I use:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/p22G1B0GUms&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;You may have noticed that I also used the formatter technique—a command word followed by some other words—to do things like dictate a sentence. This is because, as I said before, Talon doesn’t automatically assume you’re dictating the way Dragon and similar software does. You need to let Talon know that you want to dictate something.&lt;/p&gt;
&lt;p&gt;If you think about it, a sentence is just another type of formatting—first word capitalized, followed by words separated with spaces. Same for titles where each word needs to be capitalized. I also use a formatter, &lt;code&gt;more&lt;/code&gt;, which just adds a space in front of otherwise normal prose formatting. That means if I dictate few words and then stop to think, I can easily append more text by saying &lt;code&gt;more&lt;/code&gt;, followed by the rest of my sentence.&lt;/p&gt;
&lt;h3 id=&quot;cursor-movement-and-editing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#cursor-movement-and-editing&quot;&gt;Cursor movement and editing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When I first started using speech recognition for writing and coding, I felt helpless because when I made a mistake I didn’t know how to fix it. Although the end goal of speech recognition technology is to be mistake-free, for now mistakes &lt;em&gt;do&lt;/em&gt; happen. They happen when you are typing on a keyboard, too, but you aren’t usually bothered by that because you have the confidence to fix your mistakes quickly. I believe that’s important for using speech recognition, too. In order to feel confident coding by voice, you need to feel confident that you can fix mistakes as they come up. Cursor movement and text editing play a huge role in that.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;knausj_talon&lt;/code&gt; command set has a comprehensive list of commands for text navigation. My commands may differ somewhat since I use my own custom configuration but the idea is the same.&lt;/p&gt;
&lt;p&gt;The way I navigate and select text is based on the arrow keys and the keyboard shortcuts that move the cursor word by word.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/idjLCz8UjJ4&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Those are the cursor movement and text selection commands that I use. Again, this is all scriptable so you can have even more powerful behavior if you want. &lt;code&gt;knausj_talon&lt;/code&gt; comes with even more ways to move the cursor and select text.&lt;/p&gt;
&lt;h3 id=&quot;app-specific-and-language-specific-commands&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#app-specific-and-language-specific-commands&quot;&gt;App-specific and language-specific commands&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Talon scripts have the ability to become active based on the application you are currently using and even the programming language you are currently writing in. I don’t have as many of these set up in my own personal scripts yet but they can be very powerful. For example, you can make commands for writing functions, parameters, types, etc. They can be language-specific and only activate when needed.&lt;/p&gt;
&lt;p&gt;One example of app-specific commands is for playing games. A while back I experimented with &lt;a href=&quot;https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/&quot;&gt;using some custom commands to play Minecraft&lt;/a&gt;:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/mItivNjd2To&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;considerations-for-coding-by-voice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#considerations-for-coding-by-voice&quot;&gt;Considerations for coding by voice&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I described before, it does require some technical setup to get started. After downloading Talon, you’ll need to download the speech engine, a speech recognition model, and some scripts.&lt;/p&gt;
&lt;p&gt;You may find it overwhelming at first to have so many commands to learn. Fortunately, &lt;code&gt;knausj_talon&lt;/code&gt; comes with a nice contextually-aware help menu system that you can call up to get a list of available commands.&lt;/p&gt;
&lt;p&gt;Talon can be configured with &lt;code&gt;.talon&lt;/code&gt; files, which use a syntax that is simpler than a programming language, and these can take you a long way. If you want to dive deeper with customizing your scripts, you’ll need to know some Python and learn about how Talon scripts work. I only dabble in Python and that was enough to be able to write what I think is a fairly good starter command set. So you definitely don’t need to be an expert.&lt;/p&gt;
&lt;h3 id=&quot;community-and-support&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#community-and-support&quot;&gt;Community and support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;While the learning curve to using Talon may seem steep, it &lt;em&gt;is&lt;/em&gt; manageable with the help of the Talon community which is pretty active online, including the developer of Talon. There’s a &lt;a href=&quot;https://talonvoice.slack.com/&quot;&gt;Talon Slack&lt;/a&gt; with some cool, helpful folks. The developer is very active there and will help you out when you need it.&lt;/p&gt;
&lt;p&gt;If you end up using Talon and want to support the project, you can &lt;a href=&quot;https://www.patreon.com/lunixbochs&quot;&gt;support Ryan on Patreon&lt;/a&gt;. And if you support the beta tier you can get access to pre-release speech recognition improvements. There is a speech recognition model called &lt;a href=&quot;https://www.patreon.com/posts/conformer-now-in-49562777&quot;&gt;Conformer&lt;/a&gt; that’s in beta at the time of this writing that is very accurate and has received good feedback thus far.&lt;/p&gt;
&lt;h2 id=&quot;further-resources&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#further-resources&quot;&gt;Further resources&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Talon’s documentation is a work-in-progress. Talon’s official docs will get you through the initial installation and setup process. It also has some developer documentation. At the time of this writing, the best place for learning about Talon’s scripting API is the Talon community wiki. The Talon community is nice and welcoming and you can get help there too on Slack.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Talon website: &lt;a href=&quot;https://talonvoice.com/&quot;&gt;https://talonvoice.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Talon community Slack: &lt;a href=&quot;https://talonvoice.slack.com/&quot;&gt;https://talonvoice.slack.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Talon community wiki: &lt;a href=&quot;https://talon.wiki/&quot;&gt;https://talon.wiki/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I recommend you follow Talon’s installation instructions found on its website. But here’s a quick link to the &lt;code&gt;knausj_talon&lt;/code&gt; scripts as well as my personal scripts (which you are welcome to use, fork, etc).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;knausj_talon&lt;/code&gt;: &lt;a href=&quot;https://github.com/knausj85/knausj_talon&quot;&gt;https://github.com/knausj85/knausj_talon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Blake’s Talon scripts: &lt;a href=&quot;https://github.com/blakewatson/talon-scripts&quot;&gt;https://github.com/blakewatson/talon-scripts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was deeply inspired by &lt;a href=&quot;https://www.youtube.com/watch?v=Mz3JeYfBTcY&quot;&gt;Emily Shea’s “Perl Out Loud” talk&lt;/a&gt;, which you should definitely check out (note that specific info about Talon is obsolete but the talk shows the concepts really well).&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m not a doctor, and I’m only describing RSI briefly because I know some people use Talon to prevent RSI symptoms. You should seek proper medical advice if you are experiencing symptoms of RSI. &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Talon supports two speech engines at this time—wav2letter, which you can get from Talon’s website, and Dragon, which you can purchase from Nuance. Dragon for Mac was discontinued in 2018 but at the time of this writing, Talon supports the latest Dragon version for Mac. You will likely need to find it on eBay as you can no longer get the Mac version from Nuance. The wav2letter speech engine requires a speech recognition model. There’s a model available from Talon’s website. If you join the Patreon beta tier, you can get the Conformer speech model which has improved accuracy over the publicly available model. Conformer will be available publicly sometime later this year. &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Talon has the concept of “modes,” which means that it can support dictation mode—a mode that continually listens and transcribes what you say, similar to the way other dictation software works. &lt;a href=&quot;https://blakewatson.com/journal/speaking-in-code-hands-free-input-with-talon/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>The making of d20 version 3</title>
      <link href="https://blakewatson.com/journal/the-making-of-d20-version-3/"/>
      <updated>2021-02-19T23:35:15Z</updated>
      <id>https://blakewatson.com/journal/the-making-of-d20-version-3/</id>
      <content xml:lang="en" type="html">&lt;p&gt;In hindsight, I can’t believe anyone paid money&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; for the &lt;a href=&quot;http://d20.blakewatson.com/&quot;&gt;first version of d20&lt;/a&gt;, which I released in &lt;a href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#criticalhit&quot;&gt;September 2016&lt;/a&gt;. But they did, and those few sales I made inspired a much more useful version 2, which was released in January 2018.&lt;/p&gt;
&lt;p&gt;By the end of 2018, I had been using d20 extensively and running into some problems I wanted to address. I started writing some brand new code in December of that year. Two years and 144 commits later, I’m happy to announce that d20 version 3 is now for sale on the Mac App Store.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2021/02/2-1024x640.png&quot; alt=&quot;Screenshot of d20, showing a roll formula in a text input with multiple results underneath. Showing presets pane expanded with custom buttons like &amp;quot;Long Bow&amp;quot;.&quot; width=&quot;1024&quot; height=&quot;640&quot; class=&quot;alignnone size-large wp-image-510&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;You can check out the &lt;a href=&quot;https://d20app.me/&quot;&gt;d20 website&lt;/a&gt; or &lt;a href=&quot;https://apps.apple.com/us/app/d20-an-rpg-dice-roller/id1156311750&quot;&gt;Mac App Store page&lt;/a&gt; if you want to know more about the features. But I want to get into the decision making process, tech stack, and other tangents regarding the making of d20. Imagine this as the director’s commentary.&lt;/p&gt;
&lt;h2 id=&quot;electron%3A-can%E2%80%99t-live-with-it%2C-can%E2%80%99t-live-without-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#electron%3A-can%E2%80%99t-live-with-it%2C-can%E2%80%99t-live-without-it&quot;&gt;Electron: can’t live with it, can’t live without it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The biggest non-decision was whether the app would be powered by &lt;a href=&quot;https://www.electronjs.org/&quot;&gt;Electron&lt;/a&gt;, go fully native, or go fully web-based. I had already used Electron for the first two versions. But I felt guilty about it. Electron is basically Google Chrome and NodeJS smashed together, so it’s pretty big and resource intensive. Seeing as d20 has a simple interface, very limited scope in what it’s trying to accomplish, and is meant to be Mac-only, Electron was a really terrible option.&lt;/p&gt;
&lt;p&gt;But I went with Electron again for the same reason every other web developer does—I know how to code for it without learning too much new stuff (e.g., Swift + Apple frameworks). Yes it’s way overkill, yes it’s absolutely ridiculous. But you either get d20 the Electron app, or you get nothing. That’s the great thing about Electron. It lowers the barrier to creating desktop applications and spawns tools and apps that otherwise would not exist. You’ll have to endure a little bit of ridicule from Hacker News and, if you’re like me, your inner-critic, but I say YOLO. Don’t let your dreams be dreams.&lt;/p&gt;
&lt;h2 id=&quot;random.org&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#random.org&quot;&gt;&lt;a href=&quot;http://random.org/&quot;&gt;RANDOM.ORG&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since version 2, d20 has integrated with &lt;a href=&quot;https://www.random.org/&quot;&gt;RANDOM.ORG&lt;/a&gt; to provide true random numbers rather than pseudorandom ones generated by JavaScript. This ended up being the catalyst that pushed me to finish version 3. &lt;a href=&quot;http://random.org/&quot;&gt;RANDOM.ORG&lt;/a&gt; brought their API out of beta and began charging for it. My old API key was no longer working and so d20 was quietly falling back to using pseudorandom JavaScript RNG.&lt;/p&gt;
&lt;p&gt;This was not cool, considering that true random numbers is one of d20’s unique selling points. I made the decision to move to the commercial API, which costs $12 per month. I don’t like incurring the extra costs each month, but I do make enough in sales to cover it and it is personally one of my favorite features of d20; so I gotta keep it in there.&lt;/p&gt;
&lt;h2 id=&quot;vue%2C-sass%2C-laravel-mix&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#vue%2C-sass%2C-laravel-mix&quot;&gt;Vue, Sass, Laravel Mix&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I doubled down on using &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;. I had used it in version 2 but I was new to it at the time and I did a really poor job of code organization. I feel like the new version is much better. I’m a different programmer than I was when I first started d20 v3 so there are definitely things I would change if I were starting today (like using &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;). That’s just part of the consequences for taking two years to finish it.&lt;/p&gt;
&lt;p&gt;CSS is pretty amazing these days, but I went with &lt;a href=&quot;https://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; out of complacency or momentum or whatever you want to call it. I processed all the styles and scripts with &lt;a href=&quot;https://laravel-mix.com/&quot;&gt;Laravel Mix&lt;/a&gt; which is a pretty great way to use &lt;a href=&quot;https://webpack.js.org/&quot;&gt;webpack&lt;/a&gt; when you don’t feel like learning about webpack&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;leaving-behind-localstorage&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#leaving-behind-localstorage&quot;&gt;Leaving behind &lt;code&gt;localStorage&lt;/code&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have a bad habit of using &lt;code&gt;localStorage&lt;/code&gt;, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage&quot;&gt;web storage feature&lt;/a&gt;, for everything. In d20 v2 I was saving all the presets in &lt;code&gt;localStorage&lt;/code&gt;. But for v3 I moved to using a JSON file for saving presets and settings information. This is my first time using the file system in an Electron app so here’s hoping I did all of the Apple security stuff right.&lt;/p&gt;
&lt;p&gt;The cool thing about this though is that it’s now much easier to back up your presets, move them to another machine, or share them with others. Just save the file. Boom. Easy. I will be able to rest easier knowing that I have reliable, persistent storage and that a user won’t wake up one day to find their data missing.&lt;/p&gt;
&lt;h2 id=&quot;design&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#design&quot;&gt;Design&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These three images should give you an idea about the progression of UI design. Of course, I feel that the third version is far superior. I do think it’s funny how my color scheme seems to be trending pink-ward.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/d20-main-1024x640.png&quot; alt=&quot;D20 version 1 promotional screenshot. Basically a grid of buttons witb a list of dice roll results running down the left side of the window.&quot; width=&quot;1024&quot; height=&quot;640&quot; class=&quot;alignnone size-large wp-image-113&quot; /&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/06/screenshot-1-1024x640.png&quot; alt=&quot;d20 version 2 promotional screenshot. Dice buttons along the right side of the window. A large text input runs along the top with a list of dice roll results underneath.&quot; width=&quot;1024&quot; height=&quot;640&quot; class=&quot;alignnone size-large wp-image-260&quot; /&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2021/02/1-1024x640.png&quot; alt=&quot;Screenshot of d20, showing a rollformula in a text input with multiple results underneath. Captioned &amp;quot;An elegant, powerful dice roller.&amp;quot;&quot; width=&quot;1024&quot; height=&quot;640&quot; class=&quot;alignnone size-large wp-image-517&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;I take the UI design seriously and the lack of nicely designed dice rollers on the Mac App Store was a big reason I made d20 originally. I’m pretty happy with how it turned out and I’m hoping to start getting sales information from Apple really soon to find out whether users agree.&lt;/p&gt;
&lt;h2 id=&quot;problems-and-solutions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#problems-and-solutions&quot;&gt;Problems and solutions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I said earlier that I was beginning to run up against problems in v2. Many of those I have addressed in v3.&lt;/p&gt;
&lt;p&gt;One of the major ones is what I’m calling “multi-roll.” The easiest way to describe this is that it lets you roll attack and damage at the same time. Technically, what it is doing is letting you separate different formulas with a comma but roll them at the same time. This means that you can also &lt;em&gt;save&lt;/em&gt; them together, which means that now you can have a weapon as a preset button and clicking will roll the attack and the damage simultaneously, with each having its own result entry.&lt;/p&gt;
&lt;p&gt;Another big problem was that v2 presets were simplistic—just a list of buttons that each can roll one combo. If you have multiple characters, good luck rummaging through all your presets to find the ones you need.&lt;/p&gt;
&lt;p&gt;I’m tackling this in v3 by introducing the concept of “preset groups,” which let you create different lists of presets (e.g., one per character). This plus multi-roll solve the biggest annoyances I had with v2.&lt;/p&gt;
&lt;h2 id=&quot;submitting-to-the-mac-app-store-is-hard&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#submitting-to-the-mac-app-store-is-hard&quot;&gt;Submitting to the Mac App Store is hard&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Seriously, that was harder than building the app. There are a lot of articles recommending &lt;code&gt;electron-forge&lt;/code&gt; but there’s not much help out there about what happens when something doesn’t work.&lt;/p&gt;
&lt;p&gt;I ended up using its parts directly: &lt;code&gt;electron-packager&lt;/code&gt;, &lt;code&gt;electron-osx-sign&lt;/code&gt;, and &lt;code&gt;electron-osx-flat&lt;/code&gt;. This topic deserves its own article probably but in summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need a “Mac App Distribution” certificate from Apple.&lt;/li&gt;
&lt;li&gt;You need a “provisioning profile” from Apple.&lt;/li&gt;
&lt;li&gt;You need the entitlements files—I just grab these off of the &lt;a href=&quot;https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide&quot;&gt;Electron site&lt;/a&gt;, but if the app needs any special entitlements, you have to add those. For example: &lt;code&gt;com.apple.security.network.client&lt;/code&gt; if your app needs to hit the web for stuff.&lt;/li&gt;
&lt;li&gt;You need to package the app with &lt;code&gt;electron-packager&lt;/code&gt;, which requires you have the aforementioned Apple cert installed onto your keychain.&lt;/li&gt;
&lt;li&gt;You need to sign the app with &lt;code&gt;electron-osx-sign&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need to turn the &lt;code&gt;.app&lt;/code&gt; into an installer with &lt;code&gt;electron-osx-flat&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You need to send the resulting installer to Apple using their app called Transporter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the three npm scripts I used to package, sign, and prep the installer for distribution on the Mac App Store:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;package&amp;quot;: &amp;quot;electron-packager . d20 --out=out --platform=mas --arch=x64 --appBundleId=com.example.app_name --icon=./images/d20_icon --no-deref-symlinks --overwrite&amp;quot;,
    &amp;quot;sign:mas&amp;quot;: &amp;quot;electron-osx-sign out/d20-mas-x64/d20.app --entitlements=entitlements/parent.plist --entitlements-inherit=entitlements/child.plist --entitlements-loginhelper=entitlements/loginhelper.plist&amp;quot;,
    &amp;quot;installer&amp;quot;: &amp;quot;electron-osx-flat out/d20-mas-x64/d20.app --platform=mas&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These resources helped me out a lot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide&quot;&gt;https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://epxx.co/artigos/electronsign.html&quot;&gt;https://epxx.co/artigos/electronsign.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/electron/electron-packager&quot;&gt;electron-packager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/electron/electron-osx-sign&quot;&gt;electron-osx-sign&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;web-vs-app-stores&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#web-vs-app-stores&quot;&gt;Web vs app stores&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To be honest, I would have loved to just deploy d20 as a web app. But unfortunately it’s hard to get traffic to a web app versus getting the built-in audience an app store provides. It’s one thing to charge for a Mac app, but try to charge for a website that rolls dice and suddenly it seems ridiculous. I don’t know if there’s an app-store-like website for distributing web apps (&lt;a href=&quot;https://itch.io/&quot;&gt;itch.io&lt;/a&gt; maybe?) but I doubt a web version would have had the same success (10-20 copies sold per month) that the Mac App Store provides with $0 of marketing effort.&lt;/p&gt;
&lt;p&gt;It’s a technical challenge building an Electron version and a web version from the same codebase, but providing some kind of web version is on my radar. As much as I would love to go cross-platform and distribute Windows and Linux versions, I don’t have a good way to test those platforms. And my specific setup for working on my Mac (which I need thanks to my disability) isn’t conducive to OS or device switching. But at least providing a web version would open it up to more platforms.&lt;/p&gt;
&lt;h2 id=&quot;by-the-numbers&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#by-the-numbers&quot;&gt;By the numbers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In conclusion, here are some random stats/numbers for your amusement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;3.5&lt;/strong&gt; years on the Mac App Store&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;203&lt;/strong&gt; commits across all versions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;d1,000,000:&lt;/strong&gt; the largest die d20 v3 can roll&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100:&lt;/strong&gt; number of random integers d20 requests from &lt;a href=&quot;http://random.org/&quot;&gt;RANDOM.ORG&lt;/a&gt; when you roll a die&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;$3.99:&lt;/strong&gt; the price of d20 v1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;04/2020:&lt;/strong&gt; highest grossing month ($200)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;$3.41k&lt;/strong&gt; in lifetime total sales (before Apple’s cut)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Seriously, version 1 was so bad. The only way to roll dice was by clicking (or using keyboard shortcuts) even though it had what looked like a text input where you could type out a dice roll. But no, you could not type in it, it was a read-only thing. In addition to having &lt;em&gt;way&lt;/em&gt; too many modifier buttons, I managed to forget all about the d100, forcing players instead to roll two d10s. You can see for yourself how bad it was because it lives on as a &lt;a href=&quot;https://blakewatson.com/dice-roller&quot;&gt;free web app&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I use it on all my projects now. I’m really impressed by how sophisticated of a setup you can make while still keeping configuration files nice and easy to understand. Mix is super powerful and, despite the name, doesn’t at all rely on Laravel, the PHP framework. I’m actually using Mix on my other project, &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;, to generate builds for web in addition to Chrome and Firefox extensions. &lt;a href=&quot;https://blakewatson.com/journal/the-making-of-d20-version-3/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Finishing side projects</title>
      <link href="https://blakewatson.com/journal/finishing-side-projects/"/>
      <updated>2020-07-29T05:49:29Z</updated>
      <id>https://blakewatson.com/journal/finishing-side-projects/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Web development provides opportunities to work on different kinds of projects, learn all sorts of things, and dive deeply into specific areas of interest. It makes for a rewarding career choice. But if I’m being honest, the magic of the refresh button, the code-save-refresh feedback loop of digital creation is what drove my interest in web development when I started back in the mid-2000s.&lt;/p&gt;
&lt;p&gt;My first projects—the ones I approached with little more than slapdash curiosity—were essential to solidifying my passion of making web things and leading me to an eventual career doing it.&lt;/p&gt;
&lt;p&gt;But they were simple, half-baked ideas. They were side projects. And to this day I believe that the ability to dream up and execute a side project is the single, coolest, and funnest aspect of web dev.&lt;/p&gt;
&lt;p&gt;In a way, calling them &lt;em&gt;side&lt;/em&gt; projects doesn’t do them justice. I suppose most people would think of a side project as something that is, at most, secondary to your main job. But I don’t think of them as much in those terms. Sure, my job is important to me and I enjoy it and am grateful to have it. That said, in a longer-term view of things, I consider my side projects as equally important. I need to have both my job and my personal projects to feel like I have life balance; to feel fulfilled by my work.&lt;/p&gt;
&lt;p&gt;Side projects are important. Unfortunately they are also notorious for going unfinished—whether by lack of time or motivation. I’m not a prolific creator by any means, but I have managed to make a thing or two (despite living with a &lt;a href=&quot;https://www.curesma.org/about-sma/&quot;&gt;progressive physical impairment&lt;/a&gt; that necessitates that I peck out this article one key at a time on an &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;onscreen keyboard&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I’ll share some tips and tricks I’ve picked up along the way that helped me through the rough patches.&lt;/p&gt;
&lt;h2 id=&quot;small-things-are-ok-(and-fun!)&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#small-things-are-ok-(and-fun!)&quot;&gt;Small things are OK (and fun!)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Projects come in all shapes and sizes, and that’s cool. My personal definition of a side project can be something as small as a &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt; or as big as a large website. I enjoy working on small side projects for a number of reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They can be completed quickly before your motivation runs dry.&lt;/li&gt;
&lt;li&gt;A finished project is a success, and a series of small successes can give you the momentum you need to achieve larger ones.&lt;/li&gt;
&lt;li&gt;They are good for learning, whether it’s something technical, like a &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS trick&lt;/a&gt;, or just something that serves as a proof of concept for a bigger idea.&lt;/li&gt;
&lt;li&gt;They’re fun!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you’ve got an afternoon and you just want to get something accomplished, a &lt;a href=&quot;https://blakewatson.com/space-invaders/&quot;&gt;tiny side project&lt;/a&gt; can be the perfect outlet.&lt;/p&gt;
&lt;h2 id=&quot;scary-things-aren%E2%80%99t-scary-after-you-face-them&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#scary-things-aren%E2%80%99t-scary-after-you-face-them&quot;&gt;Scary things aren’t scary after you face them&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I often experience this phenomenon where there is one particular part of my project that, for whatever reason, I am absolutely terrified of. I will put off doing that part of the project—often going to great lengths of procrastination just to avoid facing it at all. Sometimes it’s enough to halt a project in its tracks. I think it’s related to imposter syndrome. It’s as if this one tricky thing is going to finally prove to myself that I’m not a real developer, that my goal it is too lofty to accomplish.&lt;/p&gt;
&lt;p&gt;That thought process is bullshit. Even if the thing in question is difficult, it doesn’t &lt;em&gt;prove&lt;/em&gt; anything. Furthermore, it’s been my experience that the thing I’m scared of turns out to be nothing whenever I finally look into it. You can’t escape learning in web dev. Once you accept the fact that you’re going to be doing some searching and some Stack Overflow-ing, you can start to move past the idea that you’re going to hit some insurmountable obstacle.&lt;/p&gt;
&lt;h2 id=&quot;the-one-new-thing-strategy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#the-one-new-thing-strategy&quot;&gt;The one new thing strategy&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Speaking of scary things, a good way to face them is one at a time. I often start projects where I’m going to use familiar tools and strategies except for &lt;em&gt;one new thing&lt;/em&gt; that I want to use or learn. For example, I was scared of learning &lt;a href=&quot;https://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; for a long time. CSS is already hard enough, the thought process went, without adding all these extra rules and setup. But eventually, on some side project, I decided that this would be the project where I would finally use Sass. It was my one new thing for that project.&lt;/p&gt;
&lt;p&gt;This little strategy has served me well. It allows for experimentation while building on the solid foundation that is your existing knowledge. I learned jQuery, Sass, Knockout, Vue and a whole lot of other stuff by making them my one new thing on a project.&lt;/p&gt;
&lt;p&gt;Beyond a learning tool, it can also help you keep things fresh and exciting. Maybe you always use WordPress, but this time you want to use a fancy &lt;a href=&quot;https://jamstack.org/&quot;&gt;JAMstack&lt;/a&gt; thing just because. Maybe you always wanted to try a popular library, but never had a reason to move away from the one that you are most familiar with. Well now you have a reason—just to have one new thing.&lt;/p&gt;
&lt;h2 id=&quot;git-is-not-just-for-source-control&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#git-is-not-just-for-source-control&quot;&gt;Git is not just for source control&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are writing code, you should probably be using some sort of source control like Git; you could even make it your one new thing!&lt;/p&gt;
&lt;p&gt;But I have found another great use for Git. Well, it’s more of a side effect really. A commit in Git represents a little piece of something you created or fixed. It’s an accomplishment. And the more they accumulate, the better. If you feel your motivation seeping away, take a look at your commit history and remind yourself how far you’ve come. It’s an automatic to-done list.&lt;/p&gt;
&lt;p&gt;You should commit as often as it makes sense for your project. In my experience, making small commits with relevant messages helps you stay on track by knowing what you were working on previously, what you are doing now, and giving you that feeling of progress being made.&lt;/p&gt;
&lt;h2 id=&quot;scratching-an-itch&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#scratching-an-itch&quot;&gt;Scratching an itch&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A great motivator for a side project is making something for yourself. Completely original ideas are rare, but maybe no one is solving a particular  problem the way &lt;em&gt;you&lt;/em&gt; want to. Most of my side projects start with this being the core motivation.&lt;/p&gt;
&lt;p&gt;I didn’t like the built-in new tab page in web browsers so I made &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;. I didn’t like the dice rolling applications available for the Mac, so I made &lt;a href=&quot;https://d20app.me/&quot;&gt;d20&lt;/a&gt;. I wanted a better way to maintain a digital character sheet for my D&amp;amp;D character, so I made &lt;a href=&quot;https://minimalcharactersheet.com/&quot;&gt;Minimal Character Sheet&lt;/a&gt;. I wanted to listen to and collect the best synthwave mixes on YouTube, so I made &lt;a href=&quot;https://synthwave.live/&quot;&gt;synthwave.live&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;don%E2%80%99t-rely-on-memory&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#don%E2%80%99t-rely-on-memory&quot;&gt;Don’t rely on memory&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We don’t always control when ideas strike. Even though you are working on the user login feature, your brain might suddenly come up with the perfect animation for the hero section of your homepage. When these situations happen, you need low-friction tools at your disposal to capture your thoughts before they evaporate into the ether.&lt;/p&gt;
&lt;p&gt;Whether it’s the issue tracking capabilities of GitHub or the simplicity of a plain text list, you need a way to record an idea and be confident that you (or someone else if you have contributors) are going to tackle said thing in the future.&lt;/p&gt;
&lt;p&gt;For me, that mostly involves keeping notes in &lt;a href=&quot;https://simplenote.com/&quot;&gt;Simplenote&lt;/a&gt; and keeping my todo list in &lt;a href=&quot;https://culturedcode.com/things/&quot;&gt;Things&lt;/a&gt; or &lt;a href=&quot;https://www.taskpaper.com/&quot;&gt;Taskpaper&lt;/a&gt;. When I truly need low-friction and can’t be bothered to categorize or even give a title to quick note, I use &lt;a href=&quot;https://tot.rocks/&quot;&gt;Tot&lt;/a&gt; as a virtual sticky note. Before Tot, I used macOS’ built-in app, &lt;a href=&quot;https://support.apple.com/guide/stickies/welcome/mac&quot;&gt;Stickies&lt;/a&gt;, which is also great for just having a place to write something down.&lt;/p&gt;
&lt;p&gt;It doesn’t really matter what tool you use as long as you have one that you &lt;em&gt;will&lt;/em&gt; use. We can’t keep everything in our heads—we’re only human.&lt;/p&gt;
&lt;h2 id=&quot;other-motivators&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#other-motivators&quot;&gt;Other motivators&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I already covered making something for yourself to “scratch an itch” but there other motivators for side projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making money. Not every side project needs to be a business. But one certainly &lt;em&gt;could&lt;/em&gt; be. Even if it’s just a little bit of hobby money, it feels good when people give you cash for a thing you created.&lt;/li&gt;
&lt;li&gt;Portfolio / resume / self promotion. This is especially helpful if you’re just starting out in web development. No matter what skills you say you have, what education you might have, employers want to see what you can do. Side projects serve well for building out your portfolio when you don’t have as many real-world examples.&lt;/li&gt;
&lt;li&gt;Making helpful things. This is related to scratching an itch, but it’s about scratching someone else’s itch. This metaphor is going in a weird direction. All I’m trying to say is that it feels good when people use something you’ve made and it helps them. It’s a pretty darn good motivator.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;time-is-relative&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#time-is-relative&quot;&gt;Time is relative&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You may have deadlines whether they be external or self-imposed; that’s fine. Deadlines can be a good motivator. But in my experience, putting too much pressure on yourself is a good way to snuff out a project before it gets going. What helps me is to remember that as long as progress is being made, that’s a win.&lt;/p&gt;
&lt;p&gt;When you start thinking about your project and everything it entails, it can be overwhelming. But if you’ve used your tools to gather your thoughts, and if you have a to-do list of any sort, then try to focus on just a small piece. Go for a small win. Every little bit of progress gets you that much closer. And like we’ve already said, small successes can lead to big ones.&lt;/p&gt;
&lt;p&gt;Figure out whatever takes the pressure off and use that. Pace yourself. Slow and steady wins the race.&lt;/p&gt;
&lt;h2 id=&quot;just-do-it&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#just-do-it&quot;&gt;Just do it&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are just a few of the tips and tricks that help me to stay motivated and productive when working on side projects. But even with all of these tools at my disposal, I can procrastinate and binge media with the best of them. And sometimes that’s okay. You don’t always need to be working on something.&lt;/p&gt;
&lt;p&gt;But if you feel like you’re stuck or unmotivated, it might be time to rip off the band-aid and just get started already. Sometimes starting is half the battle. Use whatever productivity method (or lack thereof) you prefer and make yourself focus for at least a little bit of time on making progress on your side project. You may stumble upon a motivator, like the ones we discussed, that revives your interest.&lt;/p&gt;
&lt;h2 id=&quot;my-side-projects&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/finishing-side-projects/#my-side-projects&quot;&gt;My side projects&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ll leave you with a quick note about some of my projects in case you’re interested in checking them out. Most of them can be found on my &lt;a href=&quot;https://blakewatson.com/my-apps/&quot;&gt;apps&lt;/a&gt; page. My brother and I enjoy making &lt;a href=&quot;https://www.watsonbrosgames.com/&quot;&gt;tiny web games&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The side project that is most dear to me—and one that I use every day—is &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt;, my custom new-tab browser extension.&lt;/p&gt;
&lt;p&gt;I also make stuff for playing D&amp;amp;D, most notably &lt;a href=&quot;https://d20app.me/&quot;&gt;d20&lt;/a&gt;, an RPG dice roller for Mac.&lt;/p&gt;
&lt;p&gt;If it isn’t already clear, let me just say: I love side projects. If you’ve made something cool, shoot me an &lt;a href=&quot;mailto:blake@blakewatson.com&quot;&gt;email&lt;/a&gt; or find me on &lt;a href=&quot;https://twitter.com/blakewatson&quot;&gt;Twitter&lt;/a&gt; and let me know.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Why I host my websites with NearlyFreeSpeech.NET</title>
      <link href="https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/"/>
      <updated>2020-02-08T05:56:54Z</updated>
      <id>https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/</id>
      <content xml:lang="en" type="html">&lt;p&gt;There are a lot of web hosting options. You’ve got popular serverless platforms like &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt; and &lt;a href=&quot;https://zeit.co/home&quot;&gt;Zeit Now&lt;/a&gt;. If you’re using WordPress, you’ve got fully managed WordPress-optimized hosting services like &lt;a href=&quot;https://wpengine.com/&quot;&gt;WPEngine&lt;/a&gt;/&lt;a href=&quot;https://getflywheel.com/&quot;&gt;Flywheel&lt;/a&gt;. There are VPS options like &lt;a href=&quot;https://www.digitalocean.com/&quot;&gt;Digital Ocean&lt;/a&gt; and &lt;a href=&quot;https://www.linode.com/&quot;&gt;Linode&lt;/a&gt;. There’s the venerable &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt;, upon which many hosting providers are built. Then there’s the plethora of shared hosting services—&lt;a href=&quot;https://en.wikipedia.org/wiki/Endurance_International_Group#Subsidiary_brands&quot;&gt;many of which are owned by EIG&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;—but also others like &lt;a href=&quot;https://www.dreamhost.com/&quot;&gt;DreamHost&lt;/a&gt;, which I’ve heard good things about. But there’s one web hosting company I rarely see mentioned anywhere which has nonetheless been a wonderful home for my &lt;a href=&quot;https://blakewatson.com/my-apps/&quot;&gt;apps&lt;/a&gt;, &lt;a href=&quot;https://blakewatson.com/&quot;&gt;personal site&lt;/a&gt;, and a sea of half-baked &lt;a href=&quot;https://web.archive.org/web/20231204170618/https://lofiapp.net/&quot;&gt;side-projects&lt;/a&gt;. This is a love letter to &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt;. &lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; (hereafter, “NFSN”) doesn’t have an affiliate program or really much of a marketing machine at all. My endorsement of their service gets me nothing. I just think more people should know about them because they have been in the business for a long time and they offer a great service.&lt;/p&gt;
&lt;h2 id=&quot;no-frills&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#no-frills&quot;&gt;No frills&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2020/02/Screenshot_2020-02-07-NearlyFreeSpeech-NET-Web-Hosting-1024x681.png&quot; alt=&quot;A screenshot of the NFSN homepage. It&#39;s an older looking, text-based layout that&#39;s very simple.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; homepage&lt;/p&gt;
&lt;p&gt;NFSN’s unique value proposition is running a lean, but robust, operation and passing the savings to the customer. NFSN runs on a pay-as-you go cost model. They offer email support, but if you don’t want it you don’t pay for it. NFSN is a great match for someone who’s comfortable enough with web dev and admin basics to use a little bit of SSH and do web development without a lot of hand-holding. They offer a custom interface that’s straightforward and doesn’t get in your face with any upselling or marketing BS. From the &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#MostImportant&quot;&gt;FAQs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To put it another way, some people change their own oil. Some people pay a mechanic to do it because although they could do it themselves, they want to spend their time another way. And some people pay a mechanic to do it because they just want their car to work and the details don’t interest them. &lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; is a service for people who want to change their web site’s oil.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;NFSN’s site design screams early 2000s. But that’s alright in my book. The user interface of their custom administration system is eminently usable. If you’ve ever had to click around a hosting admin area looking for something as simple as an IP address or FTP information then you will love the utilitarian nature of NFSN’s service.&lt;/p&gt;
&lt;h2 id=&quot;pay-for-what-you-use&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#pay-for-what-you-use&quot;&gt;Pay for what you use&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think services like Amazon’s AWS made this pricing model much more mainstream. But among shared hosting providers, a fixed monthly rate is much more common. NFSN lays out the argument that by charging for what resources you actually use, their interest and that of their customers are aligned—the more successful your site becomes (and, thus, the more resources it uses) the more you pay. Your success is good for you and good for NFSN. Contrast that with a fixed monthly rate. A host that charges a fixed monthly rate has an incentive for your site to use as little resources as possible. It’s a good argument. I don’t think that means that every hosting company charging a fixed monthly rate is evil or anything. But the pay-for-what-you-use pricing model is a good, honest system. It seems fair and reasonable. And it makes NFSN great for low-traffic sites (which, let’s be honest, most websites are low-traffic 99% of the time; don’t get me wrong, though, NFSN can and does handle high-traffic websites).&lt;/p&gt;
&lt;h2 id=&quot;fully-managed%2C-but-customizable&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#fully-managed%2C-but-customizable&quot;&gt;Fully managed, but customizable&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NFSN has the perks of being a fully managed service, but I think it also has some of the perks that running a VPS provides. You have the option to get your typical Apache/PHP setup. But NFSN offers a blank slate option that lets you set up your own web server should you want to use something like NodeJS and Express. NFSN offers support for &lt;a href=&quot;https://2020q1.nfshost.com/&quot;&gt;many languages&lt;/a&gt;. There is even a completely static server option, which costs less since it uses less resources. From the &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#Easy&quot;&gt;FAQs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is your service easy to use?&lt;/strong&gt; No. Compared to the endless parade of hosts that provide tons of “one-click installs,” one-size-fits-all web site templates, unlimited toll-free telephone support, and cookie-cutter control panels, our service is arcane and complex. We consider this a positive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;documentation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;NFSN has a robust collection of searchable FAQs that not only serve to document their service but also give you a glimpse into the creators’ views on a variety of web-related topics. And as I’ve demonstrated already, they come with a bit of earnest flair. From the &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#Gigabyte&quot;&gt;FAQs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How big is a gigabyte?&lt;/strong&gt; On our system, a gigabyte is 1,073,741,824 bytes. Hard drive manufacturers would have you believe that it’s 1,000,000,000 bytes, but we don’t sell hard drives. Technically 1,073,741,824 bytes is a gibibyte, but we have a hard time calling it that without a childish urge to snicker, and nobody likes a snickerer. If you want to be strictly accurate, the hard drive manufacturers are right, and we bill storage and bandwidth based on gibibytes* and mebibytes* (1,048,576 bytes), not gigabytes and megabytes. Someday we’ll grow up about this, but that day has not yet arrived. We are moderately more mature when it comes to the abbreviations, and we try to use MiB and GiB to represent base-2 prefixes correctly wherever possible. *Must… keep from… snickering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Writing this article is taking me forever because I keep being distracted by NFSN’s excellent and entertaining docs. I’ve been linking to the publicly available FAQs, but there’s a members-only version that constitutes their self-serve support documentation (or “knowledgebase,” if you prefer).&lt;/p&gt;
&lt;h2 id=&quot;support-for-introverts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#support-for-introverts&quot;&gt;Support for introverts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That’s a description I’ve assigned it, not what NFSN themselves call it (though I suspect they would agree). NFSN doesn’t offer phone support. Every NFSN membership comes with access to the extensive members-only FAQs I mentioned as well as access to a forum. You can add a $5 per month subscription for email support, but you don’t have to get it if you don’t want it. The FAQs are quite extensive and answer my questions 95% of the time.&lt;/p&gt;
&lt;h2 id=&quot;free-speech&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#free-speech&quot;&gt;Free speech&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The name “NearlyFreeSpeech” is not only a reference to their affordable pricing but also a nod to their libertarian tendencies. Politics aside, I think most of us (in the US) would agree that the First Amendment is pretty important. It’s perhaps most important on the world wide web, where publishing has been democratized. NFSN definitely requires that you follow US law and the laws of your government. But they consider takedown requests on a case-by-case basis—they won’t follow a takedown request without examining the situation first. For example, this is from the &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#CourtOrder&quot;&gt;FAQs&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Will you honor a court order requiring the takedown of my site?&lt;/strong&gt; Usually. However, we do handle these issues on a case-by-case basis, considering a number of important factors. … Some countries’ legal systems now include the theory that their courts can exercise jurisdiction over any content on the Internet that is visible from inside that country. We repudiate that theory, and do not accept orders from courts that cannot exercise personal jurisdiction over us or you unless they have been properly domesticated, and domestication of such orders is frequently disallowed by US law. (However, if Elbonia instead requires all Elbonian ISPs to block access to your site, that is not something we’re likely to be able to help with.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#Normal&quot;&gt;another&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is your service only for controversial or extreme websites?&lt;/strong&gt; Not at all! It’s true that our libertarian attitude toward personal responsibility attracts a handful of controversial websites, some of which make a person wonder, “Ok, sure, you can say that, but why?” However, the vast majority of sites we host (greater than 99.9%) are perfectly ordinary blogs, forums, wikis, and personal pages run by people just like you. For the bulk of our member base, the “fringe” web sites we host frequently serve as the proverbial canary in the coal mine: they act as our global censorship early warning system. As long as the fringe sites can remain online, we can all be confident that the rest of us with more moderate views have real freedom to express ourselves. When people (or governments) attack such sites or attempt to get them shut down, we learn more about what legal and technological techniques we need to use to keep your site protected. &lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; isn’t necessarily about saying something controversial. In a lot of cases, it’s merely about knowing that if you need to someday, you won’t find out that your freedom to do so atrophied away while you weren’t looking.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;quirks-are-a-feature%2C-not-a-bug&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#quirks-are-a-feature%2C-not-a-bug&quot;&gt;Quirks are a feature, not a bug&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As you can see from their site design and the content of the &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq&quot; title=&quot;Frequently Asked Questions&quot;&gt;FAQs&lt;/a&gt;, NFSN isn’t like other web hosts you’ve seen. They explain it well themselves in response to &lt;a href=&quot;https://www.nearlyfreespeech.net/about/faq#UglySite&quot;&gt;why they have an old-looking site design&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why doesn’t your website look like other hosting provider sites?&lt;/strong&gt; It’s simple. We don’t want to confuse people into thinking we’re anything like other hosting providers. … So, sure, we could follow the crowd and get stock graphics of impressive racks of equipment and inspired-looking people staring blankly into space. We’ve even been told we can’t possibly be taken seriously as a hosting company unless we have them. But we’re not buying.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Over the years I’ve fallen in love with NFSN’s unique, unwavering approach to web hosting. I’m not telling you that you shouldn’t use services like Netlify—they certainly have an excellent product. But if you’re in the market for shared hosting or you want something flexible but don’t feel like managing your own VPS, consider the humble &lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt;. They just might surprise you.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I mention EIG because they &lt;a href=&quot;https://researchasahobby.com/full-list-eig-hosting-companies-brands&quot;&gt;have a bad reputation of acquiring and then ruining hosting companies&lt;/a&gt; &lt;a href=&quot;https://blakewatson.com/journal/why-i-host-my-websites-with-nearlyfreespeech-net/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>2019: My Year in Review</title>
      <link href="https://blakewatson.com/journal/2019-my-year-in-review/"/>
      <updated>2020-01-01T07:17:17Z</updated>
      <id>https://blakewatson.com/journal/2019-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;p&gt;It’s been a little while since I did one of these, but some big things happened in 2019 in my tiny little world, so here we go.&lt;/p&gt;
&lt;h2 id=&quot;new-job&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#new-job&quot;&gt;New job&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Starting with the biggest thing first, I started a new job this year. I’m on the frontend dev team at &lt;a href=&quot;https://mricompany.com/&quot;&gt;MRI Technologies&lt;/a&gt; working on projects for NASA. So far it’s been great. One interesting challenge is that I went from being the resident expert at my previous job to being a n00b. I don’t shy away from learning new things, though, so the challenge has been fun despite being difficult at times. It has given me the opportunity to use TypeScript for the first time. Coming from the wild wild wests of JavaScript and PHP I found it very difficult at first. I’m slowly improving and learning the value of types. It still feels a little unnatural, though, and I much prefer vanilla JavaScript. We’ll see how I feel next year.&lt;/p&gt;
&lt;h2 id=&quot;magnoliajs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#magnoliajs&quot;&gt;MagnoliaJS&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2019, Mississippi saw its first web development conference, &lt;a href=&quot;https://magnoliajs.com/&quot;&gt;MagnoliaJS&lt;/a&gt;. I gave my first ever conference talk based on my guest post for CSS-Tricks, &lt;a href=&quot;https://css-tricks.com/empower-through-web-development/&quot;&gt;Empower Through Web Development&lt;/a&gt;. I enjoyed giving the talk as well as seeing the other talks. Despite a tornado warning right in the middle of the conference, I think everyone had a great time. A lot of cool, talented people gave some fun and insightful talks. I definitely plan to attend again and I’m interested in giving another talk if it’s in the cards.&lt;/p&gt;
&lt;h2 id=&quot;hack-ability-camp&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#hack-ability-camp&quot;&gt;Hack Ability Camp&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My sister-in-law, Anna Wan, had this great idea for a STEM camp for students with disabilities called &lt;a href=&quot;https://hackability.camp/&quot;&gt;Hack Ability&lt;/a&gt;. It was held at her &lt;a href=&quot;https://www.eaglemakerhub.org/&quot;&gt;maker space&lt;/a&gt; on the campus of Southern Miss. My brother and I had the opportunity to give a “Create your own webpage” workshop and it was a lot of fun. It really took me back to my early days of learning HTML and CSS. We centered our material around the idea of the magic of the refresh button. How you can make small changes in code and then flip over to your browser, hit &lt;em&gt;Refresh&lt;/em&gt; and see your changes applied right before your eyes. It worked out better than we could have imagined. I absolutely loved seeing the kids’ eyes light up when we showed them how to change background and text colors, add images, and publish their site to the internet. There are already big plans in the works for Hack Ability Camp in 2020. I’m really looking forward to it.&lt;/p&gt;
&lt;h2 id=&quot;a-fine-start%2C-version-2&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#a-fine-start%2C-version-2&quot;&gt;A Fine Start, version 2&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I originally made &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; as an accessibility tool for myself. I have difficulty typing due to my disability, so I wanted an efficient, mouse-based, yet typographically nice new tab page that would present me with my frequently-visited web destinations (so I could avoid typing searches and URLs). It was called &lt;a href=&quot;http://start.blakewatson.com/&quot;&gt;Start&lt;/a&gt; and it was a single file that you could replace your new tab page with that would save bookmarks in your browser’s &lt;code&gt;localStorage&lt;/code&gt;. In 2017, I added the ability to sync bookmarks through an account and &lt;a href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/&quot;&gt;rebranded it into a freemium SaaS&lt;/a&gt;. It’s been chugging along ever since. It doesn’t make a ton of money (enough to cover its server costs, with a little to spare) but it continues to be an indispensable tool for myself and I hope to my handful of customers and free users as well. It &lt;em&gt;did&lt;/em&gt; receive &lt;a href=&quot;https://mediatemple.net/blog/tips/browser-extensions-actually-use/&quot;&gt;a great shout out&lt;/a&gt; in 2018 from &lt;a href=&quot;https://chriscoyier.net/&quot;&gt;Chris Coyier&lt;/a&gt;. I started work a year ago on rewriting the frontend code so that I could use the same code base to power the &lt;a href=&quot;https://afinestart.me/bookmarks/&quot;&gt;web version&lt;/a&gt;, the &lt;a href=&quot;https://chrome.google.com/webstore/detail/a-fine-start-minimal-new/kcgjmjiklcchbhljelchjdpoooccmhcn&quot;&gt;Chrome extension&lt;/a&gt;, and a new &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/a-fine-start/&quot;&gt;Firefox add-on&lt;/a&gt;. Unfortunately, with everything going on (and general laziness) I didn’t get around to finishing it until December! But I’m happy to say that version 2 is out as well as the new Firefox add-on. Everything basically works the same way. The big new user-facing feature is dark mode. I also gave the marketing site a little bit of a redesign.&lt;/p&gt;
&lt;h2 id=&quot;talon&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#talon&quot;&gt;Talon&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Toward the end of 2018 I came across an interesting piece of software called &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;. Talon is for “hands-free input” and has become increasingly useful to me. So much so that I’ve covered it twice on this website—once regarding &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/&quot;&gt;writing and coding by voice&lt;/a&gt; and once regarding &lt;a href=&quot;https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/&quot;&gt;playing Minecraft by voice&lt;/a&gt;. In fact, the article you’re reading now was dictated using Talon. I haven’t switched to using voice exclusively as I still find the &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;macOS Accessibility Keyboard&lt;/a&gt; useful. It really all depends on where and how I’m positioned as to which method of input I find more comfortable. But I really love Talon, I am passionate about getting people to try it, and I really hope to cover it better in a conference talk sometime.&lt;/p&gt;
&lt;h2 id=&quot;the-new-blakewatson.com&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#the-new-blakewatson.com&quot;&gt;The new &lt;a href=&quot;http://blakewatson.com/&quot;&gt;blakewatson.com&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Last, and probably also least, I redesigned this site back in the summer and transitioned it from a &lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/&quot;&gt;static site&lt;/a&gt; to a &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/&quot;&gt;WordPress-powered one&lt;/a&gt;. I noted how this seemed to be against the trend of &lt;a href=&quot;https://jamstack.org/&quot;&gt;JAMstack&lt;/a&gt; sites. Chris Coyier made a good point, though, that &lt;a href=&quot;https://twitter.com/chriscoyier/status/1138484839726796800&quot;&gt;static site generators can use WordPress as a data source&lt;/a&gt;, so they aren’t necessarily at odds. The design was inspired by the &lt;a href=&quot;https://www.reddit.com/r/outrun/&quot;&gt;synthwave&lt;/a&gt; music genre and aesthetic. As a little treat, I added an option for switching between light and dark themes.&lt;/p&gt;
&lt;h2 id=&quot;happy-new-year&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2019-my-year-in-review/#happy-new-year&quot;&gt;Happy New Year&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Things are looking up for 2020 from my view. I hope they are from yours, too.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Why I chose Simplenote over Standard Notes and nvUltra</title>
      <link href="https://blakewatson.com/journal/why-i-chose-simplenote-over-standard-notes-and-nvultra/"/>
      <updated>2019-09-17T06:42:58Z</updated>
      <id>https://blakewatson.com/journal/why-i-chose-simplenote-over-standard-notes-and-nvultra/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;strong&gt;Edit, Sep. 29, 2024:&lt;/strong&gt; I redacted this article for the last few years because it was unfair of me to review an app in beta against other apps that weren’t. It’s been five years and nvUltra is still in beta. At this point, I think this review is fair enough to publish again. But keep in mind that I had an older beta version at the time.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I spent the evening having a crisis about what note-taking application to use. For years I used &lt;a href=&quot;http://notational.net/&quot;&gt;Notational Velocity&lt;/a&gt;/&lt;a href=&quot;https://brettterpstra.com/projects/nvalt/&quot;&gt;nvAlt&lt;/a&gt;. It was light, fast, and I could sync my notes over Dropbox as a folder of files.&lt;/p&gt;
&lt;p&gt;Brett Terpstra, the maintainer of nvAlt, had BitWriter in the works for years but as a result of life getting in the way, it never came to be. Meanwhile I kept on using nvAlt.&lt;/p&gt;
&lt;p&gt;Then, several months ago, I saw the news that Brett and Fletcher Penney of MultiMarkdown were working on nvAlt’s successor, &lt;a href=&quot;https://nvultra.com/&quot;&gt;nvUltra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I got excited about my notes again but realized how badly I had been wanting another setup.&lt;/p&gt;
&lt;p&gt;That’s when I remembered &lt;a href=&quot;https://simplenote.com/&quot;&gt;Simplenote&lt;/a&gt;. When I discovered it was under the care of Automattic and provided as a free service, my interest was piqued. When I realized they had a native Mac app, I was impressed.&lt;/p&gt;
&lt;p&gt;I did something irrational—I switched over to using Simplenote even though the app I had been waiting years for, nvAlt’s successor, was soon to be released.&lt;/p&gt;
&lt;p&gt;That brings us to today. I got an invite to download the nvUltra beta.&lt;/p&gt;
&lt;p&gt;I don’t feel like reviewing nvUltra in detail here, but let’s just say I wasn’t into it like I thought I would be. I went down a web rabbit hole reading about note-taking apps and really giving my setup some thought. The following represents my preferred features with a note about how well various apps delivered. I compared Simplenote, nvUltra, and &lt;a href=&quot;https://standardnotes.org/&quot;&gt;Standard Notes&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;typography&quot;&gt;Typography&lt;/h2&gt;
&lt;p&gt;This shouldn’t have to be the first point, but damn there is some terrible typography in note-taking apps. Standard Notes was the worst. Their website is awesome but their default editor has such tight line-spacing that I almost couldn’t believe it. nvUltra (barely) wins out here because of how easy theming it is. Standard Notes has theming, but I didn’t test it. The defaults are so bad that I didn’t even bother. Simplenote has the best typography out-of-the-box, but the macOS app needs some looser line-spacing. It has &lt;em&gt;just enough&lt;/em&gt; Markdown formatting without forcing your note to be Markdown-compliant. &lt;strong&gt;Winner: nvUltra&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;line-spacingrantskipifyouwant&quot;&gt;Line-spacing rant; skip if you want&lt;/h2&gt;
&lt;p&gt;Seriously, though. Line-spacing of 1.0 (or 1 times the font size) is too tight. And in a lot of fonts, 1.5 is too loose. Anything between 1.2 and 1.45 usually is pretty good. I get that most people probably don’t give a shit about the nuance of line-spacing. That’s fine. But developers, can we make this a preference? Because you know you guys aren’t designers. Please, just let us snobs set our own line-spacing and other typographic properties. Ok, rant over.&lt;/p&gt;
&lt;h2 id=&quot;syncing&quot;&gt;Syncing&lt;/h2&gt;
&lt;p&gt;I need to sync two Macs. Having a web interface is a plus but not required. This is one of the reasons I was interested in Standard Notes. They implement end-to-end encryption which is pretty awesome. They take a strong stance on privacy, security, and longevity and I love that.&lt;/p&gt;
&lt;p&gt;nvUltra relies on third-party syncing. In my case, it’s Dropbox. I sync a &lt;em&gt;ton&lt;/em&gt; of files, though, so sometimes my notes get held hostage while I’m waiting for Dropbox to finish syncing. That said, it’s just a folder of files so that provides maximum portability. nvUltra (as far as I can tell) is perfectly happy for other apps to edit your notes.&lt;/p&gt;
&lt;p&gt;Simplenote runs its own syncing service. Your notes aren’t encrypted in storage (though they are in transit). You also get a web interface. Having the separate syncing service is nice because there’s no waiting for Dropbox.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Winner: Standard Notes&lt;/strong&gt; because of their commitment to privacy, security, and longevity. But Simplenote is a close second if you can get past the fact that your notes are stored in the clear.&lt;/p&gt;
&lt;h2 id=&quot;designandsimplicity&quot;&gt;Design and simplicity&lt;/h2&gt;
&lt;p&gt;Standard Notes talks a big game when it comes to simplicity but I don’t think the app delivers. Upgrading to Extended gets you all these wild add-ons and extensions. That’s cool, but like I just want text with decent line-spacing—not the kitchen sync. And as much as I love what Electron enables us web peeps to do (I mean I have &lt;a href=&quot;https://d20app.me/&quot;&gt;an Electron app on the App Store&lt;/a&gt;), I don’t want to run yet another one. Especially for my notes, which I want to be snappy at a moment’s notice.&lt;/p&gt;
&lt;p&gt;nvUltra brings the legendary simplicity of Notational Velocity but also the legendary flexibility of things made by Brett Terpstra and Fletcher Penney. For my needs, nvUltra is over-powered. In terms of design, it’s lackluster and needs some TLC if you want it looking good—which thanks to themes and some hidden preferences you can totally do.&lt;/p&gt;
&lt;p&gt;Simplenote is what it says on the tin. It’s UI is nice, it’s editor is nice (save the aforementioned macOS line-spacing). It’s the most Mac-like in my opinion—it follows your system setting for dark mode, for example. There’s &lt;em&gt;just enough&lt;/em&gt; Markdown. There are options I appreciate such as setting line-length to “Narrow” or “Full” (spoiler: you want “Narrow”) which while not as specific as I might want, follows the idea of embracing simplicity. You have options, but not too many.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Winner: Simplenote&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;mychoice&quot;&gt;My choice&lt;/h2&gt;
&lt;p&gt;The problem with writing articles like this is that I may very well change my mind within days. And to be fair, nvUltra is in beta.&lt;a id=&quot;fnref-1&quot; class=&quot;footnote&quot; title=&quot;see footnote&quot; href=&quot;https://blakewatson.com/journal/why-i-chose-simplenote-over-standard-notes-and-nvultra/#fn-1&quot;&gt;1&lt;/a&gt; But tonight I decided to stick with Simplenote.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;really&lt;/em&gt; wish it stored encrypted notes, but I’m not willing to sacrifice my other wants for that. I enjoyed the portability of the folder-of-files setup for years, but I’m going with the walled garden of Simplenote because it makes jotting down a quick note (that’s everywhere) effortless. And there’s a great export tool if I ever want to hit the eject button. Simplenote also quietly packs some powerful features like note collaboration and publishing. But they’re totally out of your way if you don’t care about them.&lt;/p&gt;
&lt;p&gt;While I appreciate Standard Notes’ commitment of longevity, I’m choosing Automattic’s track record of the same. Remember they make WordPress which is like 1 in 3 websites and they recently acquired Tumblr, the other popular blogging site. They have the resources to provide Simplenote, and they haven’t neglected it thus far. Matt Mullenweg needs notes too, right? Simplenote should be with us for a while.&lt;/p&gt;
&lt;p&gt;If security is your primary concern, you want &lt;a href=&quot;https://standardnotes.org/&quot;&gt;Standard Notes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want maximum portability, compatibility, and some nerd power, then you want a folder of text files that you edit with &lt;a href=&quot;https://nvultra.com/&quot;&gt;nvUltra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to write a quick note down easily and elegantly, then you want my choice, &lt;a href=&quot;https://simplenote.com/&quot;&gt;Simplenote&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
    &lt;li id=&quot;fn-1&quot;&gt;nvUltra can nerd out in some pretty awesome ways but it’s missing some UI niceties I’ve become accustomed to—like having a list of my tags that I can click to filter the notes list. It’s really a keyboard-centric app and, unfortunately, my disability makes me more mouse-centric. &lt;a class=&quot;reversefootnote&quot; title=&quot;return to article&quot; href=&quot;https://blakewatson.com/journal/why-i-chose-simplenote-over-standard-notes-and-nvultra/#fnref-1&quot;&gt; ↩&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content>
    </entry>
    <entry>
      <title>How to: array reduce in JavaScript and PHP</title>
      <link href="https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/"/>
      <updated>2019-06-25T04:53:06Z</updated>
      <id>https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/</id>
      <content xml:lang="en" type="html">&lt;p&gt;If you make websites, chances are that you work with arrays. &lt;em&gt;A lot&lt;/em&gt;. They’re everywhere—a list of posts, a list of followers, a list of links. But working with arrays can sometimes feel a little cumbersome. Sometimes it can take more code than it seems like it should to process an array. Sometimes it can feel… hacky.&lt;/p&gt;
&lt;p&gt;You may have heard other developers say, “Just use a reducer.” Or, “a reducer could do that!” Or maybe even, “Reduce is cool and you have to be a functional programming genius like me to understand it.”&lt;/p&gt;
&lt;p&gt;Not true, I say! I know next to nothing about functional programming (so far). But I was able to understand and start using reduce functions in my own work. And so can you!&lt;/p&gt;
&lt;h2 id=&quot;arrays%2C-the-conventional-way&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#arrays%2C-the-conventional-way&quot;&gt;Arrays, the conventional way&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before we look at the power of the reduce function, let’s look at some of the other ways you might access an array. In JavaScript, for example, you are probably familiar with something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var fruits = [&#39;orange&#39;, &#39;apple&#39;, &#39;banana&#39;];
for(let i = 0; i &amp;lt; fruits.length; i++) {
    // do something with fruits[i]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above code shows a &lt;code&gt;for&lt;/code&gt; loop that is being used to iterate over each element in the fruits array. Really, all it is doing is incrementing a counter, which you can then use to access your array.&lt;/p&gt;
&lt;p&gt;You might even be aware of the nicer way of doing this, using an array method:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var fruits = [&#39;orange&#39;, &#39;apple&#39;, &#39;banana&#39;];
fruits.forEach(fruit =&amp;gt; {
    // do something with fruit
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;forEach&lt;/code&gt; method accepts a callback function, and runs that function over each element in the array.&lt;/p&gt;
&lt;p&gt;This is the first important point to understanding a reducer. The idea of writing a callback function that gets run for each element in the array. Each time it runs, it takes an array element as its argument. So just hang on to that for a second.&lt;/p&gt;
&lt;h2 id=&quot;list-operations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#list-operations&quot;&gt;List operations&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s another functional programming term for you. &lt;em&gt;List operations&lt;/em&gt; just refers to methods that run against arrays (lists). Most of the time, they iterate over the array, do things, and return another array as the result.&lt;/p&gt;
&lt;p&gt;As a quick example, take the &lt;code&gt;filter&lt;/code&gt; function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var fruits = [&#39;orange&#39;, &#39;apple&#39;, &#39;banana&#39;];
var fruitsILike = fruits.filter(fruit =&amp;gt; fruit === &#39;banana&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;filter&lt;/code&gt; function runs a callback function over each element in the array. The callback function must return &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, depending on whether you want the current element to be included in the final array. What I just called the “final array” is what is returned by &lt;code&gt;filter&lt;/code&gt;—it’s a new array containing all of the elements for which you returned &lt;code&gt;true&lt;/code&gt;. In this case, an array containing just one element, &lt;code&gt;banana&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another useful list operation is the map. Let’s look at this one in PHP.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;$fruits = [ &#39;orange&#39;, &#39;apple&#39;, &#39;banana&#39; ];
$fruit_initials = array_map( function( $fruit ) {
    return substr( $fruit, 0, 1 );
}, $fruits );

// Expected return value: [ &#39;o&#39;, &#39;a&#39;, &#39;b&#39; ];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;array_map&lt;/code&gt; function iterates over each element in the array. It returns a new array with the same number of elements as the original, but with each element being whatever you chose to return. Each element in the old array &lt;em&gt;maps&lt;/em&gt; to an element in the new one.&lt;/p&gt;
&lt;h2 id=&quot;enter-the-reducer&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#enter-the-reducer&quot;&gt;Enter the reducer&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we have looked at other list operations, we have the basis for understanding the reducer. Before I show you a code sample, consider the following metaphor.&lt;/p&gt;
&lt;p&gt;Imagine you have a piece of paper with a list of numbers. You have a calculator which you use to add up all the numbers. As you are adding up the numbers, you have a running total. As you progress down your list of numbers, you simply keep adding each number to the running total.&lt;/p&gt;
&lt;p&gt;This is very similar to how a reducer works. You have a list of things (the array) that you are iterating over. As you do, you have access to a variable that represents the current element. Just like we have seen earlier. But you also have a variable that represents the “running total,” if you will. We’ll call it, “carry.” Let’s take a look at this in JavaScript:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var numbers = [42, 7, 99, 2, 33];
var total = numbers.reduce((carry, num) =&amp;gt; carry + num, 0);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the code above, we are supplying &lt;code&gt;reduce&lt;/code&gt; two arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Our callback function, which should return the new running total at the end of each iteration.&lt;/li&gt;
&lt;li&gt;The initial value of our running total, which in this case we want to be &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay, so we’re iterating over the &lt;code&gt;numbers&lt;/code&gt; array. The &lt;code&gt;reduce&lt;/code&gt; function expects our callback function to return the new running total for each iteration. That’s the &lt;code&gt;carry + num&lt;/code&gt; bit&lt;a href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#fn:1&quot; title=&quot;see footnote&quot;&gt;[1]&lt;/a&gt;. If we were to &lt;code&gt;console.log()&lt;/code&gt; the value of &lt;code&gt;carry&lt;/code&gt; at the beginning of each iteration, it would look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// torchlight! {&amp;quot;lineNumbers&amp;quot;: false}
0
42
49
148
150
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the final total would be 183.&lt;/p&gt;
&lt;p&gt;Here’s the same reducer in PHP:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;$numbers = [42, 7, 99, 2, 33];

$total = array_reduce( $numbers, function($carry, $num) {
    return $carry + $num;
}, 0 );
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;so-i-can-add-some-numbers-together%3F-big-deal%E2%80%A6&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#so-i-can-add-some-numbers-together%3F-big-deal%E2%80%A6&quot;&gt;So I can add some numbers together? Big deal…&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay, now this is where reducers get their reputation for being all-powerful. We’ve been thinking of the carry value as being a running total. But here’s the thing—your callback function can return any type of value, and whatever value you return will be passed to your callback function on the next iteration.&lt;/p&gt;
&lt;p&gt;Let’s look at a contrived example to see how you can use a reducer for something that has nothing to do with adding numbers together.&lt;/p&gt;
&lt;p&gt;Let’s say we have one array that contains fruits and vegetables. Instead we would like to have an object that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;{
    fruits: [], // array containing only fruits
    veggies: [] // array containing only veggies
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how we could do it with a reducer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var food = [&#39;apple&#39;, &#39;okra&#39;, &#39;banana&#39;, &#39;spinach&#39;];

var organizedFood = food.reduce((carry, item) =&amp;gt; {
    if(item === &#39;apple&#39; || item === &#39;banana&#39;) {
        carry.fruits.push(item);
    } else {
        carry.veggies.push(item);
    }
    
    return carry;
}, { fruits: [], veggies: [] });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s set aside the fact that this function doesn’t scale very well (it can’t handle any other fruits except apples and bananas). It &lt;em&gt;does&lt;/em&gt; show how we can use a reducer to keep a running value of any type. Let’s step through the code.&lt;/p&gt;
&lt;p&gt;We pass &lt;code&gt;reduce&lt;/code&gt; our callback function. We also pass it the initial value. In our case, we want the initial value to be an empty object with the properties &lt;code&gt;fruits&lt;/code&gt; and &lt;code&gt;veggies&lt;/code&gt;. We set the value of both of those properties to an empty array.&lt;/p&gt;
&lt;p&gt;Our callback function looks at each element in the array. If it matches one of the fruits, we push that element to the &lt;code&gt;carry.fruits&lt;/code&gt; array. If it doesn’t, we assume that it is a vegetable and we push it to the &lt;code&gt;carry.veggies&lt;/code&gt; array. Then, &lt;em&gt;critically&lt;/em&gt;, we return the object after we’ve modified it. That ensures that we save our updated running value.&lt;/p&gt;
&lt;p&gt;Once we get to the end of the function, &lt;code&gt;organizedFood&lt;/code&gt; should look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;{
    fruits: [ &#39;apple&#39;, &#39;banana&#39; ],
    veggies: [ &#39;okra&#39;, &#39;spinach&#39; ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here’s the exact same reducer in PHP:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;$food = [&#39;apple&#39;, &#39;okra&#39;, &#39;banana&#39;, &#39;spinach&#39;];

$organizedFood = array_reduce( $food, function( $carry, $item ) {
    if( $item === &#39;apple&#39; || $item === &#39;banana&#39; ) {
        array_push( $carry[&#39;fruits&#39;], $item );
    } else {
        array_push( $carry[&#39;veggies&#39;], $item );
    }
    
    return $carry;
}, [ &#39;fruits&#39; =&amp;gt; [], &#39;veggies&#39; =&amp;gt; [] ] );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, the secret sauce here is the fact that we have this running value, &lt;code&gt;$carry&lt;/code&gt;, that can be anything we want. And we have access to it on each iteration of our loop. On the last iteration, whatever we return as the &lt;code&gt;$carry&lt;/code&gt; value will be what is returned by the &lt;code&gt;array_reduce&lt;/code&gt; function.&lt;/p&gt;
&lt;h2 id=&quot;reducer-redux&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-array-reduce-in-javascript-and-php/#reducer-redux&quot;&gt;Reducer redux&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I hope this article has helped to demystify the reducer function and how it can be used for all sorts of things. In summary, a reducer function works like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It iterates over list of things, running your callback function.&lt;/li&gt;
&lt;li&gt;It receives an initial running value, which can be anything.&lt;/li&gt;
&lt;li&gt;For each thing in the list, your callback has a chance to modify/replace the running value.&lt;/li&gt;
&lt;li&gt;After passing over the whole list, the reducer function returns the running value.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In JavaScript, you can call &lt;code&gt;.reduce()&lt;/code&gt; directly on an array. In PHP, you use the &lt;code&gt;array_reduce()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;The next time you find yourself about to use a &lt;code&gt;for&lt;/code&gt; loop for the purpose of looping over an array and keeping up with some other arbitrary value as you go, it’s almost certainly a great time to consider using a reducer.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Unpopular opinion: switching to WordPress in 2019</title>
      <link href="https://blakewatson.com/journal/switching-to-wordpress-in-2019/"/>
      <updated>2019-06-10T03:56:34Z</updated>
      <id>https://blakewatson.com/journal/switching-to-wordpress-in-2019/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Static sites continue to be popular with web developers, a trend that, as far as I can tell, began several years ago&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. I joined that trend back in 2015 when I &lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/&quot;&gt;made blakewatson.com a static site&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t have any ill-will toward WordPress. It’s a great CMS. It’s &lt;em&gt;the&lt;/em&gt; CMS. But I just don’t need it for this site. I don’t need its commenting system, its URL handling, its media library, or its database. As they say, use the right tool for the job.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I went on to sing the praises of wok, a now defunct static site generator written in Python. While I still stand behind my comments about the benefits of static sites, I no longer agree with my quote above, and I have some better insight on the cons of static sites.&lt;/p&gt;
&lt;h2 id=&quot;wordpress-is-really-convenient&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#wordpress-is-really-convenient&quot;&gt;WordPress is really convenient&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t need its commenting system, its URL handling, its media library, or its database.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Maybe that’s technically true. I don’t &lt;em&gt;need&lt;/em&gt; them. But it turns out that stuff is really useful.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; Let’s say I notice a typo on my website while I’m on a device that doesn’t have my development set up. With WordPress, there’s no cloning, committing, and deploying just to change some text. I just log in, make the change, and save it. Easy peasy.&lt;/p&gt;
&lt;p&gt;It’s true that the local dev environment of a static site is easier to get up and running. But it’s just me working on my site—the setup basically only happens once and I’m good to go. And I’m already used to WordPress and moving it around, thanks to working with it for over a decade. More often than not—for me anyway—the convenience of having that database outweighs the convenience of having my content versioned in a Git repo.&lt;/p&gt;
&lt;p&gt;The performance of a static site rocks. I can’t deny that. My site gets very little traffic, so I’m hoping that doing some caching will get the job done.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;But static site generators let you use Markdown.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Plot twist. I can still use Markdown with WordPress. In fact, I’m using it right now. I’m drafting this in &lt;a href=&quot;https://ia.net/writer&quot;&gt;iA Writer&lt;/a&gt;. When I get mostly finished, I’ll copy and paste the HTML into WordPress, fine tune it, and then publish. (Edit: the Jetpack plugin lets you opt-in to writing your posts with Markdown). I realize this workflow isn’t for everybody, but that’s part of the beauty of WordPress—it can be fine tuned to an individual’s preferences. In my case, for example, I turned off Gutenberg as well as the classic visual editor, opting instead for the code editor &lt;em&gt;only&lt;/em&gt;. I added a plug-in that gives me syntax highlighting. With most of my writing done in another app, editing a bit of HTML is no big deal. (using Markdown now!)&lt;/p&gt;
&lt;h2 id=&quot;wordpress-is-the-helvetica-of-cmss&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#wordpress-is-the-helvetica-of-cmss&quot;&gt;WordPress is the Helvetica of CMSs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With 30% of the web, we might as well say that it is ubiquitous. And it’s good. Much like Helvetica, WordPress is very seldom the worst choice that you could have made (even if it isn’t always the best). It’s just not trendy to make your site with WordPress today. If you follow web circles, you will hear a lot about Gatsby, Next, Nuxt, and a whole bunch of other stuff. That’s totally fine, it’s just important to remember that &lt;a href=&quot;https://metafizzy.co/blog/new-tech-gets-chatter/&quot;&gt;new tech gets chatter&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You don’t hear about TextMate because TextMate is old. What would I tweet? Still using TextMate. Still good.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class=&quot;caption&quot;&gt;— David DeSandro, Metafizzy blog&lt;/p&gt;
&lt;p&gt;While there are &lt;a href=&quot;http://wpmail.me/&quot;&gt;great places to keep up with WordPress&lt;/a&gt;, in most publications on the web, you are much more likely to read about bleeding edge tech.&lt;/p&gt;
&lt;h2 id=&quot;simple-and-boring&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#simple-and-boring&quot;&gt;Simple and boring&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I admit that the static site generator I chose was a bit obscure, but still, there’s not a static site generator with the popularity and longevity of WordPress. It’s being actively developed, and just about any problem you could come across has already been documented and answered. I got burned by wok (heh). I got burned by picking something trendy instead of something established. At the risk of coming off as a curmudgeonly web developer, I’m becoming kind of obsessed with the idea keeping things &lt;a href=&quot;https://css-tricks.com/simple-boring/&quot;&gt;simple and boring&lt;/a&gt;. At least when it comes to code. I’m still very much in favor of &lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/&quot;&gt;weird homepages&lt;/a&gt;, though, and I think everybody should have one.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I mean, yeah. I guess static sites were the first kind of websites. They’ve always been a thing. But when I say they are trending, I’m referring to the uptick in web developers using modern static site generators. &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Okay maybe not commenting system. And not because it’s not a cool technical feature. But just because comment sections on the Internet kind of suck. &lt;a href=&quot;https://blakewatson.com/journal/switching-to-wordpress-in-2019/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Playing Minecraft by voice with Talon</title>
      <link href="https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/"/>
      <updated>2019-02-12T23:35:14Z</updated>
      <id>https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;em&gt;Edit 02/2021: this article was written about what is now a legacy version of Talon. The concepts remain the same but the scripts probably won’t work on the latest version of Talon. Visit &lt;a href=&quot;https://talonvoice.com/&quot;&gt;https://talonvoice.com/&lt;/a&gt; for the most recent documentation.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In times past I was an avid console gamer. Those days ended about a decade ago when my hands became too weak to operate a controller. I began to be interested in PC games that had simple controls and mechanics. At one point, with the help of my iPhone, I was able to access enough keys to play the beloved Minecraft. Several years ago I lost the ability to play that game as well. However, I’m back to playing Minecraft again—this time by voice with &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/mItivNjd2To&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;full-keyboard-access&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/#full-keyboard-access&quot;&gt;Full keyboard access&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What makes playing Minecraft possible is having full access to the keyboard. I’m able to control a mouse. And I can press the left click button (sometimes a second button, depending on my setup). After turning on auto-jump, a built-in Minecraft feature, I depend on Talon to handle all other functionality. Even without customization for Minecraft, including the &lt;code&gt;basic_keys.py&lt;/code&gt; &lt;a href=&quot;https://github.com/talonvoice/examples&quot;&gt;example script&lt;/a&gt; is enough to give you access to your inventory as well as the ability to place blocks. There are two important functions that require more nuanced behavior than simple keypresses—walking and digging. When I’m using my two-button setup, I can use one button for walking forward and the other for digging. But when I’m using my one-button setup, I need to use Talon for one of those. That’s where customization comes in.&lt;/p&gt;
&lt;h2 id=&quot;custom-talon-scripts-for-minecraft&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/#custom-talon-scripts-for-minecraft&quot;&gt;Custom Talon scripts for Minecraft&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I explained in &lt;a href=&quot;https://www.blakewatson.com/journal/writing-and-coding-by-voice-with-talon/&quot;&gt;my last article about Talon&lt;/a&gt; how Talon can be scripted to perform custom actions. Scripting Minecraft controls required me to dig in a little deeper, going beyond keypresses by programming macro-like sequences. For example, digging. I needed the ability to hold down the attack key for specific amount of time, depending on the block I’m trying to break. I came up with this format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;attack AMOUNT_OF_TIME&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I settled on using half-seconds as the time increment. With the command added to the keymap, it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;ctx.keymap({
    &#39;attack (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)&#39;: hold_key
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To use this command, I speak the word “attack” followed by a number one through nine. When Talon recognizes that command, it passes my dictation to the &lt;code&gt;hold_key&lt;/code&gt; function. The &lt;code&gt;hold_key&lt;/code&gt; function looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from talon import ctrl
from ..utils import parse_words_as_integer

def hold_key(m):
    keymap = {
        &#39;attack&#39;: &#39;k&#39;,
        &#39;eat&#39;: &#39;u&#39;
    }
    half_seconds = parse_words_as_integer(m._words[1:])
    if half_seconds != None and half_seconds &amp;gt; 0 and half_seconds &amp;lt; 10:
        microseconds = half_seconds * 500000
        key_to_press = keymap[m._words[0]]
        ctrl.key_press(key_to_press, hold=microseconds)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s kind of a lot going on here, but essentially what’s happening is that it’s figuring out which key I want to press and then it’s holding it for the specified number of half-seconds. The &lt;code&gt;parse_words_as_integer&lt;/code&gt; function comes from the &lt;a href=&quot;https://github.com/dwiel/talon_community&quot;&gt;community&lt;/a&gt; &lt;code&gt;utils.py&lt;/code&gt; script. It’s taking a spelled out number from my dictation (e.g., “four”) and turning it into an actual number (e.g., “4”)—an integer type—that I can use to set the hold time. It’s a handy command, but when I’m doing a lot of digging, it gets repetitive. That’s okay, because I have another option. I made a second command for attack that simply holds down the key until I tell it to stop.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def start_attack(m):
    ctrl.key_press(&#39;k&#39;, down=True)

def stop_attack(m):
    ctrl.key_press(&#39;k&#39;, up=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Added to the keymap, it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;ctx.keymap({
    &#39;attack (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)&#39;: hold_key,
    &#39;hitter&#39;: start_attack,
    &#39;stop&#39;: stop_attack,
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you’re interested in more, you can see my full Minecraft script as well as the rest of &lt;a href=&quot;https://github.com/blakewatson/talon-scripts&quot;&gt;my user scripts on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;endless-possibilities&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/playing-minecraft-by-voice-with-talon/#endless-possibilities&quot;&gt;Endless possibilities&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After being limited to mouse-only and turn-based games for a while now, I’m excited by the possibilities Talon brings for gaming. I can imagine writing custom scripts for something like World of Warcraft—speak the phrase “go ham,” and my character starts firing off its attack rotation. Talon could also help with in-game text chat, something that hasn’t been feasible for me before. I honestly can’t say whether I’m having more fun &lt;em&gt;writing&lt;/em&gt; scripts for Talon or &lt;em&gt;using&lt;/em&gt; them to write, code, and play games. #nerd #winning&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>Writing and coding by voice with Talon</title>
      <link href="https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/"/>
      <updated>2018-12-31T23:32:39Z</updated>
      <id>https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/</id>
      <content xml:lang="en" type="html">&lt;p&gt;&lt;em&gt;Edit 02/2021: this article was written about what is now a legacy version of Talon. The concepts remain the same but the scripts probably won’t work on the latest version of Talon. Visit &lt;a href=&quot;https://talonvoice.com/&quot;&gt;https://talonvoice.com/&lt;/a&gt; for the most recent documentation.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I previously wrote about &lt;a href=&quot;https://www.blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/&quot;&gt;writing and coding with the macOS Accessibility Keyboard&lt;/a&gt;. It continues to be the most essential piece of assistive technology I use. That said, I recently discovered another amazing tool, Talon.&lt;/p&gt;
&lt;p&gt;In recent months, I’ve been spending more time out of my wheelchair in order to get some pressure relief for my legs. As such, I’ve been working a lot on my laptop. I use it in a lying down position, which makes using the mouse somewhat difficult for me. My biggest hindrance is typing on the Accessibility Keyboard.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://talonvoice.com/&quot;&gt;Talon&lt;/a&gt;. Talon is freeware software for macOS that provides “powerful hands-free input” by way of eye-tracking and voice recognition. In particular, its voice recognition system is novel, offering a user experience that’s quite different (and, to me, better) than what you get with Dragon or macOS’ built-in solutions.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The trick is that Talon doesn’t simply type out whatever you dictate. It listens to you then determines what to type based on a set of rules that you can control. For example, if I say:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title hello world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Talon will output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is because I have a script installed that knows if it hears a phrase beginning with the word &lt;code&gt;title&lt;/code&gt;, it should output the rest of that phrase with each word being capitalized. Whereas if I had said:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hello world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Talon would have output nothing at all. Why is that? Because I don’t have any rules installed that care about the phrase, &lt;code&gt;hello world&lt;/code&gt;. If I &lt;em&gt;did&lt;/em&gt; want to literally type &lt;code&gt;hello world&lt;/code&gt;, I would dictate:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;say hello world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By starting the phrase with &lt;code&gt;say&lt;/code&gt;, Talon knows—again, because of a currently installed rule—to output the rest of the phrase normally. Several of these formatters are included in this particular ruleset. Here are just a few of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sentence hello world&lt;/code&gt; → &lt;code&gt;Hello world&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;camel hello world&lt;/code&gt; → &lt;code&gt;helloWorld&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snake hello world&lt;/code&gt; → &lt;code&gt;hello_world&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spinal hello world&lt;/code&gt; → &lt;code&gt;hello-world&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;smash hello world&lt;/code&gt; → &lt;code&gt;helloworld&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-talon%3F-isn%E2%80%99t-dragon-or-macos-dictation-way-better%3F&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#why-talon%3F-isn%E2%80%99t-dragon-or-macos-dictation-way-better%3F&quot;&gt;Why Talon? Isn’t Dragon or macOS dictation way better?&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, that depends. Coders will immediately recognize from my above example what kind of flexibility Talon provides in controlling your output. If you are simply writing natural language, you might not find Talon as useful. But if you need precision—as with programming and editing—Talon really shines. Its number one feature, in my opinion, is its ability to be customized.&lt;/p&gt;
&lt;h2 id=&quot;controlling-talon-with-scripts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#controlling-talon-with-scripts&quot;&gt;Controlling Talon with scripts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For many purposes, the community scripts are enough to provide great functionality. But the real fun is in customizing it to do exactly what you want. Let’s take look at how that works. To do that, we need to use Python. When you install Talon, it creates a &lt;code&gt;user&lt;/code&gt; folder where you can add scripts to control how Talon behaves. You’ll find it at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.talon/user
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is where you can drop in some Python scripts. Any scripts you put there will be loaded automatically by Talon.&lt;/p&gt;
&lt;h3 id=&quot;community-scripts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#community-scripts&quot;&gt;Community scripts&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s first take a look at existing scripts you can use to get Talon up and running with some basic functionality. You’ll find some great starting scripts in the &lt;a href=&quot;https://github.com/dwiel/talon_community&quot;&gt;talon_community&lt;/a&gt; repo. A good start is to include these three files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;utils.py&lt;/code&gt;: used by a bunch of the other files&lt;/li&gt;
&lt;li&gt;&lt;code&gt;misc/basic_keys.py&lt;/code&gt;: what it says on tin, plus a spelling alphabet&lt;/li&gt;
&lt;li&gt;&lt;code&gt;misc/std.py&lt;/code&gt;: includes the formatters I described in the intro&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just drop &lt;code&gt;utils.py&lt;/code&gt; into the &lt;code&gt;user&lt;/code&gt; folder. Then create a &lt;code&gt;misc&lt;/code&gt; folder in &lt;code&gt;user&lt;/code&gt; and drop the other two files in. Feel free to edit these files. Personally, I removed a good bit of the coding-related commands from &lt;code&gt;std.py&lt;/code&gt; because they either didn’t support my primary languages or were registering as false positives. Once you launch Talon, it will load those files and you will have access to their functions. For example, &lt;code&gt;basic_keys.py&lt;/code&gt; includes a spelling alphabet for typing single letters—&lt;code&gt;air&lt;/code&gt; becomes &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;bat&lt;/code&gt; becomes &lt;code&gt;b&lt;/code&gt;, and so on. This method gives you greater precision than normal dictation gives you and is especially useful for coding, which contains many terms that can’t be dictated easily.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;writing-custom-scripts&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#writing-custom-scripts&quot;&gt;Writing custom scripts&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Of course the real fun is writing your own scripts.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt; Let’s say, like me, you enjoy using the em dash (&lt;code&gt;—&lt;/code&gt;) character. You want to add it your repertoire in Talon. Start by creating a new file, &lt;code&gt;my_scripts.py&lt;/code&gt;. We’re going to be using a module from Talon that is needed to create a keymap—the thing that maps our commands to the output we want.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from talon.voice import Context
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s say we want to type &lt;code&gt;—&lt;/code&gt; by dictating &lt;code&gt;bigger dash&lt;/code&gt;. We would construct our keymap like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ctx = Context(&#39;my_scripts&#39;)

ctx.keymap({
    &#39;bigger dash&#39;: &#39;&amp;amp;mdash;&#39;
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s all there is to it. Congratulations, you just wrote your first Talon script!&lt;/p&gt;
&lt;p&gt;But let’s keep going. We’ll add a command for activating Spotlight in macOS (command + space). In order to press the modifier key, we need to import something else from Talon. After our addition, the code should look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from talon.voice import Context, Key

ctx = Context(&#39;my_scripts&#39;)

ctx.keymap({
    &#39;bigger dash&#39;: &#39;&amp;amp;mdash;&#39;,
    &#39;spotlight&#39;: Key(&#39;cmd-space&#39;)
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when we say &lt;code&gt;spotlight&lt;/code&gt;, Talon will virtually type the shortcut for summoning Spotlight search.&lt;/p&gt;
&lt;h2 id=&quot;scratching-the-surface&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#scratching-the-surface&quot;&gt;Scratching the surface&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That’s all we’ve done. Snoop around in the &lt;a href=&quot;https://github.com/dwiel/talon_community&quot;&gt;talon_community&lt;/a&gt; repo and start to see how powerful Talon really is. If you’re not a coder, don’t worry, there’s a friendly &lt;a href=&quot;https://talonvoice.slack.com/&quot;&gt;Slack&lt;/a&gt; where you can get help from the developer of Talon&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; as well as the community. If you have trouble typing, but haven’t had any luck with dictation in the past, give Talon a try.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Talon actually makes use of Dragon if it’s installed, but also comes with built-in voice recognition, which is what I use. &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;If Talon isn’t picking up certain words or some words are getting false positives, don’t be afraid to experiment with &lt;em&gt;different&lt;/em&gt; words. Even if you can’t code, changing the words is as simple as finding the the word list in &lt;code&gt;basic_keys.py&lt;/code&gt; and editing it. &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Note that, at the time of this writing, there is a new API on the horizon. So keep an eye on the release notes and community repo for changes. &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The developer has a Patreon so, if you find Talon useful, consider &lt;a href=&quot;https://patreon.com/lunixbochs&quot;&gt;supporting its development&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-by-voice-with-talon/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Writing and coding with the macOS Accessibility Keyboard</title>
      <link href="https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/"/>
      <updated>2018-06-02T23:31:17Z</updated>
      <id>https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/</id>
      <content xml:lang="en" type="html">&lt;p&gt;For years, macOS lacked a proper on-screen keyboard. The built-in &lt;a href=&quot;https://www.blakewatson.com/ihs/onscreen-keyboard-fail-why-macs-keyboard-viewer-is-utter-atrocity/&quot;&gt;Keyboard Viewer provided little relief&lt;/a&gt;. Many disabled macOS users turned to a third-party option, a $300 piece of software called &lt;a href=&quot;http://www.assistiveware.com/product/keystrokes&quot;&gt;AssistiveWare KeyStrokes&lt;/a&gt;. Despite its cost, it served me well for years. But the app was old and development had essentially ceased. Fortunately, in September 2017, Apple shipped a utility in macOS High Sierra called Accessibility Keyboard.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/osk-side-by-side.png&quot; alt=&quot;&quot; /&gt;
  &lt;figcaption&gt;Side by side view of AssistiveWare KeyStrokes and Accessibility Keyboard&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;on-screen-keyboard-basics&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#on-screen-keyboard-basics&quot;&gt;On-screen keyboard basics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For many users who are unable to type on a physical keyboard, on-screen keyboards (OSKs) are a necessity. As with any app, the nuanced details matter. At a bare minimum, though, an OSK must have the following features to be useable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A QUERTY layout with access to all keys&lt;/li&gt;
&lt;li&gt;Sticky modifier keys that stay held on click&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But for proper, productive use, an OSK needs more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Customizable key layout&lt;/li&gt;
&lt;li&gt;Word prediction&lt;/li&gt;
&lt;li&gt;Custom keys for text macros&lt;/li&gt;
&lt;li&gt;Resizable window&lt;/li&gt;
&lt;li&gt;Configurable window transparency&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The macOS Accessibility Keyboard has all this and more.&lt;/p&gt;
&lt;h2 id=&quot;accessibility-keyboard-customization&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#accessibility-keyboard-customization&quot;&gt;Accessibility Keyboard customization&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most important feature to me is the ability to customize the keyboard layout. I’m a diehard fan of the &lt;a href=&quot;https://blakewatson.com/journal/my-journey-with-the-chubon-keyboard-layout/&quot;&gt;Chubon layout&lt;/a&gt;, developed by &lt;a href=&quot;http://chubon.org/bob/&quot;&gt;Dr. Robert Chubon&lt;/a&gt; years after he was paralyzed in a childhood accident. It places common keys in the center of the keyboard, offering a target-based approach with the letter “E” in the center.&lt;/p&gt;
&lt;p&gt;Accessibility Keyboard ships with a panel editor that allows you to design complex, powerful keyboards. Keys can simulate keystrokes, enter text strings, and even run AppleScripts. You can set text labels on keys or use images instead. And you aren’t limited to one layout. Accessibility Keyboard holds multiple panels and provides a mechanism for switching between them.&lt;/p&gt;
&lt;p&gt;Overall, it does a fantastic job at replacing my beloved KeyStrokes. It has a few glitches here and there, and seems to need a good amount of RAM, but it’s good quality for being a version 1—and Apple is actively developing it.&lt;/p&gt;
&lt;h2 id=&quot;using-accessibility-keyboard-for-web-development&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#using-accessibility-keyboard-for-web-development&quot;&gt;Using Accessibility Keyboard for web development&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;p&gt;&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/accessibility-keyboard-customizations.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;&lt;figcaption&gt;My customized version of Accessibility Keyboard with custom functionality keys labeled&lt;/figcaption&gt;&lt;p&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;p&gt;I use a heavily customized version of Accessibility Keyboard that’s optimized for writing code. It includes single-click access (no Shift required) to all the punctuation and special characters required in programming syntaxes. Moving around in text can be tedious with a mouse or arrow keys alone. To help with that, I added keys for moving the text cursor by word, jumping to the beginning and end of lines, and selecting text by character or word.&lt;/p&gt;
&lt;p&gt;To aid in coding, I added some common strings (I also take advantage of my code editor’s snippets feature) as well as shortcuts for indenting and commenting code. Since I’m a web developer, I do a lot of browser refreshing.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; The Last key helps me quickly switch between my editor and browser,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; where I can then use the reload or hard reload keys.&lt;/p&gt;
&lt;p&gt;As general productivity helpers, I have keys for summoning &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt;, my app launcher of choice, and invoking macOS utilities like Mission Control and the screenshot tool.&lt;/p&gt;
&lt;h2 id=&quot;get-my-layout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#get-my-layout&quot;&gt;Get my layout&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can &lt;a href=&quot;https://blakewatson.com/externalfiles/accessibility-keyboard-chubon.ascconfig.zip&quot;&gt;download my layout here&lt;/a&gt;. You will also need to download the &lt;a href=&quot;https://blakewatson.com/externalfiles/last-app.scpt&quot;&gt;accompanying AppleScript&lt;/a&gt; as it doesn’t seem to carry over properly. In fact, you will need to open the panel editor and re-assign the AppleScript to the Last key.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blakewatson.com/contact/&quot;&gt;Email me&lt;/a&gt; if you have any questions or comments about this layout. And if you have one of your own, please share!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Yes, I know there are apps and npm packages that can reload the browser for you, but I’m a control freak, okay? &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Because of some glitchy behavior with Accessibility Keyboard and the app switching shortcut, I had to have the key trigger an AppleScript to get this to work. &lt;a href=&quot;https://blakewatson.com/journal/writing-and-coding-with-the-macos-accessibility-keyboard/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>My answer to the gratuitous new tab page</title>
      <link href="https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/"/>
      <updated>2017-10-22T23:07:37Z</updated>
      <id>https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Several years ago, Safari shipped with a terrible, over-the-top new tab page that showed your recently visited sites as a giant TV grid. It even had the signature reflective floor. It looked like this:&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/safari-4-recent-sites.jpg&quot; alt=&quot;Safari 4 recent sites&quot; /&gt;&lt;figcaption&gt;Safari 4&amp;#8217;s new tab page is an inwardly-curved, three dimensional grid of website thumbnail images&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The situation has improved somewhat since then. Current versions of Safari and Chrome still show a grid of recent site screenshots (though Safari has options to show something else&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;), but they embrace a softer, more elegant design.&lt;/p&gt;
&lt;p&gt;Still, I find having a handful of website screenshots on a fresh tab to be incredibly inefficient and, frankly, ugly.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;So several years ago I created an HTML file with a pretty list of links and used that as my new tab page. When I tired of editing HTML just to add a link to the page, I made it into a single page application that saved the links to the browser’s local storage. That became &lt;a href=&quot;http://start.blakewatson.com/&quot;&gt;Start&lt;/a&gt;, a downloadable file or hosted page that I offered for free. I used it happily for several years, but struggled to keep my links synced between browsers.&lt;/p&gt;
&lt;h2 id=&quot;introducing-a-fine-start&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#introducing-a-fine-start&quot;&gt;Introducing A Fine Start&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Fast forward to 2017. I began rewriting Start from scratch with the goal of adding user accounts for syncing links. I released &lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; to some testers in June and now it’s publicly available as a &lt;a href=&quot;https://afinestart.me/bookmarks/&quot;&gt;hosted web page&lt;/a&gt; or &lt;a href=&quot;https://chrome.google.com/webstore/detail/a-fine-start-a-concise-ne/kcgjmjiklcchbhljelchjdpoooccmhcn&quot;&gt;Chrome extension&lt;/a&gt;. The idea is simple—you open a new tab, you get a list of links, grouped and sorted to your liking.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/laptop.png&quot; alt=&quot;A MacBook showing the A Fine Start page—three columns, each made up of lists of links to various websites&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; is for getting in, then getting out. It doesn’t force your brain to parse tiny images of websites or stress over which sites to “pin” in place. Add whatever groups and links you want. They’re stored in local storage, and you can import/export them to share them between browsers and devices. No emails, accounts, or payments necessary.&lt;/p&gt;
&lt;p&gt;For $5 a month, you can get a Premium account that will automatically keep your links synced.&lt;/p&gt;
&lt;h2 id=&quot;the-zen-of-the-list&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#the-zen-of-the-list&quot;&gt;The zen of the list&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ve been using this system in one form or another for years now and whenever I’m using a web browser without it, I feel lost. I suspect the keyboard-oriented folks couldn’t care less about what shows up in a new tab—they’re going to immediately invoke the location bar’s search and suggest functionality. But for the click-happy (or OCD organizers) among us, seeing a neatly displayed list of links is supremely satisfying. No messy screenshots and no BS.&lt;/p&gt;
&lt;p&gt;Designers, you may appreciate the minimal aesthetic with an obsession over typography. This is far from a plain old ugly list of links. I went through several iterations of list, link, heading styles to get the right look. The design embraces cool gray for negative space which is intended to make it feel more like a native tool than a web page.&lt;/p&gt;
&lt;h2 id=&quot;try-it-out&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#try-it-out&quot;&gt;Try it out&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://afinestart.me/&quot;&gt;A Fine Start&lt;/a&gt; is absolutely free for the majority of its functionality. Give it a shot and &lt;a href=&quot;https://blakewatson.com/contact&quot;&gt;let me know&lt;/a&gt; what you think. If you love it and want to use it everywhere, consider grabbing an account. I think you’ll enjoy it as much as I do.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Including a custom URL, which is how you may use &lt;a href=&quot;https://afinestart.me/bookmarks/&quot;&gt;A Fine Start&lt;/a&gt; in Safari. &lt;a href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Have a list of news sites? Now you have &lt;a href=&quot;https://unitscale.com/mb/bomb-in-the-garden/&quot;&gt;notoriously bad web design&lt;/a&gt; plastered all over every new tab. &lt;a href=&quot;https://blakewatson.com/journal/my-answer-to-the-gratuitous-new-tab-page/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Why I left Facebook</title>
      <link href="https://blakewatson.com/journal/why-i-left-facebook/"/>
      <updated>2017-07-04T23:02:56Z</updated>
      <id>https://blakewatson.com/journal/why-i-left-facebook/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I joined Facebook in April 2005 shortly after it was opened up to Mississippi State students. Despite being an early Facebook supporter, I deleted my account back in May 2017. Privacy and ethical concerns rank at the top of the list, while other factors—my waning usage of the service for example—also contribute.&lt;/p&gt;
&lt;h2 id=&quot;the-price-of-facebook-is-privacy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#the-price-of-facebook-is-privacy&quot;&gt;The price of Facebook is privacy&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Companies that do business in big data have astonishing access to information about you, much of which you provide to them yourself and the rest they collect by any number of creepy but (presumably) legal ways. In the case of Facebook—which recently hit the &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_social_platforms_with_at_least_100_million_active_users&quot;&gt;2 billion user mark&lt;/a&gt;—we’re talking data mining on a truly massive scale. Facebook is building complex profiles on you, gathering thousands of data points, and even &lt;a href=&quot;https://www.propublica.org/article/facebook-doesnt-tell-users-everything-it-really-knows-about-them&quot;&gt;purchasing information it doesn’t already know about you from data brokers&lt;/a&gt;. Even if you aren’t a Facebook user, they likely still keep a record of you in the form of &lt;a href=&quot;http://mashable.com/2013/06/26/facebook-shadow-profiles&quot;&gt;shadow profiles&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You’ve seen those Facebook like buttons and “Sign-in with Facebook” buttons on other websites? Yeah, that’s Facebook tracking you around the internet. Their &lt;a href=&quot;https://www.facebook.com/about/privacy&quot;&gt;privacy policy&lt;/a&gt; says clearly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We collect information when you visit or use third-party websites and apps that use our Services (like when they offer our Like button or Facebook Log In or use our measurement and advertising services). This includes information about the websites and apps you visit, your use of our Services on those websites and apps, as well as information the developer or publisher of the app or website provides to you or us.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you were tasked to write down everything you think Facebook knows about you, you probably would get a lot of it right by just thinking through it. Like, &lt;em&gt;of course&lt;/em&gt; they have all the information I give them. And with a bit more reasoning you might realize &lt;em&gt;of course they track me when I use their widgets on other websites&lt;/em&gt;. But they also collect information that you would likely not consider.&lt;/p&gt;
&lt;p&gt;For example, &lt;a href=&quot;http://www.slate.com/articles/technology/future_tense/2013/12/facebook_self_censorship_what_happens_to_the_posts_you_don_t_publish.html&quot;&gt;Facebook tracks posts and comments even before you post them&lt;/a&gt;. That time you were about to tell somebody off for their dumb opinion but then, in a sudden rapture of empathy, decided not to hit “Send”—Facebook collects that.&lt;/p&gt;
&lt;p&gt;John Gruber of Daring Fireball &lt;a href=&quot;https://daringfireball.net/linked/2017/06/22/navistone-form-data&quot;&gt;writes&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sending form data surreptitiously is morally wrong, and everyone knows it.&lt;/p&gt;
&lt;p&gt;This might sound hyperbolic, but I mean it: I think we’d be better off if JavaScript had never been added to web browsers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a person who writes a lot of JavaScript and (mostly) enjoys it, this makes me sad because while I enjoy the interactivity it provides, I must concede that big data companies and advertisers have weaponized it against us.&lt;/p&gt;
&lt;p&gt;In addition to the information Facebook collects about you, there are the entities that your data gets shared with—all those silly games and quizzes people are adding to their account are making off with all sorts of information about you.&lt;/p&gt;
&lt;p&gt;At this point, you may be thinking, &lt;em&gt;So what? I know they’re tracking me. So is Google and every other website. Who cares?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It’s a valid question. All of this tracking might not personally, directly affect you in a bad way now—aside from a lot of creepy advertisements—but unfortunately, the trend is getting worse. And there are negative consequences to the pillaging of your privacy by Big Data:&lt;/p&gt;
&lt;p&gt;Tech entrepreneur and educator, Salim Virani, &lt;a href=&quot;http://www.salimvirani.com/facebook/&quot;&gt;writes&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you’ve ever admitted to something illegal in a private Facebook message, or even mentioned your support for a political cause, this can be used against you in the future, especially by another country’s government. You may find yourself arrested for being at the wrong place at the wrong time, or just pulled aside at the airport one day, now facing jail time because you revealed you did something that government considers illegal 5 years ago. One New York comedian had a SWAT team break into his house based on a joke post. Law enforcement often acts in error, and you’re giving them more power and more chance of error. You’re loading the gun, pointing it at your head, and handing it to every trigger-happy “enforcer” who’s willing to buy your data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your privacy and that of your loved ones is at all important to you, now is the time to start taking steps to maintain it.&lt;/p&gt;
&lt;h2 id=&quot;emotional-manipulation-and-the-slot-machine-effect&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#emotional-manipulation-and-the-slot-machine-effect&quot;&gt;Emotional manipulation and the slot machine effect&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Over time, we’ve become hooked on the social validation Facebook (and other services) provide. Before I hit the delete button on my account, one of the last things that kept me on Facebook—after I had largely stopped posting and reading the News Feed—was simply checking my notifications. I unconsciously craved that little hit of happiness one gets when they see, &lt;em&gt;So-and-so liked your post&lt;/em&gt;. But that’s not real happiness. It’s an unhealthy addiction.&lt;/p&gt;
&lt;p&gt;Julian Morgans of Vice &lt;a href=&quot;https://www.vice.com/en_us/article/vv5jkb/the-secret-ways-social-media-is-built-for-addiction&quot;&gt;writes&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Former Google designer and ethicist Tristan Harris lays out the most common ways we’re being manipulated on his blog. And as he explains, all of them use something called intermittent variable rewards.&lt;/p&gt;
&lt;p&gt;The easiest way to understand this term is by imagining a slot machine. You pull the lever to win a prize, which is an intermittent action linked to a variable reward. Variable meaning you might win, or you might not. In the same way, you refresh your Facebook updates to see if you’ve won. Or you swipe right on Tinder to see if you’ve won.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not only can Facebook use its power to manipulate our emotions, it experiments on its users without their knowledge and consent. In 2012, Facebook worked with researchers to carry out a large-scale study that &lt;a href=&quot;https://www.theguardian.com/technology/2014/jun/29/facebook-users-emotions-news-feeds&quot;&gt;manipulated the emotions&lt;/a&gt; of its subjects. From the &lt;a href=&quot;http://www.pnas.org/content/111/24/8788.full&quot;&gt;paper’s abstract&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In an experiment with people who use Facebook, we test whether emotional contagion occurs outside of in-person interaction between individuals by reducing the amount of emotional content in the News Feed. When positive expressions were reduced, people produced fewer positive posts and more negative posts; when negative expressions were reduced, the opposite pattern occurred.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When you are reading your News Feed, you might reasonably assume that it consists of posts from your network of friends, roughly ordered by date. In reality, it’s a sick concoction of friends’ posts and advertisements, strategically and algorithmically generated to manipulate you for the purpose of keeping you interacting with Facebook’s real customers—its advertisers.&lt;/p&gt;
&lt;p&gt;Even if you know about all this stuff—or at least have a vague idea—you’ll likely find it difficult to do anything about it. Because of network effects, Facebook has something of an emotional lock-in on us. The very thought of leaving Facebook can induce a serious case of FOMO in even the most anti-social &lt;a href=&quot;https://www.16personalities.com/intj-personality&quot;&gt;INTJ&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;ripping-off-the-band-aid&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#ripping-off-the-band-aid&quot;&gt;Ripping off the band-aid&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s the thing. You won’t be as outcast and lonely as you think. Your friends—and I know this is hard to believe—are still your friends in real life. You just won’t get notifications of what they ate on their lunch break. Unless, you know, you follow them in the myriad other ways it’s possible to do so online. Look, I’m not saying we have a mass exodus from the interwebs. I’m talking about one website.&lt;/p&gt;
&lt;p&gt;Not that they make it easy. Don’t be fooled into merely “deactivating” your account—something that people often do because they need a break from Facebook&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Deactivation means you artificially disappear from Facebook until you get ready to come back. Then it’s all waiting for you right where you left off. To delete your account fully, you will need to jump through the following hoops.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dig into the support section to find &lt;a href=&quot;https://www.facebook.com/help/224562897555674/&quot;&gt;this page that tells you how to delete your account&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Optionally, you can download your data from Facebook. I didn’t find this to be very useful and I’m pretty sure there’s some stuff missing. But that said, it helps ease the fear of loss that accompanies this process.&lt;/li&gt;
&lt;li&gt;Finally—and this is the hardest part—you must pass Facebook’s test of your fortitude by not logging into your account during the 14-day grace period leading up to the deletion of your account.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s difficult to know how much of your information will be truly deleted. You have to go into this process with the assumption that it’s none. I personally hold on to a hope that some of the basic stuff is deleted (e.g., my posts) but I realize that’s naive. Think of it more in terms of not providing them any more information than what they already have.&lt;/p&gt;
&lt;h2 id=&quot;replacing-facebook&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#replacing-facebook&quot;&gt;Replacing Facebook&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is going to look differently for everyone, depending on their preferences and their friends’ preferences. For me that could mean spending more time on Twitter. Twitter is in many ways in the same boat as Facebook as far as advertising goes, but at least you know from the outset that everything is public&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I’m hoping that it will mean more time making content like this for my website—yes, it turns out there’s already a built-in way to have your own “profile” where you can post things and people can “follow” you, and it’s called Your Own Website™—but I know better than to promise content.&lt;/p&gt;
&lt;p&gt;If you are interested in short form posting, check out the recently Kickstarted &lt;a href=&quot;https://micro.blog/&quot;&gt;Micro.blog&lt;/a&gt; platform. Not sure if I will be using it much but I like the idea.&lt;/p&gt;
&lt;p&gt;Of course, I would be remiss not to mention that you can simply call your friends and talk to them—your smartphone comes with a built-in app that will let you do just that. You can even get together in the same location and hang out (novel, I know!).&lt;/p&gt;
&lt;h2 id=&quot;the-extra-mile&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#the-extra-mile&quot;&gt;The extra mile&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This article is all about Facebook, but I have also scaled back my use of other big services like Google. For search, I recommend &lt;a href=&quot;https://duckduckgo.com/&quot;&gt;DuckDuckGo&lt;/a&gt;, a search engine that doesn’t track you. Instead of using a free email provider, I use &lt;a href=&quot;https://www.pobox.com/&quot;&gt;Pobox&lt;/a&gt;, an independent email provider, for $50 a year.&lt;/p&gt;
&lt;p&gt;A lot of folks use ad blockers—which I highly recommend—and I also use a browser extension called &lt;a href=&quot;https://www.ghostery.com/&quot;&gt;Ghostery&lt;/a&gt; that blocks all the various trackers you find all over the web&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, if you are interested in reading more, here are a few articles that I found invaluable while putting this article together.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.salimvirani.com//facebook/&quot;&gt;Get your loved ones off Facebook.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vickiboykis.com/2017/02/01/what-should-you-think-about-when-using-facebook/&quot;&gt;What should you think about when using Facebook?&lt;/a&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The fact that this feature exists tells you it’s a potentially harmful thing to have in your life. &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Yes, I’m ignoring the fact that some people prefer private Twitter accounts. &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It blocks a lot of third-party JavaScript that you might want to allow. Personally, I start off by blocking everything but then I allow services like Gravatar that I don’t mind running. It’s worth mentioning that Ghostery has an opt-in setting for gathering data about the trackers you encounter (tracking the trackers). Personally, I recommend not opting in as it’s unclear exactly what’s being tracked and how that data’s being used. &lt;a href=&quot;https://blakewatson.com/journal/why-i-left-facebook/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>An ode to web pages</title>
      <link href="https://blakewatson.com/journal/an-ode-to-web-pages/"/>
      <updated>2017-03-04T23:01:30Z</updated>
      <id>https://blakewatson.com/journal/an-ode-to-web-pages/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Last year, when I read this &lt;a href=&quot;https://hackernoon.com/how-it-feels-to-learn-javascript-in-2016-d3a717dd577f&quot;&gt;satire of modern web development&lt;/a&gt;, I chuckled. When the &lt;a href=&quot;http://www.haneycodes.net/npm-left-pad-have-we-forgotten-how-to-program/&quot;&gt;npm left-pad dependency controversy&lt;/a&gt; left many npm projects unable to build, I questioned what we were doing. These days, I just chalk it up to the maturing of web development. It’s the JavaScript renaissance, right?&lt;/p&gt;
&lt;p&gt;But in my heart of hearts, I miss the early days, when I was nothing more than a website enthusiast. Back then, there was nothing to npm install. No dependency trees. Version control meant adding the suffix “-old” to file names. I thought my code-editor with built-in FTP to be the ultimate tool because you could edit files directly on the server! Local development was as simple as editing a doc in a folder. Did you know that web browsers are perfectly happy to open an HTML file on your computer? No domain, hosting, MAMP, Vagrant, or database necessary.&lt;/p&gt;
&lt;h2 id=&quot;all-of-our-profiles-look-alike&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#all-of-our-profiles-look-alike&quot;&gt;All of our profiles look alike&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before social media, before apps, before vlogs, blogs, and the like, there were &lt;em&gt;web pages&lt;/em&gt;. Often, someone would refer to their online profile as their “home page.” I kind of feel bad for web developers just starting out who may not experience the wonderful delight of designing and building their own unique and quirky online abodes. Don’t get me wrong, many developers have personal websites. But they are just boring blogs and portfolio sites&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; like the one you are reading now. They’re well designed, minimal, or look like Bootstrap. But they &lt;a href=&quot;https://blakewatson.com/journal/hard-refresh&quot;&gt;used to be alive&lt;/a&gt; with personality.&lt;/p&gt;
&lt;p&gt;Before social media monoliths made us into little mechanical turks for advertising platforms, we had organic homes on the web. We had pages that were ours. And they could look however you wanted. And you could write whatever you wanted on there. And there wasn’t a “report/flag” button. There weren’t weirdos tagging themselves in your photos. There weren’t advertisements if you didn’t want them. There weren’t comments if you didn’t want them. There were no photo dimensions to adhere to. No 140-character limits. No BS. Or lots of BS. Either way, the choice was yours because you owned your site and you could do whatever you wanted.&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-a-web-page&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#how-to-make-a-web-page&quot;&gt;How to make a web page&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spoiler alert. &lt;em&gt;This is still a perfectly valid way to make a website&lt;/em&gt;. Just because you see a bunch of tutorials about hard-to-use frameworks, libraries, and services doesn’t mean you &lt;em&gt;have&lt;/em&gt; to use them. Just because you &lt;em&gt;can&lt;/em&gt; use build scripts, CDNs, Sass, Less, React, Gulp, Grunt, WordPress, Laravel, Django, Rails, or whatever it is, doesn’t mean you &lt;em&gt;must&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you are just starting out, here’s an &lt;a href=&quot;https://css-tricks.com/get-started-web-design/&quot;&gt;excellent guide&lt;/a&gt; by Chris Coyier on CSS-Tricks that will get you through the technical hoops of getting a domain and a web server. From the there you can start making a web page.&lt;/p&gt;
&lt;p&gt;Don’t know HTML or CSS? Try this &lt;a href=&quot;http://www.htmldog.com/guides/html/beginner/&quot;&gt;beginner guide&lt;/a&gt; on HTML Dog.&lt;/p&gt;
&lt;h2 id=&quot;challenge&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#challenge&quot;&gt;Challenge&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Make a web page. Make it about anything you want. Put it on your web server or hosting service. Don’t have web hosting? You can get some at &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; for $0.25&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;. Then share it with the world.&lt;/p&gt;
&lt;h2 id=&quot;addendum&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#addendum&quot;&gt;Addendum&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chris Hawkes, a developer I follow on YouTube, happened to post a video that coincides with my point here that web development has gotten kind of crazy.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/uhlnkbpq86k&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m exaggerating to make a point. I don’t want a resurgence of sparkling MySpace profiles any more than you do. &lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; doesn’t have an affiliate program—I get nothing by linking to them. I do it because they are awesome. &lt;a href=&quot;https://blakewatson.com/journal/an-ode-to-web-pages/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>2016: My year in review</title>
      <link href="https://blakewatson.com/journal/2016-my-year-in-review/"/>
      <updated>2016-12-31T22:55:09Z</updated>
      <id>https://blakewatson.com/journal/2016-my-year-in-review/</id>
      <content xml:lang="en" type="html">&lt;style&gt;
	.inline-svg {  
    max-width: 100%;  
	}

	#ex1-logo-wrap * {  
			transform-box: fill-box;  
	}

	#ex1-btn:hover rect {  
			fill: #ccc;  
			cursor: pointer;  
	}
&lt;/style&gt;
&lt;p&gt;With 2016 coming to a close I wanted to take a moment of reflection — a temporary reprieve from thinking about the future — to review some of my accomplishments on the year. This year had quite a few firsts. I joined the Apple Developer Program and published my first-ever app to the Mac App Store. Working with the &lt;a href=&quot;http://madg.com/people&quot;&gt;Mad Genius team&lt;/a&gt;, I had the pleasure of being part of some cool website launches this year. And in the area of professional growth, I picked up some new skills I have been wanting to tackle for a while now.&lt;/p&gt;
&lt;h2 id=&quot;but-first%2C-some-non-tech-stuff&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#but-first%2C-some-non-tech-stuff&quot;&gt;But first, some non-tech stuff&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This not-so-humble article concerns itself largely with the web-related stuff I’m into, but other notable events in my larger circle deserve a mention. Among them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A new treatment for spinal muscular atrophy became the first one to get FDA approval.&lt;/li&gt;
&lt;li&gt;My brother, a former Spanish lecturer and PhD student, switched careers abruptly to join Mad Genius &lt;a href=&quot;https://web.archive.org/web/20210306070538/https://madg.com/person/matt-watson/&quot;&gt;as a web developer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The weirdest U.S. presidential election I’ve ever seen happened.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;critical-hit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#critical-hit&quot;&gt;Critical hit&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This year, I started a Dungeons &amp;amp; Dragons group with some friends online. Being an app junkie, I searched many an hour for apps to make my life as the dungeon master easier. Running a D&amp;amp;D game takes a lot of dice rolling as it turns out, and none of the dice rolling apps I tried worked like I wanted. Being the designer/developer I am, I decided to make my own. I’ve always wanted to make an app and sell it. Thanks to an awesome tool called &lt;a href=&quot;http://electron.atom.io/&quot;&gt;Electron&lt;/a&gt;, I was able to take the web coding skills I already had and repurpose them into making a Mac application. The result is &lt;a href=&quot;http://d20.blakewatson.com/&quot;&gt;d20&lt;/a&gt;, a design-y RPG dice roller.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/d20-main-1024x640.png&quot; alt=&quot;D20 main&quot; width=&quot;1024&quot; height=&quot;640&quot; class=&quot;size-large wp-image-113&quot; /&gt;
&lt;figcaption&gt;d20 - an elegant, powerful dice roller&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It’s not a grand technical achievement, but it &lt;em&gt;is&lt;/em&gt; the culmination of a lot of nights and weekends. Let’s be honest, I made this for me and didn’t expect to win any awards or make a ton of money. But I am thrilled with the sixty-something dollars of sales I’ve made since releasing the app in 2016. It was also a fun challenge to execute all the branding surrounding a publicly released app — from the app icon and App Store description to the marketing and support website. I won’t go into a lot of detail here, but if you are interested, check out &lt;a href=&quot;https://itunes.apple.com/us/app/d20-an-rpg-dice-roller/id1156311750&quot;&gt;d20 on the App Store&lt;/a&gt; (or kick the tires with the &lt;a href=&quot;https://www.blakewatson.com/dice-roller&quot;&gt;free web-based version&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;everything-old-is-new-again&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#everything-old-is-new-again&quot;&gt;Everything old is new again&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/blakewatson.com-2016-1024x713.png&quot; alt=&quot;Blakewatson.com 2016&quot; width=&quot;1024&quot; height=&quot;713&quot; class=&quot;size-large wp-image-114&quot; /&gt;
&lt;figcaption&gt;The newly designed homepage of blakewatson.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Over a year ago, I wrote about how my &lt;a href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/&quot;&gt;website’s design was not original&lt;/a&gt;. The situation has improved, though, because in October, I redesigned my site. According to my estimates, this constitutes the thirteenth iteration of &lt;a href=&quot;http://blakewatson.com/&quot;&gt;blakewatson.com&lt;/a&gt; since I first bought the domain in 2005. After fellow Genius &lt;a href=&quot;https://madg.com/person/shawn-palmer/&quot;&gt;Shawn Palmer&lt;/a&gt; designed a new (awesome) mark for me last year, I knew I needed a website that would do the new mark justice. With limited available time, this was the best I could do. :-)&lt;/p&gt;
&lt;h2 id=&quot;a-banner-year-in-the-labs&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#a-banner-year-in-the-labs&quot;&gt;A banner year in the labs&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;2016 was my first full calendar year as an Interactive Designer at Mad Genius. We launched a lot a of great websites for our clients this year and I am incredibly proud an honored to have been a part of that. Among the &lt;a href=&quot;https://blakewatson.com/work&quot;&gt;sites I had a hand&lt;/a&gt; in were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mississippi Organ Recovery Agency’s “It’s Super Easy” campaign&lt;/li&gt;
&lt;li&gt;Mid-South Medical Imaging&lt;/li&gt;
&lt;li&gt;Reformed Theological Seminary’s 50th anniversary microsite&lt;/li&gt;
&lt;li&gt;Laguna Blue, a new microfiber towel manufacturer&lt;/li&gt;
&lt;li&gt;Mississippi Center for Plastic Surgery - a website Matt and I got to build together&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Last but not least, I had the honor of leading the development side of the &lt;a href=&quot;https://madg.com/&quot;&gt;new Mad Genius website&lt;/a&gt;. All in all, it’s been a fun year in the labs and I can’t wait to see what 2017 has in store for us.&lt;/p&gt;
&lt;h2 id=&quot;lessons-learned&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#lessons-learned&quot;&gt;Lessons learned&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In addition to making a lot of stuff this year, I learned a few things. A bunch of projects I’ve been working on lately have given me the opportunity to experiment with &lt;a href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/journal/svg-logo-animation-with-anime-js/&quot;&gt;web animation&lt;/a&gt;. That’s been fun to play around with and it’s a useful tool in the interactive designer’s tool belt.&lt;/p&gt;
&lt;p&gt;&lt;svg class=&quot;inline-svg&quot; viewBox=&quot;0 0 779 462&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;g id=&quot;Page-1&quot; stroke=&quot;none&quot; stroke-width=&quot;1&quot; fill=&quot;none&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;g id=&quot;ex1&quot;&gt;&lt;rect id=&quot;Rectangle&quot; fill=&quot;#ECECEC&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;779&quot; height=&quot;462&quot;&gt;&lt;/rect&gt;&lt;g id=&quot;ex1-logo-wrap&quot; transform=&quot;translate(247.000000, 128.000000)&quot; fill=&quot;#4A4A4A&quot;&gt;&lt;g id=&quot;ex1-logo&quot;&gt;&lt;polyline id=&quot;ex1-logo-left&quot; points=&quot;128.120102 119.371031 78.15047 119.371031 0.0706686047 0.831846523 50.0403004 0.831846523 128.120102 119.371031&quot;&gt;&lt;/polyline&gt;&lt;path d=&quot;M79.692916,0.842154364 L64.9465262,23.4594724 L78.2720615,33.5492566 L89.7512064,16.1198082 C89.7512064,16.1198082 89.7469961,16.1109726 89.7388051,16.0938385 L142.940763,96.8651319 L167.930082,58.9405276 L129.655758,0.831846523 L79.6861265,0.831846523 L79.692916,0.842154364 Z M118.118069,104.182254 C118.118069,104.182254 120.014825,110.500181 121.277926,112.418287 C123.348836,115.563107 128.120102,119.371031 128.120102,119.371031 L142.918246,96.8470983 L129.295487,87.2081535 L118.118069,104.182254 Z&quot; id=&quot;ex1-logo-middle&quot;&gt;&lt;/path&gt;&lt;polyline id=&quot;ex1-logo-right&quot; points=&quot;207.722049 119.371031 157.752418 119.371031 235.832219 0.831846523 285.801851 0.831846523 207.722049 119.371031&quot;&gt;&lt;/polyline&gt;&lt;/g&gt;&lt;/g&gt;&lt;g id=&quot;ex1-btn&quot; transform=&quot;translate(320.000000, 354.000000)&quot;&gt;&lt;rect id=&quot;Rectangle-2&quot; fill=&quot;#D9D9D9&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;141&quot; height=&quot;48&quot; rx=&quot;8&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M41.0909515,29.2404273 L43.0173685,29.2404273 L38.1911869,19 L37.7856254,19 L33,29.2404273 L34.9466951,29.2404273 L35.8997646,27.0503953 L40.0973259,27.0503953 L41.0909515,29.2404273 Z M37.9072939,22.4472726 L38.0492404,22.4472726 L39.4078713,25.4889836 L36.568941,25.4889836 L37.9072939,22.4472726 Z M46.2821384,19 L45.6737962,19 L45.6737962,29.2404273 L47.539379,29.2404273 L47.539379,22.6703314 L47.7016036,22.6703314 L54.4744802,29.3418177 L55.0828225,29.3418177 L55.0828225,19.1013904 L53.2172397,19.1013904 L53.2172397,25.6917644 L53.0550151,25.6917644 L46.2821384,19 Z M61.0445762,19.1013904 L59.1789934,19.1013904 L59.1789934,29.2404273 L61.0445762,29.2404273 L61.0445762,19.1013904 Z M73.880597,23.5220105 L74.6917199,29.2404273 L76.5775808,29.2404273 L74.9553349,19 L74.5497734,19 L70.6563832,26.2392724 L70.595549,26.2392724 L66.5602123,19 L66.1546508,19 L64.5324049,29.2404273 L66.4182658,29.2404273 L67.2293887,23.5220105 L67.2902229,23.5220105 L70.4738805,29.3418177 L70.6361051,29.3418177 L73.8197627,23.5220105 L73.880597,23.5220105 Z M86.9193985,29.2404273 L88.8458155,29.2404273 L84.0196339,19 L83.6140724,19 L78.828447,29.2404273 L80.7751421,29.2404273 L81.7282116,27.0503953 L85.9257728,27.0503953 L86.9193985,29.2404273 Z M83.7357409,22.4472726 L83.8776874,22.4472726 L85.2363183,25.4889836 L82.397388,25.4889836 L83.7357409,22.4472726 Z M98.7820717,20.7033582 L98.7820717,19.1013904 L89.9813876,19.1013904 L89.9813876,20.7033582 L93.4286602,20.7033582 L93.4286602,29.2404273 L95.294243,29.2404273 L95.294243,20.7033582 L98.7820717,20.7033582 Z M108.637216,19.1013904 L101.844061,19.1013904 L101.844061,29.2404273 L108.839996,29.2404273 L108.839996,27.6384595 L103.709644,27.6384595 L103.709644,24.8806414 L108.028873,24.8806414 L108.028873,23.2786736 L103.709644,23.2786736 L103.709644,20.7033582 L108.637216,20.7033582 L108.637216,19.1013904 Z&quot; id=&quot;animate&quot; fill-opacity=&quot;0.649003623&quot; fill=&quot;#000000&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;I’ve also been pushing forward with my command-line and server administration skills. Without getting too into the weeds, let’s just say I now know how to set up a basic web server on a Linux computer and put it on the internet!&lt;/p&gt;
&lt;h2 id=&quot;happy-new-year&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/2016-my-year-in-review/#happy-new-year&quot;&gt;Happy New Year&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I hope you will take a moment to think about your own accomplishments in 2016. If you have ever thought about getting into programming or web development, there’s no time like the present. Why don’t you go ahead and make it a New Year’s resolution? If you need help, &lt;a href=&quot;https://blakewatson.com/contact&quot;&gt;email me&lt;/a&gt; and I will try to point you in the right direction.&lt;/p&gt;
&lt;p&gt;But no matter what you are into, whatever your passion may be, keep it up.&lt;/p&gt;
&lt;p&gt;Here’s to a new year.&lt;/p&gt;
&lt;script&gt;
document.querySelector(&#39;#ex1-btn&#39;).addEventListener(&#39;click&#39;, function() {
		exampleAnimation(&quot;#ex1&quot;);  
});

function exampleAnimation(id) {
  anime({  
    targets: id+&quot;-logo&quot;,  
    opacity: 0,  
    easing: &quot;easeOutSine&quot;,  
    duration: 300,  

    complete: function() {  
      document.querySelector(id+&quot;-logo-middle&quot;).style.opacity = &#39;0&#39;;
      document.querySelector(id+&quot;-logo-left&quot;).style.transform = &quot;translateX(100%)&quot;;
      document.querySelector(id+&quot;-logo-right&quot;).style.transform = &quot;translateX(-100%)&quot;
      document.querySelector(id+&quot;-logo&quot;).style.transform = &quot;translateY(50%)&quot;;

      anime({  
        targets: id+&quot;-logo&quot;,  
        translateY: [&quot;50%&quot;, &quot;0%&quot;],  
        opacity: 1,  
        easing: &quot;easeOutSine&quot;,  
        delay: 500,  
        complete: function() {  
          anime({  
            targets: [id+&quot;-logo-left&quot;, id+&quot;-logo-right&quot;],  
            translateX: function(el, index) {  
              if(el.getAttribute(&#39;id&#39;) === id.substring(1)+&quot;-logo-left&quot;) {  
                return [&quot;100%&quot;, &quot;0%&quot;];  
              } else {  
                return [&quot;-100%&quot;, &quot;0%&quot;];  
              }
            },  
            easing: &quot;easeInOutQuad&quot;,  
            duration: 500  
          });

          anime({  
            targets: id+&quot;-logo-middle&quot;,  
            opacity: 1,
            easing: &quot;easeInOutExpo&quot;,  
          });  
        }
      });  
    }
  });  
}
&lt;/script&gt;</content>
    </entry>
    <entry>
      <title>SVG logo animation with Anime.js</title>
      <link href="https://blakewatson.com/journal/svg-logo-animation-with-anime-js/"/>
      <updated>2016-10-14T22:05:03Z</updated>
      <id>https://blakewatson.com/journal/svg-logo-animation-with-anime-js/</id>
      <content xml:lang="en" type="html">&lt;style&gt;
	.inline-svg {  
    max-width: 100%;  
	}

	#ex1-logo-wrap *, #ex2-logo-wrap * {  
			transform-box: fill-box;  
	}

	#ex1-btn:hover rect, #ex2-btn:hover rect {  
			fill: #ccc;  
			cursor: pointer;  
	}
&lt;/style&gt;
&lt;p&gt;Many a library exist for animation on the web these days. &lt;a href=&quot;http://anime-js.com/&quot;&gt;Anime&lt;/a&gt; is my favorite. It&amp;#8217;s approachable,[^1] comes with decent &lt;a href=&quot;https://github.com/juliangarnier/anime&quot;&gt;documentation&lt;/a&gt; and &lt;a href=&quot;http://codepen.io/collection/XLebem/&quot;&gt;examples&lt;/a&gt;, and packs phenomenal cosmic power in an &lt;a href=&quot;https://youtu.be/SfTfXLLJlzM&quot;&gt;itty bitty living space&lt;/a&gt; (9.15 KB minified).&lt;/p&gt;
&lt;p&gt;Anime lets you run animations on just about anything — CSS, SVG, DOM attributes — but what I love most about it is its ability to run animations on individual CSS &lt;code&gt;transform&lt;/code&gt; properties. With Anime, you can write something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;anime({
	// specfiy a string selector, a DOM node, or an array of those things
	targets: &#39;.a-dead-body&#39;,
	// we can animate on a specific transform property
	translateX: 100,
	// as many of these as you want
	rotate: 180,
	// doesn’t have to be a transform, anything numerically-based will do
	color: &#39;rgb(255,0,0)&#39;,
	// how long?
	duration: 1000,
	// cool built-in easing curves
	easing: &#39;easeOutElastic&#39;,
	// do something afterward
	complete: function() {
		console.log(&#39;It’s alive!&#39;);
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which could produce something like this:&lt;/p&gt;
&lt;p class=&quot;code-a-dead-body&quot; style=&quot;width: 120px&quot; onclick=&quot;codeAnimateDeadBody()&quot;&gt;💀 Click me!&lt;/p&gt;
&lt;p&gt;See?&lt;/p&gt;
&lt;p&gt;Of course, that&amp;#8217;s a nearly useless animation. Let me show you a real-world example — the logo animation on the home page of this very website.&lt;/p&gt;
&lt;h2 id=&quot;animatingmylogo&quot;&gt;Animating my logo&lt;/h2&gt;
&lt;p&gt;My logo (or &lt;a href=&quot;https://blakewatson.com/journal/new-personal-mark/&quot;&gt;personal mark&lt;/a&gt;, as I like to call it) is an SVG that resembles the initials &amp;#8220;bw&amp;#8221; stylized to look like a futuristic &amp;#8220;w&amp;#8221;. Take a look below and, when you are ready, click the animate button to see how we want our final animation to look.&lt;/p&gt;
&lt;p&gt;&lt;svg class=&quot;inline-svg&quot; viewBox=&quot;0 0 779 462&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;g id=&quot;Page-1&quot; stroke=&quot;none&quot; stroke-width=&quot;1&quot; fill=&quot;none&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;g id=&quot;ex1&quot;&gt;&lt;rect id=&quot;Rectangle&quot; fill=&quot;#ECECEC&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;779&quot; height=&quot;462&quot;&gt;&lt;/rect&gt;&lt;g id=&quot;ex1-logo-wrap&quot; transform=&quot;translate(247.000000, 128.000000)&quot; fill=&quot;#4A4A4A&quot;&gt;&lt;g id=&quot;ex1-logo&quot;&gt;&lt;polyline id=&quot;ex1-logo-left&quot; points=&quot;128.120102 119.371031 78.15047 119.371031 0.0706686047 0.831846523 50.0403004 0.831846523 128.120102 119.371031&quot;&gt;&lt;/polyline&gt;&lt;path d=&quot;M79.692916,0.842154364 L64.9465262,23.4594724 L78.2720615,33.5492566 L89.7512064,16.1198082 C89.7512064,16.1198082 89.7469961,16.1109726 89.7388051,16.0938385 L142.940763,96.8651319 L167.930082,58.9405276 L129.655758,0.831846523 L79.6861265,0.831846523 L79.692916,0.842154364 Z M118.118069,104.182254 C118.118069,104.182254 120.014825,110.500181 121.277926,112.418287 C123.348836,115.563107 128.120102,119.371031 128.120102,119.371031 L142.918246,96.8470983 L129.295487,87.2081535 L118.118069,104.182254 Z&quot; id=&quot;ex1-logo-middle&quot;&gt;&lt;/path&gt;&lt;polyline id=&quot;ex1-logo-right&quot; points=&quot;207.722049 119.371031 157.752418 119.371031 235.832219 0.831846523 285.801851 0.831846523 207.722049 119.371031&quot;&gt;&lt;/polyline&gt;&lt;/g&gt;&lt;/g&gt;&lt;g id=&quot;ex1-btn&quot; transform=&quot;translate(320.000000, 354.000000)&quot;&gt;&lt;rect id=&quot;Rectangle-2&quot; fill=&quot;#D9D9D9&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;141&quot; height=&quot;48&quot; rx=&quot;8&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M41.0909515,29.2404273 L43.0173685,29.2404273 L38.1911869,19 L37.7856254,19 L33,29.2404273 L34.9466951,29.2404273 L35.8997646,27.0503953 L40.0973259,27.0503953 L41.0909515,29.2404273 Z M37.9072939,22.4472726 L38.0492404,22.4472726 L39.4078713,25.4889836 L36.568941,25.4889836 L37.9072939,22.4472726 Z M46.2821384,19 L45.6737962,19 L45.6737962,29.2404273 L47.539379,29.2404273 L47.539379,22.6703314 L47.7016036,22.6703314 L54.4744802,29.3418177 L55.0828225,29.3418177 L55.0828225,19.1013904 L53.2172397,19.1013904 L53.2172397,25.6917644 L53.0550151,25.6917644 L46.2821384,19 Z M61.0445762,19.1013904 L59.1789934,19.1013904 L59.1789934,29.2404273 L61.0445762,29.2404273 L61.0445762,19.1013904 Z M73.880597,23.5220105 L74.6917199,29.2404273 L76.5775808,29.2404273 L74.9553349,19 L74.5497734,19 L70.6563832,26.2392724 L70.595549,26.2392724 L66.5602123,19 L66.1546508,19 L64.5324049,29.2404273 L66.4182658,29.2404273 L67.2293887,23.5220105 L67.2902229,23.5220105 L70.4738805,29.3418177 L70.6361051,29.3418177 L73.8197627,23.5220105 L73.880597,23.5220105 Z M86.9193985,29.2404273 L88.8458155,29.2404273 L84.0196339,19 L83.6140724,19 L78.828447,29.2404273 L80.7751421,29.2404273 L81.7282116,27.0503953 L85.9257728,27.0503953 L86.9193985,29.2404273 Z M83.7357409,22.4472726 L83.8776874,22.4472726 L85.2363183,25.4889836 L82.397388,25.4889836 L83.7357409,22.4472726 Z M98.7820717,20.7033582 L98.7820717,19.1013904 L89.9813876,19.1013904 L89.9813876,20.7033582 L93.4286602,20.7033582 L93.4286602,29.2404273 L95.294243,29.2404273 L95.294243,20.7033582 L98.7820717,20.7033582 Z M108.637216,19.1013904 L101.844061,19.1013904 L101.844061,29.2404273 L108.839996,29.2404273 L108.839996,27.6384595 L103.709644,27.6384595 L103.709644,24.8806414 L108.028873,24.8806414 L108.028873,23.2786736 L103.709644,23.2786736 L103.709644,20.7033582 L108.637216,20.7033582 L108.637216,19.1013904 Z&quot; id=&quot;animate&quot; fill-opacity=&quot;0.649003623&quot; fill=&quot;#000000&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;In order to achieve this effect, we need to break the logo into three distinct pieces:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;#ex1-logo&lt;/code&gt;
 &lt;ul&gt;
 &lt;li&gt;&lt;code&gt;#ex1-logo-left&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;#ex1-logo-middle&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;#ex1-logo-right&lt;/code&gt;&lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First we need to get our logo into its pre-animation state — the starting point. To do that, we need to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure the whole logo starts off transparent&lt;/li&gt;
&lt;li&gt;Explicitly make the middle piece transparent&lt;/li&gt;
&lt;li&gt;Bump the entire logo down by half of its height&lt;/li&gt;
&lt;li&gt;Swap the left and right pieces&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Update 10&amp;#8211;23&amp;#8211;2017: Safari 11 requires that &lt;code&gt;transform-box: fill-box;&lt;/code&gt; be set on each piece in order to translate each piece by a percentage of its own height or width.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;$(&#39;#ex1-logo&#39;).css({
	&#39;transform&#39;: &#39;translateY(50%)&#39;,
	&#39;opacity&#39;: 0
});
$(&#39;#ex1-logo-middle&#39;).css(&#39;opacity&#39;, 0);
$(&#39;#ex1-logo-left&#39;).css(&#39;transform&#39;, &#39;translateX(100%)&#39;);
$(&#39;#ex1-logo-right&#39;).css(&#39;transform&#39;, &#39;translateX(-100%)&#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Good. If you could see it at this point, it would resemble an arrow pointing upward. Now we can bring in Anime.&lt;/p&gt;
&lt;p&gt;First, we want to move the whole logo group back up to its original position while simultaneously fading it in.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;anime({
	targets: &#39;#ex1-logo&#39;,
	translateY: [&#39;50%&#39;, &#39;0%&#39;], // start value, end value
	opacity: 1,
	easing: &#39;easeOutSine&#39;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sweet. As soon as that animation finishes, we want to do two things simultaneously:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Move the left and right pieces back to their original positions&lt;/li&gt;
&lt;li&gt;Fade in the middle piece&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can latch on to Anime&amp;#8217;s &lt;code&gt;complete&lt;/code&gt; callback in order to run code after the first animation finishes.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;anime({
	targets: &#39;#ex1-logo&#39;,
	translateY: [&#39;50%&#39;, &#39;0%&#39;], // start value, end value
	opacity: 1,
	easing: &#39;easeOutSine&#39;,
	complete: function() {
		// MORE ANIME HERE!
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#8217;m going to fire two different Anime animations inside that callback. First, the hard one — swapping the left and right pieces back to their original position.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;anime({
	targets: &#39;#ex1-logo&#39;,
	translateY: [&#39;50%&#39;, &#39;0%&#39;], // start value, end value
	opacity: 1,
	easing: &#39;easeOutSine&#39;,
	complete: function() {
		anime({
			targets: [&#39;#ex1-logo-left&#39;, &#39;#ex1-logo-right&#39;],
			translateX: function(el, index) {
				if($(el).attr(&#39;id&#39;) === &#39;ex1-logo-left&#39;) {
					return [&#39;100%&#39;, &#39;0%&#39;];
				} else {
					return [&#39;-100%&#39;, &#39;0%&#39;];
				}
			},
			easing: &#39;easeInOutQuad&#39;,
			duration: 500
		});
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What?! We have two targets? And what is this &lt;code&gt;translateX&lt;/code&gt; voodoo?&lt;/p&gt;
&lt;p&gt;A very cool feature of Anime is its ability to accept a function instead of a static value. The function will run for each target specified, and automatically recieves the current DOM element (&lt;code&gt;el&lt;/code&gt;) and the zero-based index of the current target. Very similar to a jQuery &lt;code&gt;.each()&lt;/code&gt; function, if you are familiar with that.&lt;/p&gt;
&lt;p&gt;For each target, we can now do some logic to return back the value we want. In our case, we want to give the left piece different start and end points from the right piece. That&amp;#8217;s done with an &lt;code&gt;if&lt;/code&gt; statement that checks the element&amp;#8217;s &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On to the next part. We&amp;#8217;re just going to run another Anime animation at (roughly) the same time by calling it right after this one.&lt;/p&gt;
&lt;p&gt;This is the final state of our animation code, so here it is all together now:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;$(&#39;#ex1-logo&#39;).css({
	&#39;transform&#39;: &#39;translateY(50%)&#39;,
	&#39;opacity&#39;: 0
});
$(&#39;#ex1-logo-middle&#39;).css(&#39;opacity&#39;, 0);
$(&#39;#ex1-logo-left&#39;).css(&#39;transform&#39;, &#39;translateX(100%)&#39;);
$(&#39;#ex1-logo-right&#39;).css(&#39;transform&#39;, &#39;translateX(-100%)&#39;);

anime({
	targets: &#39;#ex1-logo&#39;,
	translateY: [&#39;50%&#39;, &#39;0%&#39;], // start value, end value
	opacity: 1,
	easing: &#39;easeOutSine&#39;,
	complete: function() {
		anime({
			targets: [&#39;#ex1-logo-left&#39;, &#39;#ex1-logo-right&#39;],
			translateX: function(el, index) {
				if($(el).attr(&#39;id&#39;) === &#39;ex1-logo-left&#39;) {
					return [&#39;100%&#39;, &#39;0%&#39;];
				} else {
					return [&#39;-100%&#39;, &#39;0%&#39;];
				}
			},
			easing: &#39;easeInOutQuad&#39;,
			duration: 500
		});

		anime({
			targets: &#39;#ex1-logo-middle&#39;,
			opacity: 1,
			easing: &#39;easeInOutExpo&#39;,
		});
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lastly, we fade in the middle piece, and we even use a fancy smancy easing curve to do it.&lt;/p&gt;
&lt;h2 id=&quot;onemoretimewithfeeling&quot;&gt;One more time, with feeling&lt;/h2&gt;
&lt;p&gt;The final animation looks something like this, as we saw earlier.&lt;/p&gt;
&lt;p&gt;&lt;svg class=&quot;inline-svg&quot; viewBox=&quot;0 0 779 462&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;g id=&quot;Page-1&quot; stroke=&quot;none&quot; stroke-width=&quot;1&quot; fill=&quot;none&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;g id=&quot;ex2&quot;&gt;&lt;rect id=&quot;Rectangle&quot; fill=&quot;#ECECEC&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;779&quot; height=&quot;462&quot;&gt;&lt;/rect&gt;&lt;g id=&quot;ex2-logo-wrap&quot; transform=&quot;translate(247.000000, 128.000000)&quot; fill=&quot;#4A4A4A&quot;&gt;&lt;g id=&quot;ex2-logo&quot;&gt;&lt;polyline id=&quot;ex2-logo-left&quot; points=&quot;128.120102 119.371031 78.15047 119.371031 0.0706686047 0.831846523 50.0403004 0.831846523 128.120102 119.371031&quot;&gt;&lt;/polyline&gt;&lt;path d=&quot;M79.692916,0.842154364 L64.9465262,23.4594724 L78.2720615,33.5492566 L89.7512064,16.1198082 C89.7512064,16.1198082 89.7469961,16.1109726 89.7388051,16.0938385 L142.940763,96.8651319 L167.930082,58.9405276 L129.655758,0.831846523 L79.6861265,0.831846523 L79.692916,0.842154364 Z M118.118069,104.182254 C118.118069,104.182254 120.014825,110.500181 121.277926,112.418287 C123.348836,115.563107 128.120102,119.371031 128.120102,119.371031 L142.918246,96.8470983 L129.295487,87.2081535 L118.118069,104.182254 Z&quot; id=&quot;ex2-logo-middle&quot;&gt;&lt;/path&gt;&lt;polyline id=&quot;ex2-logo-right&quot; points=&quot;207.722049 119.371031 157.752418 119.371031 235.832219 0.831846523 285.801851 0.831846523 207.722049 119.371031&quot;&gt;&lt;/polyline&gt;&lt;/g&gt;&lt;/g&gt;&lt;g id=&quot;ex2-btn&quot; transform=&quot;translate(320.000000, 354.000000)&quot;&gt;&lt;rect id=&quot;Rectangle-2&quot; fill=&quot;#D9D9D9&quot; x=&quot;0&quot; y=&quot;0&quot; width=&quot;141&quot; height=&quot;48&quot; rx=&quot;8&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M41.0909515,29.2404273 L43.0173685,29.2404273 L38.1911869,19 L37.7856254,19 L33,29.2404273 L34.9466951,29.2404273 L35.8997646,27.0503953 L40.0973259,27.0503953 L41.0909515,29.2404273 Z M37.9072939,22.4472726 L38.0492404,22.4472726 L39.4078713,25.4889836 L36.568941,25.4889836 L37.9072939,22.4472726 Z M46.2821384,19 L45.6737962,19 L45.6737962,29.2404273 L47.539379,29.2404273 L47.539379,22.6703314 L47.7016036,22.6703314 L54.4744802,29.3418177 L55.0828225,29.3418177 L55.0828225,19.1013904 L53.2172397,19.1013904 L53.2172397,25.6917644 L53.0550151,25.6917644 L46.2821384,19 Z M61.0445762,19.1013904 L59.1789934,19.1013904 L59.1789934,29.2404273 L61.0445762,29.2404273 L61.0445762,19.1013904 Z M73.880597,23.5220105 L74.6917199,29.2404273 L76.5775808,29.2404273 L74.9553349,19 L74.5497734,19 L70.6563832,26.2392724 L70.595549,26.2392724 L66.5602123,19 L66.1546508,19 L64.5324049,29.2404273 L66.4182658,29.2404273 L67.2293887,23.5220105 L67.2902229,23.5220105 L70.4738805,29.3418177 L70.6361051,29.3418177 L73.8197627,23.5220105 L73.880597,23.5220105 Z M86.9193985,29.2404273 L88.8458155,29.2404273 L84.0196339,19 L83.6140724,19 L78.828447,29.2404273 L80.7751421,29.2404273 L81.7282116,27.0503953 L85.9257728,27.0503953 L86.9193985,29.2404273 Z M83.7357409,22.4472726 L83.8776874,22.4472726 L85.2363183,25.4889836 L82.397388,25.4889836 L83.7357409,22.4472726 Z M98.7820717,20.7033582 L98.7820717,19.1013904 L89.9813876,19.1013904 L89.9813876,20.7033582 L93.4286602,20.7033582 L93.4286602,29.2404273 L95.294243,29.2404273 L95.294243,20.7033582 L98.7820717,20.7033582 Z M108.637216,19.1013904 L101.844061,19.1013904 L101.844061,29.2404273 L108.839996,29.2404273 L108.839996,27.6384595 L103.709644,27.6384595 L103.709644,24.8806414 L108.028873,24.8806414 L108.028873,23.2786736 L103.709644,23.2786736 L103.709644,20.7033582 L108.637216,20.7033582 L108.637216,19.1013904 Z&quot; id=&quot;animate&quot; fill-opacity=&quot;0.649003623&quot; fill=&quot;#000000&quot;&gt;&lt;/path&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;If that seemed like a lot, don&amp;#8217;t worry — it kind of is. It might seem a bit odd at first, but it&amp;#8217;s just a matter of thinking through what you want to do. Think about it in terms of a starting point and an ending point. Then write out in words what you want to accomplish. If you get stuck, &lt;a href=&quot;https://github.com/juliangarnier/anime&quot;&gt;the docs&lt;/a&gt; are your friend.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Want to see more tutorials?&lt;/strong&gt; &lt;a href=&quot;https://blakewatson.com/contact&quot;&gt;Get in touch&lt;/a&gt; and let me know what you would like to see.&lt;/p&gt;
&lt;script&gt;
document.querySelector(&#39;#ex1-btn&#39;).addEventListener(&#39;click&#39;, function() {
		exampleAnimation(&quot;#ex1&quot;);  
});

document.querySelector(&#39;#ex2-btn&#39;).addEventListener(&#39;click&#39;, function() {  
		exampleAnimation(&quot;#ex2&quot;);  
});

function codeAnimateDeadBody() {  
	anime({  
			targets: &quot;.code-a-dead-body&quot;,  
			translateX: 100,  
			rotate: 180,  
			color: &quot;rgb(255,0,0)&quot;,  
			duration: 1000,  
			easing: &quot;easeOutElastic&quot;,  
			complete: function() {  
					console.log(&quot;It&#39;s alive!&quot;);  
			}
	});  
}

function exampleAnimation(id) {
  anime({  
    targets: id+&quot;-logo&quot;,  
    opacity: 0,  
    easing: &quot;easeOutSine&quot;,  
    duration: 300,  

    complete: function() {  
      document.querySelector(id+&quot;-logo-middle&quot;).style.opacity = &#39;0&#39;;
      document.querySelector(id+&quot;-logo-left&quot;).style.transform = &quot;translateX(100%)&quot;;
      document.querySelector(id+&quot;-logo-right&quot;).style.transform = &quot;translateX(-100%)&quot;
      document.querySelector(id+&quot;-logo&quot;).style.transform = &quot;translateY(50%)&quot;;

      anime({  
        targets: id+&quot;-logo&quot;,  
        translateY: [&quot;50%&quot;, &quot;0%&quot;],  
        opacity: 1,  
        easing: &quot;easeOutSine&quot;,  
        delay: 500,  
        complete: function() {  
          anime({  
            targets: [id+&quot;-logo-left&quot;, id+&quot;-logo-right&quot;],  
            translateX: function(el, index) {  
              if(el.getAttribute(&#39;id&#39;) === id.substring(1)+&quot;-logo-left&quot;) {  
                return [&quot;100%&quot;, &quot;0%&quot;];  
              } else {  
                return [&quot;-100%&quot;, &quot;0%&quot;];  
              }
            },  
            easing: &quot;easeInOutQuad&quot;,  
            duration: 500  
          });

          anime({  
            targets: id+&quot;-logo-middle&quot;,  
            opacity: 1,
            easing: &quot;easeInOutExpo&quot;,  
          });  
        }
      });  
    }
  });  
}
&lt;/script&gt;</content>
    </entry>
    <entry>
      <title>A decade of Mac</title>
      <link href="https://blakewatson.com/journal/a-decade-of-mac/"/>
      <updated>2016-08-08T21:59:00Z</updated>
      <id>https://blakewatson.com/journal/a-decade-of-mac/</id>
      <content xml:lang="en" type="html">&lt;p&gt;In 2006 I switched to the Mac after being a Windows user for about 10 years. December this year marks my 10-year anniversary as a Mac user. When I realized that, it got me to thinking about what it is that I have loved so much about the Mac, and why I’m still just as excited about it now as I was on the day I switched.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/first-mac.jpg&quot; alt=&quot;First mac&quot; title=&quot;first-mac.jpg&quot; border=&quot;0&quot; /&gt;
&lt;figcaption&gt;My first Mac&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;But to talk about my decade with Mac requires a look back at my decade of PCs.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; Like many people my age I was a kid when my family got its first personal computer. It was a classic beige behemoth with a weighty CRT monitor and the computing power of a cheap flip phone.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; And it was &lt;em&gt;spectacular&lt;/em&gt;. I spent hours just playing with the stuff on the Windows 95 disk – you know, the one that had that Weezer music video on it.&lt;/p&gt;
&lt;p&gt;It wasn’t long before we got America Online and experienced the Internet for the very first time. After that, I went through a series of desktops and then laptops.&lt;/p&gt;
&lt;p&gt;The worst one I had was a Gateway laptop that came with the worst operating system in the history of operating systems: Windows ME. It was the most unreliable computer I’ve ever had. Luckily, I was able to get a pretty good Dell laptop for college. That’s when the seed was planted. It had not been long since I bought this little MP3 player. The one that could “fit a thousand songs in your pocket.” The one with the click wheel. The Apple iPod.&lt;/p&gt;
&lt;p&gt;After my web browser (Firefox at the time), my favorite program on my computer was the one made by Apple: iTunes. I used it to manage my iPod of course but I also used it regularly to listen to music on my computer. I was fascinated by its ease-of-use and its stability. It was just nice. It’s easy to take that for granted now, in a world of well-designed apps for an array of various devices. But at the time my expectations of what it meant for a program to be “nice” was established entirely by programs like Microsoft Word, EditPad Pro, and Macromedia Fireworks. I’m not even saying these programs are bad (Winamp was awesome), just that they worked under a different philosophy of user experience.&lt;/p&gt;
&lt;figure&gt;
 &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/blake-aeanola08-macbook.jpg&quot; alt=&quot;Me at An Event Apart, MacBook open and ready for the next talk to start.&quot; border=&quot;0&quot; /&gt;
&lt;figcaption&gt;An Event Apart, 2008, with my MacBook&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The thing about PCs was that it seemed you needed to be tech savvy in order to do anything cool with them. Even when purchasing one, you needed to know all about computer specs to make sure you got something good and you weren’t paying too much. For people like me – people who enjoy tinkering and figuring things out – that was fine, even fun. But for a lot of people, dealing with a crappy PC was a crappy time.&lt;/p&gt;
&lt;p&gt;So when it came time to upgrade my computer for grad school, I decided just for kicks to take a look at Apple. Coming from the PC world my instinct was to go straight to the tech specs and start crunching the numbers to analyze the bang-to-buck ratio. But Apple’s marketing folks are good at their jobs and I started realizing that a computer was more than the sum of its parts – it’s about what you can do with it and the experience that you have while using it. More and more I became convinced that I wanted to try the Mac.&lt;/p&gt;
&lt;p&gt;In December 2006 I booted up for the very first time my 20-inch Apple iMac running Mac OS X Tiger. It took me about two weeks to get use to just moving around the system and doing basic tasks. But once I got the hang of it I realized that the effort was really in unlearning the bad habits from my PC days. I realized that the Mac was &lt;em&gt;easier&lt;/em&gt;. The Apple-made apps that came with the Mac are powerful and gorgeous. My creativity exploded as I began using the iLife suite and stunning third-party apps to make art of all kinds – musical, visual, and written.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/two-macs.jpg&quot; alt=&quot;A very messy pair of tables in the living room, each with a Mac. The top of my head is just visible above my Apple Cinema Display.&quot; /&gt;
&lt;figcaption&gt;Sometimes creation is messy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;On the Mississippi State campus I started to see MacBooks popping up all over the place. The Starbucks in the student union was full of them. We were all having the same idea. The Mac was taking over. As a web designer and developer I began to see a move to the Mac as the new dev machine. Incredible web authoring tools like Panic’s Transmit and Coda brought the high standard of Apple user experience to development tools. The standard of quality I so frequently encounter in Mac apps has made me notice the difference between good and bad design - a skill I now employ regularly as an interactive designer.&lt;/p&gt;
&lt;p&gt;This user experience was not an accident. This was years of research and work by the folks at Apple to prioritize and make the decisions that would lead to that experience. A classic example of Apple’s philosophy on user experience is their original &lt;em&gt;Human Interface Guidelines&lt;/em&gt; from 1987.&lt;/p&gt;
&lt;blockquote&gt;
To be in charge, the user must be informed. When, for example, the user initiates an operation, immediate feedback confirms that the operation is being carried out, and (eventually) then it’s finished… This communication should be brief, direct, and expressed in the user’s vocabulary rather than the programmer’s.
&lt;/blockquote&gt;
&lt;p class=&quot;caption&quot;&gt;&amp;mdash; Apple’s Human Interface Guidelines, 1987, pg. 7&lt;/p&gt;
&lt;p&gt;The Mac has given me new expectations of what a computer is. Do I still look at the tech specs? Of course I do. Once a nerd, always a nerd. But now I expect my computer to be friendly. I expect it to be fun. I expect, as a user and a customer, to be treated with respect. I expect for the details to be right. For the hardware to be as beautiful as the software. I expect a perfect balance of form and function. I expect there to be no such thing as a “bad computer.”&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2020/07/mbp-writing.jpg&quot; alt=&quot;An over-the-shoulder shot of my screen, the blank page of a novel staring back at me.&quot; /&gt;
&lt;figcaption&gt;Distraction-free writing during NaNoWriMo.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Obviously, the Mac versus Windows versus Linux debate can never be settled. There is no winner. Your choice of computer is going to depend on your individual requirements and preferences. But for me, the Mac is the highest form of personal computing available. As I sit here and write this on a 27-inch retina iMac, I’m amazed by how far the computer has come from its days as a glorified calculator occupying entire rooms. And that’s not to mention the tablet and pocket-sized computers that (I suppose) are even more popular than their desk-suited counterparts.&lt;/p&gt;
&lt;p&gt;Despite frequent claims that mobile devices are going to kill the computer as we know it, that iPhones and iPads will kill the Mac, I’m excited for the future of the Mac. I think it’s going to continue to carve itself out a place for power users and people who use it to get stuff done — whether work or play. Despite Windows’ recent improvements (and Ubuntu in the Linux world) I haven’t seen a machine I would rather use than the Mac. And I suspect it’s going to be that way for a long time.&lt;/p&gt;
&lt;p&gt;My decade of Mac saw many historic moments, a few of which include the iPhone launch, the iPad launch, and the death of Steve Jobs. It saw the switch to Intel, the introduction of the App Stores, the birth of retina. It saw my first novel draft and my first paying website gig. It’s been a wild, weird ten years for me and my Mac, but I wouldn’t trade them for anything.&lt;/p&gt;
&lt;p&gt;Here’s to the next ten.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/retina-mac-1.jpg&quot; alt=&quot;A photo of my new retina iMac with a draft of this article on screen.&quot; /&gt;
&lt;figcaption&gt;Writing this article on the 27-inch retina iMac&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m kind of guesstimating that we got our first household computer in 1996. Feels right, anyway. &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Actually, our first computer had a 90 MHz processor, which is less than half the power of the LG 450 flip phone I just bought which has a 230 MHz processor. &lt;a href=&quot;https://blakewatson.com/journal/a-decade-of-mac/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>How to lessen your exposure to Google</title>
      <link href="https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/"/>
      <updated>2016-05-01T21:53:07Z</updated>
      <id>https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’ll occasionally mention in passing the various alternatives to Google that I use for web browsing, search, and email, but I haven’t talked about it in much detail. I sometimes get funny looks from people when they hear me say that I try to avoid using Google services — like I’m some kind of internet conspiracy theorist. But it’s really not about Google being some kind of big evil company. And it’s not about getting rid of Google altogether. And it’s not even really all about Google. The services and social networks we use every day (e.g., Facebook, Twitter, etc.) collect data about us and use it to target ads at us as well as to inform the development of their own platforms.&lt;/p&gt;
&lt;p&gt;This isn’t necessarily an inherently bad thing, but I prefer to take some measures to maintain my personal privacy. What follows is not some kind of idealist manifesto, but rather a measured response to the data collection and user tracking practices that have become an industry standard.&lt;/p&gt;
&lt;p&gt;Aside from privacy, I think it’s always good to foster competition. Instead of just defaulting to Google for whatever it is you’re trying to do, consider the other options available.&lt;/p&gt;
&lt;h2 id=&quot;search&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#search&quot;&gt;Search&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Perhaps the easiest way to lessen your exposure to Google is to use a different search engine. All major web browsers that I know of allow you to set the default search engine – even Google Chrome. My personal favorite is &lt;a href=&quot;https://duckduckgo.com/&quot;&gt;DuckDuckGo&lt;/a&gt;. DuckDuckGo labels itself as the search engine that &lt;a href=&quot;http://donttrack.us/&quot;&gt;doesn’t track you&lt;/a&gt;. The folks at DuckDuckGo go out of their way to protect your privacy. Unlike many services, reading their &lt;a href=&quot;https://duckduckgo.com/privacy&quot;&gt;privacy policy&lt;/a&gt; does not give you that icky, deal-with-the-devil feeling.&lt;/p&gt;
&lt;p&gt;In addition to helping you preserve your anonymity in search, it also has some pretty cool features. Like Google, it will often provide answers to your search directly at the top of the page in the form of Instant Answers. There’s some cool stuff here (a &lt;a href=&quot;https://duckduckgo.com/?q=stopwatch&amp;amp;ia=stopwatch&quot;&gt;stopwatch&lt;/a&gt;!) and if you’re the tinkering type, you can even &lt;a href=&quot;http://duckduckhack.com/&quot;&gt;contribute your own&lt;/a&gt; Instant Answers.&lt;/p&gt;
&lt;p&gt;My favorite feature is what DuckDuckGo calls &lt;a href=&quot;https://duckduckgo.com/bang&quot;&gt;bangs&lt;/a&gt;. Let’s say you’re on DuckDuckGo but what you really intend to do is click the first Wikipedia result that shows up. Simply add &lt;code&gt;!w&lt;/code&gt; to the end of your search query and you will be automatically sent over to Wikipedia’s search page. DuckDuckGo has bangs for many other services – including Google (&lt;code&gt;!g&lt;/code&gt;) and Google Images (&lt;code&gt;!gi&lt;/code&gt;), for those times that you really just need Google. Other favorites include YouTube (&lt;code&gt;!yt&lt;/code&gt;), Amazon (&lt;code&gt;!a&lt;/code&gt;), and Creative Commons (&lt;code&gt;!cc&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Here’s some more features of DuckDuckGo in a more illustrated format:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://donttrack.us/&quot;&gt;Don’t track us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dontbubble.us/&quot;&gt;Escape your search engine’s filter bubble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://privatebrowsingmyths.com/&quot;&gt;Private browsing myths&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;web-browsing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#web-browsing&quot;&gt;Web browsing&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I catch a lot of flak for this sometimes, but I like to use Apple’s Safari (instead of Google Chrome) for general web browsing as well as web development. I don’t have any kind of smoking gun regarding Google Chrome and the data it collects. And I’m pretty sure Safari also collects a good bit of information that it sends to Apple. To me the difference is that Google is primarily an advertising company and Apple is primarily a device manufacturer. I feel like Google has a higher incentive than Apple to collect my personal information and use it in ways that I might not be okay with. I do still install Google Chrome on my system as it is an excellent web browser and sometimes I do need it in the course of my job, but my default browser is Safari.&lt;/p&gt;
&lt;p&gt;Since I use several Apple devices, I like using Safari to sync my browsing history in order to reduce the amount of typing and searching I have to do to find things like articles I’ve read previously, etc. Again, I know I’m sending a lot of information to Apple, but I just trust Apple more than Google.&lt;/p&gt;
&lt;p&gt;And if you don’t really trust Google or Apple, you can always go with &lt;a href=&quot;https://mozilla.org/firefox&quot;&gt;Mozilla Firefox&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;ad-blocking-and-browsing-privacy&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#ad-blocking-and-browsing-privacy&quot;&gt;Ad blocking and browsing privacy&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ads are not all bad, but many websites will run ads and third-party JavaScript that can collect a lot of data, track you, and make web pages bloated and sluggish. Instead of opting in by default to any arbitrary ad or script, I like to turn on ad blocking and then whitelist the services or third-party scripts that I don’t mind running. I install two browser extensions to make this happen: &lt;a href=&quot;https://getadblock.com/&quot;&gt;AdBlock&lt;/a&gt; and &lt;a href=&quot;https://www.ghostery.com/&quot;&gt;Ghostery&lt;/a&gt;. AdBlock does exactly what it says on the tin. Ghostery goes a bit further and blocks all those annoying social widgets and things that tend to slow web pages down. If there’s a widget I really want to see, I can tell Ghostery to allow it on every website or just the one I’m currently viewing. Using ad blockers is not all about getting rid of ads. It’s about protecting your privacy and browsing the web more securely.&lt;/p&gt;
&lt;p&gt;Be warned, though, that some websites will put up a wall if they detect that you are using an ad blocker. They may ask you to pay up or otherwise disable the ad blocker on their site if you want to continue browsing. I’ve never hit one of these walls on a website that I wasn’t willing to give up. So when I encounter this practice I usually just leave and get my information elsewhere. I realize that people who run these websites need to make money, but the onus is on them to figure out how to do that in a way acceptable to the consumer. If I choose to go elsewhere, that’s my choice to make. It’s no different than going to the car lot across the street because the one you’re at isn’t giving you a good deal.&lt;/p&gt;
&lt;h2 id=&quot;email&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#email&quot;&gt;Email&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m saving the best for last because one of the biggest switches I’ve made — and the one I’m probably most excited about – is my email provider. Most people probably don’t give much thought to who their email provider is. And it’s most likely going to be Google or Apple (or maybe Yahoo or one’s ISP). The upside to these services is that they don’t cost you anything. Well, you know, other than your privacy. And not to mention the fact that these services can block you from your account at any time making it impossible for you to access your email. This &lt;a href=&quot;http://www.sheltron.net/2011/05/does-google-hate-me-has-google-banned-my-ip-address-why-is-gmail-blocked-from-my-computer/&quot;&gt;has happened&lt;/a&gt; to people.&lt;/p&gt;
&lt;p&gt;You might not think about it, but email is critical to your online identity. I worked briefly in customer support for a well-known tech company and we would get so many requests from people who had forgotten their passwords or had otherwise lost access to their accounts. We would tell them that if they could email us from the email address they joined our service with, then that would be enough verification for us to believe that they were who they professed to be and we could help them reset their passwords. But not everyone would have access to the email address that they had initially signed up with. Because of that we had to tell many people that we could not give them access to the accounts they wanted.&lt;/p&gt;
&lt;p&gt;That was just one service. But think about it. Your email is the hub for every online service that you’ve ever registered with. That’s a lot of responsibility, and a lot of trust that you need to put in your email provider.&lt;/p&gt;
&lt;p&gt;So several years ago I switched to &lt;a href=&quot;https://www.pobox.com/&quot;&gt;Pobox&lt;/a&gt;, a service that is only about email.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; There’s no ads because you pay a yearly fee for your email service. At the time of this writing the cost is just $50 a year (which is about $4 a month). This makes &lt;em&gt;you&lt;/em&gt; the customer — not some advertiser that wants your data. If you need help with anything, you can get very timely and helpful support (try getting that from Google – unless you’re an advertiser they’re not going to help you much). You can set up your email account with your own domain name if you choose. This is nice because once you have an email address like &lt;a href=&quot;mailto:name@yoursite.com&quot;&gt;name@yoursite.com&lt;/a&gt;, you can keep that email address forever, even if you decide to use a different email service in the future. You’ll be able to take that name with you because it’s your own domain name.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;making-a-choice&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#making-a-choice&quot;&gt;Making a choice&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are just a few of the areas in which I’ve moved away from Google and taken steps to assert some control over my online assets. It’s worth mentioning that I’m not boycotting Google and I still use them at various times for various things. What I’m saying is make a choice — any choice, even Google — over using Google services by default without thought.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Pobox was recently acquired by &lt;a href=&quot;https://www.fastmail.com/&quot;&gt;FastMail&lt;/a&gt;, another independent email provider. I’m usually wary of such acquisitions, but in this case it was a good move and it helps ensure that there will be a solid alternative to Big Data email providers for years to come. &lt;a href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;If you’ve been handing out an “@gmail.com” address to people, it can be hard to switch email services when you suddenly decide you don’t want Google bots reading your email. I recommend switching to an email address you control and forwarding your GMail to it. &lt;a href=&quot;https://blakewatson.com/journal/how-to-lessen-your-exposure-to-google/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Better UI components with KnockoutJS</title>
      <link href="https://blakewatson.com/journal/better-ui-components-with-knockoutjs/"/>
      <updated>2016-01-17T21:51:13Z</updated>
      <id>https://blakewatson.com/journal/better-ui-components-with-knockoutjs/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I used to be a vanilla JavaScript guy, mainly because I took an excellent JavaScript course at Mississippi State. I put off learning jQuery until I couldn’t ignore it any more. And I’m glad I finally did learn it. It became my standard way of adding interactivity and various enhancements to my websites. But when a friend of mine asked me to help him write a smartphone app, I knew I needed something more powerful. New to the world of JavaScript libraries, I chose the one that looked like the easiest to learn—&lt;a href=&quot;http://knockoutjs.com/&quot;&gt;KnockoutJS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;beyond-jquery&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#beyond-jquery&quot;&gt;Beyond jQuery&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a lot of people, JavaScript &lt;em&gt;is&lt;/em&gt; jQuery. And it’s no wonder, what with its ability to easily target multiple elements and change them to your heart’s content. Even today, that covers enough ground for most projects I work on.&lt;/p&gt;
&lt;p&gt;That said, there are times when your UI relies heavily on a changing data set—a filterable product list, for instance. In those cases you &lt;em&gt;could&lt;/em&gt; use jQuery (or even vanilla JavaScript). But you would likely be better served by a JavaScript library that offers some form of &lt;em&gt;data binding&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Conceptually, data binding refers to your data set being connected to your interface on a deep level. To continue our example of the filterable product list, imagine that you select a product category from a dropdown and the product list automatically knows how to adjust to your selection. Libraries that feature data binding can help you achieve this effect with less code than you might write with jQuery or vanilla JavaScript.&lt;/p&gt;
&lt;h2 id=&quot;knockout-vs-angular-vs-react&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#knockout-vs-angular-vs-react&quot;&gt;Knockout vs Angular vs React&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m sure there are myriad articles out there that go in depth on the pros and cons of the various popular JavaScript libraries. I’m not going to do that here, partly because I don’t know enough about them all. But I have used Angular to make a single-page application. In my experience, Angular needs to control everything. I’m sure that’s not necessarily the case, but I found it easier to drop in Knockout where I needed it. To me, it seemed like Angular had more coding overhead. And you’re constantly trying to figure out the “Angular way” of doing things.&lt;/p&gt;
&lt;p&gt;I don’t have experience with React, but from talks and tutorials I’ve seen, it’s verbose and convoluted. Obviously, people use it,&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; but if you aren’t a full-blown programmer it’s going to suck for a while as you climb the steep learning curve. And I am not convinced it’s &lt;em&gt;that&lt;/em&gt; much better than Knockout.&lt;/p&gt;
&lt;h2 id=&quot;knockout-and-wordpress&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#knockout-and-wordpress&quot;&gt;Knockout and WordPress&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since Knockout is fairly easy to drop in as needed, it makes a good pairing with WordPress. While you could certainly write a completely JavaScript-based WordPress theme, you’ll miss out on all the work that the WordPress templating system does for you. Knockout excels at giving you powerful data binding right where you need it.&lt;/p&gt;
&lt;p&gt;Back to our example of a filterable product list. Using either &lt;code&gt;wp_localize_script&lt;/code&gt; or a WordPress-flavored AJAX call, you could supply Knockout with the product data it needs and let it loop through and fill out the page for you. That way, you get the data binding magic for speedy front-end filtering, while using standard WordPress template code everywhere else.&lt;/p&gt;
&lt;h2 id=&quot;a-simple-demo&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#a-simple-demo&quot;&gt;A simple demo&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ugh. Don’t you hate when people drone on and on without giving you any code samples. :-) If you have made it this far, I think you deserve a demo.&lt;/p&gt;
&lt;h3 id=&quot;a-simple-filterable-list&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#a-simple-filterable-list&quot;&gt;A simple filterable list&lt;/a&gt;&lt;/h3&gt;
&lt;p data-height=&quot;400&quot; data-theme-id=&quot;0&quot; data-slug-hash=&quot;ZQXNmK&quot; data-default-tab=&quot;result&quot; data-user=&quot;blakewatson&quot; class=&quot;codepen&quot;&gt;See the Pen &lt;a href=&quot;http://codepen.io/blakewatson/pen/ZQXNmK/&quot;&gt;Simple list filter with KnockoutJS&lt;/a&gt; by Blake Watson (&lt;a href=&quot;http://codepen.io/blakewatson&quot;&gt;@blakewatson&lt;/a&gt;) on &lt;a href=&quot;http://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://assets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;In this demo, we’re supplying Knockout with an array of data—a list of people and the categories they belong to.&lt;/p&gt;
&lt;p&gt;First, we’re writing a &lt;code&gt;PeopleViewModel&lt;/code&gt; object. Then, on line 41, we’re instantiating it and passing it to Knockout for processing.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PeopleViewModel&lt;/code&gt; has three properties. The first, &lt;code&gt;people&lt;/code&gt;, is just a standard array of objects that we’re passing in.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;selectedCategory&lt;/code&gt; is a Knockout &lt;em&gt;observable&lt;/em&gt;, which means that Knockout watches it for changes and updates our UI accordingly. We’re using this property to tell us which radio button is checked at any given point. In the HTML, we’ve declared that we want the radio buttons bound to this observable. So when a radio button is checked, Knockout automatically updates &lt;code&gt;selectedCategory&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;filteredPeople&lt;/code&gt; is a &lt;em&gt;computed observable&lt;/em&gt;. It uses our &lt;code&gt;selectedCategory&lt;/code&gt; observable, but adds some logic. In this case, it checks the selected category and then returns an array of people objects based on that value. In other words, it does the filtering for us. Why didn’t we just use a regular function? Well, since we used an observable, Knockout watches it for changes. Here comes the magic: Knockout knows that if &lt;code&gt;selectedCategory&lt;/code&gt; changes, then &lt;code&gt;filteredPeople&lt;/code&gt; also changes. This is called &lt;em&gt;dependency tracking&lt;/em&gt;, and when we use observables, Knockout handles all of that tracking for us.&lt;/p&gt;
&lt;p&gt;If you flip back over to the HTML, you’ll see that we’re using a &lt;code&gt;foreach&lt;/code&gt; binding to loop through the array we get from &lt;code&gt;filteredPeople&lt;/code&gt;. Inside our loop, each list item has access to the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;category&lt;/code&gt; of the current people object. We’re setting the text of the list item to be the value of &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully, you can see where this is going. Since our HTML elements are bound to our observables, and since Knockout watches observables for changes, we get a UI that &lt;em&gt;reacts&lt;/em&gt; (heh) to the changes in our data, as well as data that reacts to changes in our UI—like when you select a different radio button. This is called &lt;em&gt;two-way data binding&lt;/em&gt; and it’s what puts the punch in Knockout.&lt;/p&gt;
&lt;h2 id=&quot;for-complex-ui-components%2C-try-knockout&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#for-complex-ui-components%2C-try-knockout&quot;&gt;For complex UI components, try Knockout&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Like any library, there’s a learning curve to Knockout. But I argue that its learning curve is easier than that of Angular and React. It’s easy to plop it into a WordPress theme when you need some front-end magic, without it taking over everything. If you enjoyed this article and want more, the Knockout website has some nice &lt;a href=&quot;http://learn.knockoutjs.com/&quot;&gt;interactive tutorials&lt;/a&gt; and easy-to-follow &lt;a href=&quot;http://knockoutjs.com/documentation/introduction.html&quot;&gt;documentation&lt;/a&gt;. If you would like to see more Knockout tutorials on &lt;em&gt;this&lt;/em&gt; site, then &lt;a href=&quot;https://blakewatson.com/contact&quot;&gt;get in touch&lt;/a&gt; and let me know.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;People including developers at Facebook, who created it. &lt;a href=&quot;https://blakewatson.com/journal/better-ui-components-with-knockoutjs/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>A geek&#39;s defense of Monopoly</title>
      <link href="https://blakewatson.com/journal/a-geeks-defense-of-monopoly/"/>
      <updated>2016-01-16T21:49:36Z</updated>
      <id>https://blakewatson.com/journal/a-geeks-defense-of-monopoly/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Monopoly gets a bad rap. Though many gaming enthusiasts will turn their noses at the “Property trading game from Parker Brothers,” it remains one of the best-selling board games of all time. Don’t get me wrong, I like a good game of &lt;em&gt;Settlers of Catan&lt;/em&gt; or &lt;em&gt;Ticket to Ride&lt;/em&gt;, but Monopoly is a classic. It’s an oddball that is misunderstood and underrated by many gaming geeks. Its seemingly all-chance mechanics, excruciating length, and reputation for ending in a slow bleed or a rage quit leave many gamers unimpressed.&lt;/p&gt;
&lt;p&gt;Maybe you feel the same way. In which case, permit me to offer some counterarguments to common gripes people have about Monopoly.&lt;/p&gt;
&lt;h2 id=&quot;it%E2%80%99s-all-luck&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#it%E2%80%99s-all-luck&quot;&gt;It’s all luck&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Negative, Ghost Rider. People who believe this probably lose a lot. Sure, chance is a major factor. I mean, every turn requires a roll of the dice. But that doesn’t mean you as a player are powerless. In fact, you can use the knowledge of this chance to your advantage. Consider this: the highest trafficked property set on the board are the Oranges. Why? Several reasons, not the least of which is that they are aproximately one dice roll away from the Jail square, which itself is the most frequently landed on space on the entire board. If you know this, and especially if your opponents don’t, then you have an advantage.&lt;/p&gt;
&lt;p&gt;Monopoly is a game of decisions. Every turn (not just yours) presents new ones. Crucially, Monopoly allows trading. You can trade, buy, and sell with your opponents. This is the single most important gameplay mechanic of Monopoly—so much so that it’s right there on the front of the box—and it involves zero luck. This is where you get to use your knowledge of the game and your charisma to bargain with your friends (or enemies!) and enhance your position in the game. No one ever trades with you? Every player wants &lt;em&gt;something&lt;/em&gt;. Sometimes people even irrationally favor some properties over others. Figure out what other players want, and make sure that they get it—all while not realizing what valuables they are giving to you in the process.&lt;/p&gt;
&lt;h2 id=&quot;it-takes-a-long-time-to-play&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#it-takes-a-long-time-to-play&quot;&gt;It takes a long time to play&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m biased because I enjoy long games. One summer, some friends and I spent three days playing a game of &lt;em&gt;Axis and Allies&lt;/em&gt;. But Monopoly needn’t take an inordinate amount of time. One of the main reasons the game can go long is because people don’t play by the rules. Either they don’t know the rules, or they add their own house rules to the game. House rules are Monopoly’s downfall. Tournament player Ken Koury, in his book “&lt;a href=&quot;http://monopolybook.com/&quot;&gt;Monopoly Strategy&lt;/a&gt;,” wrote of house rules:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Of all of the different rule variations I have seen, I have never seen one that makes Monopoly any better. Most of them just make the game longer. These rule changes also have the effect of removing skill from the game and increasing the luck factor. In other words they reduce the skill level needed to win the game. This will only make it easier for lesser players to win. For example, when there is no money on Free Parking, it requires you to develop important skills in managing your assets that people who play house rules will never acquire.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As another example, many players do not follow the rule that governs what happens when you land on an unowned property. The official rules state, “If you do not wish to buy the property, the Bank sells it at auction to the highest bidder.” I was guilty of not following this rule for a long time as well. But by not following it, your game will take longer because A) it will take more time to get all the properties in play, and B) it will take some of the skill out of the game (knowing if and how much you should bid).&lt;/p&gt;
&lt;p&gt;House rules and the misunderstanding of the official rules are at the root of why so many people don’t like Monopoly.&lt;/p&gt;
&lt;h2 id=&quot;the-slow-bleed-of-your-opponents-gets-boring&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#the-slow-bleed-of-your-opponents-gets-boring&quot;&gt;The slow bleed of your opponents gets boring&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This happens sometimes in &lt;em&gt;Monopoly&lt;/em&gt;—a scenario in which one player has just enough of a leg up on the others such that this person is almost certainly going to win while the other players slowly lose their wealth.&lt;/p&gt;
&lt;p&gt;But it needn’t be this way. Most likely, one or more of the following problems are causing this scenario:&lt;/p&gt;
&lt;h3 id=&quot;no-one-is-trading&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#no-one-is-trading&quot;&gt;No one is trading&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is your opportunity to disrupt the field. Convince the other players that action must be taken to ensure survival against the clear winner. Remember, they want something. Help them get it while helping yourself. Don’t be afraid to give other players monopolies. Most people expect to get a monopoly out of a trade. If your strategy in trading is to never let anyone else have a monopoly, then people are going to stop trading with you. You want to be involved in all trading if you can help it. But you have to give to receive.&lt;/p&gt;
&lt;h3 id=&quot;the-players-don%E2%80%99t-understand-the-object-of-the-game&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#the-players-don%E2%80%99t-understand-the-object-of-the-game&quot;&gt;The players don’t understand the object of the game&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The point of Monopoly isn’t to gain wealth. The object of the game is to bankrupt your opponents.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; To do that, you need to develop property to bankruptcy-inducing levels. I once played with a guy would only spend his starting cash, and not his “profit stack”—money which he earned during the course of play. Fortunately, he valued his cash so much that he was willing to sell you properties for cash-only, even if it gave you a monopoly.&lt;/p&gt;
&lt;p&gt;If you look at the rent prices on any property’s title deed, you’ll notice that the price jumps significantly once a third house is built on the property. That should be a goal to guide your decisions. Work toward getting one or more monopolies developed with at least three houses on each property (more for the really cheap properties). It’s not about what you have, it’s about the damage you can do.&lt;/p&gt;
&lt;h3 id=&quot;players-aren%E2%80%99t-playing-by-the-rules&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#players-aren%E2%80%99t-playing-by-the-rules&quot;&gt;Players aren’t playing by the rules&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I’ve already mentioned how rule variants can ruin a good game of Monopoly, but it’s worth mentioning again in the context of the slow bleed. Rules like the Free Parking jackpot increase the money supply in the game and if a losing player gets it, that can artificially extend their life. If you allow trading of immunity, then you are extending the game by making it harder for the immune player to go bankrupt.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; Read the official rules before playing and make sure everyone agrees to play by the them—with no added house rules.&lt;/p&gt;
&lt;h2 id=&quot;give-monopoly-a-chance&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#give-monopoly-a-chance&quot;&gt;Give Monopoly a chance&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Monopoly is a brilliant game. It affords you an environment where your wit and charm can help you get ahead. Your intellect and sharp thinking can help you make quick decisions that can make or break you. It’s a game of structure, skill, and luck with a healthy dash of creative gameplay built right in.&lt;/p&gt;
&lt;p&gt;If this article has made you want to take a walk on the Boardwalk, then I highly recommend Ken Koury’s book “&lt;a href=&quot;http://monopolybook.com/&quot;&gt;Monopoly Strategy&lt;/a&gt;.” Ken’s book was my main inspiration for this article. Ken discusses in depth the strategy of Monopoly, including the pros and cons of every property set on the board, trading strategies, and much more. Just don’t tell people that you have read it, because they might not want to play with you.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Though the official rules say, “The object of the game is to become the wealthiest player through buying, renting and selling of property,” you will note that the rules also state, “The last player left in the game wins.” &lt;a href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Immunity is the only issue that isn’t really covered by the rules in a clear way. There is a rule that states, “No player may borrow from or lend money to another player.” If you construe immunity as a loan, then offering immunities in trades would be prohibited. This argument doesn’t satisfy some people, so the other argument you can make is that tournaments don’t allow immunity. &lt;a href=&quot;https://blakewatson.com/journal/a-geeks-defense-of-monopoly/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Why Darth Vader can&#39;t be a barista</title>
      <link href="https://blakewatson.com/journal/why-darth-vader-cant-be-a-barista/"/>
      <updated>2015-12-26T21:40:35Z</updated>
      <id>https://blakewatson.com/journal/why-darth-vader-cant-be-a-barista/</id>
      <content xml:lang="en" type="html">&lt;img src=&quot;https://blakewatson.com/uploads/2019/05/1.png&quot; alt=&quot;Frame 1: person at counter says, &#39;I will take a cup of your light roast, please. Frame 2: Darth Vader working the cash register says, &#39;You underestimate the power of the dark roast.&quot; border=&quot;0&quot; width=&quot;885&quot; height=&quot;530&quot; /&gt;</content>
    </entry>
    <entry>
      <title>5 Sublime Text packages that make it a little more like Coda</title>
      <link href="https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/"/>
      <updated>2015-12-20T21:34:56Z</updated>
      <id>https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/</id>
      <content xml:lang="en" type="html">&lt;p&gt;As a developer, one tool stands above the rest as the most essential — the almighty text editor. I’ve been a long time user of Panic’s fantastic code editor for Mac, &lt;a href=&quot;https://www.panic.com/coda/&quot;&gt;Coda&lt;/a&gt;. It packs a lot of features and is a great all around editor. That said, I find its extensibility lacking. It doesn’t have as many plugins as other editors. And Coda 2 broke one of my favorite plugins, &lt;a href=&quot;http://emmet.io/&quot;&gt;Emmet&lt;/a&gt;. So about a month ago, I switched to my second-favorite editor, the one most of my coworkers use — &lt;a href=&quot;http://www.sublimetext.com/&quot;&gt;Sublime Text&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sublime Text is very extensible. But out of the box, it doesn’t match up against Coda’s main selling point: it’s super amazing sidebar that consist of a full-featured file-browser, FTP client, and snippet manager. You will never be able to fully replicate it in Sublime Text.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; My goal was much less ambitious — to make the Sublime Text sidebar tolerable. In addition, I wanted to make it easy to create snippets and sync my text editor settings between machines. Using the powerful package manager, &lt;a href=&quot;https://packagecontrol.io/&quot;&gt;Package Control&lt;/a&gt;, I set out to make Sublime Text as much like Coda as I could. Here are the five essential plugins I’ve been using. (Note that I am using Sublime Text 3.)&lt;/p&gt;
&lt;h2 id=&quot;1.-emmet&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#1.-emmet&quot;&gt;1. &lt;a href=&quot;https://packagecontrol.io/packages/Emmet&quot;&gt;Emmet&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m starting with Emmet because it’s the primary factor in my switch to Sublime Text. Emmet takes some of the redundancy out of writing markup by allowing you to write shorthand syntax which expands into HTML. For example, this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;div.page&amp;gt;ul&amp;gt;li*3&amp;gt;a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;becomes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&amp;quot;page&amp;quot;&amp;gt;
	&amp;lt;ul&amp;gt;
		&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is extremely convenient when you need to build out a lot of HTML. It includes some cool CSS shorthand as well.&lt;/p&gt;
&lt;h2 id=&quot;2.-advancednewfile&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#2.-advancednewfile&quot;&gt;2. &lt;a href=&quot;https://packagecontrol.io/packages/AdvancedNewFile&quot;&gt;AdvancedNewFile&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This package offers a quick input field for creating a new file at some path within your project. It works a lot like the bash command &lt;code&gt;mkdir&lt;/code&gt; and will appeal to folks who prefer keeping their hands on the keyboard. Granted, this is a departure from the stated goal of making Sublime Text a little more like Coda, which favors a mouse-based approach. But at the same time, it makes Sublime Text work with the filesystem better—something Coda is pretty good at.&lt;/p&gt;
&lt;h2 id=&quot;3.-sidebarenhancements&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#3.-sidebarenhancements&quot;&gt;3. &lt;a href=&quot;https://packagecontrol.io/packages/SideBarEnhancements&quot;&gt;SideBarEnhancements&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This package adds some extra oomph to Sublime’s sidebar by expanding on the options in the context menu. If you want to the power to right click your way to productivity, then this package is for you. Move, rename, open with, move to trash, copy/paste files—these are some of the file actions available in your sidebar. This package is essential if you want a Coda-esque sidebar in Sublime Text.&lt;/p&gt;
&lt;h2 id=&quot;4.-snippetmaker&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#4.-snippetmaker&quot;&gt;4. &lt;a href=&quot;https://packagecontrol.io/packages/SnippetMaker&quot;&gt;SnippetMaker&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Snippets in Sublime Text are written in a particular syntax and added by saving files to the filesystem. This is the sort of tedious tasks that computers were meant to do &lt;em&gt;for you&lt;/em&gt;. SnippetMaker automates this tedium. Highlight some code you have written then run SnippetMaker. With very little resistance, it will create for you a snippet based on your selection. While it doesn’t give you a good way to organize your snippets, it does make it easy to add and edit them. In practice, I haven’t needed organization, so I don’t mind that my snippets are all sitting in one location together.&lt;/p&gt;
&lt;h2 id=&quot;5.-package-syncing&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#5.-package-syncing&quot;&gt;5. &lt;a href=&quot;https://packagecontrol.io/packages/Package%20Syncing&quot;&gt;Package Syncing&lt;/a&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One package to rule them all. Package Syncing does what it says on the tin by allowing you to sync your packages and settings across different computers. This is great because you can invest some time setting up Sublime Text once, just how you like it, and carry over those settings to your laptop, work computer, etc. This is akin to Coda’s “Panic Sync” feature, which lets you sync some data and settings between Coda installations.&lt;/p&gt;
&lt;h2 id=&quot;this-is-not-a-review&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#this-is-not-a-review&quot;&gt;This is not a review&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’m not pitting these applications against each other. I’m a fan of both of these editors. I’m trying Sublime Text because, at the time of this writing, Emmet doesn’t work well in Coda 2.5. But I like many things about Coda and wanted to replicate some of its features in Sublime Text as best as I could. If you are on a Mac and you are using either one of these editors, you have made a solid choice as far as I’m concerned.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I’m actually offloading the majority of file browsing and FTP access to Panic’s &lt;a href=&quot;http://panic.com/transmit/&quot;&gt;Transmit&lt;/a&gt;, which I reluctantly call an FTP client even though it is so much more. &lt;a href=&quot;https://blakewatson.com/journal/5-sublime-text-packages-that-make-it-a-little-more-like-coda/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>New personal mark</title>
      <link href="https://blakewatson.com/journal/new-personal-mark/"/>
      <updated>2015-10-16T21:31:05Z</updated>
      <id>https://blakewatson.com/journal/new-personal-mark/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I’ve owned this little space on the web for a decade. The &lt;a href=&quot;https://blakewatson.com/journal/hard-refresh/&quot;&gt;designs changed&lt;/a&gt; radically from version to version. Whatever branding was present changed with it—usually with little thought for the considerations you should make when creating an identifying mark.&lt;/p&gt;
&lt;p&gt;My personal mark improved as I became a better designer and turned my energy toward freelancing. Still, it never felt completely right. The appearance was pleasing, the color palette attractive, but they all missed the mark (heh). They lacked something. Something I couldn’t pinpoint. Much like tasting a sauce and knowing that &lt;em&gt;something&lt;/em&gt; is missing, my personal mark lacked that special, illusive attribute. Let’s call it the X-factor.&lt;/p&gt;
&lt;p&gt;Fortunately, that’s no longer the case.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/new-mark-black.svg&quot; title=&quot;new-mark-black.svg&quot; /&gt;
  &lt;figcaption&gt;Image of new logo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/new-mark-black-enclosed.svg&quot; alt=&quot;New mark black enclosed&quot; /&gt;
  &lt;figcaption&gt;Image of new logo enclosed in a solid circle&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I’m happy to unveil this new mark, courtesy of esteemed designer and &lt;a href=&quot;http://madg.com/&quot;&gt;Genius&lt;/a&gt; Shawn Palmer.&lt;/p&gt;
&lt;p&gt;After reading my own design brief for this mark I thought to myself, “if I know so much about I want, then why don’t I design it myself?” Anyone who has ever tried to design branding for themselves, personally, knows that it is a special kind of difficult. Further, a list of characteristics does not a great design make. The X-factor is hard to come by.&lt;/p&gt;
&lt;p&gt;I love this mark because though it appears simple and obvious on its surface—as great designs often do—it has subtle details that make it interesting.&lt;/p&gt;
&lt;h2 id=&quot;bravo-whiskey&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-personal-mark/#bravo-whiskey&quot;&gt;Bravo whiskey&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From the brief:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’d like a mark—without my name joining it—that either A) plays on the letter “W”, B) plays on the initials &amp;quot;BW”…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Many logo marks consist of initials that are visually joined in some way. In my own designs for my logo, I avoided using my two initials for fear that I would not be able to combine them in an appealing way. Having seen some of Shawn’s lettering work, I knew making sublimely intertwined initials was in his wheelhouse. Early sketches show the “w” with the “b” added onto the end.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/wb-sketch.png&quot; alt=&quot;Wb sketch&quot; width=&quot;476&quot; height=&quot;267&quot; /&gt;
  &lt;figcaption&gt;Image of early “WB” sketch&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;While aesthetically pleasing, Shawn felt it was important to get the order right. You can see from a later sketch how the “b” gets tilted then folds out into a “w”.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/bw-sketch.png&quot; alt=&quot;Bw sketch&quot; width=&quot;599&quot; height=&quot;339&quot; /&gt;
  &lt;figcaption&gt;Image of final sketch&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;reinvent-the-wheel&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-personal-mark/#reinvent-the-wheel&quot;&gt;Reinvent the wheel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From the brief:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;…or C) something that makes a subtle reference to my wheelchair while staying far away from anything resembling the handicap parking symbol&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My previous logo marks drew inspiration from my wheelchair, specifically the concept of a wheel:&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/old-logos.png&quot; alt=&quot;Old logos&quot; width=&quot;599&quot; height=&quot;329&quot; /&gt;
  &lt;figcaption&gt;Previous two logos&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I wanted to maintain this link in the subtlest of ways.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/new-mark-black-both.svg&quot; alt=&quot;New mark black both&quot; /&gt;
  &lt;figcaption&gt;Both versions of the new mark.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The new mark delivers. It’s not something that everyone will notice—and that’s the beauty of it. Admittedly, I could be reading into it, but for me the new mark captures the wheel in two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The obvious is the circle in the enclosed version.&lt;/li&gt;
&lt;li&gt;The “w” itself resembles the tread of my wheelchair’s tires.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Even if I am just projecting my own meaning onto the ink blot here, it’s true that the concept of the wheel played an important role in the thinking behind the mark—it’s a motif found throughout the sketching.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/logo-sketches-1.jpg&quot; alt=&quot;Logo sketches 1&quot; width=&quot;361&quot; height=&quot;600&quot; /&gt;
  &lt;figcaption&gt;Image of wheel sketches&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;lines%2C-angles%2C-and-arcs!-oh-my!&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-personal-mark/#lines%2C-angles%2C-and-arcs!-oh-my!&quot;&gt;Lines, angles, and arcs! Oh my!&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From the brief:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Works at small sizes&lt;/li&gt;
&lt;li&gt;Modern and or geometric (no grungy strokes)&lt;/li&gt;
&lt;li&gt;Finesse instead of power&lt;/li&gt;
&lt;li&gt;Cool minimal&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;I love the geometric characteristics found in the works of twentieth-century modernist designers. So much so that I asked Shawn to channel his “inner Paul Rand.”&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/paul-rand-samples.jpg&quot; alt=&quot;Paul rand samples&quot; width=&quot;599&quot; height=&quot;418&quot; /&gt;
  &lt;figcaption&gt;Snapshot of work by Paul Rand&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You won’t find any irregular shapes or muddy textures here. The new mark is informed by the math that constructs it.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/new-personal-mark/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; The enclosed version balances an elegant contrast of sharp lines and angles to the smooth curve of the circle. It brings to mind the old wax seals of yore, an apt analog metaphor.&lt;/p&gt;
&lt;p&gt;The new mark’s geometrics are precise, but not machined to perfection. The hand of the artist is at work in the subtle details like the cuts in the contour of the “b”.&lt;/p&gt;
&lt;h2 id=&quot;depth-perception&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-personal-mark/#depth-perception&quot;&gt;Depth perception&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From the brief:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Single color&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the one area where I would say that Shawn went rogue—and it paid off. Perhaps my favorite characteristic of the new mark is the ability to flip a switch (change a few fill colors) and watch this wonderfully minimal silhouette move into the third dimension.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/new-mark-color.svg&quot; alt=&quot;New mark color&quot; /&gt;
  &lt;figcaption&gt;Two-color version of the logo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The color of the shapes that connect the first diagonal stroke of the “w” to the middle diagonal stroke can be changed to create an illusion of depth. Not only that, but it provides an opportunity to play with color. I can see this being a cool effect at larger sizes.&lt;/p&gt;
&lt;h2 id=&quot;the-complexity-of-simplicity&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/new-personal-mark/#the-complexity-of-simplicity&quot;&gt;The complexity of simplicity&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Great design that appears simple and obvious rarely is. Behind the scenes, it takes thinking about and distilling complex ideas into a core meaning.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Simple ideas, as well as simple designs are, ironically, the products of circuitous mental purposes. Simplicity is difficult to achieve, yet worth the effort.” – Paul Rand&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My thanks to Shawn for hooking me up with this sweet logo. I’m thrilled to finally have a mark I’m proud of and I hope you, my dear reader, enjoy it as much as I do.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The logo implemented on this website is an SVG, so it’s rendered by your web browser according to mathematical instructions. It is literally built with math! &lt;a href=&quot;https://blakewatson.com/journal/new-personal-mark/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>How to get smart quotes in wok</title>
      <link href="https://blakewatson.com/journal/how-to-get-smart-quotes-in-wok/"/>
      <updated>2015-09-17T20:54:55Z</updated>
      <id>https://blakewatson.com/journal/how-to-get-smart-quotes-in-wok/</id>
      <content xml:lang="en" type="html">&lt;p&gt;Smart quotes (i.e., “curly quotes”) are a must-have for me. If I were designing a CMS, smart quotes would be included by default. Alas, &lt;a href=&quot;https://web.archive.org/web/20150206130752/http://wok.mythmon.com/&quot;&gt;wok&lt;/a&gt; does not include them. But that’s okay because the developer of wok intended for it to be customizable and provided us with hooks, which we can latch on to and add extra features.&lt;/p&gt;
&lt;p&gt;To get smart quotes, we’re going to use the Typogrify package. We can install it with pip:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo pip install typogrify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Typogrify comes with &lt;a href=&quot;http://daringfireball.net/projects/smartypants/&quot;&gt;SmartyPants&lt;/a&gt;, a utility that searches over text for straight quotes and turns them into curly quotes (among other things). Our content in wok is already being parsed by Markdown, so after that happens, we want to parse it with SmartyPants.&lt;/p&gt;
&lt;h2 id=&quot;wok-hooks&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-get-smart-quotes-in-wok/#wok-hooks&quot;&gt;Wok hooks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hooks live in their own folder within the wok file structure. But hooks aren’t required to run a wok website, so there’s a chance you don’t even have a hooks folder. If you don’t, go ahead and create a folder called &lt;code&gt;hooks&lt;/code&gt;. In a default wok setup, it would go in the top level of your site structure, next to your content folder.&lt;/p&gt;
&lt;p&gt;Next, create a file named &lt;code&gt;__hooks__.py&lt;/code&gt; and put it inside the hooks folder. In this file, we will write some Python code that will latch on to the appropriate hook and tell wok to run SmartyPants.&lt;/p&gt;
&lt;p&gt;Which hook? Wok’s documentation has a list of the &lt;a href=&quot;https://web.archive.org/web/20150313064252/http://wok.mythmon.com/docs/hooks/&quot;&gt;available hooks&lt;/a&gt;. Remember that we want to run SmartyPants over our content after it has been rendered by Markdown. To do that, we’ll use the &lt;code&gt;page.render.post&lt;/code&gt; hook.&lt;/p&gt;
&lt;p&gt;Wok’s documentation describes &lt;code&gt;page.render.post&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This hook will be called for each page right after the page is rendered by Markdown, reStructuredText, etc. The unrendered text will be in the variable &lt;code&gt;page.original&lt;/code&gt;, and the rendered text will be in the meta variable &lt;code&gt;page.meta[&#39;content&#39;]&lt;/code&gt;. Keep in mind that some pages won’t be run through this hook because they come from other sources, such as hooks, or pagination.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;writing-our-hook&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-get-smart-quotes-in-wok/#writing-our-hook&quot;&gt;Writing our hook&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I’ll go ahead and show you the code, then we’ll walk through it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import typogrify.filters as typogrify

def smartypants_filters(config, page):  
    if &amp;quot;title&amp;quot; in page.meta:  
        page.meta[&amp;quot;title&amp;quot;] = typogrify.smartypants(page.meta[&amp;quot;title&amp;quot;])

    if page.meta[&#39;content&#39;]:  
        page.meta[&#39;content&#39;] = typogrify.smartypants(page.meta[&#39;content&#39;])

hooks = {  
    &amp;quot;page.render.post&amp;quot;: [smartypants_filters],  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we import &lt;code&gt;typogrify&lt;/code&gt; so that we have access to one of its filters, &lt;code&gt;typogrify.filters.smartypants&lt;/code&gt;. I’m using the &lt;code&gt;as&lt;/code&gt; keyword to make using typogrify a little more concise.&lt;/p&gt;
&lt;p&gt;Next, we define a function. We can call it whatever we like, but it needs to accept the &lt;code&gt;config&lt;/code&gt; and &lt;code&gt;page&lt;/code&gt; variables that will be supplied to it by wok when the function is called.&lt;/p&gt;
&lt;p&gt;I’m going to go out of order and talk about content first. We check to see if there is any content, and if there is we run smartypants over it and replace the existing content with the result.&lt;/p&gt;
&lt;p&gt;We’re essentially doing the same thing with the title field. We first have to check to see if there is a title field defined, and if so we do the exact same maneuver we did with the content.&lt;/p&gt;
&lt;p&gt;If your wok site has additional fields that need smart quote substitution, then you can treat them the same way we did our title. Check to see if a particular field exists, then replace it with the smartypants-enhanced version.&lt;/p&gt;
&lt;p&gt;Up to this point, wok doesn’t know about our function. We need to specify that we want to attach our function to the &lt;code&gt;page.render.post&lt;/code&gt; hook. Wok automatically looks for a variable called &lt;code&gt;hooks&lt;/code&gt; within this file that contains a Python dictionary. Each &lt;code&gt;key:value&lt;/code&gt; pair in that dictionary needs the name of the hook and a list of functions to fire. We just have the one function, so it goes in a list by itself.&lt;/p&gt;
&lt;h2 id=&quot;if-only-there-was%E2%80%A6&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/how-to-get-smart-quotes-in-wok/#if-only-there-was%E2%80%A6&quot;&gt;If only there was…&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I love wok for its simplictity and that you can use it with very little programming knowledge compared to other static site generators (which makes it a good candidate for designers). That said, it does take a little bit of pragramming to get smart quotes with wok. It’s certainly not a dealbreaker, though. And with this tutorial, you should be able to get there fairly easily.&lt;/p&gt;
&lt;p&gt;We all have that one feature we feel is a must-have. I hope this tutorial gets your wheels turning on how you can use hooks in wok to get that feature you want.&lt;/p&gt;
</content>
    </entry>
    <entry>
      <title>This site’s design is not original</title>
      <link href="https://blakewatson.com/journal/this-sites-design-is-not-original/"/>
      <updated>2015-08-30T19:20:47Z</updated>
      <id>https://blakewatson.com/journal/this-sites-design-is-not-original/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I had a conversation with a co-worker of mine, who is in video production, about what it’s like to watch TV shows and movies when you know so much about the art and science of making TV shows and movies. Where others see dragons and spaceships and raw emotion, a professional sees mistakes in the color, the frame, and the cuts between dialogue. Being a professional in video production changes the way you consume media—you can’t help but see all the little mistakes and tradeoffs.&lt;/p&gt;
&lt;p&gt;Being a web designer has a similar effect. I see a website’s patterns before I see its content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“This is a WordPress site, looks like a modified TwentyEleven theme.”&lt;/li&gt;
&lt;li&gt;“Upper left logo, upper right nav.”&lt;/li&gt;
&lt;li&gt;“Let’s resize the browser window and see how responsive it is.”&lt;/li&gt;
&lt;li&gt;“Proxima Nova, we meet again.”&lt;/li&gt;
&lt;li&gt;“Tons of ads, probably tons of trackers, and tons of junk in the sidebar and footer.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just to give you a few examples. And my website is no exception:&lt;/p&gt;
&lt;p&gt;“Color bar, standard one-column blog, static.”&lt;/p&gt;
&lt;p&gt;My website’s design is not original. And chances are that yours isn’t either. Websites are built on interlinked patterns that are found throughout every website. So in a sense, no website is truly original. Just as every story can be boiled down to its archetype. Just as every song can be pulled apart into time and key.&lt;/p&gt;
&lt;h2 id=&quot;in-which-i-now-contradict-my-own-thesis&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/#in-which-i-now-contradict-my-own-thesis&quot;&gt;In which I now contradict my own thesis&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I work with a bunch of skilled folks who all have a good eye for quality. I’m constantly amazed by the links they share of websites and videos and art. They are amazing, sometimes insane, and almost always &lt;em&gt;original&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The thing is, being original does not mean being devoid of patterns. Just because we’ve heard a million stories about a good, yet troubled, unlikely hero being thrust into an adventure only to find out that they were destined to be the hero all along does not mean that Harry Potter, Star Wars, The Matrix, The Wizard of Oz, The Lord of the Rings, and [insert tons of titles here] are not great, original stories. They used the patterns in a new way that captivated people.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&quot;http://madg.com/&quot;&gt;Mad Genius&lt;/a&gt;, we just launched a site for &lt;a href=&quot;http://multicraft.com/&quot;&gt;Multicraft International&lt;/a&gt; that I think is pretty darn original. You’ll recognize common design patterns used in interesting ways—an apt characteristic given Multicraft’s business. Take the plunge into full-blown creative fusion and check out this &lt;a href=&quot;http://multicraft.com/our-process/&quot;&gt;sweet animated narrative on process&lt;/a&gt;. It’s boss.&lt;/p&gt;
&lt;h2 id=&quot;timeless-design&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/#timeless-design&quot;&gt;Timeless design&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I love books. I don’t even read as many physical books as I would like (or digital ones for that matter). But I love how you can look at a book designed a hundred years ago and it more or less looks like books designed today. We’ve pretty much nailed down book layout and typography.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I designed this website to be a nice place for words to live and be read. I’m not so grandiose as to say the design of this website is timeless, but the timeless design qualities of books, modernist advertising from the 1960’s, and recent trends in minimalist design influenced me a lot. Like any web designer who looks at this site, I see its flaws and compromises. But I also see its potential and its originality.&lt;/p&gt;
&lt;h2 id=&quot;go-forth-and-be-original&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/#go-forth-and-be-original&quot;&gt;Go forth and be original&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Much of the fun in making things comes from exploring all the pieces you can use—just ask fans of Lego. Don’t worry so much about whether what you are doing is original. Just make sure it’s useful, fun, accessible, beautiful, heartbreaking, effective, or at least consists of one kitten photo.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I would be remiss not to point you in the direction of the canonical work on typography that is &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Elements_of_Typographic_Style&quot;&gt;“The Elements of Typographic Style” by Robert Bringhurst&lt;/a&gt;. &lt;a href=&quot;https://blakewatson.com/journal/this-sites-design-is-not-original/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Making this site: Going static</title>
      <link href="https://blakewatson.com/journal/making-this-site-going-static/"/>
      <updated>2015-08-27T19:06:35Z</updated>
      <id>https://blakewatson.com/journal/making-this-site-going-static/</id>
      <content xml:lang="en" type="html">&lt;p&gt;I was thrilled with the idea of pivoting my site from a freelancer’s pitch to a developer’s journal. I really wanted to get back to basics. At its heart, the web consists of words and links to more words. Your browser sends a request for a page; my server sends a page back to you.&lt;/p&gt;
&lt;p&gt;But the above process can get bogged down quickly with loads of server-side logic, weighty scripts, and lots of vulnerabilities to hacking. So I decided to make a change. I’ve moved this site off of WordPress and it’s now a static website.&lt;/p&gt;
&lt;h2 id=&quot;i-still-love-wordpress&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#i-still-love-wordpress&quot;&gt;I still love WordPress&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don’t have any ill-will toward WordPress. It’s a great CMS. It’s &lt;em&gt;the&lt;/em&gt; CMS. But I just don’t need it for this site. I don’t need its commenting system, its URL handling, its media library, or its database. As they say, use the right tool for the job.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-going-static&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#benefits-of-going-static&quot;&gt;Benefits of going static&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;It’s fast.&lt;/strong&gt; You request a page, you get that page. There’s no database calls, no logic to assemble pages on the fly, and no clunky admin screens to wade through. If you use a robust service like &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt;, your static content will be served fast and reliably, even under heavy load.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It’s cheap.&lt;/strong&gt; Web hosting can be dirt cheap anyway, but you can get more for less out of your standard cheap web hosts with a static site. My host, &lt;a href=&quot;https://www.nearlyfreespeech.net/&quot;&gt;NearlyFreeSpeech.NET&lt;/a&gt; has a specific server type for hosting static websites that gives you very good pricing, abiding by their unique “pay for only what you use” model. You could run a low-traffic static site for a month or two with fifty cents.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It’s portable.&lt;/strong&gt; Want to move your static site to another server? Maybe your computer? With any &lt;a href=&quot;https://www.panic.com/transmit/&quot;&gt;good FTP client&lt;/a&gt;, that’s as simple as drag-and-drop. And if you are being cool and using git to version your code, well my friend, you can move your site around faster than a ferret with its fanny on fire. No database export, no SQL search and replace, no complicated re-configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It’s open.&lt;/strong&gt; You are free to use whatever tools you want to make your site. You could use all open source software. You could use some of the nice WYSIWYG apps for your operating system. You can choose from a &lt;a href=&quot;https://www.staticgen.com/&quot;&gt;huge list of static site generators&lt;/a&gt; — there’s one in just about every programming language you would want to use. As long as it produces HTML and CSS, you could use it to make your website.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;why-you-might-not-want-to-go-static&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#why-you-might-not-want-to-go-static&quot;&gt;Why you might not want to go static&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The biggest barrier to many of the static site generators that I have come across is that they aren’t easy for non-developers to use, even for basic use like adding content to an existing template. We tech-savvy folks write Markdown like it’s second-nature to us, but lots of folks don’t know how to do that. They might not know what plain text is. They might not know how to save out the site and upload changes. So if you are trying to make it easy for non-developers to add and edit content, a CMS like WordPress is a safer bet. If WordPress still feels like overkill for your project, you might be interested in &lt;a href=&quot;http://getkirby.com/&quot;&gt;Kirby&lt;/a&gt; or &lt;a href=&quot;https://grabaperch.com/&quot;&gt;Perch&lt;/a&gt;, both of which have simple admin views and fairly straight-forward templating systems.&lt;/p&gt;
&lt;h2 id=&quot;this-site-fried-up-with-wok&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#this-site-fried-up-with-wok&quot;&gt;This site fried up with wok&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did a lot of searching, thinking, and tinkering around before settling on &lt;a href=&quot;http://wok.mythmon.com/&quot;&gt;wok&lt;/a&gt; as my static-site generator. I came very close to using a generator written in Node.js called &lt;a href=&quot;http://www.metalsmith.io/&quot;&gt;Metalsmith&lt;/a&gt;, but I didn’t like dealing with its “everything’s a plugin” philosophy. If you like Gulp, though, check it out.&lt;/p&gt;
&lt;p&gt;Wok is written in Python, though you never have to write any Python code yourself to use it. I happen to know a bit of Python and I love the language. Still, that’s just icing. Wok’s greatest strengths are these:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Any kind of content you want, saved in Markdown with YAML headers&lt;/li&gt;
&lt;li&gt;Easy-to-use templating system, &lt;a href=&quot;http://jinja.pocoo.org/&quot;&gt;Jinja2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Only two command line commands to remember: &lt;code&gt;wok&lt;/code&gt; builds your site into a build folder; &lt;code&gt;wok --server&lt;/code&gt; gives you a local URL to use in development.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of all the generators I considered, wok was the only one that hit the balance of power and simplicity that I was looking for. Seriously. I came across generators with build commands that required multiple flags and arguments just to build your site with standard options. &lt;em&gt;Gross&lt;/em&gt;. It’s tempting to add features to software—I know this from being a developer. So I appreciate that the developer of wok said “no” to whatever else could have been and left us with this beautifully simple program that does exactly what you want with one, three-letter command. It really is a work of art, but I digress.&lt;/p&gt;
&lt;p&gt;I’m probably going to write some more about wok in the future as it is a great tool for beginner developers (and even &lt;a href=&quot;http://www.mattwatson.org/&quot;&gt;savvy non-developers&lt;/a&gt;!) to use for creating nice static sites. I’d like to run through how I set things up and how I got around one of wok’s flaws (oh the suspense). If you are interested in some wok tutorials, &lt;a href=&quot;https://blakewatson.com/contact&quot;&gt;let me know&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what%E2%80%99s-old-is-new-again&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#what%E2%80%99s-old-is-new-again&quot;&gt;What’s old is new again&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Websites started as static pages, and static sites have been making a comeback the last few years. I know it feels weird not having old faithful WordPress by your side, but consider going static for your next small project. I bet you’ll find it refreshing. Use &lt;a href=&quot;http://wok.mythmon.com/&quot;&gt;wok&lt;/a&gt;, and you’ll fry up a tasty website in no time.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I love NFSN. If you are still on shared hosting but you want to escape the monopoly of GoDaddy, et al, then NFSN is a great option. Even if you are running WordPress, they’ve got great resources for making it faster and more secure. They don’t have an affiliate program, so you can be confident in the knowledge that I’m promoting them simply because they’re great. &lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Technically, you could use Microsoft Word to make a website. I’m not ashamed to admit that I tried that back in the day. But this is a classic &lt;em&gt;just because you could…&lt;/em&gt; situation. Do yourself a favor and use a program that was actually designed for making websites. &lt;a href=&quot;https://blakewatson.com/journal/making-this-site-going-static/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    </entry>
    <entry>
      <title>Hard refresh</title>
      <link href="https://blakewatson.com/journal/hard-refresh/"/>
      <updated>2015-08-23T17:41:39Z</updated>
      <id>https://blakewatson.com/journal/hard-refresh/</id>
      <content xml:lang="en" type="html">&lt;p&gt;This website started out as a “personal homepage” back when those were still a thing. It was ugly because I was still learning the basics of graphic design and CSS. But it was creative and unique because I was blissfully unaware of many current trends and interaction patterns.&lt;/p&gt;
&lt;p&gt;As I began to become a practiced web designer and developer, my website transitioned from a personal one to a professional one. It showed off my portfolio and promoted my services as a freelancer. It finally became, in a word, good.&lt;/p&gt;
&lt;p&gt;I still have most of the source code for every design iteration of this site from its beginnings in 2005 to the 2013 design, which stayed in place through the summer of 2015. I managaed to put together this graphic that shows the homepage of each iteration:&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://blakewatson.com/uploads/2019/05/screenshots.jpg&quot; alt=&quot; A screenshot of a bunch of my personal websites from 2005 to 2013. The designs progressed from personal site vibe to experienced designer.&quot; /&gt;
  &lt;figcaption&gt;Early history of blakewatson.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It’s been a fun ride. Now it’s time to move into a new era. In May 2015 I joined Mad Genius as a full-time Interactive Designer. As such, I won’t be taking on any freelance web work. And this site no longer needs to promote my services as a freelancer. Like many bloggers before me—and I’m certain many after—I now hope to focus on writing more.&lt;/p&gt;
&lt;p&gt;So this is a hard refresh. I won’t make promises about what will appear on this site because like many bloggers before me—and I’m certain many after—there’s a good chance I’ll break those promises. But I’m excited that I finally feel smart enough to write intelligibly on matters of web development. I’ve always wanted to have a development blog, and it finally seems like the right time to have one.&lt;/p&gt;
&lt;p&gt;Maintaining one blog is hard enough, so I’m officially retiring &lt;em&gt;&lt;a href=&quot;http://www.ihatestairs.org/&quot;&gt;I hate stairs&lt;/a&gt;&lt;/em&gt;, though I will keep it online. Disability topics are still relevant to me and I’m interested in the convergence of web development, design, and assistive technology.&lt;/p&gt;
&lt;p&gt;Thanks to everyone who supported Blake Watson Design, especially my clients, family, friends, and online peeps.&lt;/p&gt;
</content>
    </entry>
</feed>