TinyDevCRM Update #4: Token-based authentication + hourly journal

Table of Contents

This is a summary of TinyDevCRM development for the week of February 29th, 2020 to March 7th, 2020.

Goals from last week

  • [❓] Ship some form of API backend to https://api.tinydevcrm.com
  • [❓] Wire up token-based authentication workflow to React.js front-end

What I got done this week

  • [❌] Ship some form of API backend to https://api.tinydevcrm.com
  • [✔] Wire up token-based authentication workflow to React.js front-end


  • Weeks to launch (primary KPI): 2 (has been at 2 for the past 4 weeks or so)
  • Users talked to: 0

Hour-by-hour Journal


RescueTime statistics:

Week of March 1st to March 7th (inclusive): 51h 31m (direct screen time, no explicitly marked offline time), 14h 57m software development (much of this is overinflated since I do many things in VS Code include writing reports)

Goals for next week

  • Ship some form of backend to AWS Elastic Beanstalk to get a full-stack workflow going in production
  • Figure out how to use PostgreSQL instead of SQLite for Django while self-deploying instance (i.e. don't use RDS)
  • Talk to at least 1 person on my early adopters list in order to build accountability

Things I've learned this week

  • The Django ecosystem isn't that scary after all. I never dipped my toes into the Django ecosystem because I felt for smaller projects, Flask was more appropriate and quicker to get started. On the contrary, Django has more (quality) tutorials, better accepted culture and conventions, more extensions and maintainers, all of which creates a better environment to write code in.

  • Configuration is hard. Every project necessarily has to ship with its own configuration settings, and given how configurations evolve, there's not a great way to manage them besides strings and structs in files. Django has ‘settings.py’, where many of the settings just look arbitrary. On the positive side, having a more data-driven method of configuration management makes it easier to develop more complex extensions (even django-rest-framework-simplejwt had a good number of knobs to turn, which goes to show how far out of my depth I am), and it's easier to understand the behaviors of middleware (such as authentication pipelines). I used to hate middleware, because I never understood how it worked, and I generally resent “magic” in my code. Exposing it as a series of lists, that Django tries sequentially, helps me understand how Django might fail over.

    I do appreciate SQLite after this week. I think having just a file that you carry around in a single instance makes that first deployment step much easier, especially since there's so much more configuration overhead for other parts of the stack (like even just setting up CI/CD on the backend using Jenkins / AWS CodePipeline).

  • At this time, I remain unconvinced about the need to implement front-end validation. It's not that it's not important. For larger systems, it could help in cutting down on the number of unnecessary requests, and it could save the user some time by avoiding round-trip requests to the server. For me though, I want my clients to be cheap, and I'm concerned about duplicating validation logic and having to maintain two sets of validation For example, if you update a password rule in the database, that rule would mutate validation logic on not just the backend(s) but the frontend(s) as well. You could write a validation module in JavaScript, but I'm concerned that would imply usage of Node.js or something JavaScript on the backend, and I'm not willing to pay that kind of price for validation. In the future, I might write a separate validation module in backend language of choice, and transpile to WebAssembly and load that validation as a JavaScript blob.

  • REST API endpoint conventions are hard. “There are two hard things in computer science: cache invalidation and naming things”. I find that holds true for API naming. I get that this is still just an MVP, but I don't want to form a habit of breaking backwards compatibility, or having to iterate on the number of API versions I need to support. For me, this results in a very “sparse” API. I'd rather issue an HTTP POST request /users/create than /users, because I don't want to possible conflate another, currently unknown type of POST request for the same API endpoint. This will probably result in “enterprise-y” naming conventions for this project.

  • I really like the hourly journal. I got this idea from Adora Cheung's YC Startup School video on time management, where she mentions how bullshit metrics can easily conflate with the two metrics that startups should actually look for: number of users talked to, and progress of product. I've found myself much more engaged during the day, and I like having an audit log I can go back and review. Maybe I'll even keep this going after I go back to work; who knows.

Subscribe to my mailing list