stephen.news

hypertext, words and more

Tutorials

  • This is one of those git config things you set once and forget years later when you setup a new machine. How did we get here? You can git push expecting to fly up to the remote repository right?

    fatal: The current branch feature-1234 has no upstream branch.
    To push the current branch and set the remote as upstream, use
    
        git push --set-upstream origin feature-1234
    
    To have this happen automatically for branches without a tracking
    upstream, see 'push.autoSetupRemote' in 'git help config'.

    To get rid of this message forever and prevent git from gatekeeping you just run this:

    git config --global push.default current

    This will set your git config to only push your current branch when running git push. Enjoy never having to worry about this again!

  • For much of last year, I kept my Duolingo streak alive 🔥 There’s no shortage of ways to stay frosty and learn something new in 2023. Here’s some ideas:

    Udemy and Coursera have awesome affordable courses. Codecademy and code schools can teach your programming fundamentals. Learn a new language with Duolingo. Learn from the experts with MasterClass. There’s tons of free basic cooking classes on YouTube. Already know how to cook, but want to level up your chef skills? You can pay for a fully interactive Sur la table course taken over zoom.

    Good luck everyone!

  • I love this trick more than any other macOS lifehack because 9 times out of 10 if I am on my MacBook, I am probably wearing headphones. The snag is, my headphones input mic is not great, let me tell ya.

    My favorite noise-cancelling headphones Sony XM4‘s have a small audio problem with Bluetooth. When they’re connected via Bluetooth, good ol macOS wants to use them as both input and output by default, but due to bandwidth problems the headphones switch its audio output to something like mono:

    For headsets and other audio devices, there are multiple relevant profiles: The Headset Profile (HSP) and/or the Hands Free Profile (HFP) are used when you want to use the device in two directions, so to speak – speaker output and microphone input. With HSP or HFP, the available bandwidth gets split between the speaker and the microphone, so the quality of the audio output will be lower. Maybe that’s what you mean by “mono”.

    The audio output can be so poor in fact, that I find it unusable. I’m in this weird position where I love using my headphones, but only if they are used for audio output alone. So, I am constantly switching my input to the System mic instead of my headphones mic 🤕

    Without further ado, here’s the macOS prot-tip! All you need to do is Option-Click on the volume icon in your menu bar (if you’re currently connected to headphones or some other audio output device, like a TV the icon may appear different):

    1. Hover over the volume icon in your menu bar
    2. ⌥ Click on the volume icon
    3. It should reveal a dropdown with Input and Output devices listed
  • I’ve found myself using localStorage more and more these days. Turns out there’s a fancy hook for that. Not surprised! But where’s the love for TypeScript?

    Turns out, Anders has done the refactoring for us:

    import { useState } from "react";
    
    export const useLocalStorage = <T>(key: string, initialValue: T): [string, typeof setValue] => {
      const [storedValue, setStoredValue] = useState(() => {
        try {
          const item = window.localStorage.getItem(key)
          return item ? JSON.parse(item) : initialValue
        } catch (error) {
          return initialValue
        }
      });
    
      const setValue = (value: T): void => {
        try {
          const valueToStore = value instanceof Function ? value(storedValue) : value
          setStoredValue(valueToStore)
          window.localStorage.setItem(key, JSON.stringify(valueToStore))
        } catch (error) {
          return error
        }
      };
    
      return [storedValue, setValue]
    }
    
  • Next.js is super duper dope. Versatile. Fast. Easy to understand and a dead-simple configuration. What’s not to love? Out-of-the-box, it seems to just work. Pair it with GraphQL and it’s game over. Nothing seems to compare so far in my testing.

    My one problem so far, has been FOUC with styled-components. Truly a horrible issue. However, thanks to this bloke, there’s an easy solution.

    First create a _document.js file in your pages directory. Assuming you are working with styled-components, drop this in there:

    import Document from "next/document";
    import { ServerStyleSheet } from "styled-components";
    export default class MyDocument extends Document {
      static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet();
        const originalRenderPage = ctx.renderPage;
        try {
          ctx.renderPage = () =>
            originalRenderPage({
              enhanceApp: (App) => (props) =>
                sheet.collectStyles(<App {...props} />),
            });
          const initialProps = await Document.getInitialProps(ctx);
          return {
            ...initialProps,
            styles: (
              <>
                {initialProps.styles}
                {sheet.getStyleElement()}
              </>
            ),
          };
        } finally {
          sheet.seal();
        }
      }
    }

    That’s literally it! Rebuild your app, and serve and he FOUC issue should be resolved!

  • For years I’ve been building sites with WordPress. The PHP page templating, media library, and The Loop was the holy trinity for me when I first got started with web development. Later, open-source tools like Trellis helped me speed up my development process by automating server provisioning. Sage, helped by speeding up starter theme development even faster. Now we have new paradigms such as the WP REST API and Gutenberg. We can more easily and more speedily, piece together custom blocks for editors. Every week, WordPress is inching closer and closer to becoming an agnostic CMS.

    Static PHP page generation in WordPress is pretty good out of the box. But these days, everyone and their mom wants to write JSX. So, what’s the solve here? WordPress is deeply intertwined with PHP, and themes are not exactly prepped to work well with React. One could simply start with React and Redux and you’d probably end up with something like this. Not a terrible solution, albeit still a theme-based approach, not exactly performant, and the reducers alone give me a headache. Those would be firing quite frequently. We could be more efficient.

    Enter Gatsby, or if you’re really saavy, you could opt for Next.js. Postlight has probably the most promising starter repo I have ever seen for Next.js. In this post I’ll be going over Gatsby specifically, but I definitely want to explore other avenues as well. The Jamstack, as it has come to be known is here in full-force, and it works really well. So, naturally I want to get my hands on some other approaches.

    To get started, all you just need a Gatsby site, a data store, and a means to deploy it. Some prefer Netlify, others prefer Now. To be honest, they’ll all fairly inexpensive these days, if not free. But hosting your data store will cost you some dough. You don’t have to break the bank though. The cheapest Droplet on DigitalOcean (which is roughly ~$5/month) should more than suffice.

    I setup my WordPress installation here at api.https://stephen.news but, Postlight’s approach is interesting and notable, they have their WordPress served out of port 8080. As far as I can tell, you can’t do that with Gatsby. Not a deal breaker for me, but something for you to know. So, for the WordPress + Gatsby stack to work you’ll need to setup your API url under a sub domain (or separate domain I found want) at something like cms.example.com or if you want to follow me, api.example.com works too.

    Next, there’s a lot of configuring you need to do according to their blog post tutorial. Namely, you’ll need to install some plugins on your WordPress site to expose your WordPress Data to GraphQL:

    Those two should suffice for a basic setup. Next, you’re going to have to configure your gatsby-config.js file a little bit in your Gatsby site repo. You can download this gatsby-starter-wordpress-blog and fork it. We just need to designate that API url here:

    module.exports = {
      ...
      plugins: [
        ...,
        {
            resolve: `gatsby-source-wordpress-experimental`,
            options: {
                // the only required plugin option for WordPress is the GraphQL url.
                url: process.env.WPGRAPHQL_URL || `https://api.example.co/graphql`,
            }
        },
      ]
    }

    As you can see here, gatsby-source-wordpress is currently in beta, so it carries the -experimental slug in the Gatsby Plugin name until v4 ships. But at a minimum, this is all you need to get started. From here, you can create pages in src/pages and GraphQL queries to hydrate your views with content.

    I won’t go further than here in terms of setup, because really, the world is your oyster from here. After you fork the starter blog, you just run yarn && gatsby develop, clear up any GraphQL errors, and your local Gatsby site should run at localhost:8000, and your GraphQL playground runs at localhost:8000/___graphql

    I would recommend reading up on how Gatsby routing works, and how to write (and inspect) GraphQL queries. Those two skills will give you the power to craft whatever kind of site you want.

    Now, with Gatsby, it runs all the GraphQL queries at build-time. So, when you deploy to Netlify or Now or wherever, all the pages/posts and content are generated ahead of time. The inverse would be having the client render content at run-time. Dynamic pages are neato, but they are dreadfully slow. With this setup, we can have both! For static content (think like, blog posts or pages), we can use Gatsby’s static build capabilities. But if you need dynamic content (imagine comments, or loading things in real-time), you can leverage something like @apollo/client. With Apollo, you can fetch and run queries at run-time. That’s what I use to power my personal bookmarks!

    Suggested reading:

    I imagine I’ll continue writing more about this headless revolution, so stay tuned. If you have any questions or feedback, leave me a comment below.

  • Executive Editor at Vox, Mercedes Kraus, penned a travel guide for would-be visitors to Marfa. Marfa is located in West Texas. Heck, even the Simpsons visited Prada Marfa:

    The Simpsons, S30E11: “Mad about the toy”

    Texas, is well known for many things. A couple of venerable and memorable characters from Texas’s past include Sam Houston and Lyndon B. Johnson. A few of my personal favorite things about Texas: the tall skies, grassy hills, semi-arid desert landscapes, swell thunderstorms, quiet dive bars, and loud honky-tonks. It’s easy to forget that Texas has a substantial art culture in Marfa. But, its there damnit! It has frequently been overshadowed by larger-than-life subjects such as Austin’s tech boom, and of course Texas oil booms.

    You can read the entire travel guide here at Curbed. But, I loved this pro-tip on arting and getting to know locals in Marfa:

    For art: Don’t let anyone tell you to skip Chinati. I recommend either the full tour ($25) or all three self-guided tours ($30). The self-guided are “the sheds” (where I experienced a visual symphony), the Dan Flavin buildings (for your Instagram fulfillment), and the new Robert Irwin—an artwork and experience that is in fact an entire building. The thing that I think you, a fan of this newsletter, would really miss if you don’t do the full tour is the arena. If you are unable to take the Judd Foundation tour (see above), you must do the full Chinati tour so that you can experience the arena. (Pro tip: get to know your docent—locals in Marfa are super friendly, will give you great tips, and might even invite you to a local party or happening.)

    For context, The Chinati Foundation was founded based on Donald Judd’s ideas and principles. Honorary Texan, Donald Judd is essentially Marfa’s Patron Saint of Art. For good reason too. If not for him, Marfa would look a helluva lot different.

    Mercedes is on-point about getting to know your locals too. Don’t be shy. Texas’s state motto is, after all simply, friendship. You might just make a friend. Having a Texan in your contact book is like personally knowing a hobbit. Cherished, magical and kind.

  • I use git log a lot. It’s real handy. But you know what — it’s pretty unwieldy and takes up quite a bit of terminal real estate. I finally decided to do something about it. Every time I ran git log, my terminal becomes a total mess. I knew about this little dingle:

    git log --pretty=oneline --abbrev-commit

    Which prints out a friendly, easy-to-digest, single-lined log:

    a2a722b (HEAD -> master, origin/master) Fix the NoteDetail styles.
    4fdcbc7 Split the NoteCell and NoteDetail.
    ccc4dc2 Connected the NoteCell with data.
    bce0d12 Broken components into separate pieces.
    071ea13 Change destinations, now the targeting works.
    0ecea01 NoteDetail and split it from the RootView.
    ...

    Which is great! But… can we do better? Some googling around lead me to this post by Mattias Geniar:

    There are longer versions of that same --pretty parameter. In fact, it allows you to specify all the fields you want in the output.

    Sweet! So, running the same command and flagging the specified fields like so, prints a more concise log. Awesome!

    $ git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
    
    a2a722b (HEAD -> master, origin/master) Fix the NoteDetail styles. (2 days ago) <Stephen Petrey>
    4fdcbc7 Split the NoteCell and NoteDetail. (2 days ago) <Stephen Petrey>
    ccc4dc2 Connected the NoteCell with data. (2 days ago) <Stephen Petrey>
    bce0d12 Broken components into separate pieces. (4 days ago) <Stephen Petrey>
    071ea13 Change destinations, now the targeting works. (5 days ago) <Stephen Petrey>
    0ecea01 NoteDetail and split it from the RootView. (6 days ago) <Stephen Petrey>
    ...

    Mattias has the excellent suggestion of configuring a Git Alias for this:

    $ git config --global alias.logline "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

    Now, instead of having to type out the command and flag the fields you want to print, you can just type, git logline and wham! It should print out a prettified git log that takes up way less space in your terminal.

  • First off, I didn’t write this. Ryan Hellyer did. I only came across this fix from a post written by Justin Downey. The short-end of it is, drop this block of code into the bottom of your functions.php file. I made some tiny tweaks:

    if (!function_exists('disable_emojis')) {
      function disable_emojis() {
        remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
        remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
        remove_action( 'wp_print_styles', 'print_emoji_styles' );
        remove_action( 'admin_print_styles', 'print_emoji_styles' );
        remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
        remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
        remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
      }
      add_action( 'init', 'disable_emojis' );
    }

    I really needed this personally, because MailChimp was parsing my RSS feed verbatim, and for whatever reason, when WordPress added Twemoji to core in 4.2 it forces the emoji markup to be an inline-image — which, I get it. It’s useful for older devices who may not support emoji. But it was completely wrecking my email campaigns styles, yuck! 🤢

    Thankfully, this function works in disabling the Twemoji images altogether! Tested up to: 5.2.2 👍

  • This took some googling, so I thought I would document my findings here.

    Locally

    If you’re already on the branch you’d like to rename, just run:

    git branch -m new-name

    If you’re on say master, and you have a branch you want to rename now but no checkout, run:

    git branch -m old-name new-name

    Now that you’ve taken care of your local branch, there’s the unfinished business of mending your remote branch with renaming.

    Remote

    If you use Github or Gitlab (or whatever) you’re going to want to remove the old-name branch and push the new-name branch:

    git push origin :old-name new-name

    And finally, push to reset the upstream branch so your local and remote branches are up-to-date:

    git push origin -u new-name