Going Indie

A complete guide to becoming an independent software developer

From starting a company and staying motivated, to designing, building, and launching your first product and beyond.

Coming in 2020!
Sign up for the newsletter to stay up to date!

On Uber, Lyft, and Labor Law

A storm has been brewing in California. No, not the Coronavirus pandemic or the massive fires, though both are incredibly important and widespread. California is trying to reign in a few powerful tech industry players. What we're witnessing now may become either a cautionary tale or a key example of just how these battles can be waged in the future against even bigger and more powerful giants.

Uber and Lyft have both circulated the idea that they will soon halt operations in California after a state judge forced them to comply with A.B. 5, the California law that requires businesses like Uber and Lyft to classify certain workers as employees instead of contractors. The law, which went into effect in January and has been debated for over a year in the state, would force Uber and Lyft to classify most of their drivers as employees. This change would ensure that those drivers maintained a minimum wage, health benefits, and other benefits under state law, none of which are available to contractors.

After the law went into effect, Uber and Lyft sued and have been both pursuing a legal case and supporting a ballot measure that explicitly excludes ride-share companies from A.B. 5. According to the San Diego Union Tribune, in early August a state judge, "ordered the companies to classify their drivers as employees rather than independent contractors," when they'd prefer to wait until the fate of their ballot measure is decided in November. They also argue that they don't have enough time to comply, even though they've been given months before the law went into effect and eight more months afterwards to comply.

This legal battle is unlike the one waged over the California Consumer Privacy Act (CCPA) which also went into effect recently, and was primarily targeted at data-brokers like Facebook, Google, and others. CCPA, which merely requires a few key, common-sense measures, did not directly hinder the operations of Facebook, Google, or others. It simply made their practices more transparent to users and was slightly annoying for them to implement. A.B. 5 is different. The law represents a fundamental threat to Uber and Lyft's current business model. Both rideshare companies, to varying degrees, rely on huge investor subsidies and loopholes in labor laws to make their business viable. Uber alone, loses over $1.5 billion each quarter. Let that sink in. Both companies are growing, but to do so they require investors to subsidize rates and they rely on underpaid drivers to balance their revenue model. What neither company wants to say, but that is abundantly clear from their reactions, is that they cannot exist as multi-billion dollar companies if they had to comply with California's labor laws, and they can't attract massive amounts of venture capital if they can't grow at current rates. To be fair, I'm sure that Exxon-Mobile, Walmart, Google, and Apple would be far more profitable if they could ignore labor laws too. Paying people a living wage is expensive, as is giving them health care, so companies don't want to do it, but that's why we have these laws.

