• Is Your Pricing Too High?

    How do you know if your price is too high? A few things could be happening: the product isn’t actually as valuable as you think, you’re talking to the wrong customers, you’re not conveying the value properly, or some combination of the three.

    Product isn’t actually valuable

    You may have identified a problem that isn’t critical or a solution that isn’t good enough to overcome the inertia needed for a customer to buy. This can be difficult to determine but requires keen observationβ€”especially to rule out some of the other causes below.

    Talking to the wrong customers

    If you have any sales, look at what the most successful customers have in common (not just any customer otherwise that could be misleading). What was the key challenge they were facing and how did your product address that? Similarly, look at sales lost or customers that churned to see what they had in common. Focus on a single customer profile until you’ve really figured it out before moving on to the next.

    Not conveying value

    You can have the best product in the world and people still won’t buy it if you can’t convey the value it creates. In B2B sales, it’s possible to solve a real problem but customers don’t have the motivation to do anything about it. Finding the right hooks are important to get a potential customer to take action.

    See also:


  • Alcohol Is Technology for Cooperation

    The paradox of alcohol consumption is that it’s bad for our health and costly to society yet continues to thrive. There is no evolutionary reason for humans to have evolved to enjoy the taste of alcohol (in fact certain Asian gene pools like mine have developed allergies to it). However, alcohol provides an extremely important benefit, down regulating the pre-frontal cortex and thereby improving cooperation.

    The PFC helps us focus and analyze, but it also gets in the way when we are “thinking too much”. Alcohol down regulates the PFC which improves creativity and reduces inhibition. In an important negotiation, the thing that builds trust is turning down your PFC. That’s why, since ancient times, alcohol is at the center of all gatherings and negotiations. It’s a vital technology to improve cooperation among people and, ultimately, civilization building.

    Listen to Edward Slingerland, Drinking for 10,000 Years: Intoxication and Civilization.

    See also:


  • News Diet

    A news diet is intentionally limiting yourself to certain quantities and outlets for news and media. This might help maintain focus throughout the day and improve mental health.

    There may be a link between exposure to bad news and depression. For example, researchers found a positive correlation between news about COVID-19 and depressive symptoms.


  • Learning Styles Don't Exist

    The idea that everyone has their own learning style and learning is most effective when teachers use your style is not based on any scientific evidence.

    VARK (visual, auditory, reading/writing, kinetic) was invented by Neil Fleming after observing some good teachers failing to reach certain students and while some “poor teachers” succeeded: “one topic that seemed to hold some magic, some explanatory power, was preferred modes of learning, ‘modal preferences’”.

    People seem to connect with the idea of learning style for the same reason we have a favorite color, it seems like some part of our identity.

    See also:


  • Line Clamp With React and Tailwindcss

    Tailwind has a plugin for line clamping @tailwindcss/line-clamp that uses pure CSS to truncate text to the specified number of lines. What if you want to show an indicator to read the rest of the truncated text?

    We can create a react component that dynamically truncates text and shows a toggle for expanding or hiding text.

    import React, { FunctionComponent, useState, useCallback } from 'react';
    
    type TextTruncateProps = {
      text: string;
    };
    
    /* Note: The number of lines to truncate to needs to be static
    otherwise the css classes won't be generated by tailwind. If you need
    a different number of lines, create a new component */
    export const TextTruncateThree: FunctionComponent<TextTruncateProps> = ({
      text,
    }) => {
      const [shouldTruncate, setShouldTruncate] = useState<boolean>(false);
      const [readMore, setReadMore] = useState<boolean>(false);
    
      // Measure the element to calculate the number of lines and
      // determine whether to truncate
      const measuredRef = useCallback(
        (node: any) => {
          // Before the component mounts the node ref will be null
          if (node?.parentElement) {
            // Calculate the number of lines based on height
            const elHeight = node.offsetHeight;
            const styles = window.getComputedStyle(node);
            const lineHeight = styles
              .getPropertyValue('line-height')
              .replace('px', '');
            const elLineCount = elHeight / parseInt(lineHeight, 10);
    
            setShouldTruncate(elLineCount > 3);
          }
        },
        [text]
      );
    
      const shouldClamp = shouldTruncate && !readMore;
    
      // Our toggle for expanding or hiding truncated text
      let toggle;
      if (readMore) {
        toggle = (
          <span onClick={() => setReadMore(false)}>
            Show less
          </span>
        )
      } else {
        toggle = (
          <span onClick={() => setReadMore(true)}>
            Read more
          </span>
        );
      }
    
      return (
        <div>
          <p
            ref={measuredRef}
            className={`${shouldClamp ? 'line-clamp-3' : 'line-clamp-none'}`}
          >
            {text}
          </p>
          {shouldTruncate && toggle}
        </div>
      );
    };
    

    See also:


  • Org-Mode Export to Notion

    I use org-mode for taking notes and keeping track of tasks. I use Notion for work as an internal wiki.

    I take meeting notes in org-mode but want to share them in the internal wiki for work.

    Is there a way to do that?

    Update: I used ChatGPT with Emacs to come up with the following export backend:

    (require 'org)
    (require 'ox-org)
    (require 'request)
    
    (org-export-define-derived-backend 'notion 'org
      :menu-entry
      '(?n "Export to Notion Meetings"
           ((?n "To Notion Meetings"
                (lambda (a s v b)
                  (org-notion-meetings-export a s v b))))))
    
    (defun notion-create-meeting (meeting-title meeting-notes)
      (let* ((notion-api-secret (getenv "NOTION_API_SECRET"))
             (database-id (getenv "ORG_NOTION_MEETINGS_DATABASE_ID"))
             (url (format "https://api.notion.com/v1/pages"))
             (headers `(("Notion-Version" . "2022-06-28")
                        ("Content-Type" . "application/json")
                        ("Authorization" . ,(format "Bearer %s" notion-api-secret))))
             (data `(("parent" . (("database_id" . ,database-id)))
                     ("properties" . (("Name" . (("title" . ((("text" . (("content" . ,meeting-title))))))))))
                     ("children" . ((("object" . "block")
                                     ("type" . "paragraph")
                                     ("paragraph" . (("rich_text" . ((("text" . (("content" . ,meeting-notes))))))))))))))
        (request
         url
         :type "POST"
         :headers headers
         :data (json-encode data)
         :parser 'json-read
         :error
         (cl-function (lambda (&rest args &key error-thrown response &allow-other-keys)
                        (message "Got error: %S, response: %S" error-thrown response)))
         :success (cl-function
                   (lambda (&key data &allow-other-keys)
                     (message "Meeting notes page created: %s" (assoc-default 'json data)))))))
    
    (defun org-notion-meetings-export (&optional async subtreep visible-only body-only ext-plist)
      (let ((title (org-element-property :title (org-element-at-point)))
            (body (org-export-as 'md subtreep visible-only body-only ext-plist)))
        (notion-create-meeting title body)))
    
    (provide 'org-notion-meetings-export)
    

  • Compliance Is a Limiting Factor of Opportunity

    Opportunity comes in many shapes and sizes but a consistent limiting factor complianceβ€”the set of rules (written or unwritten) that one must follow to participate in a prosperous endeavor.

    Examples of products that make compliance easier:

    • Mosey automating employment and tax compliance to simplify hiring remote and staying compliant
    • Stripe Atlas start a company and get access to financial infrastructure from anywhere in the world
    • Legalpad solving immigration and work visas
    • Gusto payroll and benefits without having to figure out tax filings
    • Vanta navigate security certifications to sell to regulated customers

  • Startup Investing Is Investing in Options

    Startups don’t have information about them needed for techniques you would typically use to value an investment. There is little history, cash flows, and even assets to do a discounted cash flow. As a result, public market investors are confused at how early-stage startups carry the valuations they do. That’s because these companies are like investing in options.


  • Three Body Problem Book Review

    The Three Body Problem captures your imagination and uses science as a plot point that I haven’t seen before. Some spoilers ahead.

    I loved that the book is framed around the Cultural Revolution in China and told in unforgiving detail. It was a unique experience for me to have science fiction told through the lens of Chinese politics and history.

    The dimension of time becomes a mind bending consideration for the decisions Earth and Trisolaris make. It’s interesting to think about how things might play out when the incoming danger is 400 years away and the advancement of technology in the intervening time between launching an invasion fleet and arriving at the destination. (Although, this does presume that no advancement can be made along the journey when matter, energy, and evidence are all that’s needed for knowledge creation).

    Some of it is admittedly far fetched. The proton computer is super cool, but it’s stretched to the absolute limitβ€”AI + multi-dimensional transformation + quantum sensing, and so on.


  • Set a Contract Minimum for Redlines

    Prospective customers will want to review an order form and master software agreement. Their lawyers will want to propose changes. This causes a few issues: it increases the cost of the deal because now you need to pay lawyers to resolve the feedback and it makes it difficult to understand contractual obligations if every customer is slightly different.

    To reduce this complication, set a contract value minimum before you will make revisions to your agreement. If someone asks about it you can tell them the rule that you’ve set for sales. If they push back, you can give a clear reason whyβ€”the expense of making revisions and maintaining your obligations.

    See also:


  • Degrees of Souledness

    People tend to think of objects and living things as having a soul or not having a soul when really it’s a continuous scale of souledness. For example, people reject the idea of eating certain animals like cats but not chickens, we remark about how, after a major cognitive decline due to old age, that person “isn’t all there”. There is a continuous assignment we make as to the degree of souledness in everything we see and interact with.

    This isn’t to say this is correct (a souledness scale points out a lot of inconsistencies and contradictions) but it provides a good explanation for the moral issues we face todayβ€”a binary view of souledness (the predominant view) requires consensus and is therefore indeterminable.

    From I Am a Strange Loop.

    See also:


  • Contingency Recruiting Doesn't Work Well for Early-Stage Startups

    Contingency recruiting is not very effective for early-stage hiring. Since contingency recruiters get paid only if they are able to fill a job opening and charge 20-25% of the new hire’s first year salary, they tend to share candidate profiles with larger companies that pay higher salaries which make them more money.

    Early-stage startups tend to get candidate profiles that the larger companies passed on. This results is less desirable candidates and a lower volume than if a startup were to do recruiting in-house.


  • There Is an Iceberg of Content Within Organizations

    There is so much writing that goes into running modern organizations but very little of it is ever seen. Every email, chat, document, slides, spreadsheets that gets produced is limited in distribution to a handful of people or teams. What you can observe from the outside is only the most polished published content.

    So what?

    A common complaint about writing is that it’s too hard to do. Yet, everyone seems to create prolific amounts of writing every day. There is more capability than people give themselves credit for.

    How might this vast trove of content be utilized? Is writing primarily for communication so disposable that it ought to never be looked at again? Perhaps there is something there, maybe that’s how we can train a minto linter.

    See also:


  • Codespaces and Emacs TRAMP

    While you can use Emacs in the browser using Codespaces, it involves getting all of your emacs config set up on Codespaces. By using the GitHub CLI you can also use emacs TRAMP over SSH to work in the Codespace instance from your local emacs.

    To do that, update your init.el to create a new tramp method. (Copied this from the emacs-codeql readme).

    (let ((ghcs (assoc "ghcs" tramp-methods))
          (ghcs-methods '((tramp-login-program "gh")
                          (tramp-login-args (("codespace") ("ssh") ("-c") ("%h")))
                          (tramp-remote-shell "/bin/sh")
                          (tramp-remote-shell-login ("-l"))
                          (tramp-remote-shell-args ("-c")))))
      ;; just for debugging the methods
      (if ghcs (setcdr ghcs ghcs-methods)
        (push (cons "ghcs" ghcs-methods) tramp-methods)))
    
    ;; provide codespace name completion for ghcs tramp method
    ;; use C-j if you use ivy to kick in host completion
    (defun my/tramp-parse-codespaces (&optional nop)
      (let ((results '())
            (codespaces
             (split-string
              (shell-command-to-string
               "gh codespace list --json name -q '.[].name'"))))
        (dolist (name codespaces)
          ;; tramp completion expects a list of (user host)
          (add-to-list 'results (list nil name)))
        results))
    
    (tramp-set-completion-function "ghcs" '((my/tramp-parse-codespaces "")))
    

    Install the GitHub CLI, authenticate your machine, and create a codespace.

    brew install gh
    gh auth login
    gh cs create
    

    Now you can use TRAMP to open files directly in your Codespace! C-x C-f then type ghcs:/ and use autocomplete to choose your codespace.

    Everything that works with TRAMP should work including eglot and magit.