<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://michael.minton.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://michael.minton.io/" rel="alternate" type="text/html" /><updated>2025-12-06T16:30:39-05:00</updated><id>https://michael.minton.io/feed.xml</id><title type="html">michael.minton.io</title><subtitle>Copyright 2017
</subtitle><entry><title type="html">omarchy - update #3</title><link href="https://michael.minton.io/2025/12/omarchy-update.html" rel="alternate" type="text/html" title="omarchy - update #3" /><published>2025-12-06T08:56:41-05:00</published><updated>2025-12-06T08:56:41-05:00</updated><id>https://michael.minton.io/2025/12/omarchy-update</id><content type="html" xml:base="https://michael.minton.io/2025/12/omarchy-update.html"><![CDATA[<p>Just a quick, random rambling update of my time on Omarchy.</p>

<p>The last time I seriously tried to run Linux as my daily I was in high school. Due to gaming (<a href="https://en.wikipedia.org/wiki/Asheron%27s_Call">Asheron’s Call</a>), it wasn’t long before I was back on Windows. That experience gave me just enough exposure to the basics and get comfy on the command line, but not long enough to fully grok all the bits and pieces that make up the Linux ecosystem. I present that background to give some understanding of the mindset I took into Omarchy as I departed from macOS.</p>

<p>Despite the rather gross looking set up with a wire dangling across my keyboard, I’m still enjoying my time on Omarchy. More specifically, my time with <a href="https://hypr.land/">Hyprland</a> on <a href="https://archlinux.org/">Arch</a>. Omarchy has been a beautiful, approachable bridge to Linux land. Without it, I’m certain I’d still be trapped in the walled garden and complaining about it. I was always aware (though recently more clearly) that most of the “Omarchy” experience is just a tasteful combination of existing software with usable defaults. It’s awesome and I’m grateful for it’s existence.</p>

<p>As I spend more time with Omarchy, it’s inevitable that I’ll peel back the layers and begin to understand how it all fits together. Instead of constantly talking about “Omarchy”, I can talk about the actual piece of software itself. Which leads me to….</p>

<h1 id="hyprland">Hyprland</h1>

<p>Described as a “Modern compositor with the looks”, it’s a dynamic, fast, lightweight tiling Wayland compositor with smooth animations and as advertised…“the looks.” It’s a vast ecosystem of “hypr*” things like Hypridle, Hyprlock, Hyprsunset, Hyprpaper and on and on. In my opinion, this is ecosystem is responsible for most of the appeal of Omarchy.</p>

<p>Hyprland itself is less than 4 years old and, as far as I can tell, mostly built by one person <a href="https://x.com/vaxryy">Vaxry</a>. He’s an unusual (or completely usual depending on your circle) fellow and his leadership is definitely felt. Here’s an example from the official <a href="https://x.com/hyprwm/status/1995621682053361886">Hyprland X</a> account:</p>

<p><img src="https://michael.minton.io/assets/lokdfhidf.png" width="600" height="auto" /></p>

<p>It’s an insane accomplishment and really impressive. For better or worse, there are times where his leadership is more obvious than usual. Take for example this lovely specimen:</p>

<p><img src="https://michael.minton.io/assets/0889.jpg" width="600" height="auto" /></p>

<p>Don’t take this as a complaint. Personally, I like the existence of this sort of thing as it’s a strong indicator that corporate money and influence has yet to infiltrate this awesome project. But, it’s worth being warned about. Especially for those coming from macOS.</p>

<h1 id="future">Future</h1>

<p>At this point, I fully expect some day in the future to venture off the Omarchy highway and into my own custom Hyprland/Arch config. Especially as I learn more about all the awesome/crazy stuff Omarchy left out of Hyprland (see <a href="https://hypr.land/hall_of_fame/">Hall of Fame</a>). But, until that day arrives, I’ll be riding happy on Omarchy.</p>]]></content><author><name>Michael Minton</name></author><category term="linux" /><category term="omarchy" /><category term="framework" /><summary type="html"><![CDATA[Just a quick, random rambling update of my time on Omarchy.]]></summary></entry><entry><title type="html">omarchy - three months later</title><link href="https://michael.minton.io/2025/11/three-months-on-omarchy.html" rel="alternate" type="text/html" title="omarchy - three months later" /><published>2025-11-11T16:04:16-05:00</published><updated>2025-11-11T16:04:16-05:00</updated><id>https://michael.minton.io/2025/11/three-months-on-omarchy</id><content type="html" xml:base="https://michael.minton.io/2025/11/three-months-on-omarchy.html"><![CDATA[<p>I’ve been a Mac user since 2007. At work we need Windows, but the entire team just runs them in a VM from macOS because nobody wants to stare at Windows all day. So when I say I was ready to jump ship from both Windows and macOS, I mean it. Windows is turning into the ad-riddled dystopia from Ready Player One, and macOS has lost whatever taste it once had. Both are frantically bolting AI slop onto everything. I needed an escape hatch at least for my personal machine.</p>

<h1 id="omarchy-enters-the-chat">Oma<del>r</del>chy enters the chat</h1>

<p>I had been hearing about <a href="https://omarchy.org">Omarchy</a> all over my X feed. Finally I watched a video put out by DHH about version 2.0, and that was enough for me. I dropped $2,200 on a Framework 13 with the AMD Ryzen AI 9 HX 370, ordered it, and a week later it was in my hands. There was no official Omarchy ISO yet, so I installed vanilla Arch and ran the install script. I had already ordered the magic <a href="https://amzn.to/49ouFkW">WJESOG DisplayPort to USB-C cable</a><sup>Poop</sup> that DHH said actually makes Apple and LG 5K displays behave on Linux. I plugged my LG UltraFine 5K into the Framework and… it just worked. Hyprland felt snappier than anything I’d used in years. I was in love.</p>

<h1 id="for-three-awesome-weeks">For three awesome weeks</h1>

<p>One morning the monitor was black. No signal. Classic Linux adventure time. A lot of Google, a lot of AI chats, and eventually I discovered the fix was in a newer kernel than the one Omarchy was shipping. Updated the kernel, monitor came back. Life was good again.</p>

<p>Then Omarchy 3.0 dropped. I upgraded. Something in the migrations broke and global shortcuts stopped launching anything. Dug through GitHub issues, manually patched a few config files, and got it working again. But now I had that nagging feeling you get with any big upgrade path: cruft. Now that Omarchy 3.1.0 finally shipped with a proper ISO, I decided to nuke it and start clean.</p>

<p>The fresh install took literally two minutes. I rebooted, grinning at how buttery smooth everything felt… and the LG was dead again. Same symptoms. Updated the kernel…still dead. This time the fix was a Framework BIOS update that the excellent people in the Omarchy Discord walked me through. Monitor sprang back to life. High-fives all around.</p>

<h1 id="the-very-next-morning-black-screen-again">The very next morning? Black screen again.</h1>

<p>At this point the Discord went quiet, and so did I. I’ve run out of google-fu. When everything is working, Omarchy (really Hyprland plus the mountain of thoughtful defaults) is the best desktop experience I’ve ever had. But I’m tired of waking up to a coin flip on whether my $2,000 laptop will acknowledge its $1,200 monitor.</p>

<h1 id="final-verdict">Final Verdict</h1>

<p>Omarchy is magical when it’s happy. The problem is it’s moody, and right now my LG 5K and Framework combo is stuck in an unhappy phase that neither I nor the community has solved. I haven’t quite given up yet, but I fear I’m days away from returning to macOS with a slightly defeated sigh.</p>

<p>Linux on the desktop is still an adventure. Sometimes that’s fun. Sometimes you just want your monitor to work.</p>

<h1 id="update-2025-11-21">Update 2025-11-21</h1>

<p>After spending way too much time on this, I appear to be having success by moving the DisplayPort and USB-A expansion cards to the nearer ports. This required putting the USB-A on one side and the DisplayPort on the other. That means I currently have a fun little wire hanging across the Framework 13’s keyboard.</p>

<p><img src="https://michael.minton.io/assets/0853.jpg" alt="Framework 13" /></p>

