 Loses it, Wordle once, builds a number app. Developers journey, we all lose eventually. So there it was, down to my last guess. I'd found the first three letters and was confident I narrowed it down to the last possible option. I had not, proxy, the word was proxy. How do you forget the word proxy as an engineer? So you lost it, Wordle, what now? You could write a self-help book. I did not do that. I experienced what could only be described as grief. With loss and failure often comes grief, even when losing a simple game. We all grieve in our own way. We process it, we handle it. In grieving failure, I still try to find opportunity. Failure often sparks inspiration for me. So I got an idea for my failure. What if I were to build something that could suggest words based on previous guesses? So now we get to the point of the talk. No, the other one. No, the other, other one. Yes, that one, fun. So personally, I was not having fun with the game, but seeing all my friends playing still made me want to participate. The idea of building something sounded fun to me. So really at the core of it, this talk is about finding fun and joy where you can. For me, it was to remember. It's been a long couple of years. I wanted to get back to the idea of engineering as an act of creativity. There's something special about working with a tool that you love. For me, Ember is one of those tools. A guitar, a paintbrush, an IDE. They're all really just vehicles for creativity. I think that most of you watching would agree that coding can be an act of creativity. Now I'm going to walk through how I turned my idea into an app. First, I wanted to define my minimum requirements so I had a goal to meet. For my initial idea, I determined that I should build something that would do the following. Given input letters of three specific types, I should be able to derive a subset of five letter words that are possible with the input data. But first, I needed words, lots of words, whoa. So I started searching for lists of five letter words and happened to find a couple of sources that looked promising. From the list I was able to find, turns out there's about 13,000 five letter words in the English language, give or take. However, many of them are either proper names or so rarely used, it should probably be excluded for efficiency. So I cross-referenced my list with another that was ranked by frequency of use and whittled it down to about 5,000 commonly used words. So now I had some words to work with. Before I go much further, I should probably explain some terminology that I used throughout the talk. For every guess, I get information that I can use to narrow down the list of options. There are correct letters that are included and in the correct position. There are included letters that are included but not in the correct position. And finally, there are excluded letters that aren't included in the word at all. Given these three types of letters, we can actually narrow down the list of possible words pretty quickly. This is because correct and included letters have additional information, specifically a location where the letter is or isn't. As an example, say that you guessed the word ember and this was the result. Now let's take a small selection of possible words and see what this information can tell us. Correct letters give us the most information as I can exclude any word that doesn't have a letter at that specific position. So given that E is the first letter, we can exclude react, learn, and bears. The rest of the words have E is the first letter so they can stay. Included letters are almost as useful as I can exclude any word that has the letter at the position. With em in the second position, we can exclude ember as a possibility. Further, we can exclude any word that does not have an em since we know that em has to be included. So egret and earth are out. And finally, excluded letters give us helpful info since we can exclude any word that includes them. Looking at the R in the last position, we can actually exclude any word that includes the R. So that leaves us with exams. In fact, out of almost 13,000 possible words, this one guess brings us down to 15 possibilities, four of which are more commonly used words. Next, I started with a small prototype. So for my first prototype, I tried building a node class that took the guess input and Bruce Force compared it to the list of 13,000 words for possible matches. As you can see here, it wasn't very performant. So obviously searching 13,000 words or even 5,000 words can be extremely slow if you're not careful. So I called my friend Al. While building my prototype, it occurred to me that I could use the known letters from the guess data as a dictionary key to look up the words that include them. For indexing, I use every common, I'm sorry. For indexing, I use every unique permutation of the letters in a word. That way we can quickly identify a subset of words that contain the letters from our guess data. For instance, the word ember would end up with something like this. First, we sort the word for normalization and then we iterate through building permutations of smaller and smaller sets of the letters in the word where we end up with something like this. Finally, we combine the data and merge it into one list. Using these values, I can build a dictionary of letter combinations to words that contain them. The alphabetical sorting that we did at the beginning makes duplicate removal very easy. To speed things up, I extracted and sorted, sorry, I extracted and stored the position indexes so I don't have to recalculate the permutations every time. Now that I had a brain, I needed a body. For which, of course, ember is awesome. Ember makes building a reactive app easy. Thanks to track properties, you can build elaborate systems that are simply driven by state flowing through the app. Auto-tracking is magical and I don't care what you say. It builds a foundation for everything. All of the app state is accessible through services which can then be used everywhere from custom classes to templates. I use custom class instances that manage state for the components throughout the track, through the track properties rather than using models. This lets me use the reactivity model to rely on guest data anywhere in the app with none of the drawbacks that you would expect for doing such a thing. So here we can see the reactivity model in action. The tile components use the derived state from the letter custom class and update automatically. As we saw earlier in Jim Schofield's async talk, resources can help encapsulate complex logic to be lazily accessed as derived state from components or templates alike. They can also solve issues other than async fetching. I was running into an issue where I was trying to render too many elements to ones, which was causing a slow initial render. I'm not exactly sure if that was the cause, but that was my theory. To test my idea, I wanted to limit how many words were being rendered in one cycle. So I wrapped the word list in a resource and use set time out to slowly feed the words into the each helper over time. The resource acted as a buffer for the process that was slowing down the rendering, which fixed the issue. With resources, you don't need to worry about how the data is getting there, just what to do when it does. Here we can see the difference that it makes, comparing the before, which takes about five seconds to start rendering, and the after, with the resource as a buffer with almost no pause at all. It's a huge difference and makes a much better user experience, all thanks to resources. In the spirit of experimentation, I implemented dynamic keyboard layouts for fun. Note that the layout is completely reactive thanks to track properties. The tile components are simply rearranged as determined by the keyboard setting. The setting is just a string that determines which keyboard information to use, which changes the letter order, and the same string is used for a CSS class that applies the style for the layout. And here we see the finished product in action to give us a clearer understanding of how it's used. With every guess, I update the letter status based off the guess feedback, which begins suggesting words. This first guess brings us to 138 possibilities. Our second brings us down to one option, Chal, impressive. So while it may seem like a solver, it's not actually optimized for that task. It takes no historical or external information into account, which would likely improve the accuracy earlier. I've never actually solved anything in less than three guesses with it. And really, the main goal is to aid word discovery because I'm bad at words. I couldn't decide on a name, which sparked an idea to make a slot machine animation to cycle through different names. I followed my interest and spent some time making an Easter egg, which was a lot of fun. Now lastly, I'd like to share some advice that's helped me on personal projects. Some tips that I've discovered for working on creative coding projects in general. Speed is absolutely necessary to get your ideas out. Getting bogged down by challenges unrelated to your intended tasks can mean death for a project. Use add-ons when possible. There's no need to solve an already solved problem. I use several add-ons for my project. So don't build it unless that's actually what you're trying to do, and then by all means, build it. Ember Apply is extremely useful for quick installs and new projects, be it Tailwind or Embroider, or you can actually use it to write a custom preset of add-ons that you use for your own projects. On the topic of speed, nothing's faster than using something that's already done. I highly recommend building your own custom starter kit. This could be a repo that you clone or fork, or you could use something like Ember Apply to create a custom preset to install on new projects. Building a template app that's already set up with your favorite add-ons can get you started that much quicker. Stylers are only as critical as you want them to be. Tailwind's great for quick prototype styling because it's so composable, but you can just use plain CSS if you're more comfortable with that, or don't style it all. It's your project, do what you like. Saves and save points can give you an extra life. So try and get into the habit of committing often. Commit often even for small changes. Having any git history can help salvage an otherwise unrecoverable wrong turn. You can use git tag to mark save points and then use combination of reset, merge, and checkout to manage history. You can then use git reset hard, plus your save point tag to load back to a specific point, but be aware that it loses any unsaved data. Or you can check out a tag as a new branch to experiment and explore. Think of it as save points in a video game. By committing frequently, you give yourself save points that you can branch or recover from. You minimize the risk of exploration because you can always go back. This frees you up to try stuff out and fail, or occasionally succeed. On the continuum of risk, it's like the difference between the save capabilities of a game on the classic NES versus the Nintendo Switch. Or for PlayStation folks, Returnal, where you lose almost all progress when you die, versus Ghost of Tsushima, where autosaves make it almost impossible to lose progress. Always try and start small in scope. I usually start with a prototype first, and then I'll try and break my ideas down into smaller tasks. I try and tackle one thing at a time, and you'll find that you get further than taking on everything at once. Don't go too far the other way either, and dive too deep into one part. It's not about excluding ideas, but rather a practice of focus. Well-rounded projects tend to live longer. Speaking of death, let's talk about project entropy. Every project has a natural lifespan that is influenced by the interest and energy that you can afford it. It's important to recognize and accept that projects die. Entropy sets in, life moves on. It's okay to let projects go. I think a project graveyard is a sign of a good developer. Some devs have tiny graveyards, and some are more prolific. And it's not unheard of to resurrect a project now and then. Along the same lines of scope, measure and follow your interest. Just because it's a fun project doesn't mean you should always default into treating it as a spike. Sometimes it's a great place to explore more rigid concepts that you wouldn't be able to do in a company setting. Follow your interest and see where it takes you. You should allow your level of interest to drive your level of complexity and effort. That is to say, don't waste your time on building things that you aren't interested in. Ember has thousands of add-ons. It's highly likely you can find an add-on to handle parts of a project that would slow your progress or distract from your main goals. Most importantly, run wild. It's a perfect opportunity to over-engineer or try out that experimental feature that's too risky for prod. Use tabs instead of spaces. The only limit is your imagination. You can find my app at jakebixby.com slash wordle and the project source is on my GitHub. If you'd like to work with me, audit board is hiring, so please reach out. And finally, thanks. Has this ever happened to you? Have you found yourself playing a popular word game that your friends talked you into? Then suddenly forget every word you've ever known. Perplexed by starting words or any word at all? Felt annoyed when your partner gloated about getting the word that you missed in three. What if I told you that there's a way that you, yes you, could somehow enjoy wordle after all? Well, now you can. Try a new wordle finder. Do more efficiently, sort through your options and find the right answer quickly. The reactive UI built with ember will help you find the answer every time. Act now and you'll also receive bragging rights as a special bonus. Take that, smug partner. 100% reactive UI built with ember, not available in stores through a cousin's room, it's MLM, or by summoning a demon. Get yours now at jakebixby.com slash wordle. That's jakebixby.com slash wordle. And start winning at wordle now.