<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Doug Tangren</title>
    <description>The latest articles on Forem by Doug Tangren (@softprops).</description>
    <link>https://forem.com/softprops</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F69440%2F9d377958-5fbe-43ee-b1fd-be5bb81c06ff.jpeg</url>
      <title>Forem: Doug Tangren</title>
      <link>https://forem.com/softprops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/softprops"/>
    <language>en</language>
    <item>
      <title>digitally unmastered: the GitHub cli edition</title>
      <dc:creator>Doug Tangren</dc:creator>
      <pubDate>Sun, 28 Jun 2020 03:28:36 +0000</pubDate>
      <link>https://forem.com/softprops/digitally-unmastered-the-github-cli-edition-1cc4</link>
      <guid>https://forem.com/softprops/digitally-unmastered-the-github-cli-edition-1cc4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Names have power.&lt;br&gt;
- Rick Riordan, The Lightning Thief&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;prelude&lt;/li&gt;
&lt;li&gt;motivation&lt;/li&gt;
&lt;li&gt;GitHub at your command line&lt;/li&gt;
&lt;li&gt;branching out&lt;/li&gt;
&lt;li&gt;takeaway&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  prelude
&lt;/h2&gt;

&lt;p&gt;There have been quite a lot of posts on the topic of renaming your default git branch from "master" to anything else recently &lt;sup id="fnref1"&gt;1&lt;/sup&gt; &lt;sup id="fnref2"&gt;2&lt;/sup&gt; &lt;sup id="fnref3"&gt;3&lt;/sup&gt;. &lt;/p&gt;

&lt;p&gt;Many have covered how to manage doing so on the command line. Most or which have covered how to manage propagating that rename to GitHub though its web UI. &lt;/p&gt;

&lt;p&gt;This post covers how to close that gap with the ✨ &lt;a href="https://cli.github.com/"&gt;GitHub CLI&lt;/a&gt;✨.&lt;/p&gt;

&lt;h2&gt;
  
  
  motivation
&lt;/h2&gt;

&lt;p&gt;I won't attempt to convince you to change your default git branch name based on its etymology, but I &lt;em&gt;will&lt;/em&gt; suggest that you do so for a pragmatic and practical reason. &lt;/p&gt;

&lt;p&gt;A common argument I've seen behind those avoiding changing default branch names so far is fear of what will break in doing so. This is typically anchored to a gap in understanding of what within your system depends on it. I invite you embrace a little bit of &lt;a href="https://en.wikipedia.org/wiki/Chaos_engineering"&gt;chaos&lt;/a&gt; in exchange for a better understanding of your software systems. A good measure of system health is that is safe to change. When it is not, there's often an underlying issue worth exploring. In any scenario, you will walk away with more confidence in knowing how your system works.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub at your command line
&lt;/h2&gt;

&lt;p&gt;The GitHub CLI, &lt;code&gt;gh&lt;/code&gt;, is GitHub's now officially supported command line interface.&lt;/p&gt;

&lt;p&gt;On MacOS, you can install it with &lt;code&gt;brew install github/gh/gh&lt;/code&gt; or your &lt;a href="https://github.com/cli/cli#installation"&gt;package manager of choice&lt;/a&gt; on other platforms.&lt;/p&gt;

&lt;p&gt;The GitHub CLI comes bundled with a handful of helpful commands for interfacing with your GitHub repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh
Work seamlessly with GitHub from the &lt;span class="nb"&gt;command &lt;/span&gt;line.

USAGE
  gh &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &amp;lt;subcommand&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;flags]

CORE COMMANDS
  issue:      Create and view issues
  &lt;span class="nb"&gt;pr&lt;/span&gt;:         Create, view, and checkout pull requests
  repo:       Create, clone, fork, and view repositories