During the initial debate of A.B. 5, Uber and Lyft, as well as many other rideshare and delivery apps, made their case to the voters in California and to the legislators that passed the bill, but they lost. Now both companies are threatening to take their ball and go home rather than accept that perhaps their entire business model is flawed and should be fixed. Uber and Lyft could reclassify their workers and still be enormous companies, but not as enormous as they are today, or they could choose to pout telling their users that it's all or nothing. I don't want to see Uber and Lyft leave California or disappear (even though Uber's corporate culture is often disgraceful and cause for separate concern). They offer a useful service. I've used both companies a lot over the years. I've also used Uber Eats, Postmates, Doordash, and other delivery companies to get a burrito and to satisfy a craving for Saag Paneer at 2AM. But that doesn't mean that I think their service is so valuable that they should be immune from laws that other companies are subject to. Taxi companies and delivery drivers have been around for a long time. Those endeavors can be profitable, and they can be mutually beneficial for both the company and the workers. This, however, isn't the framing that Uber and Lyft are building around this debate. In their eyes, either they get a pass on obeying labor law, or they go away. But it's important to remember, that's not the only choice they have. It's not the only path they could take. It is, however, the one they've chosen to take.

I'll just say this: if your company can only exist if it violates civil rights or labor law, then I don't think you should exist. - my post on Pine.blog

Two is Better than One

It finally happened. After 6 years (!) of blogging on this site, I finally felt the need to add a blogroll and sidebar. Changes like this come slowly. For one, I had to update the custom code that runs the site. But it also comes slowly for another reason: it wasn't broken, so why would I fix it? This site has worked fine with a one-column layout for years. It's only now, when I wanted to shove more into the navbar than would comfortably fit, do I feel that I needed to make this change.

Behind the scenes is the real magic. I now have the ability to feature my posts automatically and publish hidden 🤫 posts that don't appear on the feed, the archive, or the home page. I've wanted that feature for a while and I've basically been hacking something similar together for years to support my about page. Keep watching for more developments.

Novels and Insurmountable Tasks

I've wanted to write epic fantasy for years. In college I fleshed out a pretty substantial world, a unique magic-system, and an overarching conflict, but I never got deep into the characters, their journey, or their individual story-arcs. I discovered that I like building worlds and systems, but crafting plots and characters is a lot more difficult. The world, and the magic-system especially, has stuck with me, and although I'd make significant changes to it now, I still think that the idea is solid at its core. I'd love to write it someday.

Writing fiction, especially fantasy, just seems like such a monumental task. So much of the sci-fi and fantasy novels that I've read (especially from authors like Brandon Sanderson) are filled with epic stories across multiple viewpoints over decades of each character's life spanning thousands of pages. Putting something like that together, even with years of time, seems like something I just don't have the strength of will to even dream of accomplishing.

In building and launching my own apps and services like Pine.blog, Nine9s, d20.photos even Adventurer's Codex, I've learned that while I can build and maintain large projects, they take a long time to come to fruition. One of the great things about software though is that you can launch with a subset of features and improve it as you go. This means that even for huge projects like Pine.blog, I could see results, launch features, get feedback and share my work-in-progress all while improving it and staying motivated to continue. The idea of spending years writing a manuscript thousands of pages long, editing it, tweaking it, and being unable to publish it until every box was checked is just not something I think I could force myself to do. I'd get bored or burn out.

But thousands-of-page-novels are just one form of the genre. There's another, oft overlooked form: novellas.

The Wizard of Earthsea Trilogy

I love the Wizard of Earthsea trilogy. I first discovered the books in high school and eventually re-read them after college. They're a series of short, kid friendly books about a wizard who goes to a wizard school to learn magic and his adventures in the island world of Earthsea.1 Each of them is less than 200-pages long and clock in at around 50,000 words. Compare that to Brandon Sanderson's Way of Kings which clocks in at 398,460 words across over 1,280 pages and Earthsea looks tiny. To me though, it also starts to look attainable.

Writing fantasy isn't really comarable to writing non-fiction, but at an average of ~1,000 words per day a novella of similar length to Earthsea would take about 50 working days to write, just about two months working full-time. That's completely possible, even part-time a first-draft could be completed in a few months and ready for feedback, editing, review, and possibly publication.

I don't want to give off the impression that I'm going to become a fantasy writer any time soon, I'm not, but this realization did rekindle my interest in such a prospect quite a bit. Sure, the structure of a series of novellas is different than a single monumental tome, but if one would be impossible and the other attainable, then it's not really a decision worth considering.

So much about a hobby or side-project is about staying motivated through to completion and if a 1,000 page novel is out of the question, maybe it's not the novel part that needs rethinking.

1 These books predate Harry Potter by over two decades and inspired the magic system in Christopher Paolini's Inheritance Series.

The Fall of Civilizations Podcast

I love history. I grew up watching the History channel (back when they actually had real history shows) and PBS documentaries. These days those kinds of things don't really hit the spot anymore. I've turned to podcasts instead. There's a ton of great history podcasts out there and I've written before about my love of this History of Rome podcast, its successor The History of Byzantium podcast, the British History Podcast and the fantastic Revolutions podcast. But there's another show that I've really fallen in love with recently: The Fall of Civilizations Podcast.

Each episode of TFoC is a narrative re-telling of the fall of a particular civilization. The, typically 2-3 hour long, episodes start with an overview of the culture, exposing you to how it felt to live at that time and in that place, and the second half covers how this civilization fell. Each show has voice actors, music, excerpts from songs or stories shared at the time, and is chock full of well-researched, excruciatingly detailed history.

That's not why I love the show though. I love it because I've left every episode feeling some degree of the same feeling: a mixture of wonder, sadness, hope, and intense loss for the cultures of the past who watched their world come to an end. It's cheery stuff. That may not sound very... good, and perhaps it isn't, but it reminds me that history is full of tragedy, and loss, but also full of hope and positive change. It reminds me that our world has not become what it is by accident or without pain and suffering. I just finished the episode about the fall of the Aztec empire, a tale I'd studied in school, but never truly understood at the level I feel I do now. As with every episode, I know how it ends, but it's always the journey that matters.

This podcast, as well as all of the others mentioned in this post come highly recommended. Each of these shows is so captivating in its own right that I've, on many occasions, just sat with a cup of tea, coffee, or a cocktail and just listened, as if to a radio play, for hours. It's almost as if these kinds of narrative histories are like the oral tales that ancient tribes would tell around a fire: the stories of cultures, ancient and great, and the tale of how they fell.

d20.photos: A Public Domain D&D Image Repository

I bought the domain d20.photos on Nov 23rd, 2018 with the goal of building a free-to-use, public-domain image hosting service for D&D, Pathfinder, and other fantasy RPGs. Today, that goal is realized.

d20.photos Logo

Finding images for your D&D campaigns is really difficult, especially if you're looking to sell your campaign. Most artwork isn't licensed in a way that makes it easy for low-budget creators to use and often there's no way to easily find images for settings or places in your game. d20.photos aims to change that by providing a free, community-driven, human-curated image hosting service for D&D/Pathfinder related images. d20.photos aims to be a one-stop-shop for all your image needs. Since all images on the site are released into the Public Domain, you can be sure that you're ok to use, re-use, modify, them and even include them in your paid campaign or story.

I've been collecting images for years (over 100) with the goal of eventually adding them to a service like this. I have a lot more to upload, and anyone in the D&D community can do the same.

Abstract Images

One common problem for campaign or story writers is that while there are a plethora of photos on the Web that they can use in their games, pictures of the real-world are often too real. I know I will almost always choose a painting or other artwork over a photo even if they're harder to find. d20.photos tries to solve this problem as well.

Whenever a new photo is approved, a computer-generated version of the image is created by a wonderful open-source library called Primitive by Michael Fogleman. The library uses primitive shapes (in this case triangles) of various colors and sizes to reproduce the original image. These primitive, or abstract, versions are often really beautiful and have a certain fantasy air about them. Adventurer's Codex actually uses these primitive images too on the landing pages.

I find that these abstract versions "feel" more appropriate for a fantasy game and while Primitive does struggle with images with a ton of fine detail (like photos with lots of trees), it's certainly better than nothing.

The Environment (Again)

Like Nine9s.cloud, d20.photos is hosted in London in a datacenter powered by 92% clean and renewable energy. d20.photos runs on the same size of server as Nine9s, so I didn't need to recalculate the environmental impact. Unless I just can't make it work, I think I'm going to be hosting most of my software in the Linode U.K. datacenter from now on, or at least until one of their U.S. partners commits to using renewable energy in the same way. It's not a big thing, but it's a thing I can do.

I hope d20.photos is useful to you, and if it is, I'd love to hear about it. The site is donation based, so if you like what you see, please consider supporting it. If enough people do, it'll be a lot easier to justify improving it in the future.

Careful with Complex Querysets

Today I learned something about filtering Django Querysets and fixed a long standing bug. But first some context.

As a feed reader, Pine.blog needs to parse feeds. To do this, every 5 minutes, Pine.blog checks to see which feeds it needs to parse. A feed can fall into one of three categories:

  • Constantly changing feeds with active subscribers: Feeds that change regularly (i.e. microblogs, Reddit feeds, etc) and have recently active users subscribed to them.
  • Less frequently changing feeds with active subscribers: Feeds that may update rarely, but still have recently active users subscribed to them.
  • Everything else: Feeds with no one subscribed to them, but are still included in the Feed Directory, or feeds with subscribers who haven't logged in to Pine.blog recently.

To do all of this, Pine.blog keeps track of how often a feed is typically updated, but if it can't tell, it sets the approximate_update_frequency to NULL. Then each of the three categories are checked at different frequencies, ensuring that everything gets parsed at least once every 24 hours, but things that change more often, or with active users subscribed to them, are given priority and parsed more regularly: every 15 or every 30 minutes respectively.

It's the second category that's long been acting weird. And that's where my bug comes in.

The Actual Code

The bug I discovered has to do with how I group the feeds into those categories. Specifically, I learned that this:


Is not the same as this:

]) | Q(approximate_update_frequency__isnull=True)