<p>I am only getting 3840x2160 on a 5K monitor, but at least it has been reliable so far. And yes, this is a worse set up than my sleak M4 PRO with a single Thunderbolt cable that provides not only monitor, keyboard, &amp; webcam, but also power. However, Omarchy is so much better for me than macOS that it’s absolutely worth it.</p>]]></content><author><name>Michael Minton</name></author><category term="linux" /><category term="omarchy" /><category term="framework" /><summary type="html"><![CDATA[I’ve been a Mac user since 2007. At work we need Windows, but the entire team just runs them in a VM from macOS because nobody wants to stare at Windows all day. So when I say I was ready to jump ship from both Windows and macOS, I mean it. Windows is turning into the ad-riddled dystopia from Ready Player One, and macOS has lost whatever taste it once had. Both are frantically bolting AI slop onto everything. I needed an escape hatch at least for my personal machine.]]></summary></entry><entry><title type="html">adventures with ash framework</title><link href="https://michael.minton.io/2025/10/adventures-with-ash-framework.html" rel="alternate" type="text/html" title="adventures with ash framework" /><published>2025-10-14T16:10:32-04:00</published><updated>2025-10-14T16:10:32-04:00</updated><id>https://michael.minton.io/2025/10/adventures-with-ash-framework</id><content type="html" xml:base="https://michael.minton.io/2025/10/adventures-with-ash-framework.html"><![CDATA[<p>When I first heard about <a href="https://ash-hq.org/">Ash Framework</a> at ElixirConf many years ago, I ignored it as a niche within a niche. I am often skeptical of this sort of thing because inevitably you will need to go off the “happy” path and it’s either impossible or painful. However, at the 2025 ElixirConf I sat in a talk about Ash and was intrigued by what I saw. I preordered the <a href="https://pragprog.com/titles/ldash/ash-framework/">Ash Framework</a> book and then mostly forgot about it until the book arrived!</p>

<p>I read the book straight through without touching a keyboard. The concepts were well explained and easy to understand. With the book read, I decided to start an app to play with.</p>

<h1 id="the-ash-installer">the ash installer</h1>

<p>The Ash site has a cool “installer” that let’s you enter a name, select some options, and generate a single command to get up and running.</p>

<p>I went with the default options except I added Password auth.</p>

<p><img src="https://michael.minton.io/assets/ash-installer.png" alt="Ash Installer" width="600" height="auto" /></p>

<p>Running this command created a new Phoenix app called <code class="language-plaintext highlighter-rouge">Rails</code>, used <a href="https://hexdocs.pm/igniter">igniter</a> to install Ash &amp; the other selected/required libraries, set up the initial database, and ran the migrations.</p>

<p>We now have an app we can start adding resources to. However, I was mostly curious how the auth stuff was implemented.</p>

<h2 id="the-login-form">the login form</h2>

<p><img src="https://michael.minton.io/assets/ash-login.png" alt="Ash Login Form" width="400" height="auto" /></p>

<p>By default Ash handles the rendering of the account-related forms for registering, logging in, etc. These work well enough for an internal app, but will need to be customized for a real app. Let’s try to customize the login form and see how it goes.</p>

<h3 id="customizing-ashs-login-form">customizing ash’s login form</h3>

<p>You can customize <a href="https://hexdocs.pm/ash_authentication_phoenix">AshAuthentication Phoenix’s</a> (APP) forms using overrides. The <code class="language-plaintext highlighter-rouge">Rails</code> app comes with all this wired up and we can start overriding in <code class="language-plaintext highlighter-rouge">lib\rails_web\auth_overrides.ex</code>.</p>

<p>APP has the concept of a Banner that appears above the sign-in form. Here we customize it to hide the image, make the text larger, and change it to “Let’s sign in!”.</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">RailsWeb</span><span class="o">.</span><span class="no">AuthOverrides</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">AshAuthentication</span><span class="o">.</span><span class="no">Phoenix</span><span class="o">.</span><span class="no">Overrides</span>

  <span class="n">override</span> <span class="no">AshAuthentication</span><span class="o">.</span><span class="no">Phoenix</span><span class="o">.</span><span class="no">Components</span><span class="o">.</span><span class="no">Banner</span> <span class="k">do</span>
    <span class="n">set</span> <span class="ss">:image_url</span><span class="p">,</span> <span class="no">nil</span>
    <span class="n">set</span> <span class="ss">:text_class</span><span class="p">,</span> <span class="s2">"text-xl"</span>
    <span class="n">set</span> <span class="ss">:text</span><span class="p">,</span> <span class="s2">"Let's sign in!"</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Pretty sweet!</p>

<p>However, we’ve also hit the first example of not being on the happy path. We want to customize the banner text on each page. Sign-in should say “Sign in to Rails”, password reset should say “Reset your password”, and so on. Turns out, that’s not really possible. APP uses one Banner component across all authentication pages. The component doesn’t know which page it’s on. It just renders the same text everywhere.</p>

<p>My first thought it to make the Banner component smart. Maybe it could detect the current URI and show different text based on the page. Nope, it won’t work. The Banner component doesn’t have access to the current URI. The override system doesn’t pass that information down.</p>

<p>As a workaround, we can creat separate Banner override modules for each authentication route. Each module sets its own text.
Then we configured the router to use the right override for each route:</p>
<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">scope</span> <span class="s2">"/"</span><span class="p">,</span> <span class="no">RailsWeb</span> <span class="k">do</span>
    <span class="o">...</span>
    <span class="n">sign_in_route</span> <span class="ss">register_path:</span> <span class="s2">"/register"</span><span class="p">,</span>
      <span class="ss">overrides:</span> <span class="p">[</span><span class="no">RailsWeb</span><span class="o">.</span><span class="no">AuthOverrides</span><span class="o">.</span><span class="no">SignInBanner</span><span class="p">]</span>
      <span class="o">...</span>

    <span class="n">reset_route</span> <span class="ss">auth_routes_prefix:</span> <span class="s2">"/auth"</span><span class="p">,</span>
      <span class="ss">overrides:</span> <span class="p">[</span><span class="no">RailsWeb</span><span class="o">.</span><span class="no">AuthOverrides</span><span class="o">.</span><span class="no">ResetBanner</span><span class="p">]</span>
      <span class="o">...</span>

    <span class="n">confirm_route</span> <span class="no">Rails</span><span class="o">.</span><span class="no">Accounts</span><span class="o">.</span><span class="no">User</span><span class="p">,</span> <span class="ss">:confirm_new_user</span><span class="p">,</span>
      <span class="ss">overrides:</span> <span class="p">[</span><span class="no">RailsWeb</span><span class="o">.</span><span class="no">AuthOverrides</span><span class="o">.</span><span class="no">ConfirmBanner</span><span class="p">]</span>
      <span class="o">...</span>
    <span class="o">...</span>
 <span class="k">end</span>
</code></pre></div></div>

<p>Pretty sweet!</p>

<p>But we’ve hit another snag! Sign-in and register forms share the same route in APP. They use the <code class="language-plaintext highlighter-rouge">register_path</code> option to handle both forms on one route. So we can’t have different banner text for sign-in vs register. They have to share.</p>

<p>I couldn’t find a good way around this without implementing fully custom forms. For now, we have to compromise with “Welcome to Rails”. It works for both new and returning users.</p>

<h1 id="final-thoughts">final thoughts</h1>