ADDITIONAL COMMANDS
  &lt;span class="nb"&gt;alias&lt;/span&gt;:      Create shortcuts &lt;span class="k"&gt;for &lt;/span&gt;gh commands
  api:        Make an authenticated GitHub API request
  completion: Generate shell completion scripts
  config:     Manage configuration &lt;span class="k"&gt;for &lt;/span&gt;gh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What makes this CLI especially convenient is that it's git repo-aware. That means when you use &lt;code&gt;gh&lt;/code&gt; on the command line within a git repository hosted on GitHub, the CLI is able to infer a GitHub repo context for you.&lt;/p&gt;

&lt;p&gt;I leverage this often when I want to open the current git repo inside GitHub within a browser window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh repo view &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  branching out
&lt;/h2&gt;

&lt;p&gt;With it's recent &lt;a href="https://github.com/cli/cli/releases/tag/v0.10.0"&gt;&lt;code&gt;v0.10.0&lt;/code&gt; release&lt;/a&gt; the CLI gained a few new interesting features that add open a lot of new opportunities. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;gh&lt;/code&gt; now exposes direct client interface for the GitHub REST &lt;em&gt;and&lt;/em&gt; GraphQL APIs so anything thing you can do with the GitHub API, you can now technically do from the &lt;code&gt;gh&lt;/code&gt; CLI. 🤯&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh api graphql &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;':owner'&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;':repo'&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'
      query($name: String!, $owner: String!) {
              repository(owner: $owner, name: $name) {
                      releases(last: 3) {
                              nodes { tagName }
                      }
              }
      }
'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It won't take long before typing all of this out each time loses its novelty as you'll like have to keep digging through the GitHub API docs to remember out how to compose these requests.&lt;/p&gt;

&lt;p&gt;Fortunately, this release also added support for custom aliases which allow you to assign a name to an optionally parameterized command template and since API requests now supported commands, you can template aliased API requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh &lt;span class="nb"&gt;alias set &lt;/span&gt;your-alias-name &lt;span class="s1"&gt;'gh-subcommand arg1 arg2 argN'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The release of this version happened around the same time as folks were catching onto the git branch rename wave, &lt;a href="https://twitter.com/softprops/status/1271896990398337025"&gt;including me&lt;/a&gt;&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nG5RGIDe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/Eaau3bwWsAEYjFc.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--A5u6Gyby--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/493261692751466497/lI9RvcIy_normal.jpeg" alt="Doug Tangren 🐑 profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Doug Tangren 🐑
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/softprops"&gt;@softprops&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      🙌 to those posting about how to digitally  remaster or should I say "un-master" your default git branches.&lt;br&gt;&lt;br&gt;Here's my small contribution. The &lt;a href="https://twitter.com/hashtag/github"&gt;#github&lt;/a&gt; cli folks just made it easy to alias api commands. Here's one for changing your repos default branch from the cli 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      20:07 PM - 13 Jun 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1271896990398337025" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1271896990398337025" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1271896990398337025" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I created a local alias to reset my GitHub repository's default branches&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh &lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;set &lt;/span&gt;default-branch &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'api -X PATCH repos/:owner/:repo --raw-field default_branch=$1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can just do the following when you're migrating a repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gh default-branch main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I learned there's a problematic catch with this. Any open pull requests based on your old default branch will not automatically be updated.&lt;/p&gt;

&lt;p&gt;I recently learned through &lt;a href="https://twitter.com/mislav/status/1271462959458463752"&gt;another tweet&lt;/a&gt; from a GitHub employee that you can reset the base branch your open prs to this newly set default branch as well.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u3vC_R8l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EaUjkP_WoAASMHD.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i_qB0tUp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/860184226632802307/GjiGS87W_normal.jpg" alt="Mislav Marohnić profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Mislav Marohnić
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @mislav
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      We just released GitHub CLI v0.10 yesterday and here's how easy it is to use it to rename the default branch of the repository and update all its open pull requests &lt;a href="https://t.co/oQTQC8YWe0"&gt;gist.github.com/mislav/5ac6953…&lt;/a&gt; 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      15:22 PM - 12 Jun 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1271462959458463752" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1271462959458463752" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1271462959458463752" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;
&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;num &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;list &lt;span class="nt"&gt;-B&lt;/span&gt; master &lt;span class="nt"&gt;-L999&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;gh api &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-XPATCH&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"repos/:owner/:repo/pulls/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newbranch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  takeaway
&lt;/h2&gt;

