Published on
Reading Time

Primitives as a Long Term Career Strategy

Table of Contents

Overview

My goal over the next 20 years is to build (or be involved in building) multiple projects simultaneously via Hold Equity.

Hold is intended to be a permanent vehicle for products and investments. The core strategy of this model, is reusable primitives across many projects to enable faster MVPs.

This post explores some of those primitives, and will be expanded over time to add more.

Disclaimers

There are a lot of ways to build these sort of projects, and nothing here is proclaiming to be the best way, or the way you should build something similar. My goal is not to grow a single project as fast as possible. If it was, this would be a distraction.

I am trying to build up a "business in a box" so to speak. A core set of APIs, to enable new products with plug/play integrations across the portfolio. To do this well, I have to dog food. For a long time.

I will write about my long term strategy another day, but read everything below through the lens of "Functionality many projects under the same roof might need".

What is a Primitive?

Lots of people have opinions on this. For me, a reusable service. Thats it. Could be an API, could be a React library.

I am not obsessed with the defintion, other than a clean abstraction, something that could be usable on multiple projects at the same time, and useful if your core product assumption is wrong.

I explictily say "useful if your core product assumption is wrong" because I fully expect lots of things I build to fail. I'd like to slowly build ancillary services up over time, that are reusable, to speed up this process.

I will know a primitive is "successful" if it makes starting another project easier. These should compound over time.

Each primitive should do something that would take multiple hours/week to get right in one project, and make it a 5 minute job.

These will be consumed by an API layer for each project itself, but abstract away hard things that might slow down the next idea.

What are examples?

I have 3 currently in use

  • Email
  • Scheduled Jobs
  • Personalized Content

Email

This does operations like:

  • send a verification email to customers
  • verify domain so customers can send emails from their own domain
  • take in tailwind styled HTML template and deliver a styled email
  • schedule an email to be delivered at a certain point in time
  • schedule an email to be delivered with a fun syntax (kameronkales@daily.kameronkales.com) -> This would schedule an email to be delivered the next day to the email registered to a user, kameronkales at the time set in my account.

So why break this out?

Every project I've ever worked on needed to send emails. Instantly and scheduled. I have recreated this same logic over and over, in similiar ways. Usually inside a project folder, called from an API.

Every project I work on is going to use TailwindCSS. Might as well make this easy across projects with a single, clean abstraction. This will let all projects move between "providers" or "vendors" without concern of how the email is actually being sent.

An example of this being, two versions of the API. /v1 using a different provider than /v2. This removes projects from worrying about these implementation details.

This isn't exactly innovative. This is standard separation of concerns in any tech stack. Just done with the mindset of "external" consumers (AKA other projects) potentially utilizing.

Scheduled Jobs

This does operations like:

  • call an API at X time
  • log success/errors of those calls, and retry if failed

Delayed jobs are not that hard in Node. There are lots of projects you can use to do it. There are very few that avoid polling though. I was looking for a serverless solution, backed by something that will scale without me worrying about it.

I don't really intend on having 20,000 jobs in flight at the same time, but if I did, this solution would handle that just fine, without any other projects having to deal with the headache of setup.

This again, isnt the most innovative solution. But solves a recurring problem I've had without the worry a traditional queue would get backed up or server would be down, and the multiple projects that rely on this would be S.O.L.

Why break this out?

I will be happy if I never have to set this up again. I dont want to think about queing jobs and ensuring they get run (or any of the retry/alerting logic implemented here).

If I build another project or two in the next 3 years, and never have to implement this again, I will be more than happy!

Personalized Content

This does operations like:

  • Takes a URL + user and generates a link specific to that user
  • This works great if you want users to be able to view authenticated content, in a web view from their SMS app (for example)

Why break this out?

This feature is something the web seems to lack. Selfishly I've always wanted this in projects I've worked on.

In general, there are 2 approaches to this. Either, 1 size fits all, blast (usually) emails, or full blown use our UI to generate this.

I want to be able to do this across projects, with ease.

A customer of a project of Hold, should be able to decide how they want content delivered, and we should be able to deliver personalized to he/she.

Joe would like blog posts about Javascript delivered via text, at 7am so he can read them before starting work

Alexa would like blog posts about ESBuild delievered through email, around 10am so she can review with a team member.

This ^ isn't exactly "hard", but pairing this with scheduled jobs + our email ability means

  • generate unique content per customer
  • deliver on the channel he/she wants
  • when he/she wants
  • across the portfolio
  • from 1 API

^ This also inherently means, each project gets the benefit of ignoring the complexities around each service :)

Summary

This approach is intended to slowly build up services to enable faster iteration in the future. Common functionality is broken out, and made reusable, through primitives, and joined into a versioned SDK across the portfolio.

^ I just used every buzz word possible here. TLDR: do lots of stuff fast

This lets each incremental project get the benefit of the hard work (AKA lots of learning) done for that project, and forces me to dog food the projects to make them useful.

This is the exact opposite approach to take if your most pressing goal was to launch (and monetize) something ASAP. Mine is the opposite of that.

The intention is to build these services, and learn over time. These services will either end up useful, and help speed up the delivery of new projects, or I'll learn a lot about integrating, deploying and managing all of these, and still be way better off than I would be had I not done this.