I've been lucky to have the opportunity to build several software systems completely from scratch over the course of my career. While many of us spend our day jobs frustratingly making tiny changes in piles upon piles of code, starting from a fresh directory, maybe a git repo, and a blank IDE can be a refreshing experience. It's especially rewarding when you hit simple milestones, like another developer contributing a feature, or a single user finding some value from the creation that came completely from your brain. But how can one design software to not end up like so many of the projects that we hoped our (software) babies wouldn't? Even if you live in a vacuum, are only writing this code for yourself, and have literally no time constraints, chances are there are things that you're just not happy with in your project.

At almost every step in the early phases of a project, you are one decision away from disaster. Not a total disaster that renders the project useless, but some decision that later on introduces an invariant which gets manifested as tech debt and slows progress down to an arduous grind. Any when an empty directory is staring back at you, there are plenty of purely technical choices to make.

Which language(s) do I use? Which frameworks do I use? How will I structure my code? What will I write myself, and when will I reach for a library? And which library to choose? How will I configure my program? How will my program communicate with others?

And these are just some of the big ones. What about all of the tiny choices that we make on an hourly or even a per-minute basis?

Do I pass this variable as an argument to a function or store it somewhere? What do I name this thing? Which package does this class or function belong in? Should I introduce a layer of abstraction here? Should I use a switch here? How will I handle this error?

While these may seem insigificant compared to the previous list, you must be careful, since many of these little decisions can make or break your entire project.