&lt;p&gt;Even if you are on the market for changing your git branches, its useful to try to learn what dependencies you don't know you have on your branches yet.&lt;/p&gt;

&lt;p&gt;It's also worth exploring the GitHub CLI for other use cases. You can technically do anything with GitHub from the command line now.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx"&gt;https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://dev.to/horus_kol/renaming-your-master-branch-2a37"&gt;https://dev.to/horus_kol/renaming-your-master-branch-2a37&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://dev.to/mrsaeeddev/how-to-rename-your-master-branch-to-something-else-58bj"&gt;https://dev.to/mrsaeeddev/how-to-rename-your-master-branch-to-something-else-58bj&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>thoughts on GitHub design updates?</title>
      <dc:creator>Doug Tangren</dc:creator>
      <pubDate>Wed, 24 Jun 2020 05:09:34 +0000</pubDate>
      <link>https://forem.com/softprops/thoughts-on-github-design-updates-ngn</link>
      <guid>https://forem.com/softprops/thoughts-on-github-design-updates-ngn</guid>
      <description>&lt;p&gt;I was curious what folks think about GitHub's design update rollout&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.blog/changelog/2020-06-23-design-updates-to-repositories-and-github-ui/"&gt;https://github.blog/changelog/2020-06-23-design-updates-to-repositories-and-github-ui/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Better/worse?&lt;/p&gt;

&lt;p&gt;I'm a fan of the mobile improvements having spent a considerable amount of time reading code on a phone.&lt;/p&gt;

&lt;p&gt;I'm also a fan of surfacing releases on repo pages. I've long wanted a Releases tab in the old UI.&lt;/p&gt;

&lt;p&gt;A dark mode would have been nice.&lt;/p&gt;

&lt;p&gt;What do y'all think?&lt;/p&gt;

</description>
      <category>github</category>
      <category>discuss</category>
    </item>
    <item>
      <title>portable posting with devtogo</title>
      <dc:creator>Doug Tangren</dc:creator>
      <pubDate>Tue, 23 Jun 2020 05:39:21 +0000</pubDate>
      <link>https://forem.com/softprops/portable-posting-with-devtogo-2i9k</link>
      <guid>https://forem.com/softprops/portable-posting-with-devtogo-2i9k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;portability should be the default.&lt;br&gt;
- Larry Wall&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;serving dev to go&lt;/li&gt;
&lt;li&gt;dev delivery service&lt;/li&gt;
&lt;li&gt;takeaways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the last post, I touched a bit on the writing flow I'm iterating towards, one with an eye towards content portability and an offline focus. In this post I wanted to talk a bit more about the details of how I intend to make that actually work.&lt;/p&gt;

&lt;p&gt;To recap, the workflow I want is&lt;/p&gt;

&lt;p&gt;1) write content offline, locally&lt;br&gt;
2) track that in a GitHub repo&lt;br&gt;
3) on branch pushes, publish to dev.to and possibly a personal site where I can scratch some design idea itches&lt;/p&gt;

&lt;p&gt;My goal is to set myself up to build up a consistent writing routine. Posting to dev.to helps hold me accountable so my first stop was checking that box.&lt;/p&gt;
&lt;h2&gt;
  
  
  serving dev to go
&lt;/h2&gt;

&lt;p&gt;👩🏽‍💻🎒Introducing &lt;a href="https://github.com/softprops/devtogo"&gt;devtogo&lt;/a&gt;! Devtogo is a small &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; command line app that communicates with the dev.to API and synchronizes local content with a dev.to account. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⭐You can learn more about the dev.to API &lt;a href="https://docs.dev.to/api/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's how it works.&lt;/p&gt;