<p>You get a lot out of the box and it really has that Ruby on Rails feel. My fear about this type of thing boxing you into a corner seem to be well founded. Like Rails, you can move fast if you stay on the happy path, but once you venture off that sacred sidewalk and try to do something weird (i.e., pretty much anything), you’ll find out you can’t. You’re stuck on that sidewalk forever.</p>]]></content><author><name>Michael Minton</name></author><category term="phoenix" /><category term="elixir" /><category term="ash" /><summary type="html"><![CDATA[When I first heard about Ash Framework at ElixirConf many years ago, I ignored it as a niche within a niche. I am often skeptical of this sort of thing because inevitably you will need to go off the “happy” path and it’s either impossible or painful. However, at the 2025 ElixirConf I sat in a talk about Ash and was intrigued by what I saw. I preordered the Ash Framework book and then mostly forgot about it until the book arrived!]]></summary></entry><entry><title type="html">using bulma with phoenix</title><link href="https://michael.minton.io/2019/08/using-bulma-with-phoenix.html" rel="alternate" type="text/html" title="using bulma with phoenix" /><published>2019-08-06T17:10:32-04:00</published><updated>2019-08-06T17:10:32-04:00</updated><id>https://michael.minton.io/2019/08/using-bulma-with-phoenix</id><content type="html" xml:base="https://michael.minton.io/2019/08/using-bulma-with-phoenix.html"><![CDATA[<p>In this short post I’ll walk you through getting a new Phoenix 1.4 app up and running with <a href="https://bulma.io/">Bulma</a>, a responsive, modular, and modern css framework. It feels light and it’s easy to use.</p>

<h1 id="yarn">Yarn</h1>

<p>I prefer <a href="https://yarnpkg.com/">Yarn</a> so let’s make sure it’s installed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew install yarn
</code></pre></div></div>

<h1 id="generate-a-new-phoenix-14-app">Generate a new Phoenix 1.4 app</h1>

<p><em>This assumes you have both Elixir and Phoenix installed already. If not checkout their <a href="https://hexdocs.pm/phoenix/installation.html#content">guides</a> which do a great job walking through the process.</em></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mix phx.new bulma
</code></pre></div></div>
<p>Be sure <strong>NOT</strong> to install any dependencies when prompted.</p>

<p>Manually install all dependencies and create the database:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>bulma <span class="o">&amp;&amp;</span> mix deps.get <span class="o">&amp;&amp;</span> mix ecto.create <span class="o">&amp;&amp;</span> <span class="nb">cd </span>assets <span class="o">&amp;&amp;</span> yarn add node-sass sass-loader bulma <span class="nt">--dev</span> <span class="o">&amp;&amp;</span> yarn <span class="o">&amp;&amp;</span> node node_modules/webpack/bin/webpack.js <span class="nt">--mode</span> development <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ..
</code></pre></div></div>

<h1 id="switching-to-sass">Switching to sass</h1>

<p>Change our file extensions to sass and remove default styles:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mv </span>assets/css/app.css assets/css/app.scss <span class="o">&amp;&amp;</span> <span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">''</span> <span class="s1">'s/app.css/app.scss/g'</span> assets/js/app.js <span class="o">&amp;&amp;</span> <span class="nb">rm </span>assets/css/phoenix.css
</code></pre></div></div>

<p>Open <code class="language-plaintext highlighter-rouge">/assets/webpack.config.js</code> and find the place that tests for <code class="language-plaintext highlighter-rouge">css</code> files, it should look like this:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="nl">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">css$/</span><span class="p">,</span>
  <span class="nx">use</span><span class="p">:</span> <span class="p">[</span><span class="nx">MiniCssExtractPlugin</span><span class="p">.</span><span class="nx">loader</span><span class="p">,</span> <span class="dl">'</span><span class="s1">css-loader</span><span class="dl">'</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Now replace it with this:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
  <span class="nl">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">s</span><span class="se">?</span><span class="sr">css$/</span><span class="p">,</span>
  <span class="nx">use</span><span class="p">:</span> <span class="p">[</span><span class="nx">MiniCssExtractPlugin</span><span class="p">.</span><span class="nx">loader</span><span class="p">,</span> <span class="dl">'</span><span class="s1">css-loader</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">sass-loader</span><span class="dl">'</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Open <code class="language-plaintext highlighter-rouge">/assets/css/app.scss</code> and replace it with the following (mostly copied from the Bulma docs):</p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@charset</span> <span class="s2">"utf-8"</span><span class="p">;</span>

<span class="c1">// Import a Google Font</span>
<span class="k">@import</span> <span class="sx">url('https://fonts.googleapis.com/css?family=Nunito:400,700')</span><span class="p">;</span>

<span class="c1">// Set your brand colors</span>
<span class="nv">$purple</span><span class="p">:</span> <span class="mh">#8A4D76</span><span class="p">;</span>
<span class="nv">$pink</span><span class="p">:</span> <span class="mh">#FA7C91</span><span class="p">;</span>
<span class="nv">$brown</span><span class="p">:</span> <span class="mh">#757763</span><span class="p">;</span>
<span class="nv">$beige-light</span><span class="p">:</span> <span class="mh">#D0D1CD</span><span class="p">;</span>
<span class="nv">$beige-lighter</span><span class="p">:</span> <span class="mh">#EFF0EB</span><span class="p">;</span>

<span class="c1">// Update Bulma's global variables</span>
<span class="nv">$family-sans-serif</span><span class="p">:</span> <span class="s2">"Nunito"</span><span class="o">,</span> <span class="nb">sans-serif</span><span class="p">;</span>
<span class="nv">$grey-dark</span><span class="p">:</span> <span class="nv">$brown</span><span class="p">;</span>
<span class="nv">$grey-light</span><span class="p">:</span> <span class="nv">$beige-light</span><span class="p">;</span>
<span class="nv">$primary</span><span class="p">:</span> <span class="nv">$purple</span><span class="p">;</span>
<span class="nv">$link</span><span class="p">:</span> <span class="nv">$pink</span><span class="p">;</span>
<span class="nv">$widescreen-enabled</span><span class="p">:</span> <span class="bp">false</span><span class="p">;</span>
<span class="nv">$fullhd-enabled</span><span class="p">:</span> <span class="bp">false</span><span class="p">;</span>

<span class="c1">// Update some of Bulma's component variables</span>
<span class="nv">$body-background-color</span><span class="p">:</span> <span class="nv">$beige-lighter</span><span class="p">;</span>
<span class="nv">$control-border-width</span><span class="p">:</span> <span class="m">2px</span><span class="p">;</span>
<span class="nv">$input-border-color</span><span class="p">:</span> <span class="nb">transparent</span><span class="p">;</span>
<span class="nv">$input-shadow</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>

<span class="c1">//Import Bulma</span>
<span class="k">@import</span> <span class="s1">'bulma'</span><span class="p">;</span>
</code></pre></div></div>

<p>Open <code class="language-plaintext highlighter-rouge">/lib/bulma_web/templates/page/index.html.eex</code> and replace it with the following (again mostly copied from Bulma docs):</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"section"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;h1</span> <span class="na">class=</span><span class="s">"title"</span><span class="nt">&gt;</span>
    Bulma
  <span class="nt">&lt;/h1&gt;</span>

  <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"subtitle"</span><span class="nt">&gt;</span>
    Modern CSS framework based on <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox"</span><span class="nt">&gt;</span>Flexbox<span class="nt">&lt;/a&gt;</span>
  <span class="nt">&lt;/p&gt;</span>

  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"field"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"control"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;input</span> <span class="na">class=</span><span class="s">"input"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">placeholder=</span><span class="s">"Input"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;/div&gt;</span>

  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"field"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"control"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"select"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;select&gt;</span>
          <span class="nt">&lt;option&gt;</span>Select dropdown<span class="nt">&lt;/option&gt;</span>
        <span class="nt">&lt;/select&gt;</span>
      <span class="nt">&lt;/span&gt;</span>
    <span class="nt">&lt;/p&gt;</span>
  <span class="nt">&lt;/div&gt;</span>

  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"buttons"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">"button is-primary"</span><span class="nt">&gt;</span>Primary<span class="nt">&lt;/a&gt;</span>
    <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">"button is-link"</span><span class="nt">&gt;</span>Link<span class="nt">&lt;/a&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>

<h1 id="test-it-out">Test it out</h1>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mix phx.server
</code></pre></div></div>

<p><img src="https://michael.minton.io/assets/20190814-phoenix-bulma.png" alt="package contents" /></p>]]></content><author><name>Michael Minton</name></author><category term="phoenix" /><category term="elixir" /><category term="bulma" /><category term="macos" /><summary type="html"><![CDATA[In this short post I’ll walk you through getting a new Phoenix 1.4 app up and running with [Bulma], a responsive, modular, and modern css framework. It feels light and it’s easy to use.]]></summary></entry><entry><title type="html">cool basecamp tricks</title><link href="https://michael.minton.io/2019/05/cool-basecamp-tricks-copy.html" rel="alternate" type="text/html" title="cool basecamp tricks" /><published>2019-05-31T14:55:54-04:00</published><updated>2019-05-31T14:55:54-04:00</updated><id>https://michael.minton.io/2019/05/cool-basecamp-tricks%20copy</id><content type="html" xml:base="https://michael.minton.io/2019/05/cool-basecamp-tricks-copy.html"><![CDATA[<p>I have used Basecamp for years and yet the other day a coworker taught me something new about it. I was a bit surprised and also excited because the new feature was actually very useful. So to share that excitement I give you some cool Basecamp tricks.</p>

