• No-Code

    A category of products and tools that enable users to create things that previously required developers to do. Examples include business websites (Webflow), chat bots (Landbot), surveys (Typeform), native apps (Thunkable), voice apps, email marketing, etc.

    No-code is a business model similar to Naval Ravikant’s take on making things that were previously only for rich people available to everyone (Uber is just a black car service that anyone can have).


  • Venture Capital Has Conflicting Incentives With Founders When It Comes to Outcomes

    Venture capitalists and institutional investors need big returns and therefore they fund companies pursuing a big market (investor returns follow a power law). Fund sizes have increased and investors need larger and larger returns. However, there is a tension with founders' incentives to have a wide range of exit outcomes. An exit in the $100s of millions is life changing for a founder, but not a good enough outcome for investors. Investors are incentivized to push founders to riskier, but bigger opportunities even if the set of possible positive outcomes for the founder are significantly smaller (e.g. a highly competitive winner-takes-all market).

    See also:

    • This is somewhat related to the principal-agent problem, investors do often act on behalf of founders (and even entire markets).

  • Peter Principle

    A theory of management in which employees in a company are promoted until they are at a level of incompetence. For example, you get promoted for doing well at level 1 so you are promoted, but then you never get promoted again.

    See also:


  • WebAssembly

    A compilation target for executing in a virtual machine supported by web browsers and servers (via tools like wasmtime). WebAssembly is intended to be portable between platforms and has a similar ‘write once run anywhere’ ethos as Java. WebAssembly already runs significantly faster than JavaScript in the browser and there is reason to believe the gap will widen as WebAssembly support improves.

    Current limitations include by native access to manipulating the DOM, compiling from garbage collected languages results in huge binaries, and performance (Firefox is the fastest). Rust has the most mature support for compiling to wasm.

    See also:


  • The Gervais Principle

    There are three groups of people within an organization: Sociopaths (tend to be at the top running the company, characterized by self-interest and need to control), Clueless (tend to be middle management, characterized by misplaced loyalty to the organization), and Losers (tend to be at the bottom, characterized by striking a bad economic bargain). The Gervais Principle speaks to the dynamics between these three groups with the Office as allegory.

    Sociopaths (who wield all the power) promote over-performing Losers into middle management thereby making them Clueless. They maneuver the Clueless to escape their own risk. For example, Michael was a top sales person before becoming a Clueless manager.

    Sociopaths turn under-performers into Sociopaths and fast-track them to positions of power. Losers that are self-aware (knowing they made a bad economic bargain) seek opportunities to raise their standing before they run out of time and get fired. For example, Ryan the intern who is bad at sales (his actual job) and manipulates his way into management position by David (a Sociopath).

    The Losers are left to fend for themselves. They find fulfillment outside of work and do just enough to get by. This is exemplified by Stanley, who knowingly plays along to the delusions of the Clueless and does enough work to never get fired.

    Read the essay.

    See also:

    • Performance management is a way of preventing the rise of low-performing Losers into Sociopaths in positions of power
    • Peter Principle a more popular (and simplistic) explanation of organizational incompetence
    • This theory can be thought of as an example of the principal-agent problem, the organization is not properly incentives to counteract the bad behaviors of promoting low-performing Losers and senior managers manipulating the Clueless.

  • TypeScript Adds Incidental Complexity to Using Libraries

    Inter-operating with libraries in the JavaScript ecosystem from TypeScript introduces incidental complexity due to packaging and types. There are (at least) four different ways to import a library[0] in TypeScript, each with subtle differences. Depending on the way the library is packaged you will need to pick the correct incantation.

    To get the benefit of static typing for a non-typed library, you also need to add @types/name-of-lib to your dependencies. Sometimes these are no longer needed when the library adds TypeScript support as did aws-sdk which, depending on what blog post or StackOverflow question you are looking at may or may not tell you.

    Finally, types in a library that has TypeScript support can be done poorly. For example, I found a rather unfortunate issue in marked.js because the Tokens union type doesn’t have a common discriminator property. That makes it not possible, or extremely hack-y to find a specific kind of element[1].

    [0]

    import { Lib } from 'some-lib'
    import 'some-lib';
    import * as Lib from 'some-lib';
    const lib = require('some-lib');
    

    [1]

    export function extractMarkdownTitle(md: string): string | null {
      const lexer_output = marked.lexer(md) as marked.TokensList;
    
      // Hack: This isn't typeable because Tokens is not a descriminating
      // union type (Def and Space don't have a `type` prop)
      let title: any = lexer_output.find((val: any) => {
        // Without casting to `any`, this won't compile
        return val.type === 'heading';
      });
    
      return title ? title.text : null;
    }
    

  • Good Magic and Bad Magic

    Good magic just works. It’s invisible and you quickly forget that it’s there.

    Bad magic works sometimes. It’s mysterious and hard to understand.

    Good programming abstractions are the right kind of magic. You can depend on them and build on top of them with confidence.

    Bad programming abstractions are the wrong kind of magic. It’s equally a mystery when it works as when it doesn’t work. They’re leaky and you end up spending more time cleaning up after the magic than benefiting from it.


  • Airplane Test of Programming Languages

    The airplane test measures the (often binary) ability to write code in a specified programming language while secluded on an airplane with no internet access. It shows the programming language’s capability to unblock the programmer and is an indicator of productivity.

    Typed languages (such as rustlang) fair better because it’s easier to reason about code and jump to a definition when you need to understand what’s going on. However, other contributing factors include the legibility of error messages and stack traces, quality of documentation, quirks in the language, tooling, and whether it is ‘batteries included’. In this way, typed languages can also fail the test (e.g. TypeScript’s quirks with interoperating with JS libraries and Webpack generally requires access to StackOverflow).


  • Website Navigation Does Not Lend Itself to Discovery

    Modern websites rely on strict hierarchy of pages to help users navigate. This uses central pages to send users back to once they’ve completed reading an article. However, this rigidity does not optimize for serendipitous discovery and many important pages on a website can be inadvertently orphaned (either because it doesn’t fit neatly into a hierarchy or users don’t know to look for it).

    Digital gardens on the other hand eschew strict navigation and rely on hypertext linking to allow a wide range of paths to content in a self-directed way. This comes with a trade off of overall coherence between content nodes.

    Read ‘The limits of structure’ by East Gate.


  • Querying Stats From Org-Roam

    You can run queries directly on the org-roam database directly (it’s just a sqlite database) to get interesting stats about your Zettelkasten.

    The location of the database can be found by evaluating org-roam-db-location.

    Note: file names have the date embedded in it formatted as yyyy-mm-dd so taking a substring is the easiest way to group by dates.

    (Updated for org-roam v2)

    Total notes (not journal entries)

    select count(*) from files where file not like '%journal%';
    

    Notes per year (not journal entries)

    select substr(files.file, 24, 4) as year, count(files.file)
    from files
    where file not like '%journal%'
    group by year
    order by year desc;
    

    Notes per month

    select substr(files.file, 24, 7) as month, count(files.file)
    from files
    group by month
    order by month desc;
    

    Links per note

    select substr(files.file, 24, 7) as month, round(cast(count(links.source) as real) / cast(count(distinct files.file) as real), 2)
    from files
    join nodes on files.file=nodes.file
    join links on nodes.id=links.source
    where links.type = '"id"'
    group by month
    order by month desc;
    

    Notes per day

    select substr(files.file, 24, 7) as month, round(cast(count(files.file) as real) / cast(count(distinct substr(files.file, 24, 10)) as real), 2)
    from files
    group by month
    order by month desc;
    

    Words written for a given year

    Counting words written in org-roam