&lt;p&gt;To have any meaningful interaction with with the dev.to API, you first need an API key. You can create these on your &lt;a href="https://dev.to/settings/account"&gt;dev.to account page&lt;/a&gt;. Just provide a project name to refer to the key by and click "Generate API Key". I called mine "devtogo". Call yours whatever. &lt;/p&gt;

&lt;p&gt;Next, I get a list of all of my dev.to articles. I need this list to compare with what I content I have locally to avoid creating duplicate posts. I use the &lt;a href="https://docs.dev.to/api/#operation/getUserAllArticles"&gt;User's all articles API&lt;/a&gt; to fetch this list.&lt;/p&gt;

&lt;p&gt;This is made simple and easy with the &lt;a href="https://crates.io/crates/serde"&gt;serde&lt;/a&gt; and &lt;a href="https://crates.io/crates/reqwest"&gt;reqwest&lt;/a&gt; crates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⭐A crate is unit of distribution in Rust, similar to a package if you are familiar with npm or jar if you are familiar with java.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Serde makes it easy to derive a deserialization scheme for a plain old Rustlang struct at compile time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// other fields...&lt;/span&gt;
    &lt;span class="n"&gt;body_markdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reqwest makes it easy and ergonomic to make HTTP requests that can be deserialized from a JSON response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;client&lt;/span&gt;
        &lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;"https://dev.to/api/articles/me/all?per_page=1000"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s"&gt;"api-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The field of interest is an article's &lt;code&gt;body_markdown&lt;/code&gt; which has all of the information needed to make this work. Dev.to provides a useful page documenting what goes into this markdown document &lt;a href="https://dev.to/p/editor_guide"&gt;here&lt;/a&gt;. All posts require a title. A title makes an article unique.&lt;/p&gt;

&lt;p&gt;With a list of articles on hand, devtogo collects a list of local markdown files from a local directory and parses out article titles from their &lt;a href="https://jekyllrb.com/docs/front-matter/"&gt;front matter&lt;/a&gt;, validating some basic correctness rules. Front matter in this context is just structured meta data embedded within your markdown file.&lt;/p&gt;

&lt;p&gt;If a local article exists with a title that already exists it calls the &lt;a href="https://docs.dev.to/api/#operation/updateArticle"&gt;update article API&lt;/a&gt; other wise it creates a new article with the &lt;a href="https://docs.dev.to/api/#operation/createArticle"&gt;create article API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  dev delivery service
&lt;/h2&gt;

&lt;p&gt;I'd like for uploading articles to be based on pushes to a GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; fits this need like a glove. GitHub Actions is a declarative workflow automation tool built directly into GitHub. If you aren't using Actions by now, you are actively losing out value you get for free when using GitHub!&lt;/p&gt;

&lt;p&gt;So how do I make this work? To react to a repository event like a push you simply need to drop a yaml file into directory named &lt;code&gt;.github/workflows&lt;/code&gt; telling GitHub what to do when a push happens. You can call this file anything. I tend to call this &lt;code&gt;main.yml&lt;/code&gt; when it's the main workflow for my repository. Below is a full example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Main&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish-devto&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup devtogo&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;mkdir -p $GITHUB_WORKSPACE/bin&lt;/span&gt;
          &lt;span class="s"&gt;export VERSION=v0.1.0&lt;/span&gt;
          &lt;span class="s"&gt;curl -L "https://github.com/softprops/devtogo/releases/download/${VERSION}/devtogo-$(uname -s)-$(uname -m).tar.gz" \&lt;/span&gt;
            &lt;span class="s"&gt;| tar -xz -C $GITHUB_WORKSPACE/bin&lt;/span&gt;
          &lt;span class="s"&gt;$GITHUB_WORKSPACE/bin/devtogo --version&lt;/span&gt;
          &lt;span class="s"&gt;echo "::add-path::$GITHUB_WORKSPACE/bin"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;devtogo -s posts&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;DEVTO_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEVTO_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down, bit by bit.&lt;/p&gt;