<h1 id="code-formatting">Code formatting</h1>

<p>When you have a snippet of code you’d like to share via Campfire or Ping you can have Basecamp format it for you using the following command:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/code &lt;lang&gt; | [paste]
</code></pre></div></div>

<p>where <code class="language-plaintext highlighter-rouge">&lt;lang&gt;</code> is some programming language.</p>

<p>For example, imagine I have this snippet of <em>ruby</em> code on my clipboard:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">sum_eq_n?</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
  <span class="k">return</span> <span class="kp">true</span> <span class="k">if</span> <span class="n">arr</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">&amp;&amp;</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span>
  <span class="n">arr</span><span class="p">.</span><span class="nf">product</span><span class="p">(</span><span class="n">arr</span><span class="p">).</span><span class="nf">reject</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">==</span> <span class="n">b</span> <span class="p">}.</span><span class="nf">any?</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="o">==</span> <span class="n">n</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Type <code class="language-plaintext highlighter-rouge">/code ruby | </code> then <kbd>⌘</kbd> + <kbd>v</kbd> to paste and <kbd>⏎</kbd> to send the message.</p>

<p>Basecamp will output the following nicely formatted code:</p>

<p><img src="https://michael.minton.io/assets/basecamp-code-formatting.png" alt="basecamp-code-formatting" /></p>

<h1 id="playing-sounds">Playing Sounds</h1>

<p>Dating all the way back to the original version of Campfire there has been a “hidden” ability to play various sound bites. These have been updated over the years and recently include sounds from Game of Thrones, Frozen, and more.</p>

<p>To play a sound just type <code class="language-plaintext highlighter-rouge">/play &lt;sound&gt;</code> where <code class="language-plaintext highlighter-rouge">&lt;sound&gt;</code> is one of the available sounds. For example, to play the 🎉 <em>Tada</em> sound type <code class="language-plaintext highlighter-rouge">/play tada</code> and enjoy!</p>

<p><img src="https://michael.minton.io/assets/basecamp-tada.png" alt="basecamp-tada" /></p>

<h1 id="help">Help</h1>

<p>Both of these useful commands are hidden and remembering all the sounds can be a pain. To help with this they’ve included a <code class="language-plaintext highlighter-rouge">help</code> command.</p>

<p>Type <code class="language-plaintext highlighter-rouge">/help</code> and Basecamp will spit out documentation along with a list of all the available sounds:</p>

<p><img src="https://michael.minton.io/assets/basecamp-help.png" alt="basecamp-help" /></p>]]></content><author><name>Michael Minton</name></author><category term="basecamp" /><summary type="html"><![CDATA[I have used Basecamp for years and yet the other day a coworker taught me something new about it. I was a bit surprised and also excited because the new feature was actually very useful. So to share that excitement I give you some cool Basecamp tricks.]]></summary></entry><entry><title type="html">creating a form for a non-persisted ecto schema in phoenix 1.4</title><link href="https://michael.minton.io/2018/12/creating-a-form-for-a-non-persisted-ecto-schema-in-phoenix.html" rel="alternate" type="text/html" title="creating a form for a non-persisted ecto schema in phoenix 1.4" /><published>2018-12-22T07:55:54-05:00</published><updated>2018-12-22T07:55:54-05:00</updated><id>https://michael.minton.io/2018/12/creating-a-form-for-a-non-persisted-ecto-schema-in-phoenix</id><content type="html" xml:base="https://michael.minton.io/2018/12/creating-a-form-for-a-non-persisted-ecto-schema-in-phoenix.html"><![CDATA[<p>I kind of wanted to title this post, “how to create a form that doesn’t use a model” but Ecto decided to drop “Model” in favor of “Schema”; same thing, different mindset.</p>

<p>Sometimes you just want to collect some data from a user but have no plans of persisting it to the database. You can use <code class="language-plaintext highlighter-rouge">embedded_schema</code> to accomplish this. You’ll get to mostly work with Phoenix/Ecto as usual except without the migration, tables, and saving.</p>

<p>In this post we’ll be creating a <a href="https://phoenixframework.org">Phoenix</a> 1.4 app with a contact form.</p>

<h1 id="create-the-phoenix-14-app">Create the Phoenix 1.4 app</h1>

<p>The following command will</p>
<ul>
  <li>create a new Phoenix app called <code class="language-plaintext highlighter-rouge">Contact</code></li>
  <li>install its dependencies</li>
  <li>create the database</li>
  <li>open your browser to http://localhost:4000</li>
  <li>start the webserver</li>
</ul>

<p>A couple things to note:</p>
<ol>
  <li>You will told the directory already exists and asked if you want to continue: Type <code class="language-plaintext highlighter-rouge">y</code> and press <kbd>Enter</kbd></li>
  <li>You will be asked if you want to “Fetch and install dependencies?”: Type <code class="language-plaintext highlighter-rouge">y</code> and press <kbd>Enter</kbd></li>
  <li>The browser will likely tell you the page isn’t found since it tried to load the site before the webserver finished starting. Simply wait a second or two and then reload the page.</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>contact <span class="p">;</span> <span class="nb">cd </span>contact <span class="p">;</span> mix phx.new <span class="nb">.</span> <span class="nt">--app</span> contact <span class="p">;</span> mix ecto.create <span class="p">;</span> open http://localhost:4000 <span class="p">;</span> mix phx.server
</code></pre></div></div>

<p>You should be greeted with the Phoenix welcome screen.</p>

<p><img src="https://michael.minton.io/assets/20181222-welcome-to-phoenix.png" alt="Phoenix Welcome" /></p>

<h1 id="create-the-ectoschema">Create the Ecto.Schema</h1>

<p>Create a new file <code class="language-plaintext highlighter-rouge">\lib\contact\message.ex</code> with the following contents:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">Contact</span><span class="o">.</span><span class="no">Message</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Schema</span>
  <span class="kn">import</span> <span class="no">Ecto</span><span class="o">.</span><span class="no">Changeset</span>

  <span class="n">embedded_schema</span> <span class="k">do</span>
    <span class="n">field</span> <span class="ss">:name</span>
    <span class="n">field</span> <span class="ss">:email</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">changeset</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">attrs</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">message</span>
    <span class="o">|&gt;</span> <span class="n">cast</span><span class="p">(</span><span class="n">attrs</span><span class="p">,</span> <span class="p">[</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:email</span><span class="p">])</span>
    <span class="o">|&gt;</span> <span class="n">validate_required</span><span class="p">([</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:email</span><span class="p">])</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Notice we used <a href="https://hexdocs.pm/ecto/Ecto.Schema.html#embedded_schema/1">embedded_schema</a> here. This let’s <a href="https://hexdocs.pm/ecto/Ecto.html">Ecto</a> know that we don’t plan on saving this schema to the database.</p>

<h1 id="creating-the-form">Creating the form</h1>