The critical change is the switch from including None in the list of allowed items to explicitly filtering by isnull. It seems minor, and it totally feels like you should be able to use None in an IN collection, but you can't.

Funnily enough, the query sort-of works with the None in there, it just ignores the None and uses the other two. The true issue arises when you try to inverse the condition using the NOT operator. This is exactly what Pine.blog's dispatch tasks were doing. It would first fetch the list of every feed matching that criteria, and then do a second fetch of everything that didn't match, and that second one is where results were getting lost.

All this means that some feeds in the second group were being lumped into the third group, delaying their posts from appearing for hours. I've known about this issue for a while, because the posts from this blog (which squarely fall into the second group) weren't showing up in Pine.blog until the following day.

Glad to finally squash that bug.

* This update also migrates Pine.blog to Python 3.7. It's been on 3.6 for years, and I only upgraded it because homebrew screwed up my 3.6 install and it was easier to upgrade Pine.blog than downgrade my Mac's Python version. Fun times.

Announcing Nine9s.cloud 🎉

We interrupt this blog for a special announcement

I'm super excited to announce the release of Nine9s, a service providing simple, no-fuss uptime monitoring for developers on a budget. Whether you're a hobbyist with a blog, an indie-dev working on some side projects, or a small dev shop, Nine9s is here to make sure your site is up and responsive for your users and to alert you of any slowdowns or outages.