&lt;p&gt;This first line gives the workflow a name used for display in the actions UI, In your repository, this lives under the "actions" tab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second line tells GitHub what repository event to react to for this workflow. In this case, &lt;code&gt;push&lt;/code&gt; events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next lines declare a list of "jobs" to execute when a push happens. These can be arbitrary and run parallel or can be ordered by dependencies on one another and run sequentially. Here I'm only declaring a single job called "publish-devto".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish-devto&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next line tells GitHub what kind of virtualized environment to run on. I tend to default to &lt;code&gt;ubuntu-latest&lt;/code&gt;, but you can also run workflows on macos and windows if you'd like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;jobs:
&lt;/span&gt;  publish-devto:
&lt;span class="gi"&gt;+    runs-on: ubuntu-latest
&lt;/span&gt;    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup devtogo
        run: |
          mkdir -p $GITHUB_WORKSPACE/bin
          export VERSION=v0.1.0
          curl -L "https://github.com/softprops/devtogo/releases/download/${VERSION}/devtogo-$(uname -s)-$(uname -m).tar.gz" \
            | tar -xz -C $GITHUB_WORKSPACE/bin
          $GITHUB_WORKSPACE/bin/devtogo --version
          echo "::add-path::$GITHUB_WORKSPACE/bin"
      - name: Publish
        run: devtogo -s posts
        env:
          DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next lines starts list out the sequential steps performed in a job. The first step of my workflow  tells GitHub Actions to checkout the latest source code for my branch. I'll need this to get the latest content to publish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;jobs:
&lt;/span&gt;  publish-devto:
    runs-on: ubuntu-latest
    steps:
&lt;span class="gi"&gt;+     - name: Checkout
+       uses: actions/checkout@v2
&lt;/span&gt;      - name: Setup devtogo
        run: |
          mkdir -p $GITHUB_WORKSPACE/bin
          export VERSION=v0.1.0
          curl -L "https://github.com/softprops/devtogo/releases/download/${VERSION}/devtogo-$(uname -s)-$(uname -m).tar.gz" \
            | tar -xz -C $GITHUB_WORKSPACE/bin
          $GITHUB_WORKSPACE/bin/devtogo --version
          echo "::add-path::$GITHUB_WORKSPACE/bin"
      - name: Publish
        run: devtogo -s posts
        env:
          DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step installs the devtogo tool from a GitHub release asset and adds it to the jobs PATH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;jobs:
&lt;/span&gt;  publish-devto:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
&lt;span class="gi"&gt;+     - name: Setup devtogo
+       run: |
+         mkdir -p $GITHUB_WORKSPACE/bin
+         export VERSION=v0.1.0
+         curl -L "https://github.com/softprops/devtogo/releases/download/${VERSION}/devtogo-$(uname -s)-$(uname -m).tar.gz" \
+           | tar -xz -C $GITHUB_WORKSPACE/bin
+         $GITHUB_WORKSPACE/bin/devtogo --version
+         echo "::add-path::$GITHUB_WORKSPACE/bin"
&lt;/span&gt;      - name: Publish
        run: devtogo -s posts
        env:
          DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step runs to tool and performs the upload outlined above. &lt;/p&gt;

&lt;p&gt;Note the &lt;code&gt;DEVTO_API_KEY&lt;/code&gt; environment variable. The tool expects this to exist and contain a valid dev.io API key. These are considered secret, don't store these in code or share with others! Instead you can safely and securely store them inside your repository's &lt;a href="https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets"&gt;encrypted Secrets&lt;/a&gt;. The example below shows how you can dereference a secret and store it in a workflow steps environment. These steps are ephemeral. All other parts of your workflow will not have access to this secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;jobs:
&lt;/span&gt;  publish-devto:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup devtogo
        run: |
          mkdir -p $GITHUB_WORKSPACE/bin
          export VERSION=v0.1.0
          curl -L "https://github.com/softprops/devtogo/releases/download/${VERSION}/devtogo-$(uname -s)-$(uname -m).tar.gz" \
          $GITHUB_WORKSPACE/bin/devtogo --version
          echo "::add-path::$GITHUB_WORKSPACE/bin"