<p>Open <code class="language-plaintext highlighter-rouge">\lib\contact_web\templates\page\index.html.eex</code> and replace with the following:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"section"</span><span class="o">&gt;</span>
   <span class="o">&lt;</span><span class="n">p</span> <span class="n">class</span><span class="o">=</span><span class="s2">"alert alert-info"</span> <span class="n">role</span><span class="o">=</span><span class="s2">"alert"</span><span class="err">&gt;</span><span class="o">&lt;%=</span> <span class="n">get_flash</span><span class="p">(</span><span class="nv">@conn</span><span class="p">,</span> <span class="ss">:info</span><span class="p">)</span> <span class="p">%</span><span class="err">&gt;</span><span class="o">&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
  <span class="o">&lt;%=</span> <span class="n">form_for</span> <span class="nv">@changeset</span><span class="p">,</span> <span class="no">Routes</span><span class="o">.</span><span class="n">page_path</span><span class="p">(</span><span class="nv">@conn</span><span class="p">,</span> <span class="ss">:contact</span><span class="p">),</span> <span class="p">[</span><span class="ss">method:</span> <span class="s2">"post"</span><span class="p">],</span> <span class="k">fn</span> <span class="n">f</span> <span class="o">-&gt;</span> <span class="p">%</span><span class="o">&gt;</span>
  <span class="o">&lt;%=</span> <span class="k">if</span> <span class="nv">@changeset</span><span class="o">.</span><span class="n">action</span> <span class="k">do</span> <span class="p">%</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"alert alert-danger"</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="n">p</span><span class="o">&gt;</span><span class="no">Oops</span><span class="p">,</span> <span class="n">you</span> <span class="n">might</span> <span class="n">have</span> <span class="n">missed</span> <span class="n">a</span> <span class="n">field!</span> <span class="no">Please</span> <span class="n">check</span> <span class="n">the</span> <span class="n">errors</span> <span class="n">below</span><span class="o">.&lt;/</span><span class="n">p</span><span class="o">&gt;</span>
  <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="p">%</span> <span class="k">end</span> <span class="p">%</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"field"</span><span class="o">&gt;</span>
      <span class="o">&lt;%=</span> <span class="n">label</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:name</span> <span class="p">%</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"control"</span><span class="o">&gt;</span>
          <span class="o">&lt;%=</span> <span class="n">text_input</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:name</span><span class="p">,</span> <span class="p">[</span><span class="ss">class:</span> <span class="s2">"input is-large"</span><span class="p">,</span> <span class="ss">placeholder:</span> <span class="s2">"Your name"</span><span class="p">]</span> <span class="p">%</span><span class="o">&gt;</span>
          <span class="o">&lt;%=</span> <span class="n">error_tag</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:name</span> <span class="p">%</span><span class="o">&gt;</span>
      <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"field"</span><span class="o">&gt;</span>
      <span class="o">&lt;%=</span> <span class="n">label</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:email</span><span class="p">,</span> <span class="ss">class:</span> <span class="s2">"label is-large"</span> <span class="p">%</span><span class="o">&gt;</span>
      <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"control"</span><span class="o">&gt;</span>
          <span class="o">&lt;%=</span> <span class="n">text_input</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:email</span><span class="p">,</span> <span class="p">[</span><span class="ss">class:</span> <span class="s2">"input is-large"</span><span class="p">,</span> <span class="ss">type:</span> <span class="s2">"email"</span><span class="p">,</span> <span class="ss">placeholder:</span> <span class="s2">"Your email"</span><span class="p">]</span> <span class="p">%</span><span class="o">&gt;</span>
          <span class="o">&lt;%=</span> <span class="n">error_tag</span> <span class="n">f</span><span class="p">,</span> <span class="ss">:email</span> <span class="p">%</span><span class="o">&gt;</span>
      <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="n">div</span> <span class="n">class</span><span class="o">=</span><span class="s2">"control"</span><span class="o">&gt;</span>
      <span class="o">&lt;%=</span> <span class="n">submit</span> <span class="s2">"Send"</span><span class="p">,</span>  <span class="ss">class:</span> <span class="s2">"button is-primary is-large"</span> <span class="p">%</span><span class="o">&gt;</span>
  <span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
  <span class="o">&lt;</span><span class="p">%</span> <span class="k">end</span> <span class="p">%</span><span class="o">&gt;</span>     
<span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>          
</code></pre></div></div>

<h1 id="hooking-up-the-controller">Hooking up the controller</h1>

<p>Open <code class="language-plaintext highlighter-rouge">lib\contact_web\controllers\page_controller.ex</code> and replace with the following:</p>

<div class="language-elixir highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">ContactWeb</span><span class="o">.</span><span class="no">PageController</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">ContactWeb</span><span class="p">,</span> <span class="ss">:controller</span>
  <span class="n">alias</span> <span class="no">Contact</span><span class="o">.</span><span class="no">Message</span>

  <span class="k">def</span> <span class="n">index</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">_params</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">changeset</span> <span class="o">=</span> <span class="no">Message</span><span class="o">.</span><span class="n">changeset</span><span class="p">(%</span><span class="no">Message</span><span class="p">{},</span> <span class="p">%{})</span>
    <span class="n">render</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s2">"index.html"</span><span class="p">,</span> <span class="ss">changeset:</span> <span class="n">changeset</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">contact</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="p">%{</span><span class="s2">"message"</span> <span class="o">=&gt;</span> <span class="n">message_params</span><span class="p">})</span> <span class="k">do</span>
    <span class="n">changeset</span> <span class="o">=</span>
      <span class="p">%</span><span class="no">Message</span><span class="p">{}</span>
      <span class="o">|&gt;</span> <span class="no">Message</span><span class="o">.</span><span class="n">changeset</span><span class="p">(</span><span class="n">message_params</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">changeset</span><span class="o">.</span><span class="n">valid?</span> <span class="k">do</span>
      <span class="c1"># Do something with message_params</span>

      <span class="n">conn</span>
      <span class="o">|&gt;</span> <span class="n">put_flash</span><span class="p">(</span><span class="ss">:info</span><span class="p">,</span> <span class="s2">"Message sent!"</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="n">redirect</span><span class="p">(</span><span class="ss">to:</span> <span class="no">Routes</span><span class="o">.</span><span class="n">page_path</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="ss">:index</span><span class="p">))</span>
    <span class="k">else</span>
      <span class="n">changeset</span> <span class="o">=</span> <span class="p">%{</span><span class="n">changeset</span> <span class="o">|</span> <span class="ss">action:</span> <span class="ss">:index</span><span class="p">}</span>
      <span class="n">render</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="s2">"index.html"</span><span class="p">,</span> <span class="ss">changeset:</span> <span class="n">changeset</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>]]></content><author><name>Michael Minton</name></author><category term="phoenix" /><summary type="html"><![CDATA[I kind of wanted to title this post, “how to create a form that doesn’t use a model” but Ecto decided to drop “Model” in favor of “Schema”; same thing, different mindset.]]></summary></entry><entry><title type="html">modern rails with webpacker and stimulus</title><link href="https://michael.minton.io/2018/06/modern-rails-with-webpacker-and-stimulus.html" rel="alternate" type="text/html" title="modern rails with webpacker and stimulus" /><published>2018-06-10T14:55:54-04:00</published><updated>2018-06-10T14:55:54-04:00</updated><id>https://michael.minton.io/2018/06/modern-rails-with-webpacker-and-stimulus</id><content type="html" xml:base="https://michael.minton.io/2018/06/modern-rails-with-webpacker-and-stimulus.html"><![CDATA[<p>I recently had the opportunity to start fresh with a new Rails app. Instead of building another traditional Rails app I took this chance to investigate using some modern tools like Webpacker and a modern CSS framework Bulma. In this post I’ll explain how I got everything wired together.</p>

<p>Here’s an outline of what we’ll cover in this post:</p>

<ul>
  <li>creating a new Rails 5.2 app using <a href="https://github.com/rails/webpacker/">Webpacker</a> and <a href="https://stimulusjs.org/">Stimulus</a></li>
  <li>installing <a href="https://bulma.io/">Bulma</a>, my preference over Bootstrap</li>
  <li>installing <a href="https://fontawesome.com/">Font Awesome 5</a>, for icons</li>
  <li>creating a basic site layout with navigation</li>
  <li>wiring up the burger menu with stimulus</li>
</ul>

<h1 id="create-the-rails-app">Create the Rails app</h1>

<p><strong>Yarn</strong></p>

<p><a href="https://yarnpkg.com/">Yarn</a> claims to be “Fast, reliable, and secure dependency management” and it really is.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>yarn
</code></pre></div></div>

