This month’s newsletter is purposefully shorter because I got married this month! I decided to take off time from work and other obligations to embrace the moment. There’s times in our lives we want to cherish the experience over spending time lost in our devices, so I dedicated two weeks to wedding preparation, having the wedding, and enjoying a much needed break on our honeymoon.
Walking away from the altar
I hope you all are doing wonderful and looking forward to starting something fresh in June!
After a month long break, we’re back! The reason for my absence is I got married! 💒
At the altar
It’s been one crazy month. Everything leading up to the wedding was a whirlwind.
Everything after the wedding has been nice and calm. We spent our honeymoon in Maui, then all of last week after our return, we spent on the couch sick with COVID-19.
This week, we’re back. I’m coming back at you all with some links that I found for the entire month. After this update, I’m going to overhaul a few things about the weekly notes.
Link Roll
The goal of a book isn’t to get to the last page, it’s to expand your thinking.
— Dave Rupert
Everyone is waiting for that one post, that one video, that one podcast from someone that explains things is just such a way they can understand.
— Jim Nielsen
I’m pretty mad about this article. What I’m taking away from it is the low level details don’t matter for human comprehension. That’s really not true. Many times, assumptions are made early on that take a codebase one way, then later on, the requirements change and logic needs to be adjusted.
I’m not sure this person has spent enough time with LLMs on how messy the code they write is. Like it’s fairly unoptimized and feels extremely hacky. Yes, the code will be better in the future, but today’s LLMs don’t have this yet. And to expect a CEO to determine how this code is run is terrible because the nuances of what needs to be comprehended is not there.
Instead, the work of an engineer isn’t to read prompting with the LLMs output is but to decide if the code is maintainable. The idea of configuration over convention increases cognitive exercise, not decreases it. The article assumes the LLM output can read and write through the code and the engineer is lazy and doesn’t want to read through technical details. The best engineers are the ones who read through those technical details and understands those nuances.
I agree though in that businesses don’t care about code craft. They have other priorities - and it boils down to being able to make money (in a for-profit anyway).
Wood chips or the material cut from a book can be used as bonus material
I just realized TikTok and short form video appeal is when you’re reading articles and books on behalf of an audience. Like duh. People don’t read and it’s easier than reading
One creator I didn’t know I was missing from my life was Van Neistat. His philosophy about the spirited man really speaks to me in a way I wish I found earlier. One of his videos surfaced about screws. It’s not a comprehensive look at them more than a practical one. I spent a lot of time with my dad at Home Depot, and screws have always fascinated me on our 3-hour long trips there.
Also from Colin and Samir interviewing Van. On why digital tools don’t translate for him. His brain is wired different.
While the Republican-led Congress has used its power to condemn any protests on behalf of Palestinians, where was the same outrage and zealousness when white nationalists came to college campuses?
I think about the Shiny Toy Syndrome every so often. A few years ago, I was being interviewed on a live stream, and the chat kept bringing up more technology I’ve heard of but haven’t used yet. It’s one of those nagging things in the back of your mind that you must catch up with the latest and greatest. However, having worked in software for the past decade, the latest and greatest is oftentimes obfuscated with what is known to work and what doesn’t. Best practices take time to discover. Many corner cases are not covered. And sometimes the new shiny thing is hidden from your readers or customers, so you are cranking widgets over creating value.
I love playing with new toys. But there comes a point where to get anything done with that toy, you have to learn from YouTube tutorials, blog posts, and Reddit threads. After mindlessly scrolling through this, your brain is too tired to start. (I’m looking at you Anki). Sometimes, it’s best to get started with what you already know today, and later pick up the tool if it meets your criteria.
If you know how to use Postgres and SQLite, use them! Are those new databases fun to play with? Yeah, I bet they are, but you know that will be time spent on learning that new tool. I’ve been in tutorial hell since starting my programming journey, and I realize it’s better to pick up a new tool when you’ve got a project in mind. But be warned, it should be the only new variable. If you try to stack new technologies together, you’re in for one hell of a ride. Like if you want to use a new Database, caching layer, and server framework, good luck to you. I don’t have the time or patience for that. I’d rather spend my evenings working on enough knowns.
That brings me to the Should vs. Must. In Elle Luna’s book, The Crossroads of Should and Must, she describes this pull of doing what you know in your gut is right. For her, it was painting on canvases in her private studio. I rarely think my pull is to learn R for the fun of it. It’s typically with a different goal in mind, like using R for statistical methods to run on a specific dataset to help me determine statistical significance. With a more specific goal in mind, I’m able to let go of my brain’s tendency to try and understand everything before getting started. An old co-worker of mine thinks about this like inertia. You need a certain amount of activation energy to get you started. When that goal is clearer in my mind, I’m able to lower that activation energy and get the ball rolling faster.
Don’t know enough breadth? Call an expert to get you started.
Don’t know how all of these technologies might go together? Oh boy, there’s an exciting new thing called Large Language Models that might be able to help make you a scaffold.
And many times, the technical aspects are the easiest. The harder part is the context in which you’re creating something. And understanding the market to validate your ideas. Or interviewing your customers to understand the needs of the customer.
Stick with the boring stack. In a recent episode of the Changelog, Kelvin Omereshone (K.O.O) talked about SAILS and being a boring stack. SAILS is a full-stack framework that’s been around for over a decade. It’s reliable. It’s using technology that’s been around for a while, hence “boring”. But that’s the point of being boring. It shouldn’t be there to stop you from what you’re doing. It should liberate you to think about the next thing.
Just start. In An Invocation for Beginnings, Ze Frank talks about all the little ways we start or don’t start. Starting looks different to different people. What you should steer away from is how an idealized version of starting should look like. Embrace the mess. Start with a brainstorm, a post-it note, or a lot of Post-it notes. Fill your desk and reject the idea everything has to be perfect-looking. Life is not a super well-organized bullet journal with neatly made gridlines. It’s imperfect and full of unknowns and assumptions. Start the process before making the template. Don’t edge towards a premature optimization. Just start.
Then, once it’s up and running, we talk about what will work tomorrow.
The weather in the Bay Area during this season is like Mother Nature flipping the switch between cold and hot. She can’t make up her mind if it’s ready for full blown summer or cold rainy days. This comes as I think if lavender bushes will bloom for my wedding next month 🤞🏼. Like most things in life, these forces are outside our control. You prepare as much as you can and let the rest play out.
As with the previous months, I come with some website updates.
Inspirations
I carved my own space of curated inspirations. A table of websites that should technically be a mood board of the vibes I think could go with CraftByZen’s website.
For the past few years, I’ve kept a note of inspirational websites. These websites include blogs that I continue to follow, creatives showing their talents, and web design that makes me wonder.
In the future, I want to expand this to other types of inspirations. It’s driven by my own curiosity attractors.
The Stream
I created a separate feed called “The Stream”. I wrote a short blog about it.
The stream is a personal feed of my thoughts on things I’m working on, interested in, or a random shower thought that might be worth putting some additional thought into. The stream is a form of expression, posting something spur of the moment, without the crowdedness of a social network like Twitter or Facebook. Don’t get me wrong, those places are great for comment and reply interactions. But I also need my own trail of what I’m writing and thinking about that’s not hammered by likes, comments, and other social features that I find distracting.
Classifieds
As part of an ongoing effort to engage my network, I want to use this opportunity for anyone to advertise on my newsletters. If you’ve got a big launch, trying to look for work, maybe find that missed connection, feel free to reach out to me.
As mentioned in the last newsletter, I’ve been practicing something along the lines of my theme, “The year of renewal”. In March, it was testing out different activities to break my dopamine addiction. A dopamine detox if you will. I realized how strong my pulls were and it will take more than a month to break those addictions, like doomscrolling and a constant feed of consumption. During April, I’m experimenting with renewed interests in language learning. I’m almost half a year with my streaks on Duolingo!
I hope you are all doing well and enjoy this lovely spring transition!
A modern action adventure road story where a 17-year-old girl named Suzume helps a mysterious young man close doors from the other side that are releasing disasters all over in Japan.
With the protests happening on US university and college campuses, I want to give some time and pause to reflect on what’s going on nationwide. There’s a lot of political discourse and turmoil over the past month, and I might mix some politics with the next few weekly notes.
Note: this week and next week my notes might be late due to some last minute wedding planning.
A Few Thoughts on Cryptographic Engineering (Matthew Green) - A quick post on Chen’s algorithm. A primer on Chen’s algorithm for quantum cryptography, although as of this writing, a bug has been discovered within it.
A checklist to setup for larger projects by Alex Kladov - Basic Things
Nadia Asparouhova writing in Asterisk - Manufacturing Bliss. I read her book, Working in Public. This seems to be a wildly different article about jhanas meditation and some Bay Area practitioners. Interesting read.
I forked a small demo from Wes Bos and ran in on my own sandbox. It seems much cleaner than using a script tag per each dependency, and works on all major browsers.
In my little demo app, I placed the importmap in the head of the document. I’m using react as well as my own utils file to test out the functionality.
From there, I imported these libraries in a script module.
<body> <div id="app"></div> <script type="module"> /* eslint-disable */ import { useState } from "react"; import { createRoot } from "react-dom"; import { formatMoney } from "utils"; createRoot(document.querySelector(`#app`)).render(formatMoney(100.2365)); </script></body>
I had a hiccup with [plugin:vite
] as I found countless others have, so I wrote a custom bun server to host this project. Hopefully there’s a better setup I can find with Vite using importmap in the future.
Luxon datetime library defaults startOf and endOf methods to UTC. But this isn’t great for end users who don’t live in UTC / GMT. To offset this, we need to grab the time zone offset from the user’s system.
I’ve become a lot more cognizant of how those first six words might be the only thing that show up in the notification panel on their phone, so I need to make sure that those words are a succinct and accurate overview in their own right.
This past week, I’ve been busy at work finishing up loose ends for the next major project. At home, we’re three weeks left until my wedding. We’ve got all major purchases out of the way for the event, as well as booking tickets to Maui for our honeymoon. 💒
The golden visa program brought Spain billions of euros in investments. But property prices paid by rich foreigners are well beyond the earning power of locals.
Today, I have my caps lock key remapped to escape. Hyperkey is an interesting proposition to have the cmd + option + control + shift key down at the same time to unlock more shortcut keys. I’m tempted.
This goes beyond site incident reports. I used to do this for testing as a quick way to determine if we had any weird testing debug outputs. But of course, Sentry bugs should fall under this too. We need to write this in.
No Mercy / No Malice - Prof K on Ketamine Therapy and Ketamine Seizures
While Kelvin talks about the benefits of using Sails, I was thinking about the other “boring” things that constitute a boring stack. It goes beyond tecnologies, like how to run a business, how to organize your team, and how to market the product. And when those things are boring, they are unsexy and oftentimes neglected.
A feature flag is a decision point in your code that can change the behavior of your application.
Temporary flags are often used to safely deploy changes to your
application or to test new behaviors against old ones. After a new behavior
is being used by 100% of your users, the flag is intended to be removed.
Traffic light showing a green light. Unsplash - Eliobed Suarez
Permanent flags give you a way to control the behavior of your
application at any time. You might use a permanent flag to create a
kill-switch or to reveal functionality only to specific users.
Traffic light showing a green light. Unsplash - Eliobed Suarez
Feature Flags Are Context Sensitive
The code path token can change based on the context provided; for example, the user’s identity, the plan they’ve paid for, or any other data.
Feature Flags Are Deployment Agnostic
Feature flags can be used to control which users can see each change. This decouples the act of deploying from the act of releasing.
Use Cases for Flags
Release - A temporary flag that initially serves false to all targets, then progressively rolls out true to targets until it reaches 100%
Kill Switch - A permanent safety mechanism used to shut off non-core functionality or third-party tools in an emergency
Experiment - A flag to test a hypothesis and provide continuous optimization using beta users and A/B tests
Migration - A temporary flag used to migrate data or systems while keeping your application available and disruption free
These are the ones advertised by LaunchDarkly. There are many more use cases, and they allow for customization.
What is LaunchDarkly?
LaunchDarkly is a company that provides feature flags as a service.
At work, flags are served and managed by LaunchDarkly’s services.
LaunchDarkly is integrated through streaming via web sockets, meaning each web app user session receives messages only when necessary. Changes can be pushed out to clients in real time.
A diagram showing the end-to-end connection between LaunchDarkly’s flag
delivery network and your application.
From here, we usually add conditional logic to toggle the flag logic to the target code.
We can also use the same method to do the same on the server-side as well.
Adding User Context
LaunchDarkly uses context to target which flags should be on or off.
The user’s context, known in LaunchDarkly as identity, must be used when initializing the application.
Anonymous Users
On initialization, a user session will be identified as an anonymous user.
This is because in the initialization, the user’s session token (access token) has not been verified yet.
Because we want to use flags for public users as well, i.e. those not logged into the app, we initialize the Provider before the token check.
An anonymous user has two attributes:
key - a unique identifier for the anonymous user and a field on the ldUser type.
anonymous - a field on the ldUser type that notes if a user is anonymous or not. Stored as a Boolean.
Authenticated Users
Once the user authenticates, and the application has retrieved the user context,
we identifies the user using the ldClient.identify function.
In this identify function, we pass along the following information about our user:
key: Our user’s unique identifier (as a uuid)
anonymous: false
email: the user’s email address
In addition, we pass along some custom fields that we can use to narrow down the user’s targeting.
This includes their role and their organization, since our app is a multi-tenant.
If this user has already been added to LaunchDarkly, their flag profile will be returned.
If this user is new, LaunchDarkly will automatically create this user, create their flag profile, and be returned.
Logout
On logout, the application re-identifies the user using the ldClient.identify function.
Since the application has a logout hook, we add a handler to identify the user to be an anonymous user again.
This resets all flags to switch over for anonymous users.
When do we change our flags?
Per Release - For each release, our release team has a list of flags to modify, including toggling targeting and changing rules and segments per rules.
On Market Support - There may be a request to make a non-release changes. These include new customer onboarding and turning on a feature for an existing customer.
Deployments
There are different types of deployments:
Canary Releases - User groups who would like to opt in
Ring Deployments - Different user segments at a time - e.g. beta or power users
Percentage-based Deployments - Start with low percentage, then move to higher. For operational changes
Each of these can be implemented using feature flags.
Feature flags and blue/green deploys are complementary techniques. Although there are areas of overlap, each approach has distinct benefits, and the best strategy is to use both.
Testing
It isn’t necessary (or even possible) to test every combination of feature flags. Testing each variation of a flag in isolation (using default values for the other flags) is usually enough, unless there’s some known interaction between certain flags.
Here’s an example using jest and LaunchDarkly’s mock testing library.
import { mockFlags } from 'jest-launchdarkly-mock';it('tests with the flag on' , () => { mockFlags({ [FLAG_IN_QUESTION]: true, }); // Write your test here});it('tests with the flag off' , () => { mockFlags({ [FLAG_IN_QUESTION]: false, }); // Write your test here});
Flag Maintenance
Cleaning up flags aggressively is the key to preventing technical debt from building up. There’s no royal road to flag cleanup, but there are some processes that make it manageable.
A stale flag is a temporary flag that is no longer in use and has not been cleaned up. Too many stale flags are a form of technical debt and an antipattern that you should avoid.
At work, we follow a practice to do it prior to any major release. This is about every 3 to 4 months.
Questions you should be able to answer now
What is feature management?
A decision point in your code that can change the behavior of your
application.
What is the difference between a temporary vs. a permanent flag?
A temporary flag will ultimately be removed from the application. A
permanent won’t and will stay as a kill switch.
How do flags configured in LaunchDarkly get delivered to our applications?
LaunchDarkly uses streaming via web sockets.
How can flag management be resilient to failures?
LaunchDarkly has multiple fallbacks. If their CDN goes down, it goes to
their service. If their service goes down, you can route it to an
external service like their relay proxy. If all of those go down, then
there will be cached results from the last sucessful response. And if
this is a first time request, then a fallback default value is used.
I wrote a script that updates my daily notes to add properties. Since I’ve been using Obsidian for awhile, properties was introduced much later. I’ll walk through my code.
// Get the current file title, which is in a common date format: YYYY-MM-DDconst currentFileTitle = tp.file.title;// Set folder you want to get latest file for hereconst folder = "Calendar/Personal Reviews/journal and daily review/2022";// Get all files in that folder, including nested foldersconst filesInFolder = app.vault.getMarkdownFiles().filter(file => { return file.path.startsWith(folder);});// Sort files by file namefilesInFolder.sort((a, b) => a.basename < b.basename ? 1 : -1);// Get the index of the current fileconst currentIndex = filesInFolder.findIndex(file => file.basename === currentFileTitle);// Get basename of previous and next TFiles to be used in linklet previousEntry = '';let nextEntry = '';// Wrap it around a try catch block in case there's something wrong with getting these basenamestry { previousEntry = `[[${filesInFolder[currentIndex + 1].basename}]]`} catch (err) { console.error(err);}try { nextEntry = `[[${filesInFolder[currentIndex - 1].basename}]]`} catch (err) { console.error(err);}
Here’s my template that the templater plugin uses in markdown.
<%*This is where the JS code above is inserted-%>---tags: - logs/daily created: <% currentFileTitle %>previousEntry: - "<% previousEntry %>"nextEntry: - "<% nextEntry %>"---
I’ve had to modify this depending if the file already has properties or not.
I’ve been enjoying micro-blogging a lot more than I anticipated. It lowers the barrier for writing a quick post and sharing it. An essay is something that is a much heavier lift, and goes through many edits before I publish.
I didn’t realize where we were with AI-generated music.
Besides the Fuzzy Search, VSCode also now has locked scrolling when you have two windows side by side
I’ve been listening to the podcast, Shit You Don’t Learn in School. There are a lot of gems, especially around finding business ideas. I might take the patent one at some point
Also, if anyone would like to collaborate with me for a potential business idea brainstorm, let me know
There’s a waitlist for Ali Abdaal’s Productivity Lab. I’m debating it
I got a chance to play around with Elicit and was reading through Adam Wiggin’s
Tweet. I think
I might make a quick web app trying multi-column queries about a particular
topic and allow more of a computational style of conversational chat.
Computational style of conversational AI using Elicit