&lt;span class="gi"&gt;+     - name: Publish
+       run: devtogo -s posts
+       env:
+         DEVTO_API_KEY: ${{ secrets.DEVTO_API_KEY }}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for today. In a future post I'll likely post about experimenting with static site generators. Stay tuned.&lt;/p&gt;

&lt;h2&gt;
  
  
  takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;dev.to api is really straight forward and makes the platform that much more compelling to use.&lt;/li&gt;
&lt;li&gt;If you're into the idea of portable content, give &lt;a href="https://github.com/softprops/devtogo"&gt;devtogo&lt;/a&gt; a whirl. I'm interested in your feedback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are just interesting in experimenting locally you can also install the tool with homebrew&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;softprops/tools/devtogo
  &lt;span class="nv"&gt;$ &lt;/span&gt;devtogo &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tools</category>
      <category>showdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>dev together</title>
      <dc:creator>Doug Tangren</dc:creator>
      <pubDate>Fri, 19 Jun 2020 04:45:04 +0000</pubDate>
      <link>https://forem.com/softprops/dev-together-cno</link>
      <guid>https://forem.com/softprops/dev-together-cno</guid>
      <description>&lt;p&gt;👩🏽‍💻👩🏻‍💻👨🏽‍💻👩‍💻🧑🏿‍💻&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A group needs only two things to be a tribe: a shared interest and a way to communicate. &lt;br&gt;
- Seth Godin: Tribes&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;a goal&lt;/li&gt;
&lt;li&gt;from the top&lt;/li&gt;
&lt;li&gt;trying size medium&lt;/li&gt;
&lt;li&gt;rediscovering community&lt;/li&gt;
&lt;li&gt;principle flow&lt;/li&gt;
&lt;li&gt;takeaway&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  a goal
&lt;/h2&gt;

&lt;p&gt;A goal without plan is just a wish&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. I've been wishing I could write more often for a very long time. It's something I know I should put more time into. I've been thinking lately about how I could reframe that wish as a goal.&lt;/p&gt;

&lt;p&gt;Making a routine of writing is an effective means of learning how to communicate well. Communication is idea delivery. Ideas you can't transfer well to others aren't useful despite their potential usefulness. Programming is also idea delivery but programming alone without writing is like eating unbalanced diet for if you want to get better at delivering ideas.&lt;/p&gt;

&lt;p&gt;I haven't blogged in a while so I recently starting reflecting. Written on the first page of my &lt;a href="https://en.wikipedia.org/wiki/Five_whys"&gt;junior investigator's memopad&lt;/a&gt; are the words: 🗒️ "Question: Why don't I write more often?" &lt;/p&gt;

&lt;h2&gt;
  
  
  from the top
&lt;/h2&gt;

&lt;p&gt;My blogging journey started with a humble tumblr&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. A few to be precise&lt;sup id="fnref3"&gt;3&lt;/sup&gt; &lt;sup id="fnref4"&gt;4&lt;/sup&gt;. My goal at that time was to capture what I was learning and share it with others with some hope that others might find it useful. Simply tracking links set a relatively low bar for writing but at least it created a space for sharing random things and ideas I learned on my programmer's journey. Eventually I got distracted with tumblr's theme engine and lost focus on my goal. &lt;/p&gt;

&lt;p&gt;I soon after felt the young developer's itch and pang of curiosity to write my own blog publishing tool. For historical context, this was during era of what I call Ruby on Rails' "golden age", back when Rails was first starting to take off. If you wanted to start a new project you were &lt;a href="https://www.youtube.com/watch?v=Gzj723LkRJY&amp;amp;feature=youtu.be"&gt;already half way done almost as soon as you started&lt;/a&gt;. There's still something to be said today for the virtue of being able to do that way back then, circa 2005.&lt;/p&gt;