<p><strong>Webpacker</strong></p>

<p>This is Rail’s gateway to the land of JavaScript apps and npm packages. Webpacker can live side-by-side with the asset pipeline, although once you fully embrace it, you’ll find little need for the asset pipeline. You can use webpacker to manage all your assets.</p>

<p><strong>Stimulus</strong></p>

<p>A JavaScript framework from <a href="https://basecamp.com/">Basecamp</a> that integrates nicely with <a href="https://github.com/turbolinks/turbolinks/">Turbolinks</a>. We’ll use this to “sprinkle” in some behavior to our views.</p>

<p><strong>Rails new</strong></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails new myapp <span class="nt">--webpack</span><span class="o">=</span>stimulus
<span class="nb">cd </span>myapp
</code></pre></div></div>

<p><strong>An initial controller</strong></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bin/rails generate controller Home index about
</code></pre></div></div>

<p><strong>A default route</strong></p>

<p>Change your <code class="language-plaintext highlighter-rouge">config/routes.rb</code> file to look like this:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Rails</span><span class="p">.</span><span class="nf">application</span><span class="p">.</span><span class="nf">routes</span><span class="p">.</span><span class="nf">draw</span> <span class="k">do</span>
  <span class="n">get</span> <span class="s1">'home/index'</span>
  <span class="n">get</span> <span class="s1">'home/about'</span>
  <span class="n">root</span> <span class="ss">to: </span><span class="s1">'home#index'</span>
<span class="k">end</span>
</code></pre></div></div>

<p><strong>Switching from the Asset Pipeline</strong></p>

<p>Open <code class="language-plaintext highlighter-rouge">app/views/layouts/application.html.erb</code> and replace <code class="language-plaintext highlighter-rouge">stylesheet_link_tag</code> with <code class="language-plaintext highlighter-rouge">stylesheet_pack_tag</code>. Next replace <code class="language-plaintext highlighter-rouge">javascript_include_tag</code> with <code class="language-plaintext highlighter-rouge">javascript_pack_tag</code>.</p>

<h1 id="bulma">Bulma</h1>

<p><a href="https://bulma.io/">Bulma</a> is a relatively new CSS framework. It feels like a light, streamlined alternative to Bootstrap. Bulma doesn’t include any JavaScript at all. This means some stuff just won’t work out of the box. For example, the burger menu won’t toggle without a little JavaScript help. We’ll get to that later.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn add bulma
</code></pre></div></div>

<p>Open <code class="language-plaintext highlighter-rouge">app/javascript/packs/application.js</code> and add the following to the top:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="dl">'</span><span class="s1">../styles</span><span class="dl">'</span>
</code></pre></div></div>

<p>Create <code class="language-plaintext highlighter-rouge">app/javascript/styles.scss</code>:</p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="s1">'~bulma/bulma'</span><span class="p">;</span>
</code></pre></div></div>

<h1 id="font-awesome-5">Font Awesome 5</h1>

<p>To use icons in Bulma you need to include <a href="https://fontawesome.com/">Font Awesome</a>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn add @fortawesome/fontawesome
yarn add @fortawesome/fontawesome-free-regular
yarn add @fortawesome/fontawesome-free-brands
</code></pre></div></div>

<h1 id="the-view">The View</h1>

<p><strong>The navbar</strong></p>

<p>Open <code class="language-plaintext highlighter-rouge">app/views/layouts/application.html.erb</code> and add the following just above the <code class="language-plaintext highlighter-rouge">yield</code> line:</p>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;%=</span> <span class="n">render</span> <span class="s1">'layouts/navbar'</span> <span class="cp">%&gt;</span>
</code></pre></div></div>

<p>Create <code class="language-plaintext highlighter-rouge">app/views/layouts/_navbar.html.erb</code>:</p>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;nav</span> <span class="na">class=</span><span class="s">"navbar"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"navbar-brand"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;a</span> <span class="na">class=</span><span class="s">"navbar-item"</span> <span class="na">href=</span><span class="s">"#"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"https://bulma.io/images/bulma-logo.png"</span> <span class="na">width=</span><span class="s">"112"</span> <span class="na">height=</span><span class="s">"28"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;/a&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"navbar-burger burger"</span> <span class="na">data-target=</span><span class="s">"main-nav"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
        <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
        <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"main-nav"</span> <span class="na">class=</span><span class="s">"navbar-menu"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"navbar-start"</span><span class="nt">&gt;</span>
        <span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="n">root_url</span><span class="p">,</span> <span class="ss">class: </span><span class="s1">'navbar-item'</span> <span class="k">do</span> <span class="cp">%&gt;</span>
          <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"icon"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;i</span> <span class="na">class=</span><span class="s">"far fa-gem"</span><span class="nt">&gt;&lt;/i&gt;</span>
          <span class="nt">&lt;/span&gt;</span>
          <span class="nt">&lt;span&gt;</span>Home<span class="nt">&lt;/span&gt;</span>
        <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span>
        <span class="cp">&lt;%=</span> <span class="n">link_to</span> <span class="n">home_about_url</span><span class="p">,</span> <span class="ss">class: </span><span class="s1">'navbar-item'</span> <span class="k">do</span> <span class="cp">%&gt;</span>
          <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"icon"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;i</span> <span class="na">class=</span><span class="s">"far fa-star"</span><span class="nt">&gt;&lt;/i&gt;</span>
          <span class="nt">&lt;/span&gt;</span>
          <span class="nt">&lt;span&gt;</span>About<span class="nt">&lt;/span&gt;</span>
        <span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;/nav&gt;</span>  
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>This is basically copied from the Bulma examples. It is a basic nav bar with two menu items; Home and About.</p>

<p>We now have all the pieces in place and can start wiring up our Stimulus controllers.</p>

<h1 id="create-a-stimulus-controller">Create a Stimulus controller</h1>

<p>To keep this example simple, we’re going to create a single controller which we’ll attach to the <code class="language-plaintext highlighter-rouge">body</code> tag in the main layout. This controller will be responsible for rendering the Font Awesome icons (as described in a <a href="/2018/01/using-font-awesome-5-with-rails-5-turbolinks.html">previous post</a>) as well as handling our Bulma burger menu.</p>