I've used Uptime Monitoring services for years, but I've always been left slightly dissatisfied. There's lots of great services out there and they do a lot of stuff, but they either feel like overkill, cost way too much, or don't quite do what I need. That's why I built Nine9s.

If you're in the market for inexpensive, but powerful, Uptime Monitoring, then please check out Nine9s. You can even get started for free and see what it has to offer, and check out the roadmap for what's coming.

Nine9s.cloud: No-fuss Uptime Monitoring for Developers →

Nine9s and the Environment

Nine9s is the first service I've ever run that's powered by servers outside the U.S., and there's a reason for that. I care about the environment and about mitigating the effects of Climate Change (I'm a vegetarian for some of the same reasons). I've always preferred to use Linode for my hosting and while they have lots of datacenters in the U.S., none have committed to using energy from clean and renewable sources; though, their datacenters in Europe do.

I've written up a whole explanation about how and why Nine9s is hosted in London as well as calculating the environmental impact of running the service, and I hope you check it out. Running a small service like Nine9s off of green energy isn't really going to make a big difference in the world, but it's not going to actively make things worse either, and that's what matters.

From Idea to Launch in Two Weeks

I've had the idea for Nine9s for years, but I'd never gotten around to actually building out the service. Besides the fact that I never do anything until I have a domain name, I'd just never had the time. That has changed recently.

On May 27th, exactly two weeks ago, I bought the domain nine9s.cloud and got to work. Everything you see was built and designed in that time. This is the fastest I've ever launched a commercial product, and I don't think I could really do it again. Nine9s is a fairly simple service, and I ripped most of the infrastructure from Pine.blog which made getting started really trivial. That said, I'm really amazed just how quickly I was able to put everything together. I took very few shortcuts, wrote good code, and spent a good chunk of time designing and implementing the service; I don't think it's what I did that matters, it's what I didn't do. Nine9s has no dynamic front-end, it runs on one server, it uses tools I know by heart, and it does one job and does it well.

This Site Supports Webmentions!

Today is an exciting day! As of today, this static blog supports Webmentions. For those who aren't aware, Webmentions is a technology that allows websites to let each other know when one mentions another. Webmentions can be used to support likes, comments, replies, and reposts over the Open Web with no platform in the middle. This means blogging gets all of the great social features that previously required a Social Media company. Webmentions rock.

Typically, Webmentions require code running on the host server, and since this is a static site, it hasn't been possible for me to implement them here. However, the newest version of Pine.blog now lets you add Webmention support to any site. Pine.blog acts as a simple middle man and provides you with a Mentions timeline just like you'd expect from social media. All you have to do is add a <link> tag to your site's header. Which is precisely what I've done here. There's no server code on my end, and I can see all of my mentions in my Pine.blog Mentions timeline.

Cross-Site mentions are yet another way that Pine.blog is trying to push us towards the Open and Indie Web future! No matter where you blog you can get all the interactivity of Webmentions and cross-site replies.

Blogs can and should be the social network of the future, and Pine.blog is here to help make that better world a reality.

Bring Us Your Static Sites, Yearning to Breathe Free →

A Whole New Mac

Today was an important day. Today I'm finally retiring my 2013 MacBook Pro. I'm even writing these words on a new Mac. It's been a long road, but my dependable, old 2013 MBP has reached the end of its life... as my primary computer. It still works well, so I can't bear getting rid of it. At this point I think I'll wipe it and use it for editing music.

A New Fantastic Point of View