&lt;p&gt;As expected, my little toy posting machine ended out resembling much of what tumblr already did well and in the end, keeping the pieces of that tool in place took as much time if not more that my writing time itself. Well played past me ✋. The exercise is always more important than the artifact so I ditched the artifact and learned from the exercise. I'm glad I did. I learned the useful lesson in the cost of time spent on &lt;a href="https://aws.amazon.com/blogs/aws/we_build_muck_s/"&gt;undifferentiated heavy weight lifting&lt;/a&gt;. You write it, you run it. Whose got time to run it? Oh and it's software so you have to maintain it, so...&lt;/p&gt;

&lt;p&gt;I stopped writing for a while and reflected for a bit after about what I wanted from a writing platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  trying size medium
&lt;/h2&gt;

&lt;p&gt;At that time what I wanted was a quality, hands off writing platform. No maintenance. Fewer jazz hands. Just a platform to focus on writing. Soon afterwards I fell in with &lt;a href="https://medium.com/@softprops"&gt;"The Medium"&lt;/a&gt; crowd.&lt;/p&gt;

&lt;p&gt;The allure of medium.com when it first arrived on the scene was that it positioned itself as being &lt;a href="https://www.theatlantic.com/technology/archive/2013/08/what-is-medium/278965/"&gt;&lt;em&gt;the&lt;/em&gt; place&lt;/a&gt; to discover quality and thought leading writing. Not to knock on a well done and nicely designed product, but what I actually experienced in practice was a platform where nearly every poster followed roughly the same cookie cutter recipe. The content eventually felt uninspired, and as such, eventually as was I. Nothing felt original.&lt;/p&gt;

&lt;p&gt;Medium also eventually came with an exclusivity price. I found myself inflicting more self injury as time passed  stubbing my feet &lt;a href="https://help.medium.com/hc/en-us/articles/360017581433-About-the-metered-paywall"&gt;tripping over paywalls&lt;/a&gt; while trying to consume content I got push notifications about than I did absorbing new ideas. As a content creator I felt odds with the product asking me to pay for a service I was actively contributing content to.&lt;/p&gt;

&lt;p&gt;It's a solid product but ended out not feeling like something I felt invested in. Something was missing.&lt;/p&gt;

&lt;p&gt;So I dialed writing down to 0 for a while again.&lt;/p&gt;

&lt;h1&gt;
  
  
  rediscovering community
&lt;/h1&gt;

&lt;p&gt;These days I mostly offer small denominations of &lt;a href="https://carbon.now.sh/"&gt;code graphics&lt;/a&gt; embedded in tweets but I've found even that quickly loses its novelty. It's also not horribly accessible! What Twitter lacks is ample space to communicate context, &lt;a href="https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action"&gt;the why&lt;/a&gt;, and most importantly -- what I learned. What I wanted was a place to share both long and short TIL posts.&lt;/p&gt;

&lt;p&gt;I've recently revisited the idea of hand crafting a blog but rather than writing a tool from scratch for the joy of reinventing existing publishing mechanics, I wanted a place to explore creativity using the the often forgotten raw materials of the web: HTML, CSS and JavaScript. The HCJ stack doesn't have a cool ring to it but It will make a come back. Just you wait! I don't get to exercise those muscles enough and I feel my inner designer belly needs some situps. I didn't want to fall into a trap of maintaining a new tool. Fortunately, &lt;a href="https://www.staticgen.com/"&gt;I don't have to and neither do you&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Around that same time I rediscovered &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt;. I'd actually already heard about dev.to much earlier but ignored it without good excuse. I now regret that. It was only by chance that I saw &lt;a href="https://twitter.com/leewynne/status/1268567098101547009?s=19"&gt;this tweet&lt;/a&gt; which caught my eye with this graphic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--81adYBAN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EZrbAfbWAAIlhnf%3Fformat%3Djpg%26name%3D900x900" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--81adYBAN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/EZrbAfbWAAIlhnf%3Fformat%3Djpg%26name%3D900x900" alt="dev.to image" width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tweet reminded me of another reason I sometimes avoid writing: the internet troll patrol and the reserve natural guard of developers just waiting to be deployed when &lt;a href="https://xkcd.com/386/"&gt;someone is wrong on the internet&lt;/a&gt;. I think this is currently the biggest draw of dev.to and the thing I've been missing with writing platforms: a supportive community.&lt;/p&gt;