<p>Create <code class="language-plaintext highlighter-rouge">app/javascript/Controllers/main_controller.js</code>:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">fontawesome</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@fortawesome/fontawesome</span><span class="dl">'</span>
<span class="k">import</span> <span class="nx">icons</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@fortawesome/fontawesome-free-regular</span><span class="dl">'</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">Controller</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">stimulus</span><span class="dl">'</span>
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="kd">extends</span> <span class="nx">Controller</span> <span class="p">{</span>
  <span class="nx">initialize</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fontawesome</span><span class="p">.</span><span class="nx">library</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">icons</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="nx">connect</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fontawesome</span><span class="p">.</span><span class="nx">dom</span><span class="p">.</span><span class="nx">i2svg</span><span class="p">()</span>

    <span class="c1">// Get all "navbar-burger" elements</span>
    <span class="kd">var</span> <span class="nx">$navbarBurgers</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">.navbar-burger</span><span class="dl">'</span><span class="p">),</span> <span class="mi">0</span><span class="p">);</span>

    <span class="c1">// Check if there are any navbar burgers</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">$navbarBurgers</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>

      <span class="c1">// Add a click event on each of them</span>
      <span class="nx">$navbarBurgers</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">$el</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">$el</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>

          <span class="c1">// Get the target from the "data-target" attribute</span>
          <span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">$el</span><span class="p">.</span><span class="nx">dataset</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span>
          <span class="kd">var</span> <span class="nx">$target</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">target</span><span class="p">);</span>

          <span class="c1">// Toggle the class on both the "navbar-burger" and the "navbar-menu"</span>
          <span class="nx">$el</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">toggle</span><span class="p">(</span><span class="dl">'</span><span class="s1">is-active</span><span class="dl">'</span><span class="p">);</span>
          <span class="nx">$target</span><span class="p">.</span><span class="nx">classList</span><span class="p">.</span><span class="nx">toggle</span><span class="p">(</span><span class="dl">'</span><span class="s1">is-active</span><span class="dl">'</span><span class="p">);</span>

        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This controller imports the icons from Font Awesome when <code class="language-plaintext highlighter-rouge">initialize</code> is called. Everytime connect is called it renders the icons and then searches for navbar burgers to attach the appropriate click events on.</p>

<h1 id="connect-the-controller">Connect the controller</h1>

<p>Now we want to connect the body tag to our controller using an HTML5 data attribute.</p>

<p>Open <code class="language-plaintext highlighter-rouge">app/views/layouts/application.html.erb</code> and add the following attribute to the <code class="language-plaintext highlighter-rouge">&lt;body&gt;</code> tag.</p>

<div class="language-erb highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;body</span> <span class="na">data-controller=</span><span class="s">"main"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<h1 id="testing">Testing</h1>

<p>Run your rails app and you should see the simple site with a navbar across the top:</p>

<p><img src="https://michael.minton.io/assets/Screen Shot 2018-06-10 at 4.33.28 PM.png" alt="" /></p>

<p>Now try shrinking the window until the menus are hidden and replaced with the burger menu. Notice when you click it, the menus reappear:</p>

<p><img src="https://michael.minton.io/assets/Screen Shot 2018-06-10 at 4.33.46 PM.png" alt="" /></p>

<h3 id="you-now-have-a-rails-5-app-with-turbolinks-stimulus-and-font-awesome-5-">You now have a Rails 5 app with Turbolinks, Stimulus, and Font Awesome 5. 🥑🍞</h3>]]></content><author><name>Michael Minton</name></author><category term="rails" /><category term="stimulus" /><category term="webpacker" /><category term="bulma" /><summary type="html"><![CDATA[I recently had the opportunity to start fresh with a new Rails app. Instead of building another traditional Rails app I took this chance to investigate using some modern tools like Webpacker and a modern CSS framework Bulma. In this post I’ll explain how I got everything wired together.]]></summary></entry><entry><title type="html">font awesome 5 with turbolinks and stimulus</title><link href="https://michael.minton.io/2018/06/font-awesome-5-with-turbolinks-and-stimulus.html" rel="alternate" type="text/html" title="font awesome 5 with turbolinks and stimulus" /><published>2018-06-07T21:55:54-04:00</published><updated>2018-06-07T21:55:54-04:00</updated><id>https://michael.minton.io/2018/06/font-awesome-5-with-turbolinks-and-stimulus</id><content type="html" xml:base="https://michael.minton.io/2018/06/font-awesome-5-with-turbolinks-and-stimulus.html"><![CDATA[<p>In a <a href="/2018/01/using-font-awesome-5-with-rails-5-turbolinks.html">previous post</a> I wrote about how to use <a href="https://fontawesome.com">Font Awesome 5</a>’s with <a href="https://github.com/turbolinks/turbolinks">Turbolinks</a>. Some of you have asked how you might do something similar but using <a href="https://stimulusjs.org">Stimulus</a> instead of coffeescript. Recently I started a new Rails app using webpacker and stimulus. Here are the steps I used to get this setup working with Font Awesome 5.</p>

<h1 id="the-rails-app">The Rails app</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rails new myapp --webpack=stimulus
</code></pre></div></div>

<h1 id="setting-up-font-awesome-5">Setting up Font Awesome 5</h1>

<p>One of the great things about using FA5 via JS is the ability to only import the icons you’ll actually be using. In this case I only needed the twitter icon.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yarn add @fortawesome/fontawesome
yarn add @fortawesome/fontawesome-free-brands
</code></pre></div></div>

<h1 id="create-a-stimulus-controller">Create a Stimulus controller</h1>

<p>We’re going to create a controller which we’ll attach the <code class="language-plaintext highlighter-rouge">body</code> tag in the main layout. This controller will be responsible for importing the needed icons and for telling Font Awesome when they need to be rendered.</p>

<p><em>Create <code class="language-plaintext highlighter-rouge">app/Javascript/Controllers/fa_controller.js</code></em></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">fontawesome</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@fortawesome/fontawesome</span><span class="dl">'</span>
<span class="k">import</span> <span class="nx">faTwitter</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@fortawesome/fontawesome-free-brands/faTwitter</span><span class="dl">'</span>

<span class="k">import</span> <span class="p">{</span> <span class="nx">Controller</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">stimulus</span><span class="dl">'</span>
<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="kd">extends</span> <span class="nx">Controller</span> <span class="p">{</span>
  <span class="nx">initialize</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fontawesome</span><span class="p">.</span><span class="nx">library</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">faTwitter</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="nx">connect</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">fontawesome</span><span class="p">.</span><span class="nx">dom</span><span class="p">.</span><span class="nx">i2svg</span><span class="p">()</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h1 id="connect-the-controller">Connect the controller</h1>

<p>Now we want to connect the body tag to our controller using an HTML5 data attribute (i.e., <code class="language-plaintext highlighter-rouge">&lt;body data-controller='fa'&gt;</code>) like so:</p>

<p><em><code class="language-plaintext highlighter-rouge">app/views/layouts/application.html.haml</code></em></p>
<div class="language-haml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">%body</span><span class="p">{</span> <span class="ss">data: </span><span class="p">{</span><span class="ss">controller: </span><span class="s1">'fa'</span> <span class="p">}}</span>
</code></pre></div></div>

<p><em>I’m a big fan of <a href="http://haml.info">Haml</a> so this is my layout but yours may be <code class="language-plaintext highlighter-rouge">application.html.erb</code>.</em></p>

<h1 id="done">Done</h1>

<p>You now have a Rails 5 app with Turbolinks, Stimulus, and Font Awesome 5. 🥑🍞</p>]]></content><author><name>Michael Minton</name></author><category term="rails" /><category term="turbolinks" /><category term="stimulus" /><category term="font awesome 5" /><summary type="html"><![CDATA[In a previous post I wrote about how to use Font Awesome 5’s with Turbolinks. Some of you have asked how you might do something similar but using Stimulus instead of coffeescript. Recently I started a new Rails app using webpacker and stimulus. Here are the steps I used to get this setup working with Font Awesome 5.]]></summary></entry><entry><title type="html">using font awesome 5 with turbolinks</title><link href="https://michael.minton.io/2018/01/using-font-awesome-5-with-rails-5-turbolinks.html" rel="alternate" type="text/html" title="using font awesome 5 with turbolinks" /><published>2018-01-27T20:03:54-05:00</published><updated>2018-01-27T20:03:54-05:00</updated><id>https://michael.minton.io/2018/01/using-font-awesome-5-with-rails-5-turbolinks</id><content type="html" xml:base="https://michael.minton.io/2018/01/using-font-awesome-5-with-rails-5-turbolinks.html"><![CDATA[<p><a href="https://fontawesome.com">Font Awesome 5</a>’s SVG with JS is slick and modern. It uses javascript to find all the <code class="language-plaintext highlighter-rouge">&lt;i&gt;</code> tags with icons (e.g., <code class="language-plaintext highlighter-rouge">fas fa-camera</code>) and replaces them with an <code class="language-plaintext highlighter-rouge">&lt;svg&gt;</code> tag. The best part is the SVG icons will respect all your CSS styles like <code class="language-plaintext highlighter-rouge">size</code> and <code class="language-plaintext highlighter-rouge">color</code>. Truly <em>awesome</em> stuff. However, there is a problem. Out of the box this won’t play nice with Rails 5 and <a href="https://github.com/turbolinks/turbolinks">Turbolinks</a>. What will happen is the initial page load will correctly show the icons but after clicking a link Turbolinks will reload the page but not your icons. In this article I’ll walk you through a few steps to fix this.</p>

<h1 id="setting-up-font-awesome-5">Setting up Font Awesome 5</h1>

<p><em>These instructions are current as of v5.0.6. Check <a href="https://fontawesome.com">https://fontawesome.com/get-started</a> for the latest instructions.</em></p>

