750 Words V2 Progress
Weekly technical notes on progress as we rebuild 750.
Disclaimer: My plan is to share unpolished notes on progress at least weekly while building 750 Words V2. It’s going to be filled with details that you may find incomprehensible, boring, or completely misguided. Lots of details that should be included will be missing, while at the same time many details that could have been left out will be included. I’m sharing it here without attempting to make it entertaining or worth your time at all, because that would take too long for me to curate, and I just want to share it in case someone is willing to do the work filtering out all the noise. That said, feel free to comment on things or reply with suggestions or ideas however you like.
Questions we’re pondering
- What can we do to emphasize community on the site a bit more, without changing anything about the privacy of posts (it’ll always be private)?
- Should we reconsider how time zones are used? Right now, they’re basically a way to hack when the “day” ends. But maybe we could just let people tweak that without having to pretend they live in Hawaii.
- Would it be interesting to consider showing people how fast they’re writing today’s words relative to others who wrote the same day? I don’t want to add stress to the experience, but I think there might be something here that improves the feeling of solidarity in the group. We run faster when we’re running together. Something worth exploring, at least.
Week 4: January 13th-17th, 2020
After a somewhat extended time off for the holidays, we’re back in our seats and have reminded ourselves of what we were doing way back in 2019. This week is turning out to be pretty productive. Made progress on:
- Smoothing out some of the login/logout flows so that if people accidentally log out, a prompt to log in will appear. And if people try to log out before the autosave feature has run, that’ll get called out too.
- Added code to the composer to save the “pace” of writing. We’re saving words and paces to the browser first, and then to the server every 10 seconds or so, so we can both have more granular data without increasing the server load. This also helps with error handling. It’s interesting to now see how Medium indicates saving and saved status in subtle ways as well.
- Calculating number of distractions in a writing session.
- Tracking when entries reach 750 words and saving streak information and other metadata necessary to award badges.
- When re-implementing streak stuff, I added a way to track how many total days you’ve written anything, and how many total days you’ve completed. This will allow us to implement a less strict badge system for those who aren’t able (or interested) in writing every day.
Questions we’re pondering
- How can we improve the writing experience and avoid making things worse? What should be on the compose page? Can I improve the green boxes? Jan 2020 update: we’re taking the minimal approach. Removing everything until we absolutely need to add it back on. This includes the green boxes, for now.
- Should we rethink how points work? At the very least can we find a way to better account for the fact that people in Australia/New Zealand are always at the top of the list because they have a timezone advantage? (See how points work today and leave comments on other proposals.) Jan 2020 update: I think there’s a good reason to keep points working the same way it usually does, and to potentially add more ways to boost those points by not being distracted, or finishing within a reasonable amount of time, etc. Nothing too fancy though.
- What are some good fonts I should consider? Which products do themes well that I could “be inspired” by / copy? Jan 2020 update: we tested a couple fonts and got sick of them after a bit. We’ll keep looking.
Week 3: December 9th-16th
After the very “systems administrator”-heavy first couple weeks, I am excited to poke my head up and work on some actual user flows. That’s what I like to do. And I also like to work with smart people to help me think through the best experiences. Jon Bell, Sterling White, Vicki Tan, Kevin McGillivray, Evy, Miri, Ashley, Cristin, and several others in my Discord community (holler if you want an invite) have all been giving valuable input on all kinds of user experience questions and possibilities.
I wrote a blog post to start getting people excited about V2, and to share the very high-level plans as they are forming. Including people in the process is one of the things I’m looking forward to most throughout this project. There are two pieces to this:
- Things are built better when a diverse set of perspectives are included. I see so many decisions in 750 that were made in a vacuum, and they’ve been unchanged in 10 years. If decisions are going to last that long, having more input from others is worth the extra effort.
- Sharing the product-building process might help others who are building products, even if they’re very different from the one I’m building. A lot of the building blocks are the same.
Things that I’m working on this week:
- Got entries to save to localStorage and then to the database seamlessly.
- Started a list of all the edge cases (like opening two browser tabs and writing in them both, or cutting and pasting things, or going offline for a while) and build test cases that replicate the weird things that happen here so I can be sure to catch them all. (There are a lot.)
- Started playing with fonts. Sterling White recommended Sentinel, which I like, and we’re using it for a while to see how that feels.
- I floated the idea of designing a 750 Words logo, and Jon Bell said, “The site is about writing. Unadorned. So there’s something really great about essentially being like ‘No Need For a Logo’ because it goes along with the point of the site (in my opinion).” I love when something like this becomes so obvious when spoken that I become surprised that I didn’t start with that opinion myself.
Week 2: December 2st-8th
This week will forever be known as the week of cursing Devise (though I’m sure it’s more about my own failings than failings of this authentication framework). Devise is a very comprehensive and flexible (to a fault) way of implementing authentication. One of the most important parts of 750 Words is that it is secure, and that means I had to be really at the top of my game when making decisions about how to sign up, log in, etc. I spent at least 5 days working through this tutorial and running into many dead ends and edge cases over the coming weeks. Ultimately, I got it working and I’m happy with the end result — now all that flexibility is going to come very handy. For example, I can use this to also authenticate between the frontend and backend servers, and eventually I could use this to generate tokens for mobile and maybe even 3rd party apps that build on top of 750. So many of my hopes and dreams tied up in this particular gem. This is the key for me to being able to build a mobile app without essentially having to re-build the entire set of functionality.
Once this was working, I had to implement Nuxt Auth on the frontend to allow people to log in. And I ended up using dotenv to store secret keys on prod. There weren’t very good tutorials for these things, since I was getting into edge cases that were more and more specific to my particular app. Try searching for “Docker Rails API Vue Devise master key configuration tutorials”. There are some results, but each one is slightly off to the point of it not helping me solve the problem. This is the hardest thing for me when it comes to coding… I can fall into a trench where something isn’t working and I can’t figure it out, and it ruins my day… sometimes multiple days. That happened here. I’m so glad it’s over.
Other small things that got done this week:
- jbuilder for JSON views: Decided to use jbuilder with Rails to handle any complicated views I need to build for the API.
- Vuetify for the design system: Decided to go with Vuetify and CSS Grid for frontend layout instead of Bootstrap, just because Vuetify seems to be really gaining momentum as the best component framework for Vue. This led me to revisit Material Design and get excited by all the progress that design system has made in the last few years.
- Vuex + localStorage for state management: Set up vuex and nuxt-vuex-localstorage to take advantage of all the new-fangled advancements in state management. This is going to help me a ton when it comes to saving entries and moving some of the computation off of my expensive servers and back into the browser. It’s also the key to eventually offering an offline mode.
- ProseMirror for text composer: Earlier in the year I researched text editors for the web to see how much those have improved in 10 years. The original 750 words uses a
<textarea>with jQuery to basically hand-build the composer. I’m very excited to be able to benefit from the brilliance of others who have spent years making ProseMirror a truly flexible and yet elegant experience. And, luckily, there’s a plugin called tiptap-vuetify that makes it easy to integrate ProseMirror into a Vue+Nuxt+Vuetify app. Crazy, huh?
- ActiveJob + Sidekiq + Redis for background jobs: Rails has good support for background jobs that I didn’t take any advantage of with the first 750 Words site. The weird thing about 750 is that most of the computationally expensive stuff has to more do with saving posts and processing them than serving pages to users. So, from the start I’m going to be planning to put all of this in background jobs so that if a bunch of people start typing at 11:45pm to get their words in, the site doesn’t come down and cause major stress to everyone who is working on streaks (hypothetically speaking). This tutorial helped a bit. The tricky part was making sure Sidekiq was on the same container as Rails, and that it pointed to the other Redis container instead of expecting it to be on the same one. I should probably finish that Docker course. This was more painful than it should have been.
- Maildev for email on dev: I needed a quick and simple solution for processing email on my dev computer and Maildev is that. I’ll probably go with Mailgun or something for the prod servers at some point, but this will suffice for now.
Week 1: November 25th-December 1st
I spent most of this week researching various technical stacks, languages, and frameworks, to figure out which new amazing technologies I should use to build this thing.
I started working on V2 earlier in the year, when my book’s manuscript was finalized and I had some time to think about what I wanted my next big project to be. But I got tangled in the weeds of various technical frameworks and coding languages. I thought at the time that I wanted to build this on a Docker + Multi-tenant AWS Elastic Beanstalk. But I didn’t find very much documentation about how to do that. I started taking this course to at least get a better understanding of Docker, and it’s then that I realized that I was going to bite the bullet and host it on Heroku instead of Elastic Beanstalk. I gut-checked this with a few technically-minded friends to make sure I wasn’t taking the cowardly route, but everyone I talked to confirmed my rationale for making this choice. Heroku is more expensive, but if I’m going to be an engineering-design-product-and-marketing department of one, and 750 had the revenue to support it, it was going to make my life a lot easier. And I want my life to be a lot easier.
The technical stack at the end of the week looked like this:
- Containers: Docker for keeping everything tidy.
- Backend API: A Rails 6.0 app in a Docker container would serve as the API and backend to the website (and eventually mobile apps as well). Rails was another “not perfect but would make my life easier” kind of decision, because the original 750 Words is also on Rails.
- Frontend: Vue + Nuxt in a Docker container. I wanted to de-couple the frontend and backend, and take advantage of some of the amazing advancements in web frameworks. After playing around with this, and React, and a few other options, this one felt the most elegant.
- Database: Postgres in a Docker container.
- Repository / Development Environment:
- Deployment: Two Heroku apps (one for the frontend and one for the backend) that deployed separately. I used this very useful 2-part tutorial (1, 2) to help me set up the basics of tying together the various pieces so that there was a relatively simple development experience for me. I liked this idea of using a single Github repo and then deploying the pieces as submodules, because a single
docker-compose upcould get all the pieces working together.