&lt;p&gt;What I really dig about dev.to is that the more time you spend with it, the more you'll start to notice its primarily an vibrant and supportive developer community and only secondarily a blogging platform. Posting articles is just a mechanic to that end. &lt;a href="https://dev.to/about"&gt;Community is the real product&lt;/a&gt; being offered. For those that know me, that's a my peanut butter and jam. The reason why I'm packing up and moving to dev.to is the community.&lt;/p&gt;

&lt;h1&gt;
  
  
  principle flow
&lt;/h1&gt;

&lt;p&gt;After Medium, I have stronger, renewed principles on what a writing platforms ought to be. If monetizing still is your thing, &lt;a href="https://dev.to/devteam/dev-is-now-web-monetized-21db"&gt;dev.to has a nicer more open approach&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But there's one more thing. My writing so far hasn't really be set up to adapt to change. My writing lives inside the platforms that I've used in the past. It seems very probably that I'll continue to move around so it makes sense that I can carry my content with me where ever I go next. I'd like to be able to &lt;a href="https://open.buffer.com/living-one-bag/"&gt;live more portably&lt;/a&gt; so that I am better equipped for future change. &lt;/p&gt;

&lt;p&gt;Offline authoring is a direction I've also wanted. I am I fan of feeling the &lt;a href="https://en.wikipedia.org/wiki/Flow_(psychology)"&gt;flow&lt;/a&gt; when trying to think creatively. Offline writing avoids online distractions and gives you space to think.&lt;/p&gt;

&lt;p&gt;Here's the flow I'm currently iterating towards.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write everything locally, offline&lt;/li&gt;
&lt;li&gt;Store posts in a GitHub code repository&lt;/li&gt;
&lt;li&gt;On git pushes, trigger a GitHub action that

&lt;ul&gt;
&lt;li&gt;builds a static content site and publish that to gh pages&lt;/li&gt;
&lt;li&gt;run a tool to upload the same content to dev.to where I can make new friends and not have think about content discovery.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a separate post, I'll write in more detail this setup in more detail and &lt;a href="https://github.com/softprops/devtogo"&gt;a little tool I wrote&lt;/a&gt; if you are interested in using the flow yourself.&lt;/p&gt;

&lt;p&gt;To me, that's best of all the worlds: distraction free writing, liberated content, participating more in an open and friendly community, and creating space to explore the HCJ stack and work on my web love handles.&lt;/p&gt;

&lt;h2&gt;
  
  
  takeaway
&lt;/h2&gt;

&lt;p&gt;It's useful reflect often.&lt;/p&gt;

&lt;p&gt;Reflecting will give you a better sense for your principles. You'll also learn how to be happier and find what you are looking for.&lt;/p&gt;

&lt;p&gt;What I learned is that my goal wasn't just creating routine for writing. It was finding a community to share it with.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.goodreads.com/quotes/87476-a-goal-without-a-plan-is-just-a-wish"&gt;https://www.goodreads.com/quotes/87476-a-goal-without-a-plan-is-just-a-wish&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://softpress.tumblr.com/"&gt;https://softpress.tumblr.com/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://asoftsea.tumblr.com/"&gt;https://asoftsea.tumblr.com/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://papertail.tumblr.com/"&gt;https://papertail.tumblr.com/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>goals</category>
      <category>writing</category>
      <category>reflection</category>
    </item>
  </channel>
</rss>