<p>In your <code class="language-plaintext highlighter-rouge">application.html.erb</code> inside the <code class="language-plaintext highlighter-rouge">&lt;head&gt;</code> tag include a link to Font Awesome from their free CDN.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;head&gt;</span>
    ...
    <span class="nt">&lt;</span><span class="err">%=</span> <span class="na">javascript_include_tag</span> <span class="err">'</span><span class="na">application</span><span class="err">',</span> <span class="err">'</span><span class="na">data-turbolinks-track</span><span class="err">'</span><span class="na">:</span> <span class="err">'</span><span class="na">reload</span><span class="err">'</span> <span class="err">%</span><span class="nt">&gt;</span>
    <span class="nt">&lt;script </span><span class="na">defer</span> <span class="na">src=</span><span class="s">"https://use.fontawesome.com/releases/v5.0.6/js/all.js"</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;/head&gt;</span>
</code></pre></div></div>

<h1 id="create-an-init-script">Create an init script</h1>

<p>We’re going to create a small script to call into Font Awesome’s API and force it to re-render the icons everytime the <code class="language-plaintext highlighter-rouge">turbolinks:load</code> event fires.</p>

<p>Create a new file called <code class="language-plaintext highlighter-rouge">fontawesome-init.coffee</code> in <code class="language-plaintext highlighter-rouge">app/assets/javascripts/</code> with the following:</p>

<div class="language-coffeescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="na">on</span> <span class="s">"turbolinks:load"</span><span class="p">,</span> <span class="o">-&gt;</span>
  <span class="nx">FontAwesome</span><span class="p">.</span><span class="na">dom</span><span class="p">.</span><span class="na">i2svg</span><span class="p">()</span>
</code></pre></div></div>

<p><strong>Important!</strong></p>

<p>If your <code class="language-plaintext highlighter-rouge">application.js</code> doesn’t have <code class="language-plaintext highlighter-rouge">//= require_tree .</code> then you’ll need to add <code class="language-plaintext highlighter-rouge">//= require fontawesome-init</code>.</p>

<h1 id="prevent-layout-shifting">Prevent layout shifting</h1>

<p>While optional, this next step will prevent your layout from constantly resizing as the intial view is loaded and the icons are being rendered. Font Awesome 5 adds the <code class="language-plaintext highlighter-rouge">fontawesome-i2svg-pending</code> class to the <code class="language-plaintext highlighter-rouge">&lt;html&gt;</code> tag while it’s rendering icons. Using a variant of the instructions <a href="https://fontawesome.com/how-to-use/performance-and-security#async-loading-indicators">here</a>, we can take advantage of this and hide the <code class="language-plaintext highlighter-rouge">&lt;body&gt;</code> tag until the icons are rendered and that class is removed.</p>

<p>Add the following to your <code class="language-plaintext highlighter-rouge">application.scss</code>:</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.fontawesome-i2svg-pending</span> <span class="nt">body</span> <span class="p">{</span>
	<span class="nl">display</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You now have Rails 5 with Turbolinks working with Font Awesome 5’s SVG with JS approach. 🍰</p>]]></content><author><name>Michael Minton</name></author><category term="rails" /><category term="turbolinks" /><category term="font awesome 5" /><summary type="html"><![CDATA[Font Awesome 5’s SVG with JS is slick and modern. It uses javascript to find all the &lt;i&gt; tags with icons (e.g., fas fa-camera) and replaces them with an &lt;svg&gt; tag. The best part is the SVG icons will respect all your CSS styles like size and color. Truly awesome stuff. However, there is a problem. Out of the box this won’t play nice with Rails 5 and Turbolinks. What will happen is the initial page load will correctly show the icons but after clicking a link Turbolinks will reload the page but not your icons. In this article I’ll walk you through a few steps to fix this.]]></summary></entry><entry><title type="html">how to tmux</title><link href="https://michael.minton.io/2017/12/how-to-tmux.html" rel="alternate" type="text/html" title="how to tmux" /><published>2017-12-04T16:03:54-05:00</published><updated>2017-12-04T16:03:54-05:00</updated><id>https://michael.minton.io/2017/12/how-to-tmux</id><content type="html" xml:base="https://michael.minton.io/2017/12/how-to-tmux.html"><![CDATA[<p><a href="http://https://github.com/tmux/tmux">tmux</a> is a terminal multiplexer which is a fancy way to say it allows multiple
“windows” in a single terminal. It’s essential to my workflow. This post will
only touch on the basics to get you up and running.</p>

<h1 id="install">Install</h1>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ brew install tmux
</code></pre></div></div>

<p><em>Using Windows?</em> See <a href="https://leanpub.com/the-tao-of-tmux/read#appendix-windows-bash">here</a>.</p>

<h1 id="the-basics">The Basics</h1>

<p><strong>Start it up</strong></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ tmux
</code></pre></div></div>

<p><strong>The leader</strong></p>

<p>To use any of the commands you have to type the leader prefix followed by your
specific command. The default is <kbd>CTRL + B</kbd>. To save space I’ll show
the prefix as <kbd>PX</kbd>.</p>

<p><strong>Creating windows</strong></p>

<p><kbd>PX</kbd> + <kbd>c</kbd></p>

<p>tmux starts with a window created by default but we can open multiple within
the same session. The windows are numbers starting at zero.</p>

<p><strong>Switching windows</strong></p>

<p><kbd>PX</kbd> + <kbd>0</kbd></p>

<p>The above would switch to window zero. At the bottom in the status bar you’ll
see each window listed. The active window is indicated with an asterisk.</p>

<p><strong>Creating panes</strong></p>

<p><kbd>PX</kbd> + <kbd>%</kbd> Vertical split<br />
<kbd>PX</kbd> + <kbd>""</kbd> Horizontal split</p>

<p>Windows a kind of useless to me. I much prefer to just split a single window
into multiple panes and keep everything in sight.</p>

<p><strong>Switching panes</strong></p>

<p><kbd>PX</kbd> + <kbd>;</kbd></p>

<p>This will cycle from one pane to the next within the same window. Instead of <code class="language-plaintext highlighter-rouge">;</code>
 you can also use the arrow keys.</p>

<p><strong>Resizing panes</strong></p>

<p>Resizing is so awkward I usually go into command mode for this.</p>

<p><kbd>PX</kbd> + <kbd>:</kbd></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>: resize-windows -L
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">L</code> indicates the direction: left. You can also specify <code class="language-plaintext highlighter-rouge">U</code>, <code class="language-plaintext highlighter-rouge">D</code>, and <code class="language-plaintext highlighter-rouge">R</code> for
the other four directions. Repeat this command as needed.</p>

<p><strong>Detach</strong></p>

<p><kbd>PX</kbd> + <kbd>d</kbd></p>

<p>This will detach the session, close tmux, <em>but leave your session running in
the background</em>.</p>

<h1 id="customize">Customize</h1>

<p><strong>vim copy and paste</strong></p>

<p>You can get lost for weeks configuring this stuff but here is a basic setup
that’ll let you copy and paste like you do in <a href="http://www.vim.org/">vim</a>. The config is
here: <code class="language-plaintext highlighter-rouge">~/.tmux.conf</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set-window-option -g mode-keys vi
bind-key -t vi-copy 'v' begin-selection
bind-key -t vi-copy 'y' copy-selection
</code></pre></div></div>

<p><strong>Disable the mouse</strong></p>

<p>The prevent accidental scrolling and trashing your tmux session I recommend you
immediately disable the mouse.</p>

<p><kbd>PX</kbd> + <kbd>:</kbd></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>: setw -g mode-mouse off
</code></pre></div></div>

<h1 id="advanced">Advanced</h1>

<p>I haven’t really even scratch the surface. After you’ve been using tmux
for a while you’ll want to customze your status bar and start messing with
powerlines glyphs. To learn how to do that and get a cooler setup I recommend
you read <a href="https://pragprog.com/book/bhtmux2/tmux-2"><strong>tmux 2</strong> <em>Productive Mouse-Free Development</em></a>.</p>]]></content><author><name>Michael Minton</name></author><category term="tmux" /><category term="macOS" /><summary type="html"><![CDATA[tmux is a terminal multiplexer which is a fancy way to say it allows multiple “windows” in a single terminal. It’s essential to my workflow. This post will only touch on the basics to get you up and running.]]></summary></entry></feed>