As I type these words on my new 13" Macbook Pro, I feel extremely relieved. This laptop feels great to use. It's small, light, powerful, and beautiful. The keyboard works well and feels good, the display is beautiful, the touch bar with an escape key is a good compromise, Touch ID is great, and Migration Assistant transferred everything over perfectly (even my blogging engine and the outdated versions of Python 2 on which it depends).*

I look forward to taking this thing through it's paces. I've taken my 2013 MBP across the US and beyond, so there's no telling where this one will go. I'll miss the HDMI port and Magsafe moreso, but c'est la vie. The years start coming and they don't stop coming; so must I march along with them.

Welcome to the party, new MacBook. I hope you're ready to rock.

* Migration Assistant remains one of the most magical and underrated pieces of software Apple makes. It transfers apps, files, .rc files, everything in /usr/local/bin and more. The idea of having to manually migrate my files and applications makes me cringe. I've never set up a new personal Mac after my first one.

Why We're Polarized

It took me way too long, but I finally finished Why We're Polarized by Ezra Klein. I got the book when it came out, but after making it half-way through I got distracted. I regret not finishing it sooner.

Before I go any further into the whats and the whys, I will pause to just briefly say: you should read this book. Just do it. It's a quick read (unless you take 6 months off) and it's exactly the kind of thing Ezra is famous for: good, thoughtful, explanatory writing on a nuanced and complicated topic.

A Systems Perspective on These United States

For the curious, Why We're Polarized details the story of, well why we're polarized. Specifically, Ezra explains what polarization means and why it's a problem in modern American politics, then takes us through how we got here, what polarization has done to our government (and us), and then offers some advice on how we can mitigate its more potent aspects.

Ezra brings the weight of recent social science to bear in supporting his theories and he's spent countless hours before and after the release of his book discussing the finer points in audio form. I won't go any deeper here, just read the book and listen to those episodes.

What drew me to this book the most is that, in it, Ezra looks at our politics not as the result of individuals and their actions, but through the lens of systems and their incentives. That perspective isn't just what brings me back to Ezra's work over and over again, it's exactly what makes me recommend it to friends and others who aren't interested in, or those who don't follow, politics. It's an uncommon take, but one that I, and I know many others really enjoy.

What Now

I can't say the book is terribly encouraging. It's pretty downright depressing at times, but it does clarify a lot of nuanced truths: from what motivates the push toward radicalism in the Republican Party, and yet moderation in the Democratic Party, to detailing how the supposed glory of midcentury American politics was in part due to the long shadow that slavery, racism, and the failures of Reconstruction cast over this nation. It's a real pick-me-up.

That said, I found myself even more hopeful and optimistic that these problems with our politics can be solved. Knowledge of the problem and understanding of its nuances is a huge part of the work towards finding a solution, and I for one, feel better armed in the fight after reading this book.

Ezra has said on his podcast, as well as in the book itself, that the solutions he offers at the end are mostly there for decorum. Books about the problems in politics usually end with solutions, so he does too for the sake of fitting in. But one of his suggestions has actually helped me significantly in my understanding (and coping) with the world of politics, law, and government.

"There are over five hundred thousand elected officials in the United States, only 537 of whom serve at the federal level." ... The 537 federal officials are the ones we have the least power to influence, if only because they have, on average, the most constituents. But we often don't know the names of the officials nearest to us, even though they'd be glad to meet for coffee...

[T]here's a real reward from rooting more of out political identities in the places we live.

This book is obviously pre-pandemic.

I live in California and lately I've tried to focus more on my state and less on the national dramas. I've started following more local papers and more state news. I feel better about the world, more hopeful about the future, and more connected to the place I live. I'm not always successful (in fact I have a lot of room for improvement), but following the goings on of my City, my County, and my State have made me more optimistic, more informed, and arguably more influential. I've started emailing my City Councilmember and my State Assemblymember, and they actually respond, not with a cheap form letter, but with a real, human response! Even if it's only to take my comment and throw it on the pile, I feel like I've actually contributed, much more so than I ever would just ranting about the President or the Senate on the Internet.

I think we've all let the inter-connectedness of the Internet overshadow the communities we have at home. Community on the Web is a marvelous thing, but there is also a sense of community to be had... in our communities.1

1 This advice also works in our current pandemic-laden world. As I said on my microblog:
In this time of crisis, look to your local goverments: city and county. There are thousands of people working hard and looking out for you and for your community.