This. I have a large directory containing side projects that will never and were never intended to see the light of day; solely built for the learning experience.
Generally speaking, when I discover some interesting technology, I attempt to implement it in whatever language I am currently trying to improve my skills with, regardless if it's not the best environment. A good example of this was implementing the Ethereum VM in PHP. After just a few weeks of tinkering, some takeaways were learning the best and fastest ways to interact with binary data in PHP, improving my mental model of state machines, improving my debugging skills, learning how JIT compilation works, handling "big numbers" properly and caveats between several available libraries, etc...
A few important rules that have proven successful for me:
1. If available, your first iteration should be built purely following a specification (e.g.: RFC, whitepaper, yellowpaper), otherwise, if you have enough domain knowledge and understanding of what the program should actually do, build it without any reference, but allow an exception for researching (when required) very specific problems such as determining the best sorting algorithm for some function. Performing either of these will challenge and improve your ability to carry out the SDLC.
2. Hand-in-hand with #1: Don't start testing against (or even looking at) other reference implementations until at least iteration two. Whichever iteration this lands on, it'll likely be your first major refactor and will be the most time consuming, but most satisfying step. You will discover things you've (supposedly) done right (awesome++), things you've done wrong (learning++), and maybe even novel solutions to problems that end up being noteworthy contributions to the community (really awesome++++).
3. For lack of better phrasing: Focus on the specific task of the program or library. For example if your project is multiplayer netcode, you will of course need a game engine of some sort to capture a realistic state from, feed the data to, display it, etc. Sure, go ahead and write a simple game engine, but as cool as it is, don't focus on that...just get it to do what you need for your netcode! Game engines are cool and so are other subsystems of multiplayer games, but don't get distracted. This example is being used because multiplayer games are complex and meticulous and spending too much time on each subsystem may lead to burn-out or disinterest for what should be a far smaller project.
4. Don't worry (too much) about the language or environment being used. Unless you're planning on the project materializing in to a product, the sole intent should be becoming a better programmer, which requires only one language and a fresh project. Learning a new language isn't going to immediately make you better at programming, although there are plenty of benefits in learning new syntaxes and paradigms. Plus, you may always use your newfound domain knowledge as motivation to pick up the appropriate language and/or platform.
5. Never be intimidated.