Gaiet's Blog https://gaiety.me/blog Various writings on code, design, art and life. en Modding Minecraft 2025 https://gaiety.me/blog/modding-minecraft/ <p class="mb-4 text-text leading-7">Making Minecraft beautiful yet optimized can be a challenge. Shaders, resource packs, launchers, mods, plugins; it can be daunting! I’ve delved into what makes Minecraft run well while looking gorgeous and am happy to share my results.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: I play games at a minimum of 60fps due to motion sickness. Thus that will be what I target as success. Hardware you’re running will lead to varied results, so where applicable I will provide alternatives.</em></p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Note 2: Everything mentioned here should work on most operating systems, I however am running Linux (specifically; PopOS!).</em></p> <h2 class="text-3xl mt-6 text-text" id="launchers" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#launchers">Launchers</a></h2> <p class="mb-4 text-text leading-7">The way Minecraft launches will determine how easy it can be to mod. There are numerous options available. This blog post will cover <a href="https://prismlauncher.org/" class="link">Prism Launcher</a> . Alternatively you want an easier solution with many quality of life mods I recommend checking out <a href="https://www.lunarclient.com/" class="link">Lunar Client</a> instead.</p> <p class="mb-4 text-text leading-7"><a href="https://prismlauncher.org/" class="link"><img src="https://gaiety.me/img/content/prism-launcher.webp" alt="Prism Launcher screenshot showing various versions of Minecraft installed at the same time" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></a> Using Prism launcher allows you to sign in with your Minecraft (likely, Microsoft) account through a secure SSO. Once installed and signed in the next step is to “Add Instance”. I then recommend choosing “Modrinth” followed by opening “Filter Options” to filter by the game version you wish to play on (if playing online, check what version the server is using and be sure it matches). Some great options are <a href="https://modrinth.com/modpack/fabulously-optimized" class="link">Fabulously Optimized</a> or the my favorite <a href="https://modrinth.com/modpack/distant-horizons-iris-shaders" class="link">Distant Horizons &amp; Iris Shaders</a>.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/prism-instance.png" alt="Prism Launcher New Instance screenshot showing Modrinth selected filtered by game version and searched for &quot;Iris&quot;" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <hr> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Next sections will discuss additional ways to modify your game. While I will primarily link to the site <a href="https://modrinth.com/" class="link">Modrinth</a> there is also a great alternative called <a href="https://www.curseforge.com/minecraft" class="link">CurseForge</a>. <em class="italic text-green">Both are supported by Prism Launcher.</em></p> </blockquote> <h2 class="text-3xl mt-6 text-text" id="%E2%80%9Cengine%E2%80%9D%2C-or-the-jvm" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#%E2%80%9Cengine%E2%80%9D%2C-or-the-jvm">“Engine”, or the JVM</a></h2> <p class="mb-4 text-text leading-7">An advanced topic is what Minecraft runs inside of - as this is a Java application that means it runs inside of a Java Virtual Machine (JVM). By default most launchers, including Prism, will install OpenJDK which is fine for most machines.</p> <p class="mb-4 text-text leading-7">However, there are alternatives! If you want a crazy fast high framerate option check out <a href="https://modrinth.com/mod/vulkanmod" class="link">VulkanMod</a> (see below for installing Mods). However, Vulkan does not support shaders or a number of mods (including Distant Horizons).</p> <p class="mb-4 text-text leading-7">Other alternatives exist, and Prism Launcher can automatically install <a href="https://adoptium.net/temurin/releases/?os=any" class="link">Adoptium (Temurin)</a>. It’s easy to switch; in Prism Launcher choose Settings -&gt; Java -&gt; Management to install it, then under General change which you are using with “Auto-detect…”</p> <h3 class="text-2xl mt-4 text-text" id="jvm-settings-%26-arguments" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#jvm-settings-%26-arguments">JVM Settings &amp; Arguments</a></h3> <p class="mb-4 text-text leading-7"><em class="italic text-green">Likely not applicable if running VulkanMod.</em></p> <p class="mb-4 text-text leading-7">Most importantly is under Settings -&gt; Java -&gt; General -&gt; Memory to set your Minimum and Maximum memory allocation to the <em class="italic text-green">same number</em>. The number depends on how much ram your computer is willing to spare. However, more is not always better due to the JVM’s garbage collection.</p> <p class="mb-4 text-text leading-7">Personally, despite having 30GB of ram I set my game to 4GB (<code>4096MiB</code>).</p> <p class="mb-4 text-text leading-7">Some guides online <a href="https://github.com/de-soot/mc-fps-jvm-args" class="link">suggest other JVM args</a> but I have not noticed much difference. But feel free to experiment!</p> <h2 class="text-3xl mt-6 text-text" id="resource-packs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#resource-packs">Resource Packs</a></h2> <p class="mb-4 text-text leading-7">Textures, models and animation are generally found in what Minecraft calls Resource Packs. Right click the instance you created in Prism Launcher, then select “Resource packs” and “Download packs” to browse and add them to your game. These rarely have a significant impact on game performance, so find and enjoy whatever you wish! Below are my favorites:</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/catppuccin-ui" class="link">Catppuccin UI</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/better-lanterns" class="link">Better Lanterns</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/enchant-icons-countxd" class="link">Enchant Icons</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/even-better-enchants" class="link">Even Better Enchants</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/faithful-64xA" class="link">Faithful</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/rays-3d-ladders" class="link">Ray’s 3D Ladders</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/rays-3d-rails" class="link">Ray’s 3D Rails</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/redstone-tweaks" class="link">Redstone Tweaks</a></li> <li class="text-subtext0"><a href="https://modrinth.com/resourcepack/xalis-potions" class="link">xali’s Potions</a></li> </ul> <hr> <p class="mb-4 text-text leading-7">Any resource packs you install can be selected and adjusted ingame via Options -&gt; Resource Packs. Keep in mind vertical load order matters! I suggest putting your broad texture packs on the bottom while having more specific items like enchanting books and UI changes higher up.</p> <h2 class="text-3xl mt-6 text-text" id="shaders" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#shaders">Shaders</a></h2> <p class="mb-4 text-text leading-7">A high impact on performance but equally high impact on visual fidelity are shaders. These tools rely on strong video cards, CPU’s, and having enough RAM.</p> <p class="mb-4 text-text leading-7">There are many <a href="https://modrinth.com/shaders" class="link">popular shaders</a> that can be installed just like a Resource Pack by editing the instance and selecting Shader packs -&gt; Download shaders.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/projbesy-photon-shader.png" alt="Beautiful snowy landscape photo by Pojbesy of the Photon shader" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">My personal favorite, shown above, is <a href="https://modrinth.com/shader/photon-shader" class="link">Photon Shaders</a>. It has the best compromise I have found of colored lighting, beautiful skies, labPBR support (fancy resource packs) without dropping my computer below 60fps like others do. It also supports <a href="https://modrinth.com/mod/distanthorizons" class="link">Distant Horizons</a> (see mods below).</p> <hr> <p class="mb-4 text-text leading-7">Any shader you install can be selected and adjusted ingame via Options -&gt; Video Settings -&gt; Shaders</p> <h2 class="text-3xl mt-6 text-text" id="mods" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#mods">Mods</a></h2> <p class="mb-4 text-text leading-7">Core changes to how your game runs fundamentally are done via mods. These go beyond visual changes and can do things like optimize your game or add in new features. While browsing mods, be sure you understand which mods are clientside or require being installed on the server.</p> <p class="mb-4 text-text leading-7">If you installed an instance through Prism Launcher congratulations you already have some mods! You can see them and download more while editing the instance under the Mods tab.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/minimap.png" alt="Screenshot of Xaero's Minimap with entity icons, coordinates and a visual overview of the surrounding space from above." class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Generally I install most mods that claim to optimize the gameplay experience. Additionally, I really love <a href="https://modrinth.com/mod/xaeros-minimap" class="link">Xaero’s Minimap</a> and <a href="https://modrinth.com/mod/xaeros-world-map" class="link">Xaero’s World Map</a> which not only does what they imply but also allows you to see your coordinates outside of the F3 menu and save waypoints (the B key by default).</p> <h3 class="text-2xl mt-4 text-text" id="distant-horizons-mod" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/modding-minecraft/#distant-horizons-mod">Distant Horizons Mod</a></h3> <p class="mb-4 text-text leading-7">An advanced gameplay mod is <a href="https://modrinth.com/mod/distanthorizons" class="link">Distant Horizons</a> which can be intalled clientside or also on the server. Note, if adding it on the server then all clients need the “Fabric API” mod installed, making it harder for clients to join without modding knowledge.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/distant-horizons.jpg" alt="Screenshot from the homepage of Distant Horizons showing a further render distance" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">What does Distant Horizons do? Simply put, it add simplified terrain past Minecraft’s default view distance to improve performance and allow for longer draw distances. Now you can finally enjoy that lookout tower you built on top of a mountain!</p> </blockquote> <p class="mb-4 text-text leading-7">Important notes; I recommend using the before-mentioned “Distant Horizons &amp; Iris Shaders” modpack instance, not all Shaders are supported (but Photon is), you need to explore the world to let the mod generate distant terrain.</p> <p class="mb-4 text-text leading-7">Lastly, this mod can have a significant performance impact. Thus I recommend the following settings:</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Minecraft Video Settings <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Render Distance: 12 Chunks</li> <li class="text-subtext0">Max Shadow Distance: 12 Chunks</li> </ul> </li> <li class="text-subtext0">Distant Horizon Settings <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Quality Preset: 2. Low</li> <li class="text-subtext0">CPU Load: 1. Minimal Impact</li> </ul> </li> </ul> Wed, 04 Jun 2025 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/modding-minecraft/ Secure your SSH with Wireguard https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/ <p class="mb-4 text-text leading-7">Oh terminal, my beloved! How I do enjoy being able to log into my various devices from wherever I may be and control them from the terminal. To do that we commonly use SSH. Locally it works quite simply, but what about being away from the same silly rounded box that calls itself a router?</p> <p class="mb-4 text-text leading-7">Port forwarding SSH on the router, commonly at <code>:22</code> is the start of an answer. But we must remember, the easier it is for us to access the device the easier it is for malicious actors to as well.</p> <p class="mb-4 text-text leading-7">There are steps to improve security with just portforwarding; disable username/password auth in favor of <a href="https://askubuntu.com/a/346863" class="link">public key authentication only</a>, change the default SSH port to a less guessable number, and implementing a system like <a href="https://github.com/fail2ban/fail2ban" class="link">fail2ban</a> to lockout anyone who fails to login too many times.</p> <p class="mb-4 text-text leading-7">But what if there was something safer yet easy to work with?</p> <h2 class="text-3xl mt-6 text-text" id="enter%3A-wireguard" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/#enter%3A-wireguard">Enter: Wireguard</a></h2> <p class="mb-4 text-text leading-7">Many people have dabbled in VPN’s if only because Nord won’t hush about them during YouTube ads. They’re particularly popular in the workplace to not only secure a connection, but create a bridge between an employee’s device and the workplace’s network.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/wireguard.svg" alt="Wireguard: Fast, Modern, Secure VPN Tunnel (logo)" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7"><a href="https://www.wireguard.com/" class="link">Wireguard</a> is one such VPN. It’s free and luckily for us there’s <a href="https://github.com/wg-easy/wg-easy/tree/production" class="link">wg-easy</a> that can spin up a Docker instance that contains the VPN and a user-friendly user-interface. The <a href="https://github.com/wg-easy/wg-easy/tree/production?tab=readme-ov-file#installation" class="link">installation is straightfroward and well documented</a>.</p> <p class="mb-4 text-text leading-7">Alternatively, below I’ve listed the Docker Compose which is my preference; simply save the code below in a file such as <code>docker-compose.yml</code> and in the same directory run <code>docker compose up</code> (with <code>--detatch</code> to let it run in the background). Note you’ll need to change the <code>PASSWORD_HASH</code> leveraging something like <a href="https://bcrypt-generator.com/" class="link">bcrypt-generator</a>.</p> <pre><code class="language-yaml"><span class="hljs-attr">services:</span> <span class="hljs-attr">wg-easy:</span> <span class="hljs-attr">environment:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">LANG=en</span> <span class="hljs-bullet">-</span> <span class="hljs-string">PORT=51821</span> <span class="hljs-bullet">-</span> <span class="hljs-string">WG_HOST=myserver.local</span> <span class="hljs-bullet">-</span> <span class="hljs-string">PASSWORD_HASH=$$example$$password$$hash</span> <span class="hljs-comment"># Use a bcrypt hasher like https://bcrypt-generator.com/ but any $&#x27;s need to be doubled here</span> <span class="hljs-bullet">-</span> <span class="hljs-string">UI_TRAFFIC_STATS=true</span> <span class="hljs-bullet">-</span> <span class="hljs-string">UI_CHART_TYPE=1</span> <span class="hljs-bullet">-</span> <span class="hljs-string">AllowedIPs=0.0.0.0/0,</span> <span class="hljs-string">::/0</span> <span class="hljs-attr">image:</span> <span class="hljs-string">ghcr.io/wg-easy/wg-easy</span> <span class="hljs-attr">container_name:</span> <span class="hljs-string">wg-easy</span> <span class="hljs-attr">volumes:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">./wireguard:/etc/wireguard</span> <span class="hljs-attr">ports:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;51820:51820/udp&quot;</span> <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;51821:51821/tcp&quot;</span> <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span> <span class="hljs-attr">cap_add:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">NET_ADMIN</span> <span class="hljs-bullet">-</span> <span class="hljs-string">SYS_MODULE</span> <span class="hljs-attr">sysctls:</span> <span class="hljs-bullet">-</span> <span class="hljs-string">net.ipv4.ip_forward=1</span> <span class="hljs-bullet">-</span> <span class="hljs-string">net.ipv4.conf.all.src_valid_mark=1</span> <span class="hljs-language-icon">yaml</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="adding-a-user-%26-connecting" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/#adding-a-user-%26-connecting">Adding a User &amp; Connecting</a></h3> <p class="mb-4 text-text leading-7">Wireguard offers many <a href="https://www.wireguard.com/install/" class="link">device clients to connect to your new VPN</a> including for Linux, Mac, Windows, iOS and Android. I personally have the Android client installed to manage my server from afar!</p> <p class="mb-4 text-text leading-7">As the wg-easy instructions describe you should now be able to access the web interface at <a href="http://0.0.0.0:51821" class="link">http://0.0.0.0:51821</a>. Once there, make a new client and scan the QR code it offers onto your new device via your chosen client.</p> <h2 class="text-3xl mt-6 text-text" id="port-forwarding" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/#port-forwarding">Port Forwarding</a></h2> <p class="mb-4 text-text leading-7">The ultimate test will be connecting while not on the same network. Everyone’s router is unique, but a little internet research will reveal how to add port forwarding to your device.</p> <p class="mb-4 text-text leading-7">The device’s local IP address for the device Wireguard (wg-easy) is installed on will be needed. The router likely has a page of devices with their IP addresses that can be referenced.</p> <p class="mb-4 text-text leading-7">Choose the correct IP, then add <code>51820</code> with the <code>UDP</code> protocol.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Note</em>: If port <code>22</code> is enabled, optionally disable it as that enables SSH access <em class="italic text-green">without</em> Wireguard. This is what makes it easy for unauthorized visitors to try to access our devices.</p> <h2 class="text-3xl mt-6 text-text" id="putting-it-all-together!" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/#putting-it-all-together!">Putting it all together!</a></h2> <ol> <li class="text-subtext0">Ensure Wireguard (wg-easy) is running</li> <li class="text-subtext0">From a device outside of the network (such as a phone not on WiFi) connect to Wireguard via a client</li> <li class="text-subtext0">Ensure Ports are forwarded in the router</li> <li class="text-subtext0">Connect via SSH at the same <em class="italic text-green">local</em> IP address, likely looking something like <code>192.168.x.x</code></li> </ol> <p class="mb-4 text-text leading-7">Having trouble? Check your SSH user (<code>ssh myuser@192.168.x.x</code>) and that Wireguard is enabled. Verify this works on WiFi as well without the Wireguard tunnel connected on the client device.</p> Fri, 02 May 2025 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/more-secure-ssh-with-wireguard.md/ Self Hosting: Backup with Rsync https://gaiety.me/blog/rsync/ <p class="mb-4 text-text leading-7">Setting up a server can be so exciting! But it’s only truly useful if in the case of a drive failure your important data isn’t lost. Personally; I have a hard drive dedicated to important personal data, the root drive with docker data among other things, and finally <strong class="font-normal text-peach dark:text-yellow">an external drive ideal for backups</strong>. Let’s go through how I’ve setup nightly backups to that very external drive.</p> <h2 class="text-3xl mt-6 text-text" id="first%2C-some-goals" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#first%2C-some-goals">First, some goals</a></h2> <ol> <li class="text-subtext0">An easy to call script that we can supply a directory to backup</li> <li class="text-subtext0">Write to a log with backup results</li> <li class="text-subtext0">Set up a cron job to run backups automatically</li> </ol> <p class="mb-4 text-text leading-7">Note: <em class="italic text-green">Much of this is applicable to personal devices, but I’ve written this from the perspective of backing up a <strong class="font-normal text-peach dark:text-yellow">linux server</strong>.</em></p> <h2 class="text-3xl mt-6 text-text" id="script" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#script">Script</a></h2> <h3 class="text-2xl mt-4 text-text" id="thinking-through-it" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#thinking-through-it">Thinking through it</a></h3> <p class="mb-4 text-text leading-7">Note: <em class="italic text-green">The full script is in the next section</em></p> <p class="mb-4 text-text leading-7">First we’ll write a new shell script and assign it as executable.</p> <pre><code class="language-shell">echo &quot;#!/bin/bash&quot;&gt;&gt;backup.sh chmod +x backup.sh <span class="hljs-language-icon">shell</span></code></pre> <h4 class="text-xl mt-2 text-text" id="logging" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#logging">Logging</a></h4> <p class="mb-4 text-text leading-7">Next it makes sense to think about logging. This will help us test our script is running as expected, almost like test-driven development practices teach.</p> <p class="mb-4 text-text leading-7"><code>backup.sh</code></p> <pre><code class="language-shell">backupPath=$1 # first argument to script will be the directory to backup backupName=${2-manual} # second argument will be the name of the backup, or &quot;manual&quot; if not specified currentDate=$(date +&quot;%m_%d_%Y&quot;) # current date as month, day and full year currentTime=$(date +&quot;%T&quot;) backupLocation=&quot;/where/your/backups/go&quot; # for example, I mount my external drive at `/disks/external` logFile=&quot;/var/log/server-backups.log&quot; # can be anywhere, any filetype that&#x27;s plain text - a `.txt` would do as well echo &quot;$currentDate $currentTime Backing up $backupName data from $backupPath&quot;&gt;&gt;$logFile <span class="hljs-language-icon">shell</span></code></pre> <p class="mb-4 text-text leading-7">Now when we run the script it should write the current date, time, backup name and directory attempting to be backed up to a log file. We can run this script and check the logs like so:</p> <pre><code class="language-shell">./backup.sh directory-to-backup example-backup tail /var/log/server-backups.log <span class="hljs-language-icon">shell</span></code></pre> <p class="mb-4 text-text leading-7">Tail will show the final few lines of the file specified. If it does not, verify the log file exists and your user has permissions to edit it. Press <code>q</code> to exit <code>tail</code> at any time.</p> <h4 class="text-xl mt-2 text-text" id="the-backup-itself" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#the-backup-itself">The backup itself</a></h4> <p class="mb-4 text-text leading-7">Depending on your needs you’ll want to decide how to run your backup.</p> <p class="mb-4 text-text leading-7">One option, is compressing your backup into a compressed file such as a <code>.tgz</code>. This is easy enough to do with a command like <code>tar -zcf output.tgz -C directory-to-backup</code> - try it sometime, it’s cool! However, I’ve found it can be difficult to verify your backups are working while hidden away in a compressed file…</p> <p class="mb-4 text-text leading-7">Instead, I opt to leverage a folder syncing option like <code>rsync</code> which come on many Linux distrobutions pre-installed. It’ll compare two directories and copy any changes between one to the other. If you’re careful you can specify it should delete files removed intentionally from your directory to backup as well. <strong class="font-normal text-peach dark:text-yellow">Tip</strong>: I strongly suggest running rsync with the <code>--dry-run</code> parameter to ensure it’s doing exactly what you expect and not the opposite. Lastly I’ll suggest many default linux system folders you <em class="italic text-green">likely</em> don’t want to backup just in case you wish to backup your root drive <code>/</code> like I do.</p> <p class="mb-4 text-text leading-7"><code>backup.sh</code></p> <pre><code class="language-shell">cd $backupLocation mkdir -p $backupName RESULT=rsync -a --stats --human-readable --delete --dry-run \ # remember to remove --dry-run when you&#x27;re ready to actually back up your files for real --exclude=/snap \ --exclude=/dev \ --exclude=/mnt \ --exclude=/proc \ --exclude=/sys \ --exclude=/tmp \ --exclude=/var/tmp \ --exclude=/media \ --exclude=/disks \ --exclude=/usr/lib \ --exclude=/usr/src \ --exclude=/lost+found \ <span class="hljs-meta prompt_"> $</span><span class="language-bash">backupPath <span class="hljs-variable">$backupName</span>)</span> EXIT_CODE = $? if [[ $EXIT_CODE = 0]]; then echo &quot;$currentDate $currentTime Backup results for $backupName data:\n\n$RESULT&quot;&gt;&gt;$logFile echo &quot;$currentDate $currentTime Backed up $backupName data from $backupPath&quot;&gt;&gt;$logFile else echo &quot;$currentDate $currentTime Error backing up for $backupName in $backupPath! rsync error code: $EXIT_CODE&quot;&gt;&gt;$logFile fi <span class="hljs-language-icon">shell</span></code></pre> <p class="mb-4 text-text leading-7">I recommend making some test folders with some example files in it you don’t mind losing while testing this script. Never can be too careful, measure twice cut once! Once again you may run your script and tail the results.</p> <h3 class="text-2xl mt-4 text-text" id="the-full-script" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#the-full-script">The full script</a></h3> <p class="mb-4 text-text leading-7"><code>backup.sh</code></p> <pre><code class="language-shell"><span class="hljs-meta prompt_">#</span><span class="language-bash">!/bin/bash</span> backupPath=$1 # first argument to script will be the directory to backup backupName=${2-manual} # second argument will be the name of the backup, or &quot;manual&quot; if not specified currentDate=$(date +&quot;%m_%d_%Y&quot;) # current date as month, day and full year currentTime=$(date +&quot;%T&quot;) backupLocation=&quot;/where/your/backups/go&quot; # for example, I mount my external drive at `/disks/external` logFile=&quot;/var/log/server-backups.log&quot; # can be anywhere, any filetype that&#x27;s plain text - a `.txt` would do as well echo &quot;$currentDate $currentTime Backing up $backupName data from $backupPath&quot;&gt;&gt;$logFile cd $backupLocation mkdir -p $backupName RESULT=rsync -a --stats --human-readable --delete --dry-run \ # remember to remove --dry-run when you&#x27;re ready to actually back up your files for real --exclude=/snap \ --exclude=/dev \ --exclude=/mnt \ --exclude=/proc \ --exclude=/sys \ --exclude=/tmp \ --exclude=/var/tmp \ --exclude=/media \ --exclude=/disks \ --exclude=/usr/lib \ --exclude=/usr/src \ --exclude=/lost+found \ <span class="hljs-meta prompt_"> $</span><span class="language-bash">backupPath <span class="hljs-variable">$backupName</span>)</span> echo &quot;$currentDate $currentTime Backup results for $backupName data:\n\n$RESULT&quot;&gt;&gt;$logFile <span class="hljs-language-icon">shell</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="adding-as-a-cron-job" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rsync/#adding-as-a-cron-job">Adding as a cron job</a></h3> <p class="mb-4 text-text leading-7">For this you’ll need super user access. Note, the below command will open in the code editor <code>vim</code> in default.</p> <pre><code class="language-shell">sudo crontab -e <span class="hljs-language-icon">shell</span></code></pre> <p class="mb-4 text-text leading-7">Most cron files have helpful comment text by default. Give it a read, it’s quite useful. Determine how <a href="https://crontab.guru/" class="link">often you wish to run the script in crontab time</a> then write a similar command as to how you’ve been testing it. <strong class="font-normal text-peach dark:text-yellow">Try with dry-run enabled before trusting your cron job to not harm your precious files!</strong></p> <p class="mb-4 text-text leading-7">Below I’ve given some examples of backups you can run, customize for your own situation.</p> <p class="mb-4 text-text leading-7"><code>crontab</code></p> <pre><code class="language-shell">@daily /path/to/my/backup.sh /disks/my-awesome-files my-awesome-backedup-files @weekly /path/to/my/backup.sh / system <span class="hljs-language-icon">shell</span></code></pre> <p class="mb-4 text-text leading-7">Save your crontab changes and you’re done. Keep checking your logs, test test test, and be happy you’re not running backups like a pro.</p> Thu, 24 Apr 2025 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/rsync/ Where to Thrive in Colorado https://gaiety.me/blog/where_to_thrive_in_colorado/ <p class="mb-4 text-text leading-7">Posted originally on Medium…</p> <p class="mb-4 text-text leading-7"><a href="https://hergaiety.medium.com/96207b991ac1" class="link"><strong class="font-normal text-peach dark:text-yellow">Where to Thrive in Colorado</strong>: A data driven dive into what sets the major cities apart in the state of Colorado.</a>]</p> <p class="mb-4 text-text leading-7">I’ve done more <a href="https://gaiety.college/category/icm-529" class="link">writing on Data Visualizations on my school blog here</a>. You may also follow the rest of my journey back to university as I pursue my masters at Quinnipiac @ <a href="https://gaiety.college/" class="link">gaiety.college</a>.</p> Fri, 25 Aug 2023 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/where_to_thrive_in_colorado/ Pronoun Monster https://gaiety.me/blog/pronoun-monster/ <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: This is an article backfill, meaning I neglected my blog for some time and inserted this article back into history as for when it happened.</em></p> <p class="mb-4 text-text leading-7">In collaboration with my good friends <a href="http://argylewerewolf.com/" class="link">Angela</a> <a href="https://pronoun.monster/it/it/its/its/itself" class="link">it</a>/<a href="https://pronoun.monster/she/her/hers/herself" class="link">she</a> and <a href="https://goth.dev" class="link">Rizzo</a> <a href="https://pronoun.monster/he/him/his/him/himself" class="link">he</a>/<a href="https://pronoun.monster/they/them/their/themself" class="link">they</a> we’ve launched <a href="https://pronoun.monster/" class="link">Pronoun Monster</a>! A way to easily share your <a href="https://pronouns.design/" class="link">neopronouns</a> for social media presences, work conventions, and whatever else life throws your way. At the end of the day, such a tool is useful for everyone to know how to speak to or about you with respect.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Like this project and want to support it’s continued existence online? <a href="https://ko-fi.com/gaiety" class="link">Buy me a coffee</a> as web hosting ain’t free but it’s worth it.</em></p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Or feel free to <a href="https://gitlab.com/gaiety/pronoun-monster" class="link">fork the project</a> and contribute directly or spin off something of your own.</em></p> Sat, 12 Aug 2023 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/pronoun-monster/ Crafting Better Multimedia for the Invisible People All Around Us https://gaiety.me/blog/multimedia_for_invisible/ <p class="mb-4 text-text leading-7">Posted originally on <a href="https://medium.com/@hergaiety/crafting-better-multimedia-for-the-invisible-people-all-around-us-952f22070e6b" class="link">Medium: Crafting Better Multimedia for the Invisible People All Around Us</a></p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7"><em class="italic text-green">All of us deserve a more equitable web:</em> professionals, creating better multimedia on a more technologically advanced web; educators, with the passion to teach accessibility early, broadly, and with support; students, with the knowledge and tools that will continue to develop from generation to generation.</p> </blockquote> <p class="mb-4 text-text leading-7">I’ve done more <a href="https://gaiety.college/category/icm-500" class="link">writing on Social Media for Public Good on my school blog here</a>. You may also follow the rest of my journey back to university as I pursue my masters at Quinnipiac @ <a href="https://gaiety.college/" class="link">gaiety.college</a>.</p> Sat, 11 Mar 2023 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/multimedia_for_invisible/ Arizona K-12 School Finance https://gaiety.me/blog/arizona_school_finance/ <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: This is an article backfill, meaning I neglected my blog for some time and inserted this article back into history as for when it happened.</em></p> <p class="mb-4 text-text leading-7">In a new initiative for my work at <a href="https://www.allovue.com/" class="link">Allovue</a> we are beginning a trend of creating solutions for <a href="https://www.allovue.com/states" class="link">helping states meet transparency requirements around education funding</a>. It all began with <a href="https://blog.allovue.com/press/announces-arizona-school-financial-transparency-portal" class="link">a partnership with the state of Arizona</a> to build their transparent edfinance public portal.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Transparency means access <em class="italic text-green">and</em> understanding</strong> Education stakeholders at every level—legislators, educators, tax payers, and more—should be able to quickly and easily access and understand school funding and spending data.</p> </blockquote> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/arizona-public-portal.svg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">I’m ecstatic to announce that the <a href="https://schoolspending.az.gov/" class="link">Arizona Public Portal is Live</a>!</strong></p> <p class="mb-4 text-text leading-7">Of note is a major feature I took the lead on as a senior software engineer building out the most advanced feature on the site, <a href="https://schoolspending.az.gov/compare/" class="link">the Comparison Report</a> which allows multiple schools or districts within the state of Arizona to be analyzed apples to apples.</p> <hr> <p class="mb-4 text-text leading-7">This project was built using the <a href="https://www.phoenixframework.org/" class="link">Phoenix framework</a>, with the fairly expected stack of Elixir, Ecto and Tailwind. Along the way we’ve been building out and leveraging a private Phoenix LiveView powered design system.</p> Thu, 16 Feb 2023 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/arizona_school_finance/ A Beautiful Deer https://gaiety.me/blog/miniature_deer/ <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: This is an article backfill, meaning I neglected my blog for some time and inserted this article back into history as for when it happened.</em></p> <p class="mb-4 text-text leading-7">Recently I set up a hobby painting station where I have been churning out some new miniatures I am becoming increasingly proud of. It’s also helped that I invested in <a href="https://www.thearmypainter.com/speedpaint/" class="link">The Army Painter’s Speedpaints</a> Etsy has some wonderful <a href="https://www.etsy.com/listing/976336032/corner-paint-brush-holder" class="link">paint stations</a> for this hobby as well.</p> Tue, 23 Aug 2022 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/miniature_deer/ Fae/Faer/Femme Neopronouns https://gaiety.me/blog/fae-femme-faer-neopronouns/ <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: This is an article backfill, meaning I neglected my blog for some time and inserted this article back into history as for when it happened.</em></p> <p class="mb-4 text-text leading-7">As a backfill article, this was the first day I admitted my “hyper-curiosity” with the set of pronouns. Truthfully this curiosity started far earlier, likely when a person I dated used them as well. But regardless, life is a journey and here we are!</p> <p class="mb-4 text-text leading-7">I now go by Fae/Femme/Faer or She/Her everywhere.</p> <p class="mb-4 text-text leading-7"><a href="https://pronoun.monster/fae/faer/faer/femme/femmeself" class="link">Example Usages at Pronoun Monster</a> <a href="https://www.hrc.org/resources/understanding-neopronouns" class="link">A guide to Neopronouns</a></p> Mon, 16 May 2022 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/fae-femme-faer-neopronouns/ Back at Allovue https://gaiety.me/blog/back-at-allovue.md/ <p class="mb-4 text-text leading-7"><em class="italic text-green">Note: This is an article backfill, meaning I neglected my blog for some time and inserted this article back into history as for when it happened.</em></p> <p class="mb-4 text-text leading-7">It was at this time that, after two long years of being furloughed after COVID, I received an offer letter to return to Allovue! This has always been my dream job and I’m so psyched to be back.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Empowering educators to strategically and equitably allocate resources to best support the needs of students. We’re building budgeting software to give school districts the tools they need to give educators the tools they need. Furthermore, Allovue stands for equity and antiracism. I get to work with fellow other transgender coworkers and I’ve never felt more at home in the workplace. ~ <a href="https://gaiety.me/work/allovue/" class="link">https://gaiety.me/work/allovue/</a></p> </blockquote> Wed, 16 Mar 2022 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/back-at-allovue.md/ FaeTale Launch https://gaiety.me/blog/faetale-launch/ <h2 class="text-3xl mt-6 text-text" id="channel" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/faetale-launch/#channel">Channel</a></h2> <p class="mb-4 text-text leading-7">I recently began to realize my dream of taking my TTRPG (TableTop Roleplaying Games) from merely at the table, as rewarding as that is, and bringing it to a wider community. My full hopes and dreams are expansive and it all starts here: YouTube!</p> <p class="mb-4 text-text leading-7">Gaiety has expanded her persona into the brand called FaeTale; meaning <a href="https://forgottenrealms.fandom.com/wiki/Fey" class="link">Fae as in Feywild</a>), and reminiscent of Femme Fatale, and to tell a Tale. Through this medium I’ll tell tales, give players and GMs (Game Masters/Mommas/Etc) tips, review D&amp;D (Dungeons and Dragons) content and discuss homebrew - user created non-canonical content. I hope for this to be a positive place with upbeat excited tones celebrating the game I love.</p> <p class="mb-4 text-text leading-7">Who knows, perhaps this channel will slowly grow into streams, guest spotlights, articles, collaborations and more. For now, I’ll be uploading weekly content plus perhaps some shorts as I’m inspired to do so. We’re already <a href="https://www.youtube.com/channel/UCvgaIxGXIsEh8mVVlS50XWQ" class="link">six weeks in so watch the six videos already published on the channel!</a></p> <h2 class="text-3xl mt-6 text-text" id="site" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/faetale-launch/#site">Site</a></h2> <p class="mb-4 text-text leading-7">I got <a href="https://faetale.com/" class="link">faetale.com</a> pretty early so as to secure an email address for the YouTube channel. This really took away any excuses to build a site, like thinking it’s too early or somehow not worth it. In fact, it was worth it just to play with some new (to me) tech.</p> <h3 class="text-2xl mt-4 text-text" id="static%2C-spa%2C-or-serverside%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/faetale-launch/#static%2C-spa%2C-or-serverside%3F">Static, SPA, or Serverside?</a></h3> <p class="mb-4 text-text leading-7">I knew I’d be working with the <a href="https://developers.google.com/youtube/v3/" class="link">YouTube Data API</a> which meant static site generation, like this blog does, was likely off the table. At least that is, not without setting up some web hooks, but knowing I’d also want a Twitter Integration meant I should consider different technology, something that could be more dynamic.</p> <p class="mb-4 text-text leading-7">So if not static site generation, my other two options are to build an SPA (Single Page Application, letting clientside Javascript handle everything) or use some serverside rendering technology. I wanted to learn something new and I have very little experience with serverside rendering so I chose that path.</p> <p class="mb-4 text-text leading-7"><a href="https://www.phoenixframework.org/" class="link">Phoenix (Framework)</a> is a skill I’d been really wanting to learn, but after scaffolding a project I realized I was fighting against the grain to achieve the simple site I wanted. Phoenix wants to help with databases, MVC (model view controller) layers, and has several ways to write templates with many of their own opinions. I feel like I’ll come back to this in another more complicated project, but not today.</p> <h3 class="text-2xl mt-4 text-text" id="nuxt---serverside-vue" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/faetale-launch/#nuxt---serverside-vue">Nuxt - Serverside Vue</a></h3> <p class="mb-4 text-text leading-7">So I went with something more familiar yet something I hadn’t really worked with much. I haven’t build anything with [Vue]<a href="https://vuejs.org/" class="link">https://vuejs.org/</a>) since v1.x.x. It’s possible to set up Vue to render on the server and send the initial page view down to the client so I leveraged <a href="https://nuxtjs.org/" class="link">Nuxt</a> which made it incredibly easy to get a proof of concept together. It was pretty straightforward to integrate <a href="https://tailwindcss.com/" class="link">TailwindCSS</a> with <a href="https://tailwindui.com/" class="link">TailwindUI</a> to quickly build out a responsive and accessible site. Even pagination was pretty straightforward to set up, Nuxt and the YouTube Data API do the heavy lifting there.</p> <p class="mb-4 text-text leading-7">I’ve yet to dive into any automation testing, but I think I’d like to when I have time. I’d also like to add in some not-so-scary analytics tracking just so I can learn what’s working and what isn’t, as well as build our a search feature and a page to watch the videos as embeds rather than redirecting to YouTube. Finally, perhaps monetizing with <a href="https://coil.com/" class="link">Coil</a> but I doubt it’d do well compared to something like Ko-Fi haha.</p> <h3 class="text-2xl mt-4 text-text" id="full-stack-for-a-change!" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/faetale-launch/#full-stack-for-a-change!">Full Stack for a Change!</a></h3> <p class="mb-4 text-text leading-7">I’m a UI Engineer by trade, I love rolling around in the grassy hills of CSS and never thinking about a backend data layer. But because this was rendered serverside that meant that I’d need… well, a server! Most of my projects I just host as a <a href="https://www.digitalocean.com/products/app-platform/" class="link">Digital Ocean App</a> (point to repo, specify command to build, point to build folder, you’re done) but this would need more.</p> <p class="mb-4 text-text leading-7">Since most of the internet is run on Amazon, Microsoft or Google servers I opted to stick with Digital Ocean and make my first <a href="https://www.digitalocean.com/products/droplets/" class="link">Droplet</a>. A Droplet is basically a provisioned server complete with its own IP address that doesn’t do much by itself besides run linux and await your command. They had a specialized Droplet that would automatically provision with Node (necessary for Vue/Nuxt) and a Node user that had privileges to configure <code>pm2</code> (a process manager) that knew how to speak Node essentially to do things like automatically run a node process - like serving up the Nuxt app!</p> <p class="mb-4 text-text leading-7">So I made this Droplet, I saved the dummy app it shipped with so I could refer to it later if I got stuck. I then ensured it was easy for me to ssh into this droplet as my own user and as the node user via ssh keys with <code>ssh-copy-id</code>.</p> <p class="mb-4 text-text leading-7">I then pointed my <a href="http://faetale.com" class="link">faetale.com</a> domain name servers and A records to my Digital Ocean droplet following several guides I found online. Nginx was already configured and listening to the dummy app on an expected port which I made note of to either change or reuse later. It worked! Well, on HTTP without SSL at least… I knew certbot was the solution here but I had such trouble with it in the past. This time around, certbot was incredibly easy to use and it just worked. Suddenly I had <a href="http://faetale.com" class="link">faetale.com</a> SSL secured pointing to the dummy app!</p> <p class="mb-4 text-text leading-7">Lastly I swapped out the dummy app with a directory that checked out my git repository with the Nuxt app. For now I manually pull changes, install npm modules, and manually run my build scripts. Then as the Node user I tell pm2 to serve the site, I check that the ports are the same as what Nginx is expecting. And now… <a href="https://faetale.com/" class="link">https://faetale.com/</a> is alive!</p> <p class="mb-4 text-text leading-7">I’m skipping all kinds of steps here but, I’m just proud that I knew what to web search the steps for at each step of the process. Then fumbling my way through each guide to make it all work in the end was incredibly rewarding.</p> <p class="mb-4 text-text leading-7">I think I’ll stick to UI Engineering, but it sure does feel great to have built a full stack app that’s running my latest passion project! It’s really rewarding to publish a new YouTube video or Tweet and see the site automatically update with the latest content.</p> Sat, 15 Jan 2022 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/faetale-launch/ Powering the latest Gaiety.life blog (here!) with 11ty https://gaiety.me/blog/blog-2022-with-11ty/ <h2 class="text-3xl mt-6 text-text" id="static-site-generation" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/blog-2022-with-11ty/#static-site-generation">Static Site Generation</a></h2> <p class="mb-4 text-text leading-7"><a href="https://www.11ty.dev/" class="link">11ty (Eleventy) just hit v1.0</a> and it’s still by far my favorite static site generator. What the heck am I talking about? Well static site generators are code that typically gets run <em class="italic text-green">once</em> to compile a static website - usually a directory full of simple html and css. Many, including eleventy work based off of content pulled directly from a collection of markdown files. <a href="https://gitlab.com/gaiety/gaiety-life/-/tree/main/content/posts" class="link">Check out this very site’s markdown to see for yourself!</a> Often times a little bit of data is thrown into the header, known as “front matter” often written in YAML to define some content like a post title, date, tags, etc. This data along with the post content can then be compiled into a static site, no databases or anything to serve really. Just run the static site generator on deploy and let your web server host the html files that come out the other end.</p> <h2 class="text-3xl mt-6 text-text" id="html-%26-css-(with-templating-and-functional-styling)" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/blog-2022-with-11ty/#html-%26-css-(with-templating-and-functional-styling)">HTML &amp; CSS (with Templating and Functional Styling)</a></h2> <p class="mb-4 text-text leading-7">Now without some styling or extra layers of HTML it’d be a bunch of black text on a white background and there would be no tab titles or anything you’d expect a site to be. That’s where eleventy offers optional templates which you can write in a wide variety of templating languages! I’ve leaned on <a href="https://mozilla.github.io/nunjucks/" class="link">nunjucks</a> as a personal preference but <a href="https://handlebarsjs.com/" class="link">handlebars</a> or anything goes really. That handles the templating that will wrap the content and place dynamic data into the files that will be statically generated, now the styling…</p> <p class="mb-4 text-text leading-7">Writing CSS manually is so very completely valid I cannot emphasize it enough. But as a <s class="text-red">lazy</s> clever developer (look at me loving myself, woo) I leveraged <a href="https://tailwindcss.com/" class="link">TailwindCSS</a> and <a href="https://tailwindui.com/" class="link">TailwindUI</a>. These tools allow for rapidly building out sites while focusing on the html “components” letting me pull together elements like a card that I can render a post into. When set up correctly, <a href="https://postcss.org/" class="link">PostCSS</a> will automatically strip away any unused CSS meaning this otherwise bulky library ends up shipping just a few kilobytes in the end, so there’s next to no downsides in the final product. Using this strategy meant there were color variables defined by some very smart people I could lean on as well, and on top of that the HTML is very accessible. Everyone wins!</p> <h2 class="text-3xl mt-6 text-text" id="writing-content" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/blog-2022-with-11ty/#writing-content">Writing Content</a></h2> <p class="mb-4 text-text leading-7">Last but not least, behind the scenes I’m now writing blog post content in <a href="https://obsidian.md/" class="link">Obsidian</a> a markdown editor that is both simple to use and highly extensible. Think of it as the VS Code of Markdown, offering a wide selection of optional core and community plugins. What’s incredibly nice is the Obsidian config is saved to the current directory, meaning I can synchronize it with this very respository. This means any of my devices can pull down this repo, open obsidian, and use the workflow I’m comfortable with to more easily write new content without some complicated admin panel or WYSIWYG editor like Wordpress would have. This also means the content is highly portable, I could move this whole blog to <a href="http://medium.com" class="link">medium.com</a> or another static site generator tomorrow if I wished.</p> <hr> <p class="mb-4 text-text leading-7">I’m really excited for this new blog. Fingers crossed I’ll begin writing in it! I have a lot of content to catch up on.</p> <figure class="inline-block mb-4"><img src="https://www.11ty.dev/img/built/IdthKOzqFA-350.webp" alt="11ty Mascot, Possum with her babies floating by on a red balloon" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Thu, 13 Jan 2022 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/blog-2022-with-11ty/ React Library and Peer Dependency Woes https://gaiety.me/blog/react-peer-dependencies/ <p class="mb-4 text-text leading-7">You’ve been building your React component library, perhaps a UI Design System or a useful component you wish to share with the world. Your tests pass and it works great! Then, <em class="italic text-green">you try consuming your component in another React app and suddenly you’re met with the following error</em>:</p> <blockquote class="font-mono fancy-blockquote"> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/react-hooks-error.png" alt="Error: Invalid hook call. Hooks can only be called inside of the body of a function." class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> </blockquote> <p class="mb-4 text-text leading-7">Worse yet is the <a href="https://reactjs.org/warnings/invalid-hook-call-warning.html" class="link">suggested documentation page</a> suggests three very different possible reasons this error could occur. I’m here to say that so long as you’re using hooks appropriately, the trouble lies in React peer dependencies resulting in you unknowingly having multiple versions of React.</p> <h2 class="text-3xl mt-6 text-text" id="how-to-fix-this" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/react-peer-dependencies/#how-to-fix-this">How to fix this</a></h2> <p class="mb-4 text-text leading-7">Whether you’ve set up your React library with <a href="https://www.npmjs.com/package/create-react-library" class="link">create-react-library</a> or <a href="https://www.npmjs.com/package/create-react-app" class="link">create-react-app</a> the first thing to check is your own <code>./package.json</code>. If you see <code>react</code> or <code>react-dom</code> inside of your <code>dependencies</code> or <code>devDependencies</code> then you’ve already found the issue!</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Ensure <code>react</code> and <code>react-dom</code> only exist within a <code>peerDependnecies</code> block.</p> </blockquote> <p class="mb-4 text-text leading-7">You’ll also want to manually remove them from the <code>./node_modules</code> directory in case they exist already.</p> <pre><code class="language-sh"><span class="hljs-built_in">rm</span> -rf node_modules/react node_modules/react-dom <span class="hljs-language-icon">sh</span></code></pre> <p class="mb-4 text-text leading-7">At this point your issue is likely solved in the consuming app.</p> <h3 class="text-2xl mt-4 text-text" id="fixing-the-fix%E2%80%A6-running-tests-and-developing-the-addon-locally" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/react-peer-dependencies/#fixing-the-fix%E2%80%A6-running-tests-and-developing-the-addon-locally">Fixing the fix… running tests and developing the addon locally</a></h3> <p class="mb-4 text-text leading-7">Okay great, if this works then you’ll soon realize that you’re unable to run tests or otherwise develop your addon locally at all because you need <code>react</code> and <code>react-dom</code>. The unfortunate reality is that you’ll need to be intentional about when you install peer dependencies depending on what you’re doing.</p> <pre><code class="language-sh">npm i --no-save react react-dom <span class="hljs-comment"># this will not affect your package.json, and they may be auto-removed on the next npm install or yarn run</span> <span class="hljs-language-icon">sh</span></code></pre> <p class="mb-4 text-text leading-7">If you’re finding this annoying, you may opt to add some scripts to your <code>./package.json</code> to make installing and removing peer dependencies really easy. You may also then call them as prerequesit commands to your other standard commands.</p> <pre><code class="language-json"><span class="hljs-punctuation">{</span> scripts<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">&quot;peers:install&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;npm i --no-save react react-dom&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;peers:remove&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;rm -rf node_modules/react node_modules/react-dom&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;prebuild&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;npm run peers:remove&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;build&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;echo pretend this command built your library&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;pretest&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;npm run peers:install&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">&quot;test&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;echo pretend this command built your library&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-punctuation">}</span> <span class="hljs-punctuation">}</span> <span class="hljs-language-icon">json</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="still-having-trouble%3F-check-your-sub-dependencies" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/react-peer-dependencies/#still-having-trouble%3F-check-your-sub-dependencies">Still having trouble? Check your sub-dependencies</a></h2> <p class="mb-4 text-text leading-7">Even after all of the above work I still ran into trouble. It turns out, this issue flows all the way down to literally any additional copy of <code>react</code> or <code>react-dom</code> from any dependency in the chain. I discovered this by wiping out my dependencies in large sections until my library successfully compiled for the consuming app, and then proceeded to narrow it down.</p> <p class="mb-4 text-text leading-7">For me, I discovered that <a href="https://github.com/aholachek/storybook-mobile" class="link">storybook-mobile</a>, an optional storybook addon I was using, was having the very same issue of including <code>react</code> and <code>react-dom</code> in its <code>devDependencies</code>. It’s an easy issue to miss, so I <a href="https://github.com/aholachek/storybook-mobile/issues/25" class="link">wrote up a detailed issue</a> and <a href="https://github.com/aholachek/storybook-mobile/pull/26" class="link">submitted a PR to fix</a> it. Thankfully, this turned out to be a success story and the latest release works wonderfully.</p> <hr> <p class="mb-4 text-text leading-7">So in conclusion, be super careful that there aren’t more than one <code>react</code> or <code>react-dom</code> dependencies <em class="italic text-green">anywhere at all in your dependency tree</em> besides in your main app. Only one copy may exist anywhere at any time.</p> Tue, 22 Jun 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/react-peer-dependencies/ Building the Dream UI Component Library talk at MagnoliaJS https://gaiety.me/blog/magnoliajs2021/ <p class="mb-4 text-text leading-7">I had a real blast speaking at <a href="https://www.magnoliajs.com/" class="link">MagnoliaJS</a> this year!</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">A well made app is visually consistent, appealing, and usable. What does it look like to build a system that can engineers, designers, quality assurance, and product can use to make all of this happen? Let’s dive into the standards and technologies that have gone into building the new design system at Oncue with accessibility and testing in mind.</p> </blockquote> <figure class="inline-block mb-4"><a href="https://www.youtube.com/watch?v=5KlBtfO1CmU" class="link"><img src="http://i3.ytimg.com/vi/5KlBtfO1CmU/hqdefault.jpg" alt="Watch video recorded during MagnoliaJS on Youtube" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></a></figure> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><a href="https://www.notion.so/hergaiety/Building-the-Dream-UI-Component-Library-df5e59e84fcc4b02a9b77f5f33cfded2" class="link">“Slides”, relevant URL’s can be found here</a></li> <li class="text-subtext0"><a href="https://noti.st/gaiety/dVFVTk/building-the-dream-ui-component-library" class="link">Noti.st</a></li> </ul> Tue, 25 May 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/magnoliajs2021/ Global Accessibility Awareness Day @ Oncue https://gaiety.me/blog/gaad2021/ <p class="mb-4 text-text leading-7"><a href="https://globalaccessibilityawarenessday.org/" class="link">Global Accessibility Awareness Day (or GAAD)</a> is a wonderful time of year to get your team onboard with a wide range of topics around a11y.</p> <p class="mb-4 text-text leading-7">I collaborated with my same-day hire buddy <a href="https://www.linkedin.com/in/jwdesign/" class="link">Jennifer Wisniewski</a> to discuss the what, how and why behind embracing a11y for Oncue’s future.</p> <p class="mb-4 text-text leading-7">First we needed to cover what a11y was, and to that we primarily referenced <a href="https://www.figma.com/resources/learn-design/inclusion/" class="link">figma’s Accessibility and Inclusion</a> article. Our focus was on how we can make a meaningful impact.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Directly impacting the world’s largest minority (people with disabilities).</p> </blockquote> <p class="mb-4 text-text leading-7">We then focused on how product accessibility can be improved. This included some proposed agile epics, goals and milestones. We briefly touched on technologies, but this was just the lightest touch on how we can get the conversation started.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Much like automation testing, while achieving 100% coverage is challenging, the first 50% is easily achievable.</p> </blockquote> <p class="mb-4 text-text leading-7">Next we discussed a11y within the organization. This covered company culture and improving our <a href="https://projectinclude.org/hiring" class="link">hiring best practices</a>.</p> <p class="mb-4 text-text leading-7">Lastly, we opened the floor for conversation and additional thoughts. A key takeaway during this time was my boss speaking on her insight from her first time trying to use a web app purely with a screen-reader and how drastically different and potentially difficult it can be.</p> <p class="mb-4 text-text leading-7">I’m hoping for much more of this kind of collaborative discussion in the future to establish some meaningful improvements for our users (movers), their users (customers), and our own employees.</p> Fri, 21 May 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/gaad2021/ UI Engineer @ Oncue https://gaiety.me/blog/oncue/ <p class="mb-4 text-text leading-7">Building and maintaining an accessible, test driven, and mobile first UI Component library in Storybook.</p> <p class="mb-4 text-text leading-7">I’ll also be collaborating with design and product teams to establish a robust design system. Lots of exciting projects coming up!</p> Mon, 19 Apr 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/oncue/ Dotfiles 2021 - Ghost Comet https://gaiety.me/blog/dotfiles-2021/ <p class="mb-4 text-text leading-7"><a href="https://gitlab.com/gaiety/dotfiles" class="link"><strong class="font-normal text-peach dark:text-yellow">Ghost Comet</strong></a>, the sequel to <a href="https://gitlab.com/gaiety/dotfiles/-/tree/2019" class="link"><em class="italic text-green">Space Octopus</em></a> and <a href="https://gitlab.com/gaiety/dotfiles/-/tree/2017" class="link"><em class="italic text-green">Void Dragon</em></a> has been dropped over on my <a href="https://gitlab.com/gaiety" class="link">GitLab</a>.</p> <p class="mb-4 text-text leading-7">It features a Fish shell, Tmux auto-loading that pairs well with NeoVim, and the Kitty terminal emulator. This combines together to offer cool features like font ligatures, superb fuzzy finding with some of the latest NeoVim LUA support, with Linux and OSX support with similar UI.</p> <p class="mb-4 text-text leading-7">Follow the README’s in the directories to get started. This assumes some level of knowledge around the terminal, tmux and linux. For assistance though I’ve included some help accessible within <code>neovim</code> by pressing <code>&lt;Leader&gt;?</code> (where the <code>&lt;Leader&gt;</code> key is the Spacebar). Enjoy!</p> Mon, 12 Apr 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/dotfiles-2021/ Eleventy, Tailwind UI, Digital Ocean Apps and my Portfolio 2021 https://gaiety.me/blog/portfolio-2021/ <p class="mb-4 text-text leading-7">I’ve been drifting out of love with both <a href="https://www.netlify.com/" class="link">Netlify</a> and cumbersome <a href="https://jamstack.org/" class="link">Jamstack</a> tools like <a href="https://jamstack.org/generators/gridsome/" class="link">gridsome</a>, <a href="https://jamstack.org/generators/hexo/" class="link">Hexo</a> and others. Especially once a theme is applied on top via a <a href="https://git-scm.com/book/en/v2/Git-Tools-Submodules" class="link">Git Submodule</a> or something similar, the idea of fixing a bug or making some site adjustment can feel nearly impossible if you come back to the project some months later. These themes quickly go out of date and it can feel so complicated to understand the unique Jamstack language way of making some magic happen.</p> <p class="mb-4 text-text leading-7">My latest favorite way to build and deploy static sites is leveraging <a href="https://jamstack.org/generators/eleventy/" class="link">Eleventy (11ty)</a> with <a href="https://tailwindui.com/components" class="link">Tailwind UI</a> deployed with <a href="https://www.digitalocean.com/products/app-platform/" class="link">Digital Ocean Apps</a>. The selling point of this stack is that it’s as simple as the following steps:</p> <ol> <li class="text-subtext0"><code>git init</code> a new project thrown up on GitLab/GitHub or your choice of repository manager</li> <li class="text-subtext0"><code>npm install -g @11ty/eleventy</code> to install Eleventy</li> <li class="text-subtext0">Create a markdown file like <code>index.md</code> with some markdown content</li> <li class="text-subtext0"><code>eleventy</code> to build that markdown file into a <code>_site/index.html</code> automatically</li> <li class="text-subtext0">Deploy with Digital Ocean! (Full GUI to deploy, can follow the same above steps above)</li> </ol> <p class="mb-4 text-text leading-7">Suddenly you’re building a site with markdown! For simple sites you can point to <a href="https://tailwindcss.com/docs/installation#using-tailwind-via-cdn" class="link">Tailwind CSS as a CDN link</a> with no need for managing dependencies.</p> <p class="mb-4 text-text leading-7">Of course, Eleventy allows you to customize html layouts and more as much as you like, but it’s never required. This simplicity of being able to launch a usable site in so few steps and few files makes it a winner in my book.</p> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/" class="link">Check out my latest Portfolio</a> built with the above tools or <a href="https://gitlab.com/gaiety/portfolio" class="link">fork it on GitLab</a>.</p> Sun, 28 Feb 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/portfolio-2021/ TestJS Summit 2021 https://gaiety.me/blog/testjssummit/ <p class="mb-4 text-text leading-7">Another successful conference with a vibrant community. I was impressed with how well <a href="https://gitnation.org/" class="link">GitNation</a> ran everything remotely!</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/testjssummit-slides.jpg" alt="Achieving A11y Automation Testing: Accessibility testing in has come a long way in recent years. We'll dive into how EmberJS prioritized A11y with meaningful RFC's, Addons, tooling and docs. Most importantly, we'll discuss how these successes can be applied to your very own apps be they Vue, React, Angular or anything else!" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I hope to be able to share the recording publicly later, we’ll see how that goes as it was a private event.</p> Fri, 29 Jan 2021 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/testjssummit/ TestJS Summit Talk Accepted https://gaiety.me/blog/testjssummit-accepted/ <p class="mb-4 text-text leading-7">I’m proud to announce I’ll be speaking at <a href="https://testjssummit.com/" class="link">TestJS Summit</a> during January 28-29 in 2021! <a href="https://ti.to/gitnation/testjs-summit" class="link">You can register for the conference here</a>.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/testjssummit-speakerbio.png" alt="Achieving A11y Automation Testing: Accessibility testing in has come a long way in recent years. We'll dive into how EmberJS prioritized A11y with meaningful RFC's, Addons, tooling and docs. Most importantly, we'll discuss how these successes can be applied to your very own apps be they Vue, React, Angular or anything else!" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">See you there~!</p> Tue, 01 Dec 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/testjssummit-accepted/ Ember-Select-Light 2.0 Released https://gaiety.me/blog/ember-select-light-2/ <p class="mb-4 text-text leading-7">Inspired by <a href="https://emberjs-1.gitbook.io/ember-component-patterns/form-components/select-element" class="link">ember-component-pattern’s for how to best write a Select Element</a>, <a href="https://github.com/ember-a11y/ember-select-light" class="link">ember-select-light</a> is now <a href="https://emberjs.com/editions/octane/" class="link">Octane Ready</a> with the latest release!</p> <p class="mb-4 text-text leading-7">Getting started is as easy as…</p> <pre><code class="language-bash">ember install ember-select-light <span class="hljs-language-icon">bash</span></code></pre> <pre><code class="language-handlebars">&lt;SelectLight @value=&quot;turtle&quot; @options= @change= /&gt; </code></pre> <p class="mb-4 text-text leading-7">See the <a href="https://github.com/ember-a11y/ember-select-light" class="link">full docs here</a> for further details of how it can be used and styled.</p> <p class="mb-4 text-text leading-7">Additionally, I’m happy to announce the addon has been moved to the <a href="https://github.com/ember-a11y" class="link">official Ember A11y GitHub Org</a>!</p> Wed, 28 Oct 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-select-light-2/ Divisibility Rules https://gaiety.me/blog/divisibility-rules/ <p class="mb-4 text-text leading-7">VSauce has a number of channels including <a href="https://www.youtube.com/channel/UClq42foiSgl7sSpLupnugGA" class="link">D1NG</a> where they post fun educational content of all kinds. Recently I found myself itching to code and inspired by <a href="https://www.youtube.com/watch?v=f6tHqOmIj1E" class="link">some handy division math tricks</a>.</p> <p class="mb-4 text-text leading-7">So I threw together this <a href="https://gitlab.com/gaiety/divisibilityrules" class="link">Python script with methods showcasing each divisibility rule example</a>. The script has no direct practical purpose as each function could be done more simply for a computer to handle (likely just with <code>%</code> modulo for all cases). But I thought this would be fun enough to share!</p> <p class="mb-4 text-text leading-7">In building out this project I learned how to write some <a href="https://gitlab.com/gaiety/divisibilityrules/-/tree/main/tests" class="link">tests in python</a> and how to set up <a href="https://gitlab.com/gaiety/divisibilityrules/-/blob/main/.gitlab-ci.yml" class="link">GitLab CI</a>, which GitLab makes very easy with their WebIDE.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/gitlab-webide.png" alt="GitLab WebIDE with Templates and file autonaming" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Always learning~</p> Tue, 15 Sep 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/divisibility-rules/ Lead Full-Stack Engineer @ SkillsEngine (TSTC) https://gaiety.me/blog/skillsengine/ <p class="mb-4 text-text leading-7">I’ll be working with Texas State Technical College (TSTC) at SkillsEngine to connect employers, educators and students in new ways through technology. My hope in this role is to build software that matters to real people giving students a strong start to their career at places they’ll be happier to work at.</p> <p class="mb-4 text-text leading-7">I’ll miss my team at Allovue, who I’ve worked with for the past year until furloughs struck due to COVID-19. I hope for a future where our paths align again.</p> <p class="mb-4 text-text leading-7">Nevertheless, I’m deeply excited for this new opportunity with SkillsEngine. Expect more Ember, community outreach, talks and open source work as I’m able. More updates soon to come!</p> Mon, 03 Aug 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/skillsengine/ Puzzle Jam II: Finished! Laser Link! https://gaiety.me/blog/puzzlejam-end/ <p class="mb-4 text-text leading-7">It all started with the theme of <em class="italic text-green">Slide</em> for <a href="https://itch.io/jam/puzzle-jam-ii" class="link">8 Bits to Infinity’s Puzzle Jam II</a>.</p> <p class="mb-4 text-text leading-7">Inspired by the teachings of <a href="https://www.youtube.com/user/McBacon1337" class="link">Game Maker’s Toolkit (GMTK)</a> I was inspired to make a puzzle game with as few controls as possible with emergent game properties that arose from simple gameplay elements. In this case, the game would use the Arrow keys to slide lasers horizontally or vertically all at once, no need to choose which laser you would move or how fast. The goal was to very obviously show cause and effect of player movements and its reaction to the active puzzle via mirrors, walls, charge points and boosters that all simply affect your lasers in simple ways.</p> <h2 class="text-3xl mt-6 text-text" id="early-prototypes" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/puzzlejam-end/#early-prototypes">Early Prototypes</a></h2> <p class="mb-4 text-text leading-7">Basic laser movement…</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/early-laser-prototype.gif" alt="Laser Prototype Animation" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">With mirrors…</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/laser-prototype-2.gif" alt="Laser Prototype Animation" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">After some art…</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/laserlink-prototype-art2.gif" alt="Laser Mirror Prototype with Art" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Art with mirrors…</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/laserlink-prototype-art.gif" alt="Laser Mirror Prototype with Art" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <h3 class="text-2xl mt-4 text-text" id="community" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/puzzlejam-end/#community">Community</a></h3> <p class="mb-4 text-text leading-7">All of this prototyping was shared in the Discord community with 8 Bits to Infinity. I found this process to be invaluable! Getting emoji reacts and hearing about other game jam participants making progress on their own games made it so much easier to complete this game within the timeframe.</p> <p class="mb-4 text-text leading-7">I was also lucky enough to team up with Alptrack who provided the music, sound effects, some level designs and lots of ideas/support along the way! You can see her contributions in the final product…</p> <h2 class="text-3xl mt-6 text-text" id="the-finished-product" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/puzzlejam-end/#the-finished-product">The Finished Product</a></h2> <p class="mb-4 text-text leading-7">The game is <a href="https://itch.io/jam/puzzle-jam-ii/rate/675405" class="link">ready for ratings in the Game Jam here</a> and will always be <a href="https://gaiety.itch.io/laser-link" class="link">available at Itch.io: Laser Link</a>.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/laserlink-1.png" alt="Laser Link Preview 1" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <hr> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/laserlink-2.png" alt="Laser Link Preview 2" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Fri, 19 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/puzzlejam-end/ Puzzle Jam II: Start https://gaiety.me/blog/puzzlejam-start/ <p class="mb-4 text-text leading-7">There’s no better way to jump start a game development hobby than diving head first into a game jam! Today the theme <strong class="font-normal text-peach dark:text-yellow">SLIDE</strong> was announced and I couldn’t be more excited! I’ll be working alongside alp again to build and ship a puzzle game in a week’s time.</p> <p class="mb-4 text-text leading-7">What will I be building? Here’s a hint and sneak preview… Lasers!</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/early-laser-prototype.gif" alt="Laser Prototype Animation" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Fri, 12 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/puzzlejam-start/ Ember New Lang RFC: Merged! https://gaiety.me/blog/ember-new-lang-merged/ <p class="mb-4 text-text leading-7">The collaboration with Joseph Sumner, Jamie White, Melanie Sumner and myself has been a massive success and a great step forward for A11y.</p> <p class="mb-4 text-text leading-7">As we wrap up the Ember A11y Strike Team and <a href="https://blog.emberjs.com/2020/06/19/the-ember-times-issue-153.html" class="link">transition to a Working Group for Digital Accessibility</a> it’s great to wrap up with a big win. The biggest win I was a part of was the writing and <a href="https://github.com/emberjs/rfcs/pull/635" class="link">merging of the Ember New Lang RFC</a> which introduces an <code>ember new --lang</code> to set a default language for new Ember applications.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">This RFC introduces the --lang flag as an option for ember new, ember init, and ember addon commands within the Ember CLI. The feature targets the ember-cli build process – specifically, when generating the file for the application’s entry point at app/index.html. If the flag is used with a valid language code, it will assign the lang attribute in the file’s root <html> element to that code. The lang attribute is formally defined within the current HTML5 specification; it is used to specify the base human language of an element or a document in a way that can be programmatically understood by assistive technology.</html></p> </blockquote> <p class="mb-4 text-text leading-7">All motivations, design details and more can be <a href="https://github.com/hergaiety/rfcs/blob/798342dd6a7ce8dcf313128bdb3202784f91a702/text/0635-ember-new-lang.md" class="link">found in the RFC’s markdown</a>. We had a lot of great collaboration at every step of the process making this a wonderful project to be a part of.</p> <p class="mb-4 text-text leading-7">In fact, we’ll be working together on more Ember projects in the future! Stay tuned…</p> <p class="mb-4 text-text leading-7"><a href="https://blog.emberjs.com/2020/06/05/the-ember-times-issue-151.html" class="link">As seen in the Ember Times</a></p> Fri, 12 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-new-lang-merged/ Delving Into Game Development: Forest Sprites Preview https://gaiety.me/blog/forest-sprites-preview/ <p class="mb-4 text-text leading-7">In the early 2000’s I would spent a perhaps unhealthy amount of time in Flash creating animations, games and learning graphic design skills that I now rely on today. Now, for the past month I’ve dabbled in creating my first full game in Unity that I’d like to announce here called Forest Sprites.</p> <p class="mb-4 text-text leading-7">Forest Sprites is a game where you control one, of many, sprites of the forest - or, essentially, balls of Earth energy that is called upon to come together for a purpose. I’m still working on the exact story and end goal, but this will be a short and sweet adventure game with a focus on exploring a beautiful environment to some beautiful music being created custom for the game by alp of <a href="https://datafruits.fm/" class="link">datafruits</a>. It’ll be a side scroller with plenty of particles and other fun visuals.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/forest-sprites-preview-menu.gif" alt="Main Menu Intro Animations" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I hope to finish the game in a little over a month’s time. Stay tuned!</p> Wed, 10 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/forest-sprites-preview/ ember new --lang https://gaiety.me/blog/ember-new-lang/ <p class="mb-4 text-text leading-7">I’ve been working with Joseph Sumner, Ava Gaiety W., Jamie White and Melanie Sumner to put together a RFC prioritized by the Ember A11y Strike team. These are talented people and I’m ever so glad I’ve had the chance to work with them!</p> <p class="mb-4 text-text leading-7"><a href="https://github.com/hergaiety/rfcs/blob/ember-new-lang/text/0000-ember-new-lang.md" class="link">Rendered RFC</a>, <a href="https://github.com/josephdsumner/ember-cli/compare/master...ember-new-lang-base" class="link">Candidate Implementation</a>, <a href="https://github.com/emberjs/rfcs/pull/635" class="link">RFC PR</a>.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">This RFC introduces the <code>--lang</code> flag as an option for <code>ember new</code>, <code>ember init</code>, and <code>ember addon</code> commands within the Ember CLI. The feature targets the ember-cli build process – specifically, when generating the file for the application’s entry point at <code>app/index.html</code>. If the flag is used with a valid language code, it will assign the <code>lang</code> attribute in the file’s root <code>&lt;html&gt;</code> element to that code. The <code>lang</code> attribute is <a href="https://html.spec.whatwg.org/#the-lang-and-xml:lang-attributes" class="link">formally defined within the current HTML5 specification</a>; it is used to specify the base human language of an element or a document in a way that can be programmatically understood by assistive technology.</p> </blockquote> <p class="mb-4 text-text leading-7"><a href="https://blog.emberjs.com/2020/06/05/the-ember-times-issue-151.html" class="link">As featured in the Ember Times (June 5th, 2020)</a></p> Mon, 08 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-new-lang/ BLM https://gaiety.me/blog/blm/ <p class="mb-4 text-text leading-7">To pretend 2020 has been a rough year is ignoring the full picture. This pandemic may be new, but far from the first frightening health threat even within these past few decades. These protests may be larger than they’ve ever been before, but we are witnessing silenced voices being heard louder than we’re used to with plenty of work ahead of us.</p> <p class="mb-4 text-text leading-7">We’re stronger together. Support your loved ones, your neighbors, the causes voiced by black people and take care to protect those at high risk.</p> <p class="mb-4 text-text leading-7">Black lives matter yesterday, today and tomorrow. <a href="https://twitter.com/lovely_gos/status/1269111596334190593" class="link">Show your support with donations</a>, <a href="https://www.bleumag.com/2020/06/03/30-blm-petitions-you-should-sign-right-now/" class="link">research and sign petitions</a> and do what you can to support those who need help right now.</p> Mon, 08 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/blm/ Looking for Work https://gaiety.me/blog/looking-for-work-2020/ <p class="mb-4 text-text leading-7">With the world going through so much trauma and difficult healing right now it can feel weird to discuss anything except what’s happening around us.</p> <p class="mb-4 text-text leading-7">Still, in-between helping out where I can I must admit I’m looking for work as Allovue had to furlough many of its employees, myself included.</p> <p class="mb-4 text-text leading-7">Thus I’m looking for work as a Web Engineer, UI/UX Designer, Team Lead or a Tech Educator. I have much experience in each of these areas and I’m open to many different kinds of opportunities.</p> <p class="mb-4 text-text leading-7">Stay strong and support one-another in these difficult times. BLM and pride month y’all~</p> <hr> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/files/resume.pdf" class="link">Resume</a> <a href="mailto:ava@wroten.me" class="link">Contact Me ava@wroten.me</a></p> Wed, 03 Jun 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/looking-for-work-2020/ Ember ATX 2020 - Introducing Ember Modifiers https://gaiety.me/blog/ember-atx-2020-spring/ <p class="mb-4 text-text leading-7"><a href="https://www.youtube.com/watch?v=KWBOYqAEh6M" class="link">Watch on YouTube here</a></p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">What modifiers are, why use them</li> <li class="text-subtext0">Using modifier shipped with Ember</li> <li class="text-subtext0">Writing your own modifier (complete with tests!)</li> <li class="text-subtext0">Exploring modifier addons <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><a href="https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/#toc_event-handlers" class="link">Ember Guides for Templating and Modifiers</a></li> <li class="text-subtext0"><a href="https://github.com/ember-modifier/ember-modifier" class="link">ember-modifier (How you get a modifier blueprint etc)</a></li> <li class="text-subtext0"><a href="https://github.com/emberjs/ember-render-modifiers" class="link">@ember/render-modifiers</a></li> <li class="text-subtext0"><a href="https://www.npmjs.com/package/ember-prop-modifier" class="link">ember-prop-modifier</a></li> <li class="text-subtext0"><a href="https://github.com/lifeart/ember-ref-modifier" class="link">ember-ref-modifier</a></li> <li class="text-subtext0"><a href="https://github.com/josemarluedke/ember-focus-trap" class="link">ember-focus-trap</a></li> <li class="text-subtext0"><a href="https://nullvoxpopuli.github.io/ember-autostash-modifier" class="link">ember-autostash-modifier</a></li> </ul> </li> </ul> Wed, 01 Apr 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-atx-2020-spring/ A11y First, and Everyone Wins https://gaiety.me/blog/ember-conf-2020-recording/ <p class="mb-4 text-text leading-7"><a href="https://www.youtube.com/watch?v=ESemqChsBEE&amp;list=PL4eq2DPpyBbkC03mdzlyej6tcbEqrZK8N&amp;index=18&amp;t=0s" class="link">Watch on YouTube here</a></p> <p class="mb-4 text-text leading-7">By putting accessibility first we can achieve a far more composable, intuitive, and testable product.</p> <p class="mb-4 text-text leading-7">Come and listen to the real tale of modern automation testing the untestable: a drag and drop user interface. The story of a drag and drop feature doomed to be unaccessible, made accessible. The telling of a feature salvaged by accessibility.</p> <p class="mb-4 text-text leading-7">We’ve all been told accessibility is important, but rarely do we feel the fruits of the labor directly. We’ll discuss how developers, QA and leads can all feel the same benefit our users feel by putting accessibility first.</p> Thu, 26 Mar 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-conf-2020-recording/ No Longer Attending Ember Conf 2020 (EDIT: Virtual Conf!) https://gaiety.me/blog/ember-conf-2020-notattending/ <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">UPDATE: 03/18/2020</strong></p> <p class="mb-4 text-text leading-7">Ember Conf 2020 went virtual! My talk was given and there were requests for follow-up A11y content which I’ll strongly consider creating. I’ll be sure to post the talk recording when it’s available.</p> <hr> <p class="mb-4 text-text leading-7">Alas due to the increasing concerns from the CDC and Allovue’s employees travel advisory I have decided to no longer attend and give <a href="https://gaiety.me/speaking-at-ember-conf-2020" class="link">my talk “A11y First, and Everyone Wins”</a> next week. It was a decision not made lightly and I’m told there’s another A11y backup talk by a speaker who’s able to attend in my stead, so look forward to that!</p> <p class="mb-4 text-text leading-7">More details are to come, but my plan will be to record the talk to be uploaded online along with the open source code.</p> <p class="mb-4 text-text leading-7">In the meantime, stay safe friends!</p> Tue, 10 Mar 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-conf-2020-notattending/ Tailwind + Reveal.js https://gaiety.me/blog/reveal-tailwind/ <p class="mb-4 text-text leading-7">While working on my <a href="https://gaiety.me/speaking-at-ember-conf-2020" class="link">Ember Conf 2020 Presentation</a> I found myself in need series of slides. I thought the likely reality was an awkward transition back and forth between the presentation and several code demos I wished to show. Immediately I had flashbacks to awkward college lectures and hoped I could do something better.</p> <p class="mb-4 text-text leading-7">That’s when I remembered <a href="https://revealjs.com/" class="link">Reveal.js</a> and I was quite excited to see the project was still thriving. Reveal.js offers live website slide backgrounds I could use to load my demos as a slide which I found quite exciting. You’re able to leverage any HTML and CSS you desire to build our your slides as well!</p> <p class="mb-4 text-text leading-7">Although, how to structure my CSS for the presentation left me uneasy. On one hand I could hack something together since this was just a presentation I was building for myself. Then I remembered the <a href="https://tailwindcss.com/" class="link">utility-first CSS framework Tailwind</a> which would let me focus on writing content with helper classes to adjust my presentation as I went.</p> <p class="mb-4 text-text leading-7">It worked <em class="italic text-green">beautifully</em>. The <a href="https://tailwindcss.com/docs/installation/" class="link">Tailwind installation docs</a> offer many ways to integrate Tailwind, though I opted for a simple cdn include in my presentation’s HTML header like so</p> <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css&quot;</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <p class="mb-4 text-text leading-7">That’s it! Then it’s easy to write your presentation with tailwind classes. Happy presenting!</p> <hr> <h2 class="text-3xl mt-6 text-text" id="useful-presentation-snippets" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/reveal-tailwind/#useful-presentation-snippets">Useful presentation snippets</a></h2> <h3 class="text-2xl mt-4 text-text" id="monospaced-fonts" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/reveal-tailwind/#monospaced-fonts">Monospaced Fonts</a></h3> <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;font-mono&quot;</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>library-name<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="citations" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/reveal-tailwind/#citations">Citations</a></h3> <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Content<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">cite</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;text-sm text-gray-400&quot;</span>&gt;</span> Citation <span class="hljs-tag">&lt;/<span class="hljs-name">cite</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="columns" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/reveal-tailwind/#columns">Columns</a></h3> <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Header<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;flex&quot;</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;w-1/2&quot;</span>&gt;</span> Column 1 <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;w-1/2&quot;</span>&gt;</span> Column 2 <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> Mon, 09 Mar 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/reveal-tailwind/ Introducing Ember Modifiers https://gaiety.me/blog/ember-modifiers/ <p class="mb-4 text-text leading-7">As a frontend developer I find myself doing plenty of UX-centric work that involves A11y, clear visual feedback based on user interactions, and at times creating new user interactions altogether. On prior versions of Ember this may have been handled by a Component API such as <code>keypress(event) {</code>… or, was it <code>keyPress(event) {</code>?</p> <p class="mb-4 text-text leading-7">All of that is in the past as we introduce <a href="https://github.com/ember-modifier/ember-modifier" class="link">Ember Modifiers</a>.</p> <h2 class="text-3xl mt-6 text-text" id="what-is-an-ember-modifier%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#what-is-an-ember-modifier%3F">What is an Ember Modifier?</a></h2> <p class="mb-4 text-text leading-7"><code>ember-modifier</code> is a library <a href="https://guides.emberjs.com/release/components/template-lifecycle-dom-and-modifiers/#toc_event-handlers" class="link">referenced in the Ember Guides while discussing event handling</a>. Modifiers are <a href="https://blog.emberjs.com/2019/03/06/coming-soon-in-ember-octane-part-4.html" class="link">a new feature introduced in Ember Octane</a> Modifiers are <a href="https://blog.emberjs.com/2019/03/06/coming-soon-in-ember-octane-part-4.html" class="link">a new feature introduced in Ember Octane</a>.</p> <p class="mb-4 text-text leading-7">In a nutshell, the next time you reach for a <code>didInsertElement()</code> with an <code>addEventListener()</code> consider any of the following examples instead.</p> <h2 class="text-3xl mt-6 text-text" id="using-ember-modifiers" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#using-ember-modifiers">Using Ember Modifiers</a></h2> <h3 class="text-2xl mt-4 text-text" id="getting-started" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#getting-started">Getting Started</a></h3> <p class="mb-4 text-text leading-7">First we install the library</p> <pre><code class="language-bash"><span class="hljs-comment"># In Your Terminal</span> ember install ember-modifier <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="handling-dom-events" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#handling-dom-events">Handling Dom Events</a></h3> <p class="mb-4 text-text leading-7">Below is an example for how to track the focus state of a DOM element.</p> <pre><code class="language-html">{{!-- my-component.hbs --}} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> {{<span class="hljs-attr">on</span> &#x27;<span class="hljs-attr">focus</span>&#x27; <span class="hljs-attr">this.handleFocus</span>}} {{<span class="hljs-attr">on</span> &#x27;<span class="hljs-attr">blur</span>&#x27; <span class="hljs-attr">this.handleBlur</span>}} <span class="hljs-attr">role</span>=<span class="hljs-string">&quot;button&quot;</span>&gt;</span> Focus Me <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// my-component.js</span> <span class="hljs-keyword">import</span> <span class="hljs-title class_">Component</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@glimmer/component&#x27;</span>; <span class="hljs-keyword">import</span> { tracked } <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@glimmer/tracking&quot;</span>; <span class="hljs-keyword">import</span> { action } <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ember/object&quot;</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">Component</span> { @tracked myButtonHasFocus = <span class="hljs-literal">false</span>; @action <span class="hljs-title function_">handleFocus</span>(<span class="hljs-params"></span>) { <span class="hljs-variable language_">this</span>.<span class="hljs-property">myButtonHasFocus</span> = <span class="hljs-literal">true</span>; } @action <span class="hljs-title function_">handleBlur</span>(<span class="hljs-params">{ target, relatedTarget }</span>) { <span class="hljs-keyword">if</span> (!target.<span class="hljs-title function_">contains</span>(relatedTarget)) <span class="hljs-variable language_">this</span>.<span class="hljs-property">myButtonHasFocus</span> = <span class="hljs-literal">false</span>; } } </span><span class="hljs-language-icon">js</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="handling-key-presses" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#handling-key-presses">Handling Key Presses</a></h3> <p class="mb-4 text-text leading-7">We can create a custom modifier like so:</p> <pre><code class="language-bash"><span class="hljs-comment"># In Your Terminal</span> ember g modifier key-down <span class="hljs-language-icon">bash</span></code></pre> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// modifiers/key-down.js</span> <span class="hljs-keyword">import</span> { modifier } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;ember-modifier&#x27;</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title function_">modifier</span>(<span class="hljs-keyword">function</span> <span class="hljs-title function_">keyUp</span>(<span class="hljs-params">element, [handler], { key: desiredKey }</span>) { <span class="hljs-keyword">let</span> <span class="hljs-title function_">keydownListener</span> = (<span class="hljs-params">evt</span>) =&gt; { <span class="hljs-keyword">if</span> (!desiredKey || desiredKey === evt.<span class="hljs-property">key</span>) { <span class="hljs-title function_">handler</span>(evt); } } element.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">&#x27;keydown&#x27;</span>, keydownListener); <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> { element.<span class="hljs-title function_">removeEventListener</span>(<span class="hljs-string">&#x27;keydown&#x27;</span>, keydownListener); } }); </span><span class="hljs-language-icon">js</span></code></pre> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// tests/integration/modifiers/key-down-test.js</span> <span class="hljs-keyword">import</span> { <span class="hljs-variable language_">module</span>, test } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;qunit&#x27;</span>; <span class="hljs-keyword">import</span> { setupRenderingTest } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;ember-qunit&#x27;</span>; <span class="hljs-keyword">import</span> { render, triggerKeyEvent } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@ember/test-helpers&#x27;</span>; <span class="hljs-keyword">import</span> hbs <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;htmlbars-inline-precompile&#x27;</span>; <span class="hljs-keyword">import</span> { set } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@ember/object&#x27;</span>; <span class="hljs-title function_">module</span>(<span class="hljs-string">&#x27;Integration | Modifier | key-down&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">hooks</span>) { <span class="hljs-title function_">setupRenderingTest</span>(hooks); <span class="hljs-title function_">test</span>(<span class="hljs-string">&#x27;it fires off a function when a key down, passing the event along with it&#x27;</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">assert</span>) { <span class="hljs-title function_">set</span>(<span class="hljs-variable language_">this</span>, <span class="hljs-string">&#x27;keyDown&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">{ key }</span>) =&gt;</span> { assert.<span class="hljs-title function_">step</span>(<span class="hljs-string">&#x27;key down&#x27;</span>); assert.<span class="hljs-title function_">equal</span>(key, <span class="hljs-string">&#x27;Enter&#x27;</span>); }); <span class="hljs-keyword">await</span> <span class="hljs-title function_">render</span>(</span>hbs`<span class="language-glimmer"> <span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-punctuation mustache">{{<span class="hljs-title">key-down</span> <span class="hljs-class">this</span><span class="hljs-punctuation">.</span><span class="hljs-property">keyDown</span>}}</span> <span class="hljs-attribute">data-test-id</span><span class="hljs-operator">=</span><span class="hljs-string">&#x27;keydown&#x27;</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span> `</span><span class="language-_js-in-gjs">); <span class="hljs-keyword">await</span> <span class="hljs-title function_">triggerKeyEvent</span>(<span class="hljs-string">&#x27;[data-test-id=keydown]&#x27;</span>, <span class="hljs-string">&#x27;keydown&#x27;</span>, <span class="hljs-string">&#x27;Enter&#x27;</span>); assert.<span class="hljs-title function_">verifySteps</span>([<span class="hljs-string">&#x27;key down&#x27;</span>]); }); <span class="hljs-title function_">test</span>(<span class="hljs-string">&#x27;it can listen for a specific key&#x27;</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">assert</span>) { <span class="hljs-title function_">set</span>(<span class="hljs-variable language_">this</span>, <span class="hljs-string">&#x27;keyDown&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">{ key }</span>) =&gt;</span> { assert.<span class="hljs-title function_">step</span>(<span class="hljs-string">&#x27;enter key down&#x27;</span>); assert.<span class="hljs-title function_">equal</span>(key, <span class="hljs-string">&#x27;Enter&#x27;</span>); }); <span class="hljs-keyword">await</span> <span class="hljs-title function_">render</span>(</span>hbs`<span class="language-glimmer"> <span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-punctuation mustache">{{<span class="hljs-title">key-down</span> <span class="hljs-class">this</span><span class="hljs-punctuation">.</span><span class="hljs-property">keyDown</span> <span class="hljs-attribute">key</span><span class="hljs-operator">=</span><span class="hljs-string">&quot;Enter&quot;</span>}}</span> <span class="hljs-attribute">data-test-id</span><span class="hljs-operator">=</span><span class="hljs-string">&#x27;keydown&#x27;</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span> `</span><span class="language-_js-in-gjs">); <span class="hljs-keyword">await</span> <span class="hljs-title function_">triggerKeyEvent</span>(<span class="hljs-string">&#x27;[data-test-id=keydown]&#x27;</span>, <span class="hljs-string">&#x27;keydown&#x27;</span>, <span class="hljs-string">&#x27;Enter&#x27;</span>); <span class="hljs-keyword">await</span> <span class="hljs-title function_">triggerKeyEvent</span>(<span class="hljs-string">&#x27;[data-test-id=keydown]&#x27;</span>, <span class="hljs-string">&#x27;keydown&#x27;</span>, <span class="hljs-string">&#x27;Spacebar&#x27;</span>); assert.<span class="hljs-title function_">verifySteps</span>([<span class="hljs-string">&#x27;enter key down&#x27;</span>]); }); }); </span><span class="hljs-language-icon">js</span></code></pre> <h4 class="text-xl mt-2 text-text" id="leveraging-a-key-down-modifier" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#leveraging-a-key-down-modifier">Leveraging a key-down modifier</a></h4> <h5 class="text-lg mt-2 text-text" id="%E2%80%9Cbinding%E2%80%9D-a-key-to-an-action" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#%E2%80%9Cbinding%E2%80%9D-a-key-to-an-action">“Binding” a key to an action</a></h5> <p class="mb-4 text-text leading-7">A simple example of a focusable element listening for the Enter key to be pressed.</p> <pre><code class="language-html">{{!-- my-component.hbs --}} <span class="hljs-tag">&lt;<span class="hljs-name">button</span> {{<span class="hljs-attr">key-down</span> <span class="hljs-attr">this.handleEnter</span> <span class="hljs-attr">key</span>=<span class="hljs-string">&#x27;Enter&#x27;</span>}} <span class="hljs-attr">My</span> <span class="hljs-attr">Button</span> &lt;/<span class="hljs-attr">button</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// my-component.js</span> <span class="hljs-keyword">import</span> <span class="hljs-title class_">Component</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@glimmer/component&#x27;</span>; <span class="hljs-keyword">import</span> { action } <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ember/object&quot;</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SortableGroupAccessibleComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">Component</span> { @action <span class="hljs-title function_">handleEnter</span>(<span class="hljs-params"></span>) { <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;enter pressed!&#x27;</span>); } </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7"><em class="italic text-green">Note, often times it may be better to listen for keyup rather than keydown for such events.</em></p> <h5 class="text-lg mt-2 text-text" id="preventing-a-default-key-behavior" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-modifiers/#preventing-a-default-key-behavior">Preventing a default key behavior</a></h5> <p class="mb-4 text-text leading-7">Sometimes you simply want to stop the default behavior of a key, such as scrolling down with an arrow key.</p> <pre><code class="language-html">{{!-- my-component.hbs --}} <span class="hljs-tag">&lt;<span class="hljs-name">dialog</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">&quot;0&quot;</span> <span class="hljs-attr">role</span>=<span class="hljs-string">&#x27;dialog&#x27;</span> {{<span class="hljs-attr">key-down</span> <span class="hljs-attr">this.preventDefault</span> <span class="hljs-attr">key</span>=<span class="hljs-string">&#x27;ArrowDown&#x27;</span>}} {{<span class="hljs-attr">key-down</span> <span class="hljs-attr">this.preventDefault</span> <span class="hljs-attr">key</span>=<span class="hljs-string">&#x27;ArrowUp&#x27;</span>}}&gt;</span> {{yield}} <span class="hljs-tag">&lt;/<span class="hljs-name">dialog</span>&gt;</span> <span class="hljs-language-icon">html</span></code></pre> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// my-component.js</span> <span class="hljs-keyword">import</span> <span class="hljs-title class_">Component</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@glimmer/component&#x27;</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">Component</span> { <span class="hljs-title function_">preventDefault</span>(<span class="hljs-params">evt</span>) { evt.<span class="hljs-title function_">preventDefault</span>(); } <span class="hljs-comment">// This can be a plain function, no need for the @action decorator</span> } </span><span class="hljs-language-icon">js</span></code></pre> <hr> <p class="mb-4 text-text leading-7">There’s plenty of more power than what I’ve shown here! Be sure to check out <a href="https://github.com/emberjs/ember-render-modifiers" class="link">ember-render-modifiers</a> and <a href="https://github.com/josemarluedke/ember-focus-trap" class="link">ember-focus-trap</a> as well.</p> Tue, 03 Mar 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-modifiers/ Form Autofocusing https://gaiety.me/blog/form-focus/ <p class="mb-4 text-text leading-7">Controlling form focusing is always a “it depends” kind of situation. However, we can often times make intelligent decisions rather than leave the user hanging.</p> <p class="mb-4 text-text leading-7">Imagine a common scenario. I have a pastry shop app and I click “New Donut”. A form pops up with inputs for attributes such as the Nickname, Toppings, and Dough type for this donut recipe. I begin typing… oops! I have to tab through every interactable element on the page until I find this newly appeared form. Eep!</p> <p class="mb-4 text-text leading-7">In such a scenario it makes sense to write reusable components for our form elements. Consider the following:</p> <pre><code class="language-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>New Donut<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> {{#if this.creatingNewDonut}} <span class="hljs-tag">&lt;<span class="hljs-name">UiForm</span> @<span class="hljs-attr">shouldAutofocus</span>=<span class="hljs-string">{{true}}</span> @<span class="hljs-attr">submit</span>=<span class="hljs-string">{{this.submitHandler}}</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">UiLabel</span>&gt;</span> Nickname <span class="hljs-tag">&lt;<span class="hljs-name">UiInput</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">UiLabel</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">UiLabel</span>&gt;</span> Toppings <span class="hljs-tag">&lt;<span class="hljs-name">UiInput</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">UiLabel</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">UiLabel</span>&gt;</span> Dough Type <span class="hljs-tag">&lt;<span class="hljs-name">UiInput</span> /&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">UiLabel</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">UiForm</span>&gt;</span> {{/if}} <span class="hljs-language-icon">html</span></code></pre> <p class="mb-4 text-text leading-7"><em class="italic text-green">The above code example is written in htmlbars (handlebars for Ember) but it’s a generalized example that could apply to any framework.</em></p> <p class="mb-4 text-text leading-7">Now in our <code>UiForm</code> component we can write some code into your framework’s render hook like so:</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-keyword">let</span> focusableQuerySuffix = <span class="hljs-string">&#x27;:not([readonly]):not([disabled]):not([tabindex=&quot;-1&quot;])&#x27;</span>; <span class="hljs-keyword">let</span> focusableQueries = [ <span class="hljs-string">`input<span class="hljs-subst">${focusableQuerySuffix}</span>`</span>, <span class="hljs-string">`textarea<span class="hljs-subst">${focusableQuerySuffix}</span>`</span>, <span class="hljs-string">`select<span class="hljs-subst">${focusableQuerySuffix}</span>`</span>, ]; <span class="hljs-keyword">let</span> element = <span class="hljs-variable language_">this</span>.<span class="hljs-property">element</span>.<span class="hljs-title function_">querySelector</span>(focusableQueries.<span class="hljs-title function_">join</span>(<span class="hljs-string">&#x27;,&#x27;</span>)); <span class="hljs-comment">// this.element will vary for your framework of choice, replace it with however you target your component&#x27;s dom element</span> <span class="hljs-keyword">if</span> (!element) <span class="hljs-keyword">return</span>; element.<span class="hljs-title function_">focus</span>(); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">Focusing an element is the easy part, simply call <code>.focus()</code> on any dom element. Finding which dom element to query is the tricky part. Generally avoiding anything with a <code>readonly</code>, <code>disabled</code> or <code>tabindex=-1</code> attribute is safe so long as you follow html semantics carefull in your application.</p> <p class="mb-4 text-text leading-7">This could be expanded to support radio buttons, button elements and other interactable dom elements should you so choose.</p> <p class="mb-4 text-text leading-7">Focus responsibly!</p> Tue, 25 Feb 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/form-focus/ Twitch Profile for Yuushagani https://gaiety.me/blog/crabs/ <p class="mb-4 text-text leading-7">Buddy of mine <a href="https://www.twitch.tv/yuushagani" class="link">Yuushagani</a> started really getting into Twitch streaming recently and needed some art done. I was happy to jump in where I could!</p> <p class="mb-4 text-text leading-7">It began with a sketch his wife (who goes by the handle of butanosuka) painted for the “King Crab” which Yuushagani roughly translates too. I digitized the crab design and packaged up an archive of a banner, avatar and several emotes.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/crab-emotes.png" alt="Emotes" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Later, Yuushagani added <a href="https://streamavatars.com/" class="link">Stream Avatars</a> which introduced little animated characters that walk around the screen with various attachments like hats and holdables. I’ve since made roughly half of the crab pixel art for the channel that the followers can enjoy as they scuttle across the screen!</p> <p class="mb-4 text-text leading-7">These commissions were a blast and I’d consider taking more in the future.</p> Mon, 17 Feb 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/crabs/ Working With Forked Repos https://gaiety.me/blog/working-with-forked-repos/ <p class="mb-4 text-text leading-7">Though I’ve been building web apps for many years, my direct experience with contributing to open source projects is surprisingly limited. Thus when I found myself forking and maintaining a fork as I submitted several PR’s for a single project over time I was a little lost with what to do.</p> <p class="mb-4 text-text leading-7">So here are some things I’ve learned thus far.</p> <h2 class="text-3xl mt-6 text-text" id="why-fork%2C-and-how-do-i-fork%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/working-with-forked-repos/#why-fork%2C-and-how-do-i-fork%3F">Why Fork, and How do I Fork?</a></h2> <p class="mb-4 text-text leading-7">Github, Gitlab and other source-code repositories allow for you to “fork” code. I previously thought this was to split work into a different direction, but in fact its also to give a developer control over proposed changes they’d like to push back to source. Thus, submitting a PR to an open source repository looks like this:</p> <ol> <li class="text-subtext0">Click <code>Fork</code> on the source-code repository</li> <li class="text-subtext0">Clone your newly forked repository</li> <li class="text-subtext0">Make your changes on a new branch</li> <li class="text-subtext0">Push your branch to your forked repository (A misconception I had was you may not push a branch to many open source repositories directly, this is intentional)</li> <li class="text-subtext0">Create a PR that merges your branch from your fork to the original non-forked repository</li> </ol> <h2 class="text-3xl mt-6 text-text" id="updating-the-forked-master-branch" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/working-with-forked-repos/#updating-the-forked-master-branch">Updating the Forked Master Branch</a></h2> <p class="mb-4 text-text leading-7">Over time your forked repository will get out of date. A common scenario is desiring to get the latest master from the source repository.</p> <pre><code class="language-bash">git remote add upstream ORIGINAL_PROJECT_CLONE_URL git fetch upstream git checkout master git rebase upstream/master <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7">Now you may do all the standard things you wish, such as merging master into your current branch <code>git merge master</code> to stay up to date with your proposed changes.</p> Sun, 02 Feb 2020 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/working-with-forked-repos/ Mocked Tasks for Ember Concurrency Rendering Tests https://gaiety.me/blog/ember-integration-mocked-tasks/ <p class="mb-4 text-text leading-7">Async can be difficult. Async testing is improving every day, but still comes with its hardships.</p> <p class="mb-4 text-text leading-7">I remember the days when deciding to adopt ember-concurrency came with the caveat that you’d be unable to write as many tests. It simply… didn’t always work as you’d hope. The tradeoff was your app simply behaved better with fewer console errors, doubled up requests, and inconsistent manually tracked <code>isLoading</code> flags.</p> <h2 class="text-3xl mt-6 text-text" id="where-are-we-today%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-integration-mocked-tasks/#where-are-we-today%3F">Where are we today?</a></h2> <p class="mb-4 text-text leading-7">We now have better tooling all around and I’m very happy that <a href="http://ember-concurrency.com/" class="link">ember-concurrency</a> is a core tool of many apps. Writing tests for the most part simply just… work as you’d hope they would!</p> <p class="mb-4 text-text leading-7">But, what about testing the asynchronous bits itself? What if you want to test that a loading spinner appears, or that it goes away a table of data loads in its place?</p> <h3 class="text-2xl mt-4 text-text" id="enter-mocked-tasks" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-integration-mocked-tasks/#enter-mocked-tasks">Enter Mocked Tasks</a></h3> <p class="mb-4 text-text leading-7"><a href="https://embermap.com/topics/rendering-tests/testing-tasks-part-2" class="link">Ember Map has a wonderful series on rendering tests</a> which inspired this article. Specifically, part two sparked the base of this coding helper.</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// tests/helpers/concurrency.js</span> <span class="hljs-keyword">import</span> <span class="hljs-title class_">EmberObject</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@ember/object&#x27;</span>; <span class="hljs-keyword">import</span> { task } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;ember-concurrency&#x27;</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TaskHelper</span> { <span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) { <span class="hljs-keyword">let</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> { <span class="hljs-variable language_">this</span>.<span class="hljs-property">finishTask</span> = resolve; }); <span class="hljs-variable language_">this</span>.<span class="hljs-property">task</span> = <span class="hljs-title class_">EmberObject</span>.<span class="hljs-title function_">extend</span>({ <span class="hljs-attr">task</span>: <span class="hljs-title function_">task</span>(<span class="hljs-keyword">function</span>* () { <span class="hljs-keyword">return</span> <span class="hljs-keyword">yield</span> promise; }), }).<span class="hljs-title function_">create</span>().<span class="hljs-property">task</span>; } } </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">Here we have a test helper we can import to have fine tuned control over how and when our tests resolve async tasks.</p> <p class="mb-4 text-text leading-7">Imagine we have a component <code>&lt;MyComponent&gt;</code> and that component has a task that fetches data from an api <code>loadingTask: task(function* () { ...</code>.</p> <p class="mb-4 text-text leading-7">Within our tests we can overwrite that loadingTask with a mocked task from our concurrency helper.</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// tests/integration/my-component-test.js</span> <span class="hljs-keyword">import</span> { <span class="hljs-variable language_">module</span>, test } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;qunit&#x27;</span>; <span class="hljs-keyword">import</span> { setupRenderingTest } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;ember-qunit&#x27;</span>; <span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@ember/test-helpers&#x27;</span>; <span class="hljs-keyword">import</span> hbs <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;htmlbars-inline-precompile&#x27;</span>; <span class="hljs-keyword">import</span> <span class="hljs-title class_">TaskHelper</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;my-ember-app/tests/helpers/concurrency&#x27;</span>; <span class="hljs-title function_">module</span>(<span class="hljs-string">&#x27;Integration | Component | my-component&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">hooks</span>) { <span class="hljs-title function_">setupRenderingTest</span>(hooks); <span class="hljs-title function_">test</span>(<span class="hljs-string">&#x27;Renders loader on render&#x27;</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">assert</span>) { <span class="hljs-keyword">let</span> mockedTask = <span class="hljs-keyword">new</span> <span class="hljs-title class_">TaskHelper</span>(); <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(<span class="hljs-string">&#x27;mockedTask&#x27;</span>, mockedTask.<span class="hljs-property">task</span>); <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(<span class="hljs-string">&#x27;testAction&#x27;</span>, <span class="hljs-function">() =&gt;</span> {}); <span class="hljs-keyword">await</span> <span class="hljs-title function_">render</span>(</span>hbs`<span class="language-glimmer"><span class="hljs-tag">&lt;<span class="hljs-title">MyComponent</span> <span class="hljs-punctuation">@</span><span class="hljs-params">loadingTask</span><span class="hljs-operator">=</span> /&gt;</span>`</span><span class="language-_js-in-gjs">); assert.<span class="hljs-title function_">dom</span>(<span class="hljs-string">&#x27;#loadingspinner&#x27;</span>).<span class="hljs-title function_">exists</span>(); }); }); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">The above test replaces our loadingTask with a task that looks to a promise that we never resolve. For the purposes of our test, that’s all we need to do!</p> <p class="mb-4 text-text leading-7">We can go a step further and resolve our promise, and therefore our task, to assert that our loading spinner goes away and data loads.</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-keyword">import</span> { render, waitFor } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@ember/test-helpers&#x27;</span>; ... <span class="hljs-title function_">test</span>(<span class="hljs-string">&#x27;Removes loading spinner, renders data&#x27;</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">assert</span>) { <span class="hljs-keyword">let</span> mockedTask = <span class="hljs-keyword">new</span> <span class="hljs-title class_">TaskHelper</span>(); <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(<span class="hljs-string">&#x27;mockedTask&#x27;</span>, mockedTask.<span class="hljs-property">task</span>); <span class="hljs-keyword">let</span> data = { <span class="hljs-attr">foo</span>: <span class="hljs-string">&#x27;bar&#x27;</span> }; <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(<span class="hljs-string">&#x27;data&#x27;</span>, <span class="hljs-literal">null</span>); <span class="hljs-comment">// Start with no data</span> <span class="hljs-keyword">await</span> <span class="hljs-title function_">render</span>(</span>hbs`<span class="language-glimmer"><span class="hljs-tag">&lt;<span class="hljs-title">MyComponent</span> <span class="hljs-punctuation">@</span><span class="hljs-params">loadingTask</span><span class="hljs-operator">=</span> <span class="hljs-punctuation">@</span><span class="hljs-params">data</span><span class="hljs-operator">=</span> /&gt;</span>`</span><span class="language-_js-in-gjs">); mockedTask.<span class="hljs-title function_">finishTask</span>(data); <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(<span class="hljs-string">&#x27;data&#x27;</span>, data); <span class="hljs-comment">// Set the data after we declare loading done above</span> <span class="hljs-keyword">await</span> <span class="hljs-title function_">waitFor</span>(<span class="hljs-string">&#x27;#loadingspinner&#x27;</span>), { <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }); assert.<span class="hljs-title function_">dom</span>(<span class="hljs-string">&#x27;#loadingspinner&#x27;</span>).<span class="hljs-title function_">doesNotExist</span>(); assert.<span class="hljs-title function_">dom</span>(<span class="hljs-string">&#x27;#datacontainer&#x27;</span>).<span class="hljs-title function_">hasText</span>(<span class="hljs-string">&#x27;bar&#x27;</span>); }); </span><span class="hljs-language-icon">js</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="where-do-we-go-from-here%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-integration-mocked-tasks/#where-do-we-go-from-here%3F">Where do we go from here?</a></h3> <p class="mb-4 text-text leading-7">This helper is just the beginning of an idea that could be easily extended. There are likely improvements where the data returned from <code>finishTask</code> can be returned more intelligently into an assignment or even to set up the data itself.</p> <p class="mb-4 text-text leading-7">We could even handle <code>reject</code> cases for failure testing with some minor adjustments.</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// tests/helpers/concurrency.js</span> ... <span class="hljs-keyword">let</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> { <span class="hljs-variable language_">this</span>.<span class="hljs-property">finishTask</span> = resolve; <span class="hljs-variable language_">this</span>.<span class="hljs-property">rejectTask</span> = reject; }); <span class="hljs-comment">// tests/integration/my-component-test.js</span> <span class="hljs-title function_">test</span>(<span class="hljs-string">&#x27;Handles failures&#x27;</span>, <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span>(<span class="hljs-params">assert</span>) { ... mockedTask.<span class="hljs-title function_">rejectTask</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&#x27;Uhoh!&#x27;</span>)) assert.<span class="hljs-title function_">dom</span>(<span class="hljs-string">&#x27;#error&#x27;</span>).<span class="hljs-title function_">hasText</span>(<span class="hljs-string">&#x27;Ouchies!&#x27;</span>); }); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">Throw some async test helpers into your app while writing your next async component and let’s see what we can come up with!</p> Thu, 19 Dec 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-integration-mocked-tasks/ Speaking at Ember Conf 2020! https://gaiety.me/blog/ember-conf-2020-acceptance/ <p class="mb-4 text-text leading-7">A11y First, and Everyone Wins is a talk I’ve given at numerous meetups and I’m proud to announce that I’ve been selected to present this topic at Ember Conf 2020!</p> <p class="mb-4 text-text leading-7">I’ll update this post when more information is available on the website.</p> <hr> <h2 class="text-3xl mt-6 text-text" id="abstract" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-conf-2020-acceptance/#abstract">Abstract</a></h2> <p class="mb-4 text-text leading-7">By putting accessibility first we can achieve a far more composable, intuitive, and testable product.</p> <p class="mb-4 text-text leading-7">Come and listen to the real tale of modern automation testing the untestable: a drag and drop user interface. The story of a drag and drop feature doomed to be unaccessible, made accessible. The telling of a feature salvaged by accessibility.</p> <p class="mb-4 text-text leading-7">We’ve all been told accessibility is important, but rarely do we feel the fruits of the labor directly. We’ll discuss how developers, QA and leads can all feel the same benefit our users feel by putting accessibility first.</p> <h2 class="text-3xl mt-6 text-text" id="intended-audience" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-conf-2020-acceptance/#intended-audience">Intended Audience</a></h2> <p class="mb-4 text-text leading-7">Those who on the surface understand the need for accessibility, but haven’t been sold a compelling success story yet.</p> <h2 class="text-3xl mt-6 text-text" id="outline" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-conf-2020-acceptance/#outline">Outline</a></h2> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Intro <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Title Slide</li> <li class="text-subtext0">Who am I, Why am I here</li> <li class="text-subtext0">Ice Breaker - “Who’s the world’s largest minority?” - People with Disabilities</li> <li class="text-subtext0">Pitch: Composable, Intuitive &amp; Testability through Accessibility</li> <li class="text-subtext0">What we’ll discuss: A Project Feature Saved by A11y (Drag &amp; Drop, A11y Research / Wrapper Components, Testing)</li> </ul> </li> <li class="text-subtext0">Set the Stage <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Project Goals</li> <li class="text-subtext0">Mouse Drag &amp; Drop</li> <li class="text-subtext0">Touch Drag &amp; Drop</li> <li class="text-subtext0">Keyboard Reordering</li> <li class="text-subtext0">Initial Designs</li> <li class="text-subtext0">How it was Done</li> <li class="text-subtext0">A11y Research - W3C Sortable Lists Pattern, Aria Roles <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Component Structure - ember-sortable &amp; accessibility wrappers</li> </ul> </li> <li class="text-subtext0">Living Styleguide to Spike the work</li> <li class="text-subtext0">Automated Tests <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">ember-native-dom-helpers (testing unification RFC #119)</li> <li class="text-subtext0">KeyboardEvent.key Triggers</li> <li class="text-subtext0">Async / Await</li> </ul> </li> <li class="text-subtext0">Example test using all of the above</li> </ul> </li> <li class="text-subtext0">Results &amp; Value Explained <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">A11y allowed us to automated test reordering!</li> <li class="text-subtext0">Spiking allowed for a quick feedback loop (with design, with PM’s)</li> <li class="text-subtext0">Sign off for UX</li> <li class="text-subtext0">Less stress on QA</li> <li class="text-subtext0">Less scope creep</li> <li class="text-subtext0">Demo of final results</li> </ul> </li> <li class="text-subtext0">Conclusion <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">A11y first allowed for a more composable, more discoverable and a testable solution</li> <li class="text-subtext0">Better UX</li> <li class="text-subtext0">Shipping with confidence</li> <li class="text-subtext0">What can YOU do right now to continue the conversation?</li> <li class="text-subtext0">Integrate tooling like ember-a11y</li> <li class="text-subtext0">Make A11y a priority</li> <li class="text-subtext0">Talk about #a11y</li> </ul> </li> </ul> <h2 class="text-3xl mt-6 text-text" id="pitch" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/ember-conf-2020-acceptance/#pitch">Pitch</a></h2> <p class="mb-4 text-text leading-7">This is a success story in a living product powered by bleeding edge Ember that makes the impossible look easy. By putting users and accessibility first I’m truly proud what we shipped. We essentially managed to write automated tests Drag &amp; Drop, a known difficult problem to solve, in an elegant way. We composed accessible wrapper components around community created ember addons for a lasting solution that’s good for developers and users alike.</p> <p class="mb-4 text-text leading-7">I’ve worked on five enterprise scale ember apps over the past five years. From teams large to small, apps in beta or with a large user base, from Ember v1.10 to the latest v3.x I’ve seen the community grow over time. This is a story truly worth telling to inspire Ember devs new and experienced alike. Everything pitched in the talk is achievable while encouraging further community involvement to build better apps for our users.</p> Tue, 17 Dec 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ember-conf-2020-acceptance/ Software Engineer @ Allovue https://gaiety.me/blog/allovue/ <p class="mb-4 text-text leading-7">Empowering educators to strategically and equitably allocate resources to best support the needs of students. We’re building budgeting software to give school districts the tools they need to give educators the tools they need.</p> <p class="mb-4 text-text leading-7">Along with a talented team we’re developing an ambitious EmberJS app using the latest web standards. <a href="https://allovue.com/about/team" class="link">I’m so proud to be here!</a></p> <p class="mb-4 text-text leading-7"><a href="https://allovue.com/" class="link">Learn more about Allovue here</a></p> Sun, 20 Oct 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/allovue/ Coming Out Again - Ava [She/Her] https://gaiety.me/blog/trans-female/ <p class="mb-4 text-text leading-7">It seems like not all that long ago that I came out as <a href="https://gaiety.me/coming-out-again-nb" class="link">Non-binary</a>, but here we go again! I’m excited to announce I’ve come out as a transgendered woman She/Her and will now be going by Ava Gaiety W.</p> <p class="mb-4 text-text leading-7">Legal name changes to come soon, along with HRT. Fingers crossed, wish me luck! Any old work with the name Jo or Joe Wroten is still my own work despite being under my dead name.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green"><a href="https://en.wikipedia.org/wiki/National_Coming_Out_Day" class="link">It’s national coming out day!</a></em></p> Fri, 11 Oct 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/trans-female/ Proud Home Owner https://gaiety.me/blog/home-owner/ <p class="mb-4 text-text leading-7">Life is kind of nuts right now, hopefully more on this later. Just know I’m so very excited!</p> <p class="mb-4 text-text leading-7">Many plans… not the least of which is hosting many more board game nights, D&amp;D, food gatherings and more.</p> Thu, 10 Oct 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/home-owner/ Ultimate Dungeon Terrain https://gaiety.me/blog/ultimate-dungeon-terrain/ <p class="mb-4 text-text leading-7">We’ll be running dungeons. Lots of dungeons.</p> <p class="mb-4 text-text leading-7">Theater of the mind can get tricky when there are three new doors at every intersection and 3D printed interlocking dungeont tiles are a lot to deal with and paint. Luckily I’ve been introduced to <a href="https://www.youtube.com/channel/UCD6ERRdXrF2IZ0R888G8PQg" class="link">Dungeon Craft</a>’s <a href="https://www.youtube.com/watch?v=dQqhTiE7i84" class="link">Ultimate Dungeon Terrain</a> crafting tutorial.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/ultimate-dungeon-terrain-1.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">It all starts with some insullation foam, a lazy susan and some patience. Soon enough you’ll have a rotatable battlefield with implied walls that doesn’t obstruct the view from your players. This setup really allows players to focus in on the important elements of an encounter.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/ultimate-dungeon-terrain-2.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I’m pretty psyched to see this used in a game soon.</p> Wed, 07 Aug 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/ultimate-dungeon-terrain/ Rockin' Ubuntu For Work, New Dotfiles https://gaiety.me/blog/rockin-ubuntu-for-work-new-dotfiles/ <p class="mb-4 text-text leading-7">I recently <a href="https://gaiety.life/moving-on-from-q2" class="link">said goodbye to my job of three and a half years as a Developer III at Q2</a> where I teased exciting things upcoming in the near future.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">More news on the job itself soon, but for now let’s talk tech!</em></p> <h2 class="text-3xl mt-6 text-text" id="the-laptop" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rockin-ubuntu-for-work-new-dotfiles/#the-laptop">The Laptop</a></h2> <p class="mb-4 text-text leading-7">I’ve fallen in love with this <strong class="font-normal text-peach dark:text-yellow">Dell XPS 13 9380</strong> with a 4k touch display and 16GB of ram shipped running Ubuntu out of the box. Coming soon are new home-office pieces such as monitors, arms, and a new desk which I’ll be sure to post about when they arrive.</p> <p class="mb-4 text-text leading-7">It came in Silver with a big Dell logo on the back before I got my hands on it, I’ve used some <strong class="font-normal text-peach dark:text-yellow">vehicle interrior Adhesive Wrap by StyleTECH</strong> trimmed with an x-acto knife to achieve the carbon fiber look and cover up the logo. A major benefit, besides the beautiful aesthetic, are I can add stickers as I please to the laptop without fear of ruining the laptop itself.</p> <p class="mb-4 text-text leading-7">The stickers are primarily from Redbubble as now many tech companies actually sell stickers directly - although I hope to add a DuckDuckGo official logo soon.</p> <h2 class="text-3xl mt-6 text-text" id="the-dotfiles-%2F-config" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/rockin-ubuntu-for-work-new-dotfiles/#the-dotfiles-%2F-config">The Dotfiles / Config</a></h2> <p class="mb-4 text-text leading-7">My <a href="https://gitlab.com/gaiety/dotfiles" class="link">2019 Dotfiles</a> are fresh and made just for this build codenamed: <em class="italic text-green">Space Octopus</em>. At a glance these dotfiles use <a href="https://hyper.is/" class="link"><strong class="font-normal text-peach dark:text-yellow">Hyper</strong></a> terminal, <a href="https://ohmyz.sh/" class="link"><strong class="font-normal text-peach dark:text-yellow">Zsh (and Oh-My-Zsh)</strong></a> shell, <a href="https://github.com/i-tu/Hasklig/" class="link"><strong class="font-normal text-peach dark:text-yellow">Hasklig</strong></a> font, <a href="https://github.com/ggreer/the_silver_searcher" class="link"><strong class="font-normal text-peach dark:text-yellow">Ag</strong></a> searching, <a href="https://github.com/junegunn/fzf" class="link"><strong class="font-normal text-peach dark:text-yellow">Fzf</strong></a> fuzzy-finding and <a href="https://neovim.io/" class="link"><strong class="font-normal text-peach dark:text-yellow">NeoVim</strong></a> as the primary editor.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/screenshot-from-2019-08-03-15-48-25.png" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I’m still on the lookup for a nice Window Tiler and tree browsing solution. We’ll see!</p> <p class="mb-4 text-text leading-7">I’ve also done a fair amount of <a href="https://github.com/GNOME/gnome-tweaks" class="link">Gnome Tweaks</a> and <a href="https://itsfoss.com/gnome-shell-extensions/" class="link">Shell Tweaks</a> including <a href="https://extensions.gnome.org/extension/1160/dash-to-panel/" class="link">Dash to Panel</a> and the <a href="https://www.pling.com/p/1214931" class="link">Flat Remix GTK shell theme</a>.</p> Sat, 03 Aug 2019 20:44:08 GMT Ava Gaiety W. https://gaiety.me/blog/rockin-ubuntu-for-work-new-dotfiles/ Moving on from Q2 https://gaiety.me/blog/moving-on-from-q2/ <p class="mb-4 text-text leading-7">It’s been quite a ride. Three and a half years at Q2. Years filled with running internal developer conferences and public development meetups. Years filled with being a mentee to many talented Ember developers and being a mentor myself. Years filled with open source and excitedly doing side projects.</p> <p class="mb-4 text-text leading-7">But all good things come to an end, or at least… they do when you have bright futures ahead! I’m truly excited for what’s coming up in my future, things that I’ll be posting here soon. I’ll be pushing my career to the next level within the next few weeks and I’ll be excited to talk all about it.</p> <p class="mb-4 text-text leading-7">For now, know that things are superb. I’ll miss all those I worked with at Q2 and yet I’m so ready for the next step in my career. Much love &lt;3</p> Fri, 02 Aug 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/moving-on-from-q2/ Metal Skies https://gaiety.me/blog/metal-skies/ <p class="mb-4 text-text leading-7">Excitedly picked up some aluminum art supplies from a local shop in Austin (<a href="https://www.jerrysretailstores.com/austin-tx/" class="link">Jerry’s Artarama</a>) and after a few months of them sitting in a corner, this is what came of it! I’m quite proud of it. This will be added to <a href="https://gaiety.gallery/" class="link">the art gallery</a>, possibly in higher quality later.</p> Sun, 28 Jul 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/metal-skies/ Three Years at Q2 https://gaiety.me/blog/three-years-at-q2/ <p class="mb-4 text-text leading-7">Six teams, seven managers, four-ish products, and more variety in EmberJS versions than I can even recall.</p> <p class="mb-4 text-text leading-7">It’s been quite a ride building out features, fixing bugs, driving innovation and being a part of so many teams. I’m most proud of my push for bettering documentation and automation testing within the company.</p> <p class="mb-4 text-text leading-7">A huge thanks to some of my biggest mentors I’ve been lucky to work with including, but not limited too; Toran Billups, Bill Heaton, Chase McCarthy and Jeffery Biles.</p> <p class="mb-4 text-text leading-7">For a glance into the kind of work I’ve done, <a href="https://gaiety.me/work/q2/" class="link">visit my Portfolio</a>.</p> Thu, 11 Jul 2019 13:32:53 GMT Ava Gaiety W. https://gaiety.me/blog/three-years-at-q2/ Using JS Set's to Find Elements https://gaiety.me/blog/using-js-sets-to-find-elements/ <p class="mb-4 text-text leading-7">Functionally for one check, this is identical to checking the <code>.indexOf()</code> or <code>.includes()</code> of an Array. However, in cases where you’re filtering a large array down to match a list of ID’s, for example, the nested looping can result in a performance hit.</p> <p class="mb-4 text-text leading-7">Traditionally hash tables were used for speeding up this search, but with ES2015 we can now leverage Sets which are easier to read and still result in a single loop that’s equal to the length of the Array and no more.</p> <p class="mb-4 text-text leading-7">(Can be further optimized by ending when running out of needles)</p> <pre><code class="language-js"><span class="language-_js-in-gjs"><span class="hljs-comment">// Example Data</span> <span class="hljs-keyword">let</span> hugeArray = [...<span class="hljs-title class_">Array</span>(<span class="hljs-number">10000</span>).<span class="hljs-title function_">keys</span>()].<span class="hljs-title function_">map</span>(<span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> { <span class="hljs-keyword">return</span> {id}; }); <span class="hljs-comment">// [{id: 0}, ..., {id: 9999}]</span> <span class="hljs-keyword">let</span> needles = [<span class="hljs-number">1010</span>, <span class="hljs-number">2020</span>, <span class="hljs-number">3030</span>, <span class="hljs-number">4040</span>, <span class="hljs-number">5050</span>, <span class="hljs-number">6060</span>, <span class="hljs-number">7070</span>, <span class="hljs-number">8080</span>, <span class="hljs-number">9090</span>]; <span class="hljs-comment">// Finding matching elements</span> <span class="hljs-keyword">let</span> needlesSet = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Set</span>(needles); <span class="hljs-keyword">let</span> matches = hugeArray.<span class="hljs-title function_">filter</span>(<span class="hljs-function"><span class="hljs-params">obj</span> =&gt;</span> needlesSet.<span class="hljs-title function_">has</span>(obj.<span class="hljs-property">id</span>)); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7"><a href="https://gitlab.com/snippets/1873655" class="link">https://gitlab.com/snippets/1873655</a></p> Tue, 09 Jul 2019 20:27:09 GMT Ava Gaiety W. https://gaiety.me/blog/using-js-sets-to-find-elements/ Coming Out Again - NB https://gaiety.me/blog/coming-out-again-nb/ <p class="mb-4 text-text leading-7">Today marks a week of wearing breasts forms and a bra during nearly all waking hours. The experience has been truly unbelievable to me… It’s something I never knew I needed, yet I’ve always known in a way.</p> <p class="mb-4 text-text leading-7">But, wait you may be thinking. Doesn’t that mean you’re transitioning towards becoming a trans-woman? Well, yes and no. This does hit many of the checkboxes for a transition, but I have been gender-fluid with an androgynous aesthetic for a long time.</p> <p class="mb-4 text-text leading-7">To me, this is the next step to androgyny. A step I’ve decided, with the support of my loved ones, paints me as being ready to embrace non-binary and what that means to me.</p> <p class="mb-4 text-text leading-7">Ive just returned from DinosaurJS, a conference in Denver CO, where I proudly dressed in exclusively women’s clothing with these breasts forms in public for the entire duration of the trip. I sported the conference’s They/Them pronoun badge proudly.</p> Sat, 22 Jun 2019 19:28:53 GMT Ava Gaiety W. https://gaiety.me/blog/coming-out-again-nb/ Barbarian of Cold https://gaiety.me/blog/generic-barbarian-mini/ <p class="mb-4 text-text leading-7">Implemented some drybrushing techniques and some experiments with washes. Plenty of room to improve but I’m stoked to have painted something that looks like you could buy in a store!</p> Mon, 10 Jun 2019 18:35:00 GMT Ava Gaiety W. https://gaiety.me/blog/generic-barbarian-mini/ Donating a Painting: Art Erotica 2019 https://gaiety.me/blog/donating-a-painting-art-erotica-2019/ <p class="mb-4 text-text leading-7"><a href="http://octopusclub.org/event/arterotica-2019/" class="link">Art Erotica 2019</a> is an annual donation-based art auction with adult themes where “100% of the money spent at the event will go directly to this fund, which assists our friends and neighbors living with HIV and AIDS in times of crisis, helping them to pay for food, rent, utilities, eyeglasses, and even medicine not covered by Medicaid.”.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/20190518_204935.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I visited in 2018 and set a goal for myself to produce and donate art for 2019. I’m very pleased to say I met that goal! The pieces were auctioned off for a good cause. I’m looking forward to putting more of my art out in the world soon.</p> Sun, 19 May 2019 23:19:03 GMT Ava Gaiety W. https://gaiety.me/blog/donating-a-painting-art-erotica-2019/ Life Training: Gun Retention Course https://gaiety.me/blog/life-training-gun-retention-course/ <p class="mb-4 text-text leading-7">Austin’s <a href="http://lionskravmaga.com/" class="link">Lions Krav Maga</a> gym hosted a highly recommended gun retention course. Being that this is TX and self defense is important, especially for queer folx, I couldn’t pass up on this opportunity.</p> <p class="mb-4 text-text leading-7">In short summary, the final drill involved working yourself to the point of exhaustion before executing a difficult shooting section involving accuracy, patience, and thinking on your feet. I learned many skills beyond simply how to handle a firearm in this class. Such growth!</p> Sun, 12 May 2019 23:26:43 GMT Ava Gaiety W. https://gaiety.me/blog/life-training-gun-retention-course/ Batch of Kobolds! https://gaiety.me/blog/batch-of-kobolds/ <p class="mb-4 text-text leading-7">I can paint monsters however I want, yeah? Great! Can’t tell I made mistakes on these critters because it’s my world and I make the rules &gt;:3</p> <p class="mb-4 text-text leading-7">But, for real, it was a blast to paint this batch of mischievous critters. Primarily I learned how to efficiently spread my paint between several minis simultaniously so as not to waste much paint.</p> Fri, 03 May 2019 23:32:11 GMT Ava Gaiety W. https://gaiety.me/blog/batch-of-kobolds/ Final Improv Show(?) https://gaiety.me/blog/final-improv-show/ <p class="mb-4 text-text leading-7">Had my last improv show as a performer for the foreseeable future. Was an absolute blast and who knows, maybe after a long break I’ll return to the stage again :) I grew so much along the way</p> Mon, 08 Apr 2019 23:35:11 GMT Ava Gaiety W. https://gaiety.me/blog/final-improv-show/ Austin Givecamp 2019 https://gaiety.me/blog/austin-givecamp-2019/ <p class="mb-4 text-text leading-7">Had a productive weekend with the lovely folks at <a href="https://www.austingivecamp.org/" class="link">Austin Givecamp</a> rebuilding the Stronger Than DIPG site! <a href="https://strongerthandipg.org/" class="link">https://strongerthandipg.org/</a></p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/55945322_2468898896480609_27218586202284231_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Mon, 01 Apr 2019 01:30:47 GMT Ava Gaiety W. https://gaiety.me/blog/austin-givecamp-2019/ Coming Out Again - Poly https://gaiety.me/blog/coming-out-again-poly/ <p class="mb-4 text-text leading-7">In improv we have a guideline to positive scene work, “Happy, Healthy, Sexy”! I’m starting to apply that to so much more.</p> <p class="mb-4 text-text leading-7">I’ve been in polyamorous relationships previously, though I never spoke much of it or looked into it deeply. For the first time I’m learning what I love in the healthiest relationships I’ve had and all signs point to this: sharing love, respect, consent, adult conversations and owning the term Polyamorous.</p> Wed, 27 Feb 2019 01:56:25 GMT Ava Gaiety W. https://gaiety.me/blog/coming-out-again-poly/ Owning Your Identity - Nickname Change https://gaiety.me/blog/owning-your-identity-nickname-change/ <p class="mb-4 text-text leading-7">As I continue to embrace my queer identity I made the decision to publicly replace my nickname from Joe to Jo. A single letter drop, but it’s difficult to express how much this means to me on the inside. Lessening the masculinity associated with my given-name while still showing respect to my family is a major milestone.</p> <p class="mb-4 text-text leading-7">Jo is a name I can own. I’ve smiled every time I’ve seen it written without the “e”. This is me. It feels so right.</p> Tue, 26 Feb 2019 02:33:23 GMT Ava Gaiety W. https://gaiety.me/blog/owning-your-identity-nickname-change/ Best Improv Performance Yet! https://gaiety.me/blog/best-improv-performance-yet/ <p class="mb-4 text-text leading-7">It’s difficult to put into words just how great this improv show was. Take my word for it and watch it here! <a href="https://www.twitch.tv/videos/391582582?filter=highlights&amp;sort=time" class="link">https://www.twitch.tv/videos/391582582?filter=highlights&amp;sort=time</a></p> Mon, 25 Feb 2019 02:14:25 GMT Ava Gaiety W. https://gaiety.me/blog/best-improv-performance-yet/ Bare Metal Tooling https://gaiety.me/blog/bare-metal-tooling/ <h1 class="text-6xl mt-6 text-pink" id="getting-to-know-your-tools" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/bare-metal-tooling/#getting-to-know-your-tools">Getting to Know Your Tools</a></h1> <p class="mb-4 text-text leading-7">I’m obsessive over my dotfiles. They’re in such a constant state of flux I’m never sure how to self document them. This was a sign. This lead me down a path to better understanding the bare-metal of my chosen tooling to increase my tooling competence.</p> <p class="mb-4 text-text leading-7">A sign that in my continous search for the best tooling plugins, perhaps <em class="italic text-green">the core problem was I didn’t know my tools well enough</em>. Ever struggled to remember what your custom Tmux bindings were? Why did I change them anyway… maybe the default <code>ctrl + b</code> bindings aren’t so bad after all.</p> <p class="mb-4 text-text leading-7">Recently I was looking to add a commenter plugin to Vim only to stumble across <a href="https://stackoverflow.com/questions/1676632/whats-a-quick-way-to-comment-uncomment-lines-in-vim/1676690#1676690%3CPaste%3E" class="link">this stack overflow result with nearly 2k upvotes</a> using zero plugins or configuration.</p> <figure class="inline-block mb-4"><img src="https://i.stack.imgur.com/lu6aU.gif" alt="Comment" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://i.stack.imgur.com/2Y7eH.gif" alt="Uncomment" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I’ll say that again. <em class="italic text-green">Zero plugins or configuration</em>, just knowing instead how to leverage <code>ctrl + v</code> to vertically select in Vim followed by a <code>shift + i</code> to insert or <code>x</code> to delete.</p> <p class="mb-4 text-text leading-7">The same goes for navigation trees. Most new Vim users, including myself, immediately jump to <a href="https://github.com/scrooloose/nerdtree" class="link">NERDtree</a> or similar plugins and then proceed to learn how they work. Instead, we could just <a href="https://blog.stevenocchipinti.com/2016/12/28/using-netrw-instead-of-nerdtree-for-vim/" class="link">leverage netrw</a> or perhaps <a href="https://shapeshed.com/vim-netrw/" class="link">use neither</a>.</p> <hr> <p class="mb-4 text-text leading-7">My dotfiles are still constantly in flux. Though, every iteration it manages to get smaller. I’m increasingly leveraging the raw power of the cores of my chosen tooling (Fish, Tmux and Vim) rather than stacking up a pile of new plugins every few weeks. Learning the bare-metal of your tools can drastically boost tooling competence.</p> Wed, 30 Jan 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/bare-metal-tooling/ On Web Components https://gaiety.me/blog/web-components/ <p class="mb-4 text-text leading-7">Components were designed to share reusable code within a project. Sometimes between projects. But, what if a projects’ base technology is fundamentally different (Ember, React, Vue)? <strong class="font-normal text-peach dark:text-yellow">Luckily all web apps speak Javascript and the DOM which is where native web components come in.</strong></p> <h2 class="text-3xl mt-6 text-text" id="hybrids-(web-component-framework)" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#hybrids-(web-component-framework)">Hybrids (Web Component Framework)</a></h2> <figure class="inline-block mb-4"><img src="https://raw.githubusercontent.com/hybridsjs/hybrids/master/docs/assets/hybrids-logo.svg?sanitize=true" alt="Hybrids Logo" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Frameworks serve the purpose of <strong class="font-normal text-peach dark:text-yellow">abstracting away browser inconsistencies</strong>, providing a <strong class="font-normal text-peach dark:text-yellow">richer API for development</strong> and tools for <strong class="font-normal text-peach dark:text-yellow">automation testing</strong>. <a href="https://hybrids.js.org/" class="link">Hybrids</a> accomplishes all this in a small 19.6kb (6.3kb gzipped) plus some for browser compatibility.</p> <figure class="inline-block mb-4"><img src="https://saucelabs.com/browser-matrix/hybrids.svg" alt="Hybrids Browser Support" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <h2 class="text-3xl mt-6 text-text" id="polyfills-(browser-support)" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#polyfills-(browser-support)">Polyfills (Browser support)</a></h2> <p class="mb-4 text-text leading-7">To achieve this level of browser support with a modern web standard such as web components a polyfill. There are additional challenges such as CSS scoping that are essential for true web components. Hybrids integrates conditional shims and polyfills to handle this as best as it can.</p> <h2 class="text-3xl mt-6 text-text" id="testing-(automation)" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#testing-(automation)">Testing (Automation)</a></h2> <p class="mb-4 text-text leading-7">I’ve found leveraging Hybrids, Karma and Jasmine can lead to some really clean automation tests. Hybrids offers an importable <code>html</code> helpers, which is the same helper it uses under the hood for its own testing and base functionality. So long as you pay close attention to when you need to target a <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/shadowRoot" class="link">shadowRoot</a> rendering tests become easy with standard DOM methods to manipulate and access the details of your component.</p> <pre><code class="language-javascript"><span class="language-_js-in-gjs"><span class="hljs-title function_">it</span>(<span class="hljs-string">&#x27;renders logo with src and alt&#x27;</span>, <span class="hljs-function">() =&gt;</span> { <span class="hljs-keyword">return</span> <span class="hljs-title function_">renderComponent</span>(html`<span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">my-component</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-component</span>&gt;</span>`</span>).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">component</span> =&gt;</span> { <span class="hljs-keyword">let</span> img = component.<span class="hljs-property">shadowRoot</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&#x27;[data-test-id=componentImg]&#x27;</span>) <span class="hljs-title function_">expect</span>(img.<span class="hljs-title function_">getAttribute</span>(<span class="hljs-string">&#x27;src&#x27;</span>)).<span class="hljs-title function_">toEqual</span>(<span class="hljs-string">&#x27;foo.png&#x27;</span>) <span class="hljs-title function_">expect</span>(img.<span class="hljs-title function_">getAttribute</span>(<span class="hljs-string">&#x27;alt&#x27;</span>)).<span class="hljs-title function_">toEqual</span>(<span class="hljs-string">&#x27;foo&#x27;</span>) }) }) </span><span class="hljs-language-icon">javascript</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="bundling" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#bundling">Bundling</a></h2> <h3 class="text-2xl mt-4 text-text" id="parcel" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#parcel">Parcel</a></h3> <p class="mb-4 text-text leading-7">Initially I had great success bundling together Hybrids with <a href="https://parceljs.org/" class="link">Parcel</a>. It was as simple as pointing parcel to my html index.</p> <p class="mb-4 text-text leading-7">However, Parcel is built for websites rather than consumable libraries. Thus I moved on to Webpack.</p> <h3 class="text-2xl mt-4 text-text" id="webpack" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#webpack">Webpack</a></h3> <p class="mb-4 text-text leading-7">Assuming you have a <code>src/index.js</code> file that imports a component it’s pretty simple to get started. I unfortunately cannot include a reference to the closed source repository here but it should get the idea across for a base webpack configuration. This config also supports JS files that <a href="https://hybrids.js.org/template-engine/styling#css-stylesheet" class="link">importing CSS into components which Hybrids supports</a>.</p> <pre><code class="language-javascript"><span class="language-_js-in-gjs"><span class="hljs-comment">// ./webpack.config.js</span> <span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;path&#x27;</span>); <span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = <span class="hljs-keyword">function</span>(<span class="hljs-params">env, argv</span>) { <span class="hljs-keyword">return</span> { <span class="hljs-attr">context</span>: path.<span class="hljs-title function_">resolve</span>(__dirname), <span class="hljs-attr">entry</span>: path.<span class="hljs-title function_">resolve</span>(__dirname, <span class="hljs-string">&#x27;src/index.js&#x27;</span>), <span class="hljs-attr">output</span>: { <span class="hljs-attr">path</span>: path.<span class="hljs-title function_">resolve</span>(__dirname, <span class="hljs-string">&#x27;dist&#x27;</span>), <span class="hljs-attr">filename</span>: argv.<span class="hljs-property">mode</span> === <span class="hljs-string">&#x27;test&#x27;</span> ? <span class="hljs-string">&#x27;[name].js&#x27;</span> : <span class="hljs-string">&#x27;index.js&#x27;</span>, }, <span class="hljs-attr">module</span>: { <span class="hljs-attr">rules</span>: [ { <span class="hljs-comment">// Inline/Component CSS</span> <span class="hljs-attr">test</span>: <span class="hljs-regexp">/\.css$/</span>, <span class="hljs-attr">use</span>: [ <span class="hljs-string">&quot;css-loader&quot;</span> ], }, { <span class="hljs-comment">// Javascript</span> <span class="hljs-attr">test</span>: <span class="hljs-regexp">/\.m?js$/</span>, <span class="hljs-attr">exclude</span>: <span class="hljs-regexp">/(node_modules)/</span>, <span class="hljs-attr">use</span>: { <span class="hljs-attr">loader</span>: <span class="hljs-string">&#x27;babel-loader&#x27;</span>, <span class="hljs-attr">options</span>: { <span class="hljs-attr">presets</span>: [ [ <span class="hljs-string">&#x27;@babel/preset-env&#x27;</span>, { <span class="hljs-attr">modules</span>: <span class="hljs-literal">false</span> } ] ] } } } ] }, }; }; </span><span class="hljs-language-icon">javascript</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="component-structure" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/web-components/#component-structure">Component Structure</a></h2> <p class="mb-4 text-text leading-7">Finally, I landed on the this project structure which I hope you may be inspired by if you follow in these footsteps.</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">src <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">components <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">component-name <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">index.js</li> <li class="text-subtext0">view.js</li> <li class="text-subtext0">test.js</li> <li class="text-subtext0">style.css</li> </ul> </li> </ul> </li> </ul> </li> </ul> <hr> <p class="mb-4 text-text leading-7">Wish I could post the full project here and go into more detail. Even still, I hope this serves as a guiding light for those interested in exploring web components in their next project.</p> Wed, 23 Jan 2019 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/web-components/ A Furry For Good https://gaiety.me/blog/a-furry-for-good/ <p class="mb-4 text-text leading-7">Q2 collaborated with the Austin Humane Society to host a Pup Pub Crawl! And that just wouldn’t be complete without a pup, so I volunteered to make some people smile.</p> Sun, 06 Jan 2019 02:38:11 GMT Ava Gaiety W. https://gaiety.me/blog/a-furry-for-good/ Catjingle 5k - A First! https://gaiety.me/blog/catjingle-5k-a-first/ <p class="mb-4 text-text leading-7">Such a rewarding experience! A lot of hard work has paid off, now for the next goal! Which I haven’t decided yet… :)</p> Sun, 16 Dec 2018 02:22:33 GMT Ava Gaiety W. https://gaiety.me/blog/catjingle-5k-a-first/ Code2College Volunteering - Resume Prep https://gaiety.me/blog/code2college-volunteering-resume-prep/ <p class="mb-4 text-text leading-7">Volunteering with Code2College has been very worthwhile! They let Hopper help out too :D</p> <p class="mb-4 text-text leading-7">This time I assisted with some resume reviewing and representing Q2 as the event space host.</p> <p class="mb-4 text-text leading-7">They’re often doing events for interview/resume prep or curriculum development. It’s easy to get into, check them out! <a href="https://code2college.org/" class="link">https://code2college.org/</a></p> Thu, 13 Dec 2018 02:24:23 GMT Ava Gaiety W. https://gaiety.me/blog/code2college-volunteering-resume-prep/ Galaxy Painting Series https://gaiety.me/blog/galaxy-painting-series/ <p class="mb-4 text-text leading-7">Practice makes perfect! I’m so proud of how these turned out. I’ve been gifting them to interested friends whenever possible.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/46185221_376245772950017_3364527015623058138_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Work held a Holidar Bazaar as well, which I decided to set up shop for to sell some paintings. I managed to make back what I spent in materials, success!</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/45373415_1190109391144790_7494390951586430213_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Sat, 08 Dec 2018 02:47:20 GMT Ava Gaiety W. https://gaiety.me/blog/galaxy-painting-series/ Code2College - Volunteering https://gaiety.me/blog/code2college-volunteering/ <p class="mb-4 text-text leading-7">Hopper and I have been assisting Code2College whenever we can this year! Be it interview practice, resume reviews, or rewriting the HTML/CSS/JS cirriculum. This year there will be a significant section focused around A11y! It’s difficult to express how important it is to teach this early.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/45626728_256318015063519_2481900999093214685_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">I’m so proud of all the volunteers and the work that’s being done.</p> Sun, 02 Dec 2018 02:42:01 GMT Ava Gaiety W. https://gaiety.me/blog/code2college-volunteering/ Learning on Rails https://gaiety.me/blog/learning_on_rails/ <p class="mb-4 text-text leading-7">Learning is an interesting thing. As I grow older I find myself paying far more attention to how I learn. It’s a journey that’s different for everyone.</p> <p class="mb-4 text-text leading-7">These past five years Ember has been my world. Seriously, I just got back from another conference and I’m to speak at a meetup this month on Ember. When I had heard Ember took a <em class="italic text-green">lot</em> of inspiration from Ruby on Rails I never paid it much mind. Now I wonder if learning Ember would have been easier after understanding <a href="https://rubyonrails.org/doctrine/" class="link">The Rails Doctrine</a>. In it are many familiar topics such as <a href="https://rubyonrails.org/doctrine/#convention-over-configuration" class="link">Convention over Configuration</a>, but also a familiar folder structure, CLI tool generators, and smart defaults for things that can be assumed.</p> <p class="mb-4 text-text leading-7">Taking the time to learn Rails has better framed my understanding of the Javascript framework I love by backing up the things I’ve simply memorized with meaningful context. It makes sense that a Controller file in Ember is optional if you don’t need to customize anything about it. Of course generators add to your routes config and automatically wire up some new tests as well. It all just clicks together now in my head.</p> <p class="mb-4 text-text leading-7">I never felt a need to venture outside of my bubble before. But by intentionally doing so, I realized the bubble only harmed by ability to learn rather than protect me in some way. There’s no need to be afraid of learning. You never know just how much it may help you.</p> <p class="mb-4 text-text leading-7">Finally, I encourage you to document and share what you learn. I’ve published <a href="https://gitlab.com/gaiety/hello-learning/-/tree/ruby-on-rails" class="link">my hello world’s in both Ruby and Rails</a> and highly recommend <a href="https://guides.rubyonrails.org/getting_started.html#hello-rails-bang" class="link">rubyonrail.org’s Getting Started guide</a> if you’d like to get started with Rails and learn something fun.</p> Mon, 08 Oct 2018 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/learning_on_rails/ Inktober 2018 https://gaiety.me/blog/inktober-2018/ <p class="mb-4 text-text leading-7">An annual drawing-a-day challenge.</p> <p class="mb-4 text-text leading-7">Alas, I only made it a week in, here’s hoping for next year! I believe I’ve been drawing so much lately that I burned myself out haha…</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/43912960_2228073850849672_5116070514651245546_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Oh little blackwing pencil &lt;3</p> Tue, 02 Oct 2018 01:51:53 GMT Ava Gaiety W. https://gaiety.me/blog/inktober-2018/ Druid Portrait Photoshoot https://gaiety.me/blog/druid-portrait-photoshoot/ <p class="mb-4 text-text leading-7">Shooting on a Nikon D40.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/37273910_2135720836698745_5561856938922213376_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/37107258_488452654914132_758243705508331520_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/37000900_290940591641235_5591772640269303808_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Wed, 25 Jul 2018 01:55:14 GMT Ava Gaiety W. https://gaiety.me/blog/druid-portrait-photoshoot/ Silhouette Spray Paintings https://gaiety.me/blog/silhouette-spray-paintings/ <p class="mb-4 text-text leading-7">A collection of silhouette based spraypaint and acrylic modified paintings on canvas.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/36604241_470185140092036_1593452438981967872_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/33962454_820600254806600_2697107335809073152_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/33535420_232421054011287_4570753369483771904_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/33640303_177006526318900_2640303348187660288_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/36798417_262825467844458_9048405471626526720_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Fri, 22 Jun 2018 02:05:15 GMT Ava Gaiety W. https://gaiety.me/blog/silhouette-spray-paintings/ Minimalist - Spray Paintings https://gaiety.me/blog/minimalist-spray-paintings/ <p class="mb-4 text-text leading-7">Wanted to see what was possible combining the common street painting methods of spray paint with the high brow art of minimalism. These pieces mean a lot to me that are difficult to put into words, so I’ll let them speak for themselves.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/33313387_169404427086397_8094833448134377472_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Sat, 09 Jun 2018 02:02:08 GMT Ava Gaiety W. https://gaiety.me/blog/minimalist-spray-paintings/ Galaxy Paws - Painting https://gaiety.me/blog/galaxy-paws-painting/ <p class="mb-4 text-text leading-7">Spraypaint and Acrylic</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/33210396_191533285005039_9073202817497300992_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Tue, 29 May 2018 02:00:33 GMT Ava Gaiety W. https://gaiety.me/blog/galaxy-paws-painting/ Falling - Spraypaint on Canvas https://gaiety.me/blog/falling-spraypaint-on-canvas/ <p class="mb-4 text-text leading-7">Some process shots:</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/32362960_387427108411768_6724668894218289152_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/32668691_235721763648687_3669037737446473728_n.jpg" alt="" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> Tue, 29 May 2018 01:58:04 GMT Ava Gaiety W. https://gaiety.me/blog/falling-spraypaint-on-canvas/ Non-Ember Things in Ember https://gaiety.me/blog/embers-app-import/ <p class="mb-4 text-text leading-7">The Ember community is great and <a href="https://www.npmjs.com/search?q=ember" class="link">full of great ember-cli friendly addons</a> to add to your project. Using <a href="https://github.com/reactjs/redux" class="link">Redux</a>? Check out <a href="https://www.npmjs.com/package/ember-redux" class="link">ember-redux</a>. Need <a href="https://github.com/ftlabs/fastclick" class="link">FastClick</a>? Check out… well, actually your best bet is <a href="https://www.npmjs.com/package/ember-hammertime" class="link">ember-hammertime</a> but you get the point.</p> <p class="mb-4 text-text leading-7">But <strong class="font-normal text-peach dark:text-yellow">sometimes you just <em class="italic text-green">need</em> to incorporate something that isn’t Ember ready</strong>. Today that’s easier than ever!</p> <h2 class="text-3xl mt-6 text-text" id="show-me" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/embers-app-import/#show-me">Show Me</a></h2> <p class="mb-4 text-text leading-7">In this example we’ll be adding <code>url-polyfill</code> to our Ember app. <em class="italic text-green">I know <code>ember-url</code> is out there but it lacks some of the functionality <code>url-polyfill</code> offers.</em></p> <ol> <li class="text-subtext0"><code>yarn add url-polyfill</code> or <code>npm install --save url-polyfill</code></li> <li class="text-subtext0">In your <code>ember-cli-build.js</code> within the <code>module.exports = function() {</code> add the following…</li> </ol> <pre><code class="language-js"><span class="language-_js-in-gjs">app.<span class="hljs-keyword">import</span>(<span class="hljs-string">&#x27;node_modules/url-polyfill/url-polyfill.js&#x27;</span>); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">You’re done!</p> <p class="mb-4 text-text leading-7">For bonus points, you can even configure which import you use based on the environment…</p> <pre><code class="language-js"><span class="language-_js-in-gjs">app.<span class="hljs-keyword">import</span>({ <span class="hljs-attr">development</span>: <span class="hljs-string">&#x27;PATH/file.js&#x27;</span>, <span class="hljs-attr">production</span>: <span class="hljs-string">&#x27;PATH/file.min.js&#x27;</span>, }); </span><span class="hljs-language-icon">js</span></code></pre> <p class="mb-4 text-text leading-7">This also works with css files to bring in your favorite CSS framework, animation library or other tool. If you’re still using bower, simply point your import path to <code>bower_components/DEPENDENCY/FILE.EXT</code>.</p> <h3 class="text-2xl mt-4 text-text" id="but%2C-wait%2C-i-have-some-setup-i-need-to-do!" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/embers-app-import/#but%2C-wait%2C-i-have-some-setup-i-need-to-do!">But, wait, I have some setup I need to do!</a></h3> <p class="mb-4 text-text leading-7">That’s cool too! An initializer is likely what you’ll want.</p> <pre><code class="language-bash">ember generate initializer myInitializer <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7">Then within there you can run any initialization code your heart desires and it’ll run at app load.</p> <h2 class="text-3xl mt-6 text-text" id="want-to-go-further%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/embers-app-import/#want-to-go-further%3F">Want to go further?</a></h2> <p class="mb-4 text-text leading-7">Make an ember-addon for your favorite tool and publish it on npm! The community would appreciate it and love the easy of an <code>ember install</code>.</p> <p class="mb-4 text-text leading-7">Go make great things. Or… combine great things into an even greater thing!</p> Thu, 26 Apr 2018 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/embers-app-import/ Dev'ing on Linux is Fun! https://gaiety.me/blog/deving_on_linux_is_fun/ <p class="mb-4 text-text leading-7">I <strong class="font-normal text-peach dark:text-yellow">love</strong> playing with my dotfiles. No, really, I could have played video games before bed but here I am up late <em class="italic text-green">again</em> customizing my tooling stack. It’s a weird passion I have. I blame my former mentor <a href="https://github.com/toranb" class="link">Toran Billups</a>, but I digress.</p> <h1 class="text-6xl mt-6 text-pink" id="why-linux%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/deving_on_linux_is_fun/#why-linux%3F">Why Linux?</a></h1> <p class="mb-4 text-text leading-7">In the past six years I’ve bounced between being a web app developer on Windows and MacOS. It should go without saying that Windows has given me numerous struggles, especially in an enterprise software environment.</p> <p class="mb-4 text-text leading-7">Recently we hit a wall. Ember would take over ten minutes to build and the more complicated apps were closer to twenty-five minutes. I’ve been not only throwing away countless development hours watching slow builds and build failures, but worse yet it’s been causing burnout.</p> <p class="mb-4 text-text leading-7">So we flipped the desk. I chose Linux over MacOS because, well, I’d hoped it would be fun and different… it has been!</p> <h2 class="text-3xl mt-6 text-text" id="the-result" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/deving_on_linux_is_fun/#the-result">The Result</a></h2> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/deving_on_linux_is_fun.png" alt="Dracula themed terminal prompt" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7">Put simply, I’m finally able to use the tools that even on MacOS didn’t run well. I was able to refer back to <a href="https://wrotenwrites.com/a_modern_terminal_workflow_1/" class="link">my previous articles on writing dotfiles</a> while making adjustments for the platform, the fact that it’s 2018, and to change things up just a little. I find it beautiful and familiar.</p> <h3 class="text-2xl mt-4 text-text" id="terminal-%E2%80%94-hyper" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/deving_on_linux_is_fun/#terminal-%E2%80%94-hyper">Terminal — Hyper</a></h3> <p class="mb-4 text-text leading-7">I push my terminal a little, but not too hard. As a visual person doing web development, <a href="https://wrotenwrites.com/a_modern_terminal_workflow_1/" class="link">Hyper</a> is perfect for me.</p> <p class="mb-4 text-text leading-7">It feels lightning quick on my linux box and is simply gorgeous with <a href="https://draculatheme.com/hyper/" class="link">dracula theme</a> applied. I followed their “Install using config file” instructions while manually git cloning <a href="https://github.com/dracula/hyper" class="link">the repo</a> for Hyper to find. The configuration is a <code>.js</code> file which is bonus points for me.</p> <h3 class="text-2xl mt-4 text-text" id="shell-%E2%80%94-fish" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/deving_on_linux_is_fun/#shell-%E2%80%94-fish">Shell — Fish</a></h3> <p class="mb-4 text-text leading-7"><a href="https://wrotenwrites.com/a_modern_terminal_workflow_3/" class="link">Previously I recommended using Zsh</a> with a bunch of customizations. Now, I just <a href="https://fishshell.com/" class="link">install Fish</a> which is configured nicely right out of the box.</p> <p class="mb-4 text-text leading-7">An <a href="https://github.com/nesl247/fish-theme-dracula" class="link">unofficial dracula theme</a> is available as well! I kept the prompt it comes with too which is nice.</p> <h3 class="text-2xl mt-4 text-text" id="neovim-and-tmux" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/deving_on_linux_is_fun/#neovim-and-tmux">NeoVim and Tmux</a></h3> <p class="mb-4 text-text leading-7">Overall I’m still rocking the same <a href="https://wrotenwrites.com/a_modern_terminal_workflow_2/" class="link">NeoVim setup</a> and <a href="https://wrotenwrites.com/a_modern_terminal_workflow_4/" class="link">Tmux setup</a> I’ve recommended in the past. Some personal minor adjustments like <code>number relativenumber</code> which is a new favorite vim config of mine, and I’m pretty satisfied with it.</p> Thu, 12 Apr 2018 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/deving_on_linux_is_fun/ Faster Test Suites, Less Code, Embracing Writing Addons. https://gaiety.me/blog/separation-of-concerns-addon/ <p class="mb-4 text-text leading-7">Less code, a faster test suite, and a tighter focus on core functionality can be achieved through embracing open source. <a href="https://www.emberaddons.com/" class="link">Ember addons</a> are on point in delivering such a promise as I’ve learned while open sourcing a widely used <a href="https://github.com/q2ebanking/ember-select-light" class="link">component at work</a>.</p> <p class="mb-4 text-text leading-7">The key is a separation of concerns. Modifying code rebuilds the app and, before shipping, all tests must be verified again regardless of what the modifcations touch. Moving chunks of an app, such as a component, to an open source addon grants all the benefits that come with code isolation. Admittedly similar can be achieved with careful abstraction and no open source, but I feel it’s the right direction for myself and likely others to aim for.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Less code</strong> a developer must retain in their heads the easier they may reason about the way an app flows. A well tested and well documented addon promises a level of functionality not often afforded by yet another file to be debugged within the app. While addon code eventually gets compiled into the final output, I’ve found the act of isolating code into an addon forces me to code more concisely and clearly for public consumption. Without the goal of open sourcing the addon I may cut corners thinking “it’s just for me, no big deal” which can do more harm than good longterm.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Faster test suite</strong> runs, without the cost of coverage, comes isolating tests to separate addon projects. This goes both ways in fact. Tests get removed from the original app and an addon will have just the tests to cover itself resulting in a quick build and test time. Isolated testing concerns can lead to higher relative code coverage and a quicker feedback loop for <a href="https://www.youtube.com/watch?v=2b1vcg_XSR8" class="link">test-driven development</a>.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Tighter focus on core functionality</strong> arises from the need to isolate an addon’s concern to a concise idea. Assigning a name and writing documentation for an addon is a healthy exercise in producing a highly intentional and hopefully valuable addon.</p> <p class="mb-4 text-text leading-7">After becoming no longer afraid of the world of open source I’ve learned to embrace the advantages that come from creating a wide range of projects. Addons are a new and exciting world for me and hopefully for you as well.</p> Fri, 17 Nov 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/separation-of-concerns-addon/ Less Blue Light, Better Sleep https://gaiety.me/blog/less_blue_light_better_sleep/ <p class="mb-4 text-text leading-7">Actively limiting blue light, both artificial and natural, can make you a healthier and happier person. No, really, it can.</p> <figure class="inline-block mb-4"><img src="https://gaiety.me/img/content/less_blue_light_better_sleep.jpg" alt="Blurry Blue Light on Face with Light Leaks" class="max-w-full rounded-lg max-h-600px contrast-more:contrast-50"></figure> <p class="mb-4 text-text leading-7"><cite>Photo by <a href="https://unsplash.com/photos/anhQGEYbnV4?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" class="link">Juil Yoon</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText" class="link">Unsplash</a></cite></p> <p class="mb-4 text-text leading-7">Imagine a workday without eye strain or grogginess. Regaining control over your ability to fall asleep comfortably. With some tweaks to daily habits and reducing blue light intake this can be a reality.</p> <h2 class="text-3xl mt-6 text-text" id="what%3F-why-blue-light%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#what%3F-why-blue-light%3F">What? Why blue light?</a></h2> <p class="mb-4 text-text leading-7">Briefly, the more harmful spectrum of light is within a band of blue light. This narrow band of harmful light contributes the most to eye strain and wakefulness. <a href="http://www.allaboutvision.com/cvs/blue-light.htm" class="link">Learn More</a></p> <h2 class="text-3xl mt-6 text-text" id="on-eye-strain" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#on-eye-strain">On Eye Strain</a></h2> <p class="mb-4 text-text leading-7">Sitting for eight or more hours staring at a screen isn’t what you’re paid for - you’re paid to produce results. You can only achieve that if you’re healthy. Eye strain can lead to headaches and health problems resulting in your eyes degrading slowly over time.</p> <h3 class="text-2xl mt-4 text-text" id="get-up.-move-around." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#get-up.-move-around.">Get up. Move around.</a></h3> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Take a break</strong> from the computer screen. Converse with your colleagues. <strong class="font-normal text-peach dark:text-yellow">Avoid eating lunch at your desk</strong>. While we’re reducing our blue, let’s up our green - <strong class="font-normal text-peach dark:text-yellow">go outside</strong> and see some grass, trees, plants <strong class="font-normal text-peach dark:text-yellow">to feel refreshed and revitalized</strong>. Some time in the sun can help too.</p> <h3 class="text-2xl mt-4 text-text" id="filtering-blue-light" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#filtering-blue-light">Filtering Blue Light</a></h3> <p class="mb-4 text-text leading-7">Just as there are glasses to protect from the sun, <strong class="font-normal text-peach dark:text-yellow">some glasses filter out blue light</strong>. Over the counter blue light filtering lenses are available or you may <em class="italic text-green">speak with your eye doctor</em> on <strong class="font-normal text-peach dark:text-yellow">adding them to your next pair</strong>. I personally use blue light filters in my primary pair of glasses and can happily say there is no color noticeable color distortion to disrupt my design work.</p> <p class="mb-4 text-text leading-7">UPDATE: Some applications you already use such as Amazon’s Kindle book reading service offers dark or sepia themes for reading with reduced eye strain.</p> <p class="mb-4 text-text leading-7">Applications like <a href="https://justgetflux.com/" class="link">F.lux</a> (or <a href="https://support.apple.com/en-us/HT207570" class="link">iOS Night Shift</a>, <a href="https://play.google.com/store/apps/details?id=com.urbandroid.lux" class="link">Android Twilight</a>, <a href="http://jonls.dk/redshift/" class="link">Linux Redshift</a> and others) allow for removing or reducing <em class="italic text-green">the output</em> of blue light from your device. Some of these tools can intelligently fade the amount of blue light based on the time of day or be disabled based on a timer.</p> <h2 class="text-3xl mt-6 text-text" id="on-sleep" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#on-sleep">On Sleep</a></h2> <p class="mb-4 text-text leading-7">Blue light activates “wake up” signals in our brain (what? this isn’t a science blog). <strong class="font-normal text-peach dark:text-yellow">Avoid these wake up signals 30-60 minutes before bed</strong> and you’ll not only <em class="italic text-green">fall asleep more easily</em>, but you’ll be <em class="italic text-green">awaken more smoothly</em> without that groggy sensation.</p> <p class="mb-4 text-text leading-7">If you’re unable to get 30-60 minutes away from a screen before bed then reconsider your nighttime habits. Worse yet, if you’re coding late into the night then immediately attempt going to sleep your mind is at its most active state or you could burn yourself out. Instead, consider shutting off the screen a little early and let your mind problem solve during the downtime and while you’re sleeping - you’ll likely be more productive.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Quality of sleep is far more important than the quantity of sleep you receive</strong>. If you’re not waking up feeling refreshed then you’ll need to reconsider your sleep habits.</p> <hr> <p class="mb-4 text-text leading-7">For bonus points, cut out caffeine from your diet some or entirely. Avoid eating just before bed and sleep in a dark room without interruptions whenever possible.</p> <h2 class="text-3xl mt-6 text-text" id="summary" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/less_blue_light_better_sleep/#summary">Summary</a></h2> <p class="mb-4 text-text leading-7">To truly live a healthy work life balance we must take care of ourselves physically and mentally. The quality of sleep we receive drastically affects our moods and health in both the short and long term. Better managing the excess of blue light from our modern world into our lives can result in better sleep and longer lasting good eyesight with fewer health problems.</p> Sat, 02 Sep 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/less_blue_light_better_sleep/ The Great App Store Trials https://gaiety.me/blog/the_great_app_store_trials/ <p class="mb-4 text-text leading-7"><a href="https://play.google.com/store/apps/details?id=io.cordova.myspells" class="link">Today marks my first day as a published app store developer</a>. It’s been a dream of mine to release work I’ve done not just on the web, but as something native you can put in your pocket without needing a browser. Some stories are of great heroes who overcome dangerous challenges through incredible feats of might; this one is of the problems and solutions of releasing a web app to the Play Store.</p> <h2 class="text-3xl mt-6 text-text" id="act-i%3A-building-the-app" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#act-i%3A-building-the-app">Act I: Building the App</a></h2> <p class="mb-4 text-text leading-7">I chose the <a href="http://quasar-framework.org/" class="link">Quasar Framework</a> powered by <a href="https://vuejs.org/" class="link">Vue.js</a> with <a href="https://cordova.apache.org/" class="link">Cordova</a> mobile conversion built in. <strong class="font-normal text-peach dark:text-yellow">Choosing tools that played well together</strong> assured me that if I <em class="italic text-green">read the documentation</em> and put in the effort <strong class="font-normal text-peach dark:text-yellow">I’d eventually succeed</strong>.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Release often</strong>. Advice I give to anyone and even easier to follow for a hobbyist project. Hit your <strong class="font-normal text-peach dark:text-yellow">minimum viable product then release</strong> the app to the public.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-releasing-a-web-app-cheaply-and-easily" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-releasing-a-web-app-cheaply-and-easily">Problem: Releasing a Web App Cheaply and Easily</a></h3> <p class="mb-4 text-text leading-7">I’m no server admin. I’ve built my app and just wish to see it online for public consumption.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-netlify" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-netlify">Solution: Netlify</a></h4> <p class="mb-4 text-text leading-7">Open Source projects can be automatically deployed and built directly from a Github repo for free to the <a href="https://www.netlify.com/" class="link">Netlify</a> servers. Once hosted you get a simple URL to include in your project.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-bugs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-bugs">Problem: Bugs</a></h3> <p class="mb-4 text-text leading-7">They happen, bugs are a natural part of application development. Keeping a todo list on your computer seems counter to the connected open source world we live in.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-github-issues" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-github-issues">Solution: Github Issues</a></h4> <p class="mb-4 text-text leading-7">Being transparent in logging bugs has a number of benefits. <a href="https://guides.github.com/features/issues/" class="link">Github Issues</a> is a great tool for this.</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">As easy as a todo list.</li> <li class="text-subtext0">Great practice, especially if you <em class="italic text-green">follow <a href="http://semver.org/" class="link">SemVer</a></em> and write <em class="italic text-green">clean commits</em>.</li> <li class="text-subtext0">Users know what’s busted and have a window into helping to <em class="italic text-green">fix the bugs themselves</em>.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Forms a public history for the project</strong> while <em class="italic text-green">encouraging a changelog</em> as the app evolves.</li> </ul> <h2 class="text-3xl mt-6 text-text" id="act-ii%3A-building-for-android" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#act-ii%3A-building-for-android">Act II: Building for Android</a></h2> <p class="mb-4 text-text leading-7">Generally <a href="http://quasar-framework.org/guide/quasar-play-app.html" class="link">Quasar makes compiling for Android easy</a> and enjoyable. Running their mobile dev tools unveiled several mobile specific bugs, which I logged then fixed.</p> <p class="mb-4 text-text leading-7">Quasar’s easy tools are great for quick feedback but are nothing compared to a real debugging APK running on your phone. Luckily there are docs for <a href="http://quasar-framework.org/guide/cordova-wrapper.html" class="link">wrapping your Quasar app in Cordova</a>.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-running-cordova-built-apk" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-running-cordova-built-apk">Problem: Running Cordova Built APK</a></h3> <p class="mb-4 text-text leading-7">The documentation drops off quickly after Cordova has done its job.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">You find yourself in a wolf’s den of opinions and tools in a world of assumed knowledge.</p> </blockquote> <p class="mb-4 text-text leading-7">Emulation through <a href="https://developer.android.com/studio/index.html" class="link">Android Studio</a> is possible, but I could never get it to work with my non-Android-Studio app.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-cordova-compile-to-device." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-cordova-compile-to-device.">Solution: Cordova compile to device.</a></h4> <p class="mb-4 text-text leading-7">After some digging, the most successful way to compile to my Android device was:</p> <ol> <li class="text-subtext0"><code>quasar build</code> from my <strong class="font-normal text-peach dark:text-yellow">root</strong>.</li> <li class="text-subtext0"><code>quasar run --device</code> from the <strong class="font-normal text-peach dark:text-yellow">cordova directory</strong> while my <strong class="font-normal text-peach dark:text-yellow">phone was plugged</strong> in with <strong class="font-normal text-peach dark:text-yellow">USB Debugging</strong> turned on.</li> </ol> <p class="mb-4 text-text leading-7">This automatically compiles and opens the app on your connected Android device.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">P.S. Android Studio may still be required here.</em></p> <h5 class="text-lg mt-2 text-text" id="also%E2%80%A6-overcoming-usb-debugging" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#also%E2%80%A6-overcoming-usb-debugging">Also… Overcoming USB Debugging</a></h5> <p class="mb-4 text-text leading-7">Enabling USB Debugging on modern Android phones is the opposite of obvious. Luckily, <a href="https://www.kingoapp.com/root-tutorials/how-to-enable-usb-debugging-mode-on-android.htm" class="link">this guide to Android USB debugging</a> explains the process.</p> <h5 class="text-lg mt-2 text-text" id="also%E2%80%A6-overcoming-usb-cable-differences" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#also%E2%80%A6-overcoming-usb-cable-differences">Also… Overcoming USB Cable Differences</a></h5> <p class="mb-4 text-text leading-7">I encountered times where USB debugging refused to work. Turns out <em class="italic text-green">some usb cables only transfer power and not data</em>. Use the correct USB cable type to avoid wasted time for silly reasons.</p> <h4 class="text-xl mt-2 text-text" id="problem%3A-local-ajax-calls-don%E2%80%99t-work" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-local-ajax-calls-don%E2%80%99t-work">Problem: Local Ajax Calls Don’t Work</a></h4> <p class="mb-4 text-text leading-7">JSON cannot be fetched locally as we could on Netlify. I did not wish to bake in all of my data on the web app to slow down initial load.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-bake-in-data-for-the-app-build-only." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-bake-in-data-for-the-app-build-only.">Solution: Bake in data for the app build only.</a></h4> <p class="mb-4 text-text leading-7">For my web app, the only concern with baking in data was app size for first load. On mobile that’s not a problem. In fact, baking in the data means an even easier offline solution.</p> <p class="mb-4 text-text leading-7">I wrote a <a href="https://github.com/hergaiety/my_spells/blob/master/build/process_spells.js" class="link">data processor</a> node script that could either compile my data to a JSON file or to a JS importable module (with <code>export default ...</code>) along with some <a href="https://github.com/hergaiety/my_spells/blob/master/package.json" class="link">package.json build scripts</a> to simplify the process during development and releases. In the app, I always import the JS module and if there is <code>data.length &gt; 0</code> I use it, else I attempt to fetch the JSON file.</p> <p class="mb-4 text-text leading-7">It took effort, but assured that my both the web and android app were quick to launch.</p> <h2 class="text-3xl mt-6 text-text" id="act-iii%3A-publishing" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#act-iii%3A-publishing">ACT III: Publishing</a></h2> <p class="mb-4 text-text leading-7">Congratulations! You have an app that runs on Android. Next, you must fumble through the <em class="italic text-green">app publishing process</em>. I’ve done my best to list the steps, problems and solutions below.</p> <h3 class="text-2xl mt-4 text-text" id="step%3A-you-want-money-and-my-soul%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#step%3A-you-want-money-and-my-soul%3F">Step: You Want Money and My Soul?</a></h3> <p class="mb-4 text-text leading-7">First step is registering for a Publisher Account with your Google User. This involves agreeing to many terms of services and paying a <strong class="font-normal text-peach dark:text-yellow">fee of $25</strong> that separates you from the potential onslaught of crapware and spam that may otherwise reach the Play Store. Relatively straightforward and <em class="italic text-green">a necessary evil</em> to progress.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-releasable-apk-file" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-releasable-apk-file">Problem: Releasable APK file</a></h3> <p class="mb-4 text-text leading-7">Up until now <em class="italic text-green">we’ve been using a debugging APK</em> file. That’s not good enough for release.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-cordova-build" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-cordova-build">Solution: Cordova Build</a></h4> <p class="mb-4 text-text leading-7"><code>cordova build</code> will create an android-release-unsigned.apk that is, as the filename implies, an <strong class="font-normal text-peach dark:text-yellow">unsigned but otherwise ready to release APK</strong>.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-signing-the-apk-file" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-signing-the-apk-file">Problem: Signing the APK file</a></h3> <p class="mb-4 text-text leading-7">One of the least documented parts of the process is signing the APK outside of a completely Android Studio made app.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-android-app-studio%2C-keystore%2C-jarsigner" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-android-app-studio%2C-keystore%2C-jarsigner">Solution: Android App Studio, Keystore, jarsigner</a></h4> <ol> <li class="text-subtext0">Install <a href="https://developer.android.com/studio/index.html" class="link">Android Studio</a> and launch it</li> <li class="text-subtext0">Open an Existing Project… choose the cordova created project directory for the app</li> <li class="text-subtext0">Build -&gt; Generate Signed APK</li> <li class="text-subtext0">Key Store Path: Create New (follow onscreen prompts)</li> </ol> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Note the place you’ve saved it, and what the key alias is (key0 is fine)</li> </ul> <ol start="5"> <li class="text-subtext0">Close Android Studio, we’ll instead use jarsigner to sign our apk:</li> </ol> <pre><code class="language-bash">jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore &lt;~/path/to/keystore.jks&gt; &lt;~/path/to/android-release-unsigned.apk&gt; &lt;KEY ALIAS&gt; <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="problem%3A-installing-onto-android-device" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-installing-onto-android-device">Problem: Installing onto Android Device</a></h3> <p class="mb-4 text-text leading-7">Let’s get it running on our Android once again, signed and ready to release.</p> <p class="mb-4 text-text leading-7"><code>adb install ~/path/to/android-release-signed.apk</code></p> <h4 class="text-xl mt-2 text-text" id="solution%3A-installing-adb" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-installing-adb">Solution: Installing <code>adb</code></a></h4> <p class="mb-4 text-text leading-7"><code>adb</code> can be installed from the Android Studio Preferences screen:</p> <ol> <li class="text-subtext0">Appearance &amp; Behavior &gt; System Settings &gt; Android SDK &gt; SDK Tools</li> <li class="text-subtext0">Check Android SDK Build-Tools, Android SDK Platform-Tools, Android SDK Tools</li> <li class="text-subtext0">If <code>adb</code> still isn’t available, correct your path like so: <a href="https://stackoverflow.com/questions/10303639/adb-command-not-found" class="link">https://stackoverflow.com/questions/10303639/adb-command-not-found</a></li> </ol> <p class="mb-4 text-text leading-7">Now running <code>adb install</code> on your apk will install directly to your device.</p> <h3 class="text-2xl mt-4 text-text" id="problem%3A-zipalign" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#problem%3A-zipalign">Problem: zipalign</a></h3> <p class="mb-4 text-text leading-7">While uploading to the Play Store you may see a notice that the apk is not zipaligned.</p> <h4 class="text-xl mt-2 text-text" id="solution%3A-zipalign-it" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/the_great_app_store_trials/#solution%3A-zipalign-it">Solution: zipalign it</a></h4> <p class="mb-4 text-text leading-7">Unfortunately this is not a tool we can install by itself, but it does come with Android Studio.</p> <p class="mb-4 text-text leading-7">The command we desire to run is something like:</p> <p class="mb-4 text-text leading-7"><code>zipalign -v 4 ~/path/to/file.apk ~/path/to/newfile.apk</code></p> <p class="mb-4 text-text leading-7">Replace <code>zipalign</code> with the path to it on your machine, likely under your android studio sdk directory.</p> <hr> <p class="mb-4 text-text leading-7">Finally we have a <strong class="font-normal text-peach dark:text-yellow">signed, zipaligned, releasable APK file ready for the Play Store</strong>. Follow the prompts on the site and your app will hopefully be published within a day.</p> <p class="mb-4 text-text leading-7">I encourage others to write about their experiences building apps for the Play Store. I’m sure there are simpler ways to achieve the same result with fewer headaches. Ultimately, having a published app on the Play Store is a very satisfying experience and this document will serve as a reminder of the trials I’ve been through in an attempt to inform others of the problems that may be encountered along the way with some solutions that worked for me.</p> <p class="mb-4 text-text leading-7">Stuck with a similar project? Reach out to me on Twitter @SharpShark28</p> Sun, 13 Aug 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/the_great_app_store_trials/ Performance Reviews - You and Your Peers https://gaiety.me/blog/performance_reviews/ <p class="mb-4 text-text leading-7">You possess something invaluable. Management relies on you to give honest feedback of your coworkers when its time for peer performance reviews.</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Perhaps writing a performance review feels boring or mandatory.</em> An empty, white, often-too-small text box with the ask of summarizing a coworker’s qualities as an employee can be daunting. Never underestimate its importance, however, just as we see importance in reviewing a peer’s code before its added to the project we consider our own, we should equally consider our peers themselves at the company we associate with.</p> <h2 class="text-3xl mt-6 text-text" id="provide-feedback-often---not-just-on-judgment-day-%F0%9F%9A%AB" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#provide-feedback-often---not-just-on-judgment-day-%F0%9F%9A%AB">Provide Feedback Often - Not Just On Judgment Day 🚫</a></h2> <p class="mb-4 text-text leading-7">Imagine you’re in a college class. You feel you’re doing well. You take your final. Suddenly you’re given a failing grade for the course.</p> <p class="mb-4 text-text leading-7">Being given poor marks when it’s too late isn’t fair and doesn’t support a healthy culture. <strong class="font-normal text-peach dark:text-yellow">Give feedback regularly throughout the year</strong> to <em class="italic text-green">avoid surprise criticism</em> and <em class="italic text-green">give time to improve</em> and fix any critiques you may have.</p> <p class="mb-4 text-text leading-7">Write any critique given as with an actionable solution. Instead of “they made me miss the deadline” perhaps “if we communicate better we should be able to make the next deadline as a team”.</p> <h2 class="text-3xl mt-6 text-text" id="questions-to-reflect-upon-%F0%9F%92%AD" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#questions-to-reflect-upon-%F0%9F%92%AD">Questions To Reflect Upon 💭</a></h2> <p class="mb-4 text-text leading-7">Below are the questions I consider when reflecting upon my experiences and understanding of a colleague I’m trying to qualify.</p> <h3 class="text-2xl mt-4 text-text" id="has-this-person-ever-made-your-day-easier%3F-%F0%9F%91%8D" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#has-this-person-ever-made-your-day-easier%3F-%F0%9F%91%8D">Has This Person Ever Made Your Day Easier? 👍</a></h3> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">“Colleague pair programmed with me to solve a difficult problem while teaching me how to debug similar problems in the future.”</li> <li class="text-subtext0">“Colleague wrote a well documented component that solved my needs and saved me many hours of work.”</li> </ul> <p class="mb-4 text-text leading-7">Acknowledge when a coworker has saved you time, stress, or helped you learn a new skill. These are often selfless offerings from people just looking to help their fellow workers and make the company a better place to work.</p> <p class="mb-4 text-text leading-7">Conversely, if an individual has made more days difficult than they have made easier that is an indicator of a problem worth speaking up about.</p> <h3 class="text-2xl mt-4 text-text" id="has-this-person-helped-you-grow%3F-%F0%9F%8C%B1" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#has-this-person-helped-you-grow%3F-%F0%9F%8C%B1">Has This Person Helped You Grow? 🌱</a></h3> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">“Colleague made me rethink how I approach testing my code.”</li> <li class="text-subtext0">“Colleague provided a great example of how to reach a work-life balance.”</li> </ul> <p class="mb-4 text-text leading-7">Positive influences, critical thinkers, and industry leaders often surround us at work. It’s easy to presume these are already known qualities to everyone. It’s important to be explicit and state what may seem obvious to us, but may not be to others such as management.</p> <p class="mb-4 text-text leading-7">If you’ve learned from those around you it’s only fair to acknowledge the source of the growth for the teachers to be rewarded. This not only could lead to their promotion, but also to a positive feedback loop of them desiring to continue to help others.</p> <h3 class="text-2xl mt-4 text-text" id="has-this-person-shown-any-or-all-the-skills-of-a-senior-engineer-or-equivalent%3F-%F0%9F%8D%B7" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#has-this-person-shown-any-or-all-the-skills-of-a-senior-engineer-or-equivalent%3F-%F0%9F%8D%B7">Has This Person Shown Any or All The Skills of a <a href="http://www.kitchensoap.com/2012/10/25/on-being-a-senior-engineer/" class="link">Senior Engineer or Equivalent</a>? 🍷</a></h3> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">“Colleague was very receptive to my code feedback despite it being my first few weeks on the job.”</li> <li class="text-subtext0">“Colleague was eager to help me learn an otherwise obscure skill.”</li> <li class="text-subtext0">“Colleague showed professionalism in their demeanor by addressing core problems while never making excuses. A real doer, not a complainer”</li> </ul> <p class="mb-4 text-text leading-7">Potential promotions are a primary goal of peer reviews. <a href="http://www.kitchensoap.com/2012/10/25/on-being-a-senior-engineer/" class="link">On Being a Senior Engineer</a> offers a new perspective on what makes a mature engineer while dismissing false qualities like years of experience.</p> <blockquote class="font-mono fancy-blockquote"> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Mature engineers seek out constructive criticism of their designs.</li> <li class="text-subtext0">Mature engineers understand the non-technical areas of how they are perceived.</li> <li class="text-subtext0">Mature engineers do not shy away from making estimates, and are always trying to get better at it.</li> <li class="text-subtext0">Mature engineers have an innate sense of anticipation, even if they don’t know they do.</li> <li class="text-subtext0">Mature engineers understand that not all of their projects are filled with rockstar-on-stage work.</li> <li class="text-subtext0">Mature engineers lift the skills and expertise of those around them.</li> <li class="text-subtext0">Mature engineers make their trade-offs explicit when making judgements and decisions.</li> <li class="text-subtext0">Mature engineers don’t practice CYAE (“Cover Your Ass Engineering”).</li> <li class="text-subtext0">Mature engineers are empathetic.</li> <li class="text-subtext0">Mature engineers are aware of cognitive biases.</li> </ul> </blockquote> <p class="mb-4 text-text leading-7">Conversely, if an individual meets very few or none of the items on this list it may be an indicator of room for improvement.</p> <h3 class="text-2xl mt-4 text-text" id="has-this-person-shown-healthy-levels-of-involvement-or-desire-to-job-craft%3F-%F0%9F%8D%BB" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#has-this-person-shown-healthy-levels-of-involvement-or-desire-to-job-craft%3F-%F0%9F%8D%BB">Has This Person Shown Healthy Levels of Involvement or <a href="https://www.mindtools.com/pages/article/newCDV_36.htm" class="link">Desire to Job Craft</a>? 🍻</a></h3> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">“Despite colleague being from team X, they were passionate while collaborating on my project.”</li> <li class="text-subtext0">“Project lead improved the designs of their reports to help in understanding the data. Their background in design really shows through their work.”</li> </ul> <p class="mb-4 text-text leading-7">It’s all too easy to sit at a desk and trudge through the <em class="italic text-green">minimum amount of work</em> assigned to earn a paycheck. It’s also <em class="italic text-green">all too common to overwork</em> oneself accepting an ever increasing quantity of that same work.</p> <p class="mb-4 text-text leading-7"><a href="https://www.mindtools.com/pages/article/newCDV_36.htm" class="link">Job Crafting</a> shows a strive for <strong class="font-normal text-peach dark:text-yellow">work-life balance</strong> through utilizing one’s own <strong class="font-normal text-peach dark:text-yellow">unique set of skills</strong>. A colleague who works on a <strong class="font-normal text-peach dark:text-yellow">diverse range of projects</strong> while <strong class="font-normal text-peach dark:text-yellow">collaborating with multiple teams</strong> is a great quality to acknowledge during a peer review. Your acknowledgment will help encourage management to consider what the individual is already doing in a more official capacity to assist in further developing their career.</p> <h2 class="text-3xl mt-6 text-text" id="start-writing" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/performance_reviews/#start-writing">Start Writing</a></h2> <p class="mb-4 text-text leading-7">Extracting answers to these questions into their <strong class="font-normal text-peach dark:text-yellow">qualities</strong> is the last step in writing a quality peer review. As with any professional writing, be <strong class="font-normal text-peach dark:text-yellow">concise</strong>. Be <strong class="font-normal text-peach dark:text-yellow">fair</strong>. <em class="italic text-green">Write about others as you wish they’d write about you.</em></p> Thu, 01 Jun 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/performance_reviews/ Self Code Review with Git Add Patch https://gaiety.me/blog/self-code-review-with-git-patch/ <p class="mb-4 text-text leading-7">Code reviews reduce logical errors, call out typos, and prevents accidentally committing more code than intended (<a href="https://www.atlassian.com/agile/code-reviews" class="link">1</a>). They’re essential for <em class="italic text-green">all sized teams</em> pushing to the same code base while <em class="italic text-green">maintaining sanity</em>.</p> <p class="mb-4 text-text leading-7">Should a developer find themselves discovering any accidental “oops!” in their pull request it’s a good indicator of a flaw in workflow. <strong class="font-normal text-peach dark:text-yellow">Introducing the interactive self code review:</strong></p> <pre><code class="language-bash">git add --interactive <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7">Interactive adding in git offers a choose-your-own-adventure style “What Now&gt;” series of options.</p> <h2 class="text-3xl mt-6 text-text" id="the-useful-bit%3A-git-patch" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#the-useful-bit%3A-git-patch">The Useful Bit: <em class="italic text-green">Git Patch</em></a></h2> <p class="mb-4 text-text leading-7">Today let’s look at the <em class="italic text-green"><strong class="font-normal text-peach dark:text-yellow">p</strong>atch</em> option. We can skip to the patch option in the future with this handy shortcut:</p> <p class="mb-4 text-text leading-7"><em class="italic text-green">Example pretends we have file.ext and have added a line that defines a version…</em></p> <pre><code class="language-bash">git add -p diff --git a/file.ext b/file.ext index sha1..sha2 sha3 -- a/file.ext ++ b/file.ext { <span class="hljs-string">&quot;name&quot;</span>: <span class="hljs-string">&quot;example json&quot;</span>, +<span class="hljs-string">&quot;version&quot;</span>: <span class="hljs-string">&quot;1.0.0&quot;</span>, <span class="hljs-string">&quot;private&quot;</span>: <span class="hljs-literal">true</span>, Stage this hunk [y,n,q,a,d,/,e,?]? <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7">Looks like a huge chunk of stuff! Broken down, the response describes what file was modified followed by a chunk of color coated git diff.</p> <h3 class="text-2xl mt-4 text-text" id="now-what%3F-staging-hunks-of-code" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#now-what%3F-staging-hunks-of-code">Now What? Staging Hunks of Code</a></h3> <p class="mb-4 text-text leading-7">Many options are provided in the “Stage this hunk?” prompt following a git add patch.</p> <p class="mb-4 text-text leading-7">Pressing <code>?</code> in response to the prompt explains each valid response. These are some essentials:</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">y</strong> - stage this hunk</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">n</strong> - do <em class="italic text-green">not</em> stage this hunk</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">q</strong> - quit</li> </ul> <p class="mb-4 text-text leading-7">You’ll find that by going through this process you can read every line you’d like to add to a commit and make better choices about them.</p> <h3 class="text-2xl mt-4 text-text" id="splitting-s" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#splitting-s">Splitting <code>s</code></a></h3> <p class="mb-4 text-text leading-7">These “magical” feeling chunks aren’t always smart enough. Sometimes there’s a need to split (with the <code>s</code> response) a chunk into smaller chunks. This comes up more often than you’d think if you’re developing empathetically.</p> <h3 class="text-2xl mt-4 text-text" id="a-add-or-d-don%E2%80%99t-add-entire-file" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#a-add-or-d-don%E2%80%99t-add-entire-file"><code>a</code> Add or <code>d</code> Don’t Add Entire File</a></h3> <p class="mb-4 text-text leading-7">An <code>a</code> response will stage the current hunk and all the following within the current file automatically. This is <strong class="font-normal text-peach dark:text-yellow"><em class="italic text-green">not</em> recommended because you’re opting to skip parts of your personal code review</strong>.</p> <p class="mb-4 text-text leading-7">However, <code>d</code> is a nice way to skip adding anything from an entire file and can save a lot of time.</p> <h3 class="text-2xl mt-4 text-text" id="manually-editing" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#manually-editing">Manually Editing</a></h3> <p class="mb-4 text-text leading-7">Typos or “oops!” can be quickly corrected with the <code>e</code> response. This will open just the chunk for quick adjustments including line adding and removal.</p> <h1 class="text-6xl mt-6 text-pink" id="summary" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/self-code-review-with-git-patch/#summary">Summary</a></h1> <p class="mb-4 text-text leading-7">Git patch has become a core part of my workflow to <strong class="font-normal text-peach dark:text-yellow">ensure quality</strong> and boost <strong class="font-normal text-peach dark:text-yellow">personal confidence in the code I ship</strong>. Give it a try today!</p> Thu, 04 May 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/self-code-review-with-git-patch/ Easy Git Commit Targeting https://gaiety.me/blog/git-commit-targeting/ <p class="mb-4 text-text leading-7">A generally agreed upon goal of a developer is to use the mouse as little as possible. An often overlooked moment of touching the mouse is the seemingly inevitable moment of having to target a git commit via it’s SHA hash. Truth is this doesn’t need to be an ordeal.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Let’s look at some alternative ways to target commits</strong>.</p> <h2 class="text-3xl mt-6 text-text" id="by-shortened-sha-hash" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#by-shortened-sha-hash">By Shortened SHA Hash</a></h2> <p class="mb-4 text-text leading-7">Traditionally to find the <code>git diff 123abc456def789ghi</code> on a SHA you’d use the entire SHA hash. Instead, you can type just the first few characters and Git will figure out the rest.</p> <pre><code class="language-bash">git diff 123abc <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="tilde" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#tilde">Tilde</a></h2> <p class="mb-4 text-text leading-7">A common target is the previous commit from the HEAD. Using <code>HEAD~</code> will specify the intention of one commit before the HEAD.</p> <pre><code class="language-bash">git diff HEAD~ <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="past-tilde" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#past-tilde">Past Tilde</a></h3> <p class="mb-4 text-text leading-7">Adding a number after the tilde <code>~</code> will target a commit prior to the head equal to the number specified.</p> <pre><code class="language-bash">git diff HEAD~3 <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="stacked-carets" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#stacked-carets">Stacked Carets</a></h2> <p class="mb-4 text-text leading-7">Alternatively, the number of caret characters after HEAD will similarly target a commit prior to HEAD equal to the number of carets.</p> <pre><code class="language-bash">git diff HEAD^^^ <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="combine-these-tricks" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#combine-these-tricks">Combine These Tricks</a></h2> <p class="mb-4 text-text leading-7">So close! Ever want to target the commit just previous to a SHA hash? It’s easier than you think.</p> <pre><code class="language-bash">git diff 123abc~ <span class="hljs-language-icon">bash</span></code></pre> <h1 class="text-6xl mt-6 text-pink" id="summary" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/git-commit-targeting/#summary">Summary</a></h1> <p class="mb-4 text-text leading-7">Through a combination of shortened SHA hashes, HEAD, and relative tilde/caret characters anyone can fly through git history with confidence.</p> Fri, 21 Apr 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/git-commit-targeting/ What Polyphasic Sleep Taught Me About Passion https://gaiety.me/blog/polyphasic-sleep-and-passion/ <p class="mb-4 text-text leading-7">Like many travelers I can at times suffer from jet lag, but this time I’ve turned the problem into an opportunity to begin a <a href="https://www.polyphasicsociety.com/polyphasic-sleep/overviews/" class="link">polyphasic sleep schedule</a>. There’s no better time to start such a sleep schedule transition than when your schedule is already thrown out of wack.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">There’s no better time than the present. <em class="italic text-green">~That’s what “They” say.</em></p> </blockquote> <p class="mb-4 text-text leading-7">Within just days of adopting polyphasic sleep I had learned a great deal. Beyond the obvious benefits of learning to manage my time better and regaining a sense of control in my life I discovered other things as well. Specifically, <strong class="font-normal text-peach dark:text-yellow">I discovered surprising things about the people I surround myself with</strong> in response to telling them about the new schedule. Additionally, I developed an <strong class="font-normal text-peach dark:text-yellow">increasing awareness of my own mortality</strong>.</p> <h2 class="text-3xl mt-6 text-text" id="surrounding-yourself-with-passionate-people" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/polyphasic-sleep-and-passion/#surrounding-yourself-with-passionate-people">Surrounding Yourself With Passionate People</a></h2> <p class="mb-4 text-text leading-7">Initially the news of my adopting polyphasic sleep was met with <em class="italic text-green">distain and shock</em>. Strong negative reactions such as “that sounds horrible” or “I’d just be bored more often” hit my psyche hard. This was a life change I truly believed in and I was <strong class="font-normal text-peach dark:text-yellow">not</strong> being met with support from those I considered close. <strong class="font-normal text-peach dark:text-yellow">I was in disbelief in how uninterested others were</strong> in what I believed to be an life altering topic.</p> <p class="mb-4 text-text leading-7">However, <strong class="font-normal text-peach dark:text-yellow">others perked their ears in interest</strong> and asked great questions like “how does that work?”, “is it healthy?”, or “has it been going well?”. <strong class="font-normal text-peach dark:text-yellow">These were meaningful conversations precipitated by people desiring to live interesting lives</strong>.</p> <p class="mb-4 text-text leading-7">Discussing polyphasic sleep as a life style choice with individuals has revealed a surprising level of <em class="italic text-green">insight into how others view the world</em>. <strong class="font-normal text-peach dark:text-yellow">Having these conversations can identify people as apathetic or as passionate</strong>.</p> <h2 class="text-3xl mt-6 text-text" id="making-the-most-of-your-time" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/polyphasic-sleep-and-passion/#making-the-most-of-your-time">Making the Most Of Your Time</a></h2> <p class="mb-4 text-text leading-7">I desire to live a passionate life. To me that means <strong class="font-normal text-peach dark:text-yellow">expressing love while creating and learning at all times</strong>.</p> <p class="mb-4 text-text leading-7">I view the world through the lens of existential realism. I’m quite aware of the limited time we live, how I’m living it and who I surround myself with. <em class="italic text-green">Polyphasic sleep promises more awake hours and consequently more life to live</em>. My formative years should be spent growing my knowledge, relationships and passions.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">More hours are meaningless without intent</strong>. Overscheduling isn’t healthy either, but without passion and intent it’s easy to ask “why bother?”. This is true regardless of polyphasic sleep or not.</p> <h1 class="text-6xl mt-6 text-pink" id="summary" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/polyphasic-sleep-and-passion/#summary">Summary</a></h1> <p class="mb-4 text-text leading-7">Polyphasic sleep has given me the gift of more life. <strong class="font-normal text-peach dark:text-yellow">I choose to use it to grow with those willing to grow alongside me in a world of passionate people and passionate actions</strong>.</p> Thu, 06 Apr 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/polyphasic-sleep-and-passion/ Getting Started Gets Better With You https://gaiety.me/blog/getting_started_gets_better_with_you/ <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">How was your onboarding experience?</strong> How were your first moments of any development job in recent recollection?</p> <p class="mb-4 text-text leading-7">If you recall it being a pleasant experience, then I’m glad for you. Generally, onboarding a new developer involves a process of awkwardly asking people you barely know what feel like stupid questions.</p> <h1 class="text-6xl mt-6 text-pink" id="getting-started-gets-better-with-you" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/getting_started_gets_better_with_you/#getting-started-gets-better-with-you">Getting Started Gets Better With You</a></h1> <p class="mb-4 text-text leading-7">Write down your questions no matter how seemingly simple they may be. Then follow up on your notes with the answers.</p> <blockquote class="font-mono fancy-blockquote"> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0">Where is the app’s repo?</li> <li class="text-subtext0">How do I install the app’s dependencies?</li> <li class="text-subtext0">How do I launch the app?</li> <li class="text-subtext0">Where do I find work to do?</li> </ul> </blockquote> <p class="mb-4 text-text leading-7">Suddenly you wind up with something akin to an <em class="italic text-green">FAQ</em> (Frequently Asked Questions). Passing along these questions and answers to the next new hire can make a dramatic impact on their <strong class="font-normal text-peach dark:text-yellow">first impression</strong> and ability to <strong class="font-normal text-peach dark:text-yellow">ramp up quickly</strong>.</p> <h2 class="text-3xl mt-6 text-text" id="making-it-real" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/getting_started_gets_better_with_you/#making-it-real">Making It Real</a></h2> <p class="mb-4 text-text leading-7">Asking for forgiveness rather than permission can be daunting when you’re new. A safe way to spread and better your notes is sharing them with the next new hire. Be sure to gather any questions they have and improve your notes with each person you work with.</p> <p class="mb-4 text-text leading-7">Ideally publishing these notes internally in an internal knowledge base, wiki, or the <a href="http://README.md" class="link">README.md</a> of the project repo can be a great resource. I encourage anyone to submit a pull request to clean up the often neglected README’s in repositories to answer the typical questions that currently may be answered by repetitive word of mouth.</p> <h1 class="text-6xl mt-6 text-pink" id="see-a-problem%3F-be-the-solution." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/getting_started_gets_better_with_you/#see-a-problem%3F-be-the-solution.">See a problem? Be the solution.</a></h1> <p class="mb-4 text-text leading-7">Anyone can make a positive impact on company culture by sharing what you’ve learned with others.</p> <p class="mb-4 text-text leading-7">Take notes. Share them. Don’t be afraid of taking initiative. Imagine the impact such an effort could’ve had on your first days and don’t let the trend of ignoring onboarding continue.</p> Thu, 16 Mar 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/getting_started_gets_better_with_you/ A Modern Terminal Workflow — Part 5 / 5 https://gaiety.me/blog/a_modern_terminal_workflow_5/ <p class="mb-4 text-text leading-7">iTerm2 is a Terminal Replacement for Mac OS offering plenty of <a href="https://iterm2.com/features.html" class="link">customization and features</a>.</p> <h1 class="text-6xl mt-6 text-pink" id="config" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#config">Config</a></h1> <p class="mb-4 text-text leading-7">Open iTerm’s preferences with “⌘,” then tick the following settings:</p> <ol> <li class="text-subtext0">“Load preferences from a custom folder or URL”</li> <li class="text-subtext0">Choose ~/dotfiles</li> <li class="text-subtext0">“Save changes to folder when iTerm2 quits”</li> </ol> <h2 class="text-3xl mt-6 text-text" id="theme%3A-dracula" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#theme%3A-dracula">Theme: Dracula</a></h2> <p class="mb-4 text-text leading-7">Dracula is not only a Vim theme but also a theme for many other applications such as iTerm2. This can be added to the dotfiles just like tpm was in part 4 by using a git subtree.</p> <pre><code class="language-bash">git remote add -f iterm-dracula https://github.com/dracula/iterm.git git subtree add --prefix=iterm-dracula/ iterm-dracula master --squash <span class="hljs-language-icon">bash</span></code></pre> <ol> <li class="text-subtext0">Profiles tab</li> <li class="text-subtext0">Colors sub-tab</li> <li class="text-subtext0">Color Presets…</li> <li class="text-subtext0">Import…</li> <li class="text-subtext0">~/dotfiles/iterm-dracula/Dracula.itermcolors</li> </ol> <h2 class="text-3xl mt-6 text-text" id="font%3A-fira-code" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#font%3A-fira-code">Font: Fira Code</a></h2> <p class="mb-4 text-text leading-7">Designers have logos, programmers have… well, frameworks and languages I suppose — but visually a great way to build a brand are our tools and our style. Themes are a great start, but it doesn’t have to stop there. Our entire terminal is made up of text, so make that text look beautiful.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Put simply: Fira Code is a free monospaced font with programming ligatures.</p> </blockquote> <p class="mb-4 text-text leading-7">What does any of that mean? It’s what you want for highly legible code and looking badass in the process.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">NOTE</strong> <em class="italic text-green">Currently the Fira Code font is only supported in <a href="https://www.iterm2.com/downloads/nightly/#/section/home" class="link">iTerm’s nightly builds</a> at the time of writing. Eventually this will simply be part of the final release.</em></p> <ol> <li class="text-subtext0">Profiles tab</li> <li class="text-subtext0">Text sub-tab</li> <li class="text-subtext0">Change Font</li> <li class="text-subtext0">Family: Fira Code (I enjoy size 18)</li> </ol> <h2 class="text-3xl mt-6 text-text" id="cursor-guide" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#cursor-guide">Cursor Guide</a></h2> <p class="mb-4 text-text leading-7">Even self proclaimed terminal pro’s who claim to never lose track of their cursor should do themselves a favor and enable iTerm2’s cursor guide. Subconciously a gentle highlight of the current line will draw your eye right to where you need to be.</p> <ol> <li class="text-subtext0">Profiles tab</li> <li class="text-subtext0">Colors sub-tab</li> <li class="text-subtext0">“Cursor Guide”</li> <li class="text-subtext0">Set color (I prefer 255, 255, 255, 35)</li> </ol> <h2 class="text-3xl mt-6 text-text" id="tmux-tab-switching" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#tmux-tab-switching">Tmux Tab Switching</a></h2> <p class="mb-4 text-text leading-7">A clever hack to enable <code>Ctrl Tab</code> and <code>Ctrl Shift Tab</code> tmux tab switching is to let iTerm handle those shortcuts, then send the default <code>Ctrl B n</code> and <code>Ctrl b p</code> hex codes to the terminal. This pairs well with NeoVim’s tabbing being the same but without holding Ctrl. (Special Thanks to <a href="http://tangledhelix.com/blog/2012/04/28/iterm2-keymaps-for-tmux/" class="link">Dan Lowe</a>)</p> <ol> <li class="text-subtext0">Keys</li> <li class="text-subtext0">New &gt; “Ctrl Tab” &gt; Send Hex Codes &gt; 0x02 0x6E</li> <li class="text-subtext0">New &gt; “Ctrl Tab” &gt; Send Hex Codes &gt; 0x02 0x70</li> </ol> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Ctrl Tab</code> to switch to next tmux tab</li> <li class="text-subtext0"><code>Ctrl Shift Tab</code> to switch to previous tmux tab</li> </ul> <h1 class="text-6xl mt-6 text-pink" id="outro" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_5/#outro">Outro</a></h1> <p class="mb-4 text-text leading-7">That wraps up my opinionated guide to created a dotfiles repo for a modern terminal workflow. While it does make assumptions about some ideal tools, configurations, and plugins to use this guide has not assumed what programming languages you the reader may be using. Next steps would be to leverage the plugin managers and configuration files created during the guide to make developing with your favorite languages an even more pleasant experience.</p> Tue, 21 Feb 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/a_modern_terminal_workflow_5/ A Modern Terminal Workflow — Part 4 / 5 https://gaiety.me/blog/a_modern_terminal_workflow_4/ <p class="mb-4 text-text leading-7">Multiplexing the terminal, huh? Tmux is a simple yet powerful way to work with multiple terminal based programs simultaniously. With Tmux one can ditch the mouse and use keyboard shortcuts to split panes and navigate between tabs of terminal workspaces making anyone a multitasking terminal master.</p> <p class="mb-4 text-text leading-7">Tmux was installed in Part 1 of this guide and its dotfile config can be modified with NeoVim like so <code>nvim tmux.conf</code>.</p> <h1 class="text-6xl mt-6 text-pink" id="config" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#config">Config</a></h1> <h2 class="text-3xl mt-6 text-text" id="fix-copy-to-global-clipboard" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#fix-copy-to-global-clipboard">Fix Copy to Global Clipboard</a></h2> <p class="mb-4 text-text leading-7"><em class="italic text-green">Bah! This article starts with a fix?</em></p> <p class="mb-4 text-text leading-7">On later versions of OSX accessing the system clipboard from within tmux became problematic. This command resolves that issue utilizing the <code>reattach-to-user-namespace</code> tool already installed in <code>init.sh</code>.</p> <pre><code class="language-vim">set -g default-shell $SHELL set -g default-command 'reattach-to-user-namespace -l ${SHELL}' </code></pre> <h2 class="text-3xl mt-6 text-text" id="tabs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#tabs">Tabs</a></h2> <p class="mb-4 text-text leading-7">The obvious way to multitask is with tabs. It’s a great place to get started. These keybindings will make working with them more intuitive.</p> <pre><code class="language-vim">set -g status-position top set -g base-index 1 set -g pane-base-index 1 set -g renumber-windows on bind-key -n C-t new-window bind-key -n C-T new-window -c &quot;#{pane_current_path}&quot; bind-key -n C-w kill-pane </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Ctrl t</code> to open new tab</li> <li class="text-subtext0"><code>Ctrl T</code> to open new tab in same directory</li> <li class="text-subtext0"><code>Ctrl w</code> to close a pane (and tab if only one pane)</li> </ul> <h2 class="text-3xl mt-6 text-text" id="create-panes" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#create-panes">Create Panes</a></h2> <p class="mb-4 text-text leading-7">A single tab can be split into multiple panes. Mastering panes not only makes the user look like a total terminal professional but can really boost efficiency. Combined with NeoVim this is as close as it gets to having your terminal act like the best parts of an IDE.</p> <pre><code class="language-vim">bind \ split-window -h bind | split-window -h -c '#{pane_current_path}' bind - split-window bind _ split-window -c '#{pane_current_path}' </code></pre> <p class="mb-4 text-text leading-7">A small tweak on the community “standard” pane splitting hotkeys.</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Ctrl b \</code> to open new vertical split</li> <li class="text-subtext0"><code>Ctrl b |</code> to open new vertical split in current directory</li> <li class="text-subtext0"><code>Ctrl b -</code> to open new horizontal split</li> <li class="text-subtext0"><code>Ctrl b _</code> to open new horizontal split in current directory</li> </ul> <h1 class="text-6xl mt-6 text-pink" id="plugins" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#plugins">Plugins</a></h1> <h2 class="text-3xl mt-6 text-text" id="plugin-manager" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#plugin-manager">Plugin Manager</a></h2> <p class="mb-4 text-text leading-7">Unlike in previous parts of this series there isn’t much to extend in terms of functionality for Tmux. However, to get the most out of Tmux it’s ideal to install some well defined community made configurations.</p> <p class="mb-4 text-text leading-7">Adding a plugin manager to Tmux is as easy as installing tpm (Tmux Package Manager) via the Terminal. This can be done with git subtrees so that when these dotfiles are cloned to other machines in the future tpm is ready to go.</p> <pre><code class="language-bash">git remote add -f tpm https://github.com/tmux-plugins/tpm.git git subtree add --prefix=tpm tpm master --squash <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7">With tpm installed we can now initialize it in our Tmux Config.</p> <pre><code class="language-vim">set -g @plugin 'tmux-plugins/tpm' # PLUGINS GO HERE!!! run '~/dotfiles/tpm/tpm' </code></pre> <h3 class="text-2xl mt-4 text-text" id="to-install-plugins" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#to-install-plugins">To Install Plugins</a></h3> <pre><code class="language-bash">tmux <span class="hljs-built_in">source</span> ~/.tmux.conf <span class="hljs-language-icon">bash</span></code></pre> <p class="mb-4 text-text leading-7"><code>Ctrl b I</code> will install any newly added plugins. A prompt will appear at the top of the terminal to show installation progress.</p> <h2 class="text-3xl mt-6 text-text" id="sensible-defaults" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#sensible-defaults">Sensible Defaults</a></h2> <pre><code class="language-vim">set -g @plugin 'tmux-plugins/tmux-sensible </code></pre> <p class="mb-4 text-text leading-7">This corrects rendering NeoVim in color through Tmux, removes the escape key delay, configures utf8, and more.</p> <h2 class="text-3xl mt-6 text-text" id="moving-panes" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#moving-panes">Moving Panes</a></h2> <p class="mb-4 text-text leading-7">Splitting and removing panes is easy, but what about moving between them? What if there are NeoVim panes open as well as Tmux panes?</p> <pre><code class="language-vim">set -g @plugin 'christoomey/vim-tmux-navigator' </code></pre> <p class="mb-4 text-text leading-7">With this simple plugin this new concern is no longer. Moving between NeoVim and Tmux panes now use the same shortcuts.</p> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Ctrl h, j, k, or l</code> to switch to split left, down, up, right</li> </ul> <h2 class="text-3xl mt-6 text-text" id="theme%3A-powerline-yellow" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#theme%3A-powerline-yellow">Theme: Powerline Yellow</a></h2> <pre><code class="language-vim">set -g @themepack 'block/yellow' set -g @plugin 'jimeh/tmux-themepack' </code></pre> <p class="mb-4 text-text leading-7">Much like vim-airline, this will give out lower tmux statusbar that powerline look. I’ve chosen gray but there are other <a href="https://github.com/jimeh/tmux-themepack" class="link">options</a>.</p> <h1 class="text-6xl mt-6 text-pink" id="what%E2%80%99s-next" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_4/#what%E2%80%99s-next">What’s Next</a></h1> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/a-modern-terminal-workflow-part-5-5" class="link">Part 5 will cover configuring iTerm2</a></p> Mon, 20 Feb 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/a_modern_terminal_workflow_4/ A Modern Terminal Workflow — Part 3 / 5 https://gaiety.me/blog/a_modern_terminal_workflow_3/ <p class="mb-4 text-text leading-7">Zsh is a UNIX command interpreter alternative to the default Mac OS shell Bash. Someone who knows Bash already knows the basics of Zsh.</p> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">So then why?</strong> Zsh is increasing in popularity with those who want more from their terminal. Zsh offers features like syntax highlighting, variables, history commands and other advanced features outside the scope of this article. I install it for the customization potential it offers and appreciate that I can grow to <a href="https://www-s.acm.illinois.edu/workshops/zsh/why.html" class="link">learn new features over time</a>.</p> <h1 class="text-6xl mt-6 text-pink" id="config" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#config">Config</a></h1> <p class="mb-4 text-text leading-7">In part 1 the init script set Zsh as the default shell by running <code>chsh -s /usr/local/bin/zsh</code>. The next time you log in Zsh is the new default. Or running <code>zsh</code> will launch the Zsh shell.</p> <p class="mb-4 text-text leading-7"><code>nvim zshrc</code></p> <h2 class="text-3xl mt-6 text-text" id="enabling-color-prompts" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#enabling-color-prompts">Enabling Color Prompts</a></h2> <h5 class="text-lg mt-2 text-text" id="note%3A-syntax-highlighting-and-color-may-not-work-as-expected-within-tmux-until-it-is-configured-in-part-4-correctly." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#note%3A-syntax-highlighting-and-color-may-not-work-as-expected-within-tmux-until-it-is-configured-in-part-4-correctly.">Note: Syntax highlighting and color may not work as expected within Tmux until it is configured in Part 4 correctly.</a></h5> <p class="mb-4 text-text leading-7">Enabling color is an important first step.</p> <pre><code class="language-vim">autoload colors zsh/terminfo colors </code></pre> <h2 class="text-3xl mt-6 text-text" id="minimal-prompt" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#minimal-prompt">Minimal Prompt</a></h2> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">This is my [Prompt]. There are many like it but this one is mine.</p> </blockquote> <p class="mb-4 text-text leading-7">Example:</p> <pre><code class="language-vim">precmd() { print &quot;&quot; } PS1=&quot;⟩&quot; RPS1=&quot;%{$fg[magenta]%}%20&lt;...&lt;%~%&lt;&lt;%{$reset_color%}&quot; </code></pre> <p class="mb-4 text-text leading-7">A prompt can be a place to put a lot of information at a glance. I’m of the opinion that information belongs hidden behind commands and called upon as needed.</p> <p class="mb-4 text-text leading-7">This prompt consists of an empty line placed above the prompt to separate it from finished commands. The left prompt (PS1) is simply a right arrow character showing where a command can be typed. The right prompt (RPS1) is an ellipsis shortened version showing up to 20 characters from the right of the current path.</p> <h2 class="text-3xl mt-6 text-text" id="autostart-tmux" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#autostart-tmux">Autostart Tmux</a></h2> <p class="mb-4 text-text leading-7">The command below does a simple check to confirm Tmux is installed before attempting to run it automatically.</p> <pre><code class="language-vim">if [ &quot;$TMUX&quot; = &quot;&quot; ]; then tmux; fi </code></pre> <p class="mb-4 text-text leading-7">In part 4 Tmux will be discussed in greater detail. For now, know that running it only enhances the possibilities so there is no reason not to autostart Zsh running with Tmux. iTerm2, which will be discused in Part 5, also plays explicitly supports Tmux.</p> <p class="mb-4 text-text leading-7">If you instead desire to run Tmux manually you may do so by running the <code>tmux</code> command at any point.</p> <h2 class="text-3xl mt-6 text-text" id="auto-cd" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#auto-cd">Auto CD</a></h2> <pre><code class="language-vim">setopt auto_cd </code></pre> <p class="mb-4 text-text leading-7">A wise man once said, we only have so many keystrokes in our lives. With this simple command we can eliminate 3 of the most common ones, <code>cd&lt;space&gt;</code>. Now when you type a directory name or filepath and press enter the cd command is assumed.</p> <h2 class="text-3xl mt-6 text-text" id="spellcheck-%2F-typo-correction" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#spellcheck-%2F-typo-correction">Spellcheck / Typo Correction</a></h2> <pre><code class="language-vim">setopt correctall alias git status='nocorrect git status' </code></pre> <p class="mb-4 text-text leading-7">Zsh has some powerful typo correction capabilities. This is less annoying than it sounds and I love the time it saves me when I mistype a long command.</p> <p class="mb-4 text-text leading-7">It does, however, mistake <code>git status</code> as a typo. An alias is included above to correct this behavior.</p> <h1 class="text-6xl mt-6 text-pink" id="plugins-to-enhance-functionality" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#plugins-to-enhance-functionality">Plugins to Enhance Functionality</a></h1> <h2 class="text-3xl mt-6 text-text" id="package-manager" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#package-manager">Package Manager</a></h2> <p class="mb-4 text-text leading-7">Stock Zsh behaves as you’d expect it to. But why stop there? Installing plugins to Zsh can enhance its base functionality with very little overhead.</p> <pre><code class="language-vim">if [[ ! -f ~/.antigen.zsh ]]; then curl https://raw.githubusercontent.com/zsh-users/antigen/master/antigen.zsh &gt; ~/.antigen.zsh fi source ~/.antigen.zsh </code></pre> <p class="mb-4 text-text leading-7">Above is the configuration to <code>curl</code> the plugin manager antigen which will make installing plugins a breeze.</p> <h2 class="text-3xl mt-6 text-text" id="syntax-highlighting" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#syntax-highlighting">Syntax Highlighting</a></h2> <pre><code class="language-vim">antigen bundle zsh-users/zsh-syntax-highlighting </code></pre> <p class="mb-4 text-text leading-7">Code has syntax highlighting, why doesnt the terminal prompt? This package highlights valid and invalid commands as one would expect. It’s amazing this isn’t built in functionality.</p> <p class="mb-4 text-text leading-7"><a href="https://github.com/zsh-users/zsh-syntax-highlighting" class="link">Learn More</a></p> <h2 class="text-3xl mt-6 text-text" id="autocomplete" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#autocomplete">Autocomplete</a></h2> <pre><code class="language-vim">antigen bundle zsh-users/zsh-autosuggestions </code></pre> <p class="mb-4 text-text leading-7">Once again, code has autocomplete, why not the terminal prompt? Allows for repeating previously typed commands with ease.</p> <p class="mb-4 text-text leading-7"><a href="https://github.com/zsh-users/zsh-autosuggestions" class="link">Learn More</a></p> <h2 class="text-3xl mt-6 text-text" id="git-shorthand" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#git-shorthand">Git Shorthand</a></h2> <pre><code class="language-vim">antigen bundle git </code></pre> <p class="mb-4 text-text leading-7">This plugin includes a lot of powerful shorthands for git. The easiest to remember and one I use most often is simply shortening <code>git</code> to <code>g</code>.</p> <h1 class="text-6xl mt-6 text-pink" id="what%E2%80%99s-next" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_3/#what%E2%80%99s-next">What’s Next</a></h1> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/a-modern-terminal-workflow-part-4-5" class="link">Part 4 will cover configuring Tmux</a></p> Fri, 10 Feb 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/a_modern_terminal_workflow_3/ A Modern Terminal Workflow — Part 2 / 5 https://gaiety.me/blog/a_modern_terminal_workflow_2/ <p class="mb-4 text-text leading-7"><a href="https://vimeo.com/53144573" class="link">Vim is about precision editing at the speed of thought</a>. Vim is also about quickly navigating a project to find and read old code.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write. ― <em class="italic text-green">Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship</em></p> </blockquote> <p class="mb-4 text-text leading-7">NeoVim is a modern drop-in replacement for Vim. In fact it is easy to share a Vim config with NeoVim via a symlink, but there are some caveats which are outside the scope of this article.</p> <h1 class="text-6xl mt-6 text-pink" id="core-config" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#core-config">Core Config</a></h1> <h5 class="text-lg mt-2 text-text" id="note%3A-syntax-highlighting-and-color-may-not-work-as-expected-within-tmux-until-it-is-configured-in-part-4-correctly." tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#note%3A-syntax-highlighting-and-color-may-not-work-as-expected-within-tmux-until-it-is-configured-in-part-4-correctly.">Note: Syntax highlighting and color may not work as expected within Tmux until it is configured in Part 4 correctly.</a></h5> <p class="mb-4 text-text leading-7">There’s a certain magic to writing your editor config with that very same editor. I suggest handwriting these configs so you can learn as you type.</p> <p class="mb-4 text-text leading-7"><code>nvim vimrc</code></p> <h2 class="text-3xl mt-6 text-text" id="setting-sensible-defaults" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#setting-sensible-defaults">Setting Sensible Defaults</a></h2> <pre><code class="language-vim">&quot; Set standard file encoding set encoding=utf8 &quot; No special per file vim override configs set nomodeline &quot; Stop word wrapping set nowrap &quot; Except... on Markdown. That's good stuff. autocmd FileType markdown setlocal wrap &quot; Adjust system undo levels set undolevels=100 &quot; Use system clipboard set clipboard=unnamed &quot; Set tab width and convert tabs to spaces set tabstop=2 set softtabstop=2 set shiftwidth=2 set expandtab &quot; Don't let Vim hide characters or make loud dings set conceallevel=1 set noerrorbells &quot; Number gutter set number &quot; Use search highlighting set hlsearch &quot; Space above/beside cursor from screen edges set scrolloff=1 set sidescrolloff=5 </code></pre> <h2 class="text-3xl mt-6 text-text" id="opinionated-defaults" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#opinionated-defaults">Opinionated Defaults</a></h2> <h3 class="text-2xl mt-4 text-text" id="remapping-%3Cleader%3E-to-%3Cspace%3E" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#remapping-%3Cleader%3E-to-%3Cspace%3E">Remapping <code>&lt;Leader&gt;</code> to <code>&lt;Space&gt;</code></a></h3> <pre><code class="language-vim">let mapleader=&quot;\&lt;SPACE&gt;&quot; </code></pre> <p class="mb-4 text-text leading-7">The <code>&lt;Leader&gt;</code> key is what is pressed before another key to activate some command via a shortcut. By default Vim uses the rather awkward key <code>\</code>. Many respected Vim users choose <code>&lt;Space&gt;</code> as their leader key instead and I agree with this change.</p> <h3 class="text-2xl mt-4 text-text" id="disable-mouse-support" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#disable-mouse-support">Disable mouse support</a></h3> <pre><code class="language-vim">set mouse=r let $NVIM_TUI_ENABLE_CURSOR_SHAPE=1 </code></pre> <p class="mb-4 text-text leading-7">These dotfiles are going to rock this world so hard we don’t need mice where we’re going. Keep those hands on the keyboard and power on.</p> <h3 class="text-2xl mt-4 text-text" id="setting-arrow-keys-to-resize-panes" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#setting-arrow-keys-to-resize-panes">Setting Arrow Keys to Resize Panes</a></h3> <pre><code class="language-vim">nnoremap &lt;Left&gt; :vertical resize -1&lt;CR&gt; nnoremap &lt;Right&gt; :vertical resize +1&lt;CR&gt; nnoremap &lt;Up&gt; :resize -1&lt;CR&gt; nnoremap &lt;Down&gt; :resize +1&lt;CR&gt; &quot; Disable arrow keys completely in Insert Mode imap &lt;up&gt; &lt;nop&gt; imap &lt;down&gt; &lt;nop&gt; imap &lt;left&gt; &lt;nop&gt; imap &lt;right&gt; &lt;nop&gt; </code></pre> <p class="mb-4 text-text leading-7"><em class="italic text-green">This was the config best decision I ever made.</em> <strong class="font-normal text-peach dark:text-yellow">Relying on arrow keys results in less efficient code editing.</strong> Should you find this frustrating, turn those frustrations into learning experiences to find the quickest way to have the cursor reach the target.</p> <h2 class="text-3xl mt-6 text-text" id="dealing-with-buffers-%2F-tabs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#dealing-with-buffers-%2F-tabs">Dealing with Buffers / Tabs</a></h2> <h3 class="text-2xl mt-4 text-text" id="return-to-the-last-file-opened" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#return-to-the-last-file-opened">Return to the last file opened</a></h3> <pre><code class="language-vim">nmap &lt;Leader&gt;&lt;Leader&gt; &lt;c-^&gt; </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Space Space</code> to open previously opened file buffer</li> </ul> <h2 class="text-3xl mt-6 text-text" id="next-%2F-previous-buffer-(tab)" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#next-%2F-previous-buffer-(tab)">Next / Previous Buffer (Tab)</a></h2> <pre><code class="language-vim">nnoremap &lt;Tab&gt; :bnext!&lt;CR&gt; nnoremap &lt;S-Tab&gt; :bprev!&lt;CR&gt;&lt;Paste&gt; </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Tab</code> to switch to next buffer</li> <li class="text-subtext0"><code>Shift Tab</code> to switch to previous buffer</li> </ul> <p class="mb-4 text-text leading-7">This keybinding becomes more intuitive after installing the plugin suggested below to convert buffers to onscreen tabs with vim-airline.</p> <h1 class="text-6xl mt-6 text-pink" id="plugins-to-enhance-functionality" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#plugins-to-enhance-functionality">Plugins to Enhance Functionality</a></h1> <h2 class="text-3xl mt-6 text-text" id="plugin-manager" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#plugin-manager">Plugin Manager</a></h2> <p class="mb-4 text-text leading-7">Stock, even heavily configured, Vim is lacking features offered by other GUI applications. While the objective is not to convert Vim into something it isn’t it is essential to implement some missing functionality through plugins.</p> <p class="mb-4 text-text leading-7">There are several plugin managers out there but vim-plug is the most minimal while being fast in uptime and concurrent plugin installation.</p> <pre><code class="language-vim">call plug#begin('~/.local/share/nvim/plugged') # PLUGINS GO HERE!!! call plug#end() </code></pre> <h3 class="text-2xl mt-4 text-text" id="to-install-plugins" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#to-install-plugins">To Install Plugins</a></h3> <p class="mb-4 text-text leading-7">Between <code>call plug#begin</code> and <code>call plug#end</code> insert the keyword <code>Plug</code> followed by the path to the plugin in Github such as <code>Plug 'username/project</code>. See further examples in the suggested plugins below.</p> <p class="mb-4 text-text leading-7">After adding a <code>Plug</code> and saving the vimrc file run the install command by hitting colon followed by <code>PlugInstall</code>.</p> <pre><code class="language-vim">:PlugInstall </code></pre> <h2 class="text-3xl mt-6 text-text" id="unite" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#unite">Unite</a></h2> <p class="mb-4 text-text leading-7">As stated earlier, Vim is not a GUI. Unite is a commonly used resource for plugins to open panels and other temporary interfaces onscreen. <strong class="font-normal text-peach dark:text-yellow">Unite is required for many plugins to work as expected.</strong></p> <pre><code class="language-vim">Plug 'Shougo/unite.vim' </code></pre> <h2 class="text-3xl mt-6 text-text" id="theme%3A-dracula" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#theme%3A-dracula">Theme: Dracula</a></h2> <pre><code class="language-vim">Plug 'dracula/vim' </code></pre> <p class="mb-4 text-text leading-7">Dracula is dark yet vibrant, needs no additional configuration, and is supported in a <a href="https://draculatheme.com/" class="link">wide variety of apps</a> for a consistent experience.</p> <pre><code class="language-vim">color Dracula </code></pre> <h2 class="text-3xl mt-6 text-text" id="indent-guides" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#indent-guides">Indent Guides</a></h2> <pre><code class="language-vim">Plug 'Yggdroot/indentLine' </code></pre> <p class="mb-4 text-text leading-7">Indentation guides provide a subconcious way of understanding how your code fits together horizontally as well as assuring that indentation is correct at a glance.</p> <pre><code class="language-vim">let g:indentLine_enabled = 1 let g:indentLine_char = &quot;⟩&quot; </code></pre> <h2 class="text-3xl mt-6 text-text" id="git-gutter" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#git-gutter">Git Gutter</a></h2> <pre><code class="language-vim">Plug 'airblade/vim-gitgutter' </code></pre> <p class="mb-4 text-text leading-7">As code is added, modified, or removed a visual aid will be placed alongside the number gutter. gitgutter takes advantage of NeoVim’s async capabilities to never slow you down.</p> <h2 class="text-3xl mt-6 text-text" id="tabs-%26-a-status-bar" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#tabs-%26-a-status-bar">Tabs &amp; a Status Bar</a></h2> <pre><code class="language-vim">Plug 'vim-airline/vim-airline' Plug 'vim-airline/vim-airline-themes' </code></pre> <p class="mb-4 text-text leading-7">Programming in vim can abstract away much of what’s happening behind the scenes. In many ways, this is great — but visual reminders are useful for making day-to-day programming a nobrainer.</p> <p class="mb-4 text-text leading-7">vim-airline is widely popular, and surprisingly beautiful, without making vim look too much like a GUI. This plugin and config will show <strong class="font-normal text-peach dark:text-yellow">current mode, current file path, % scrolled through file, tabs for current buffers, and more.</strong></p> <p class="mb-4 text-text leading-7">It automatically works with plugins it recognizes, such as CtrlP! <em class="italic text-green">(Which we’ll install next…)</em></p> <pre><code class="language-vim">let g:airline#extensions#tabline#enabled=1let g:airline_powerline_fonts=1 set laststatus=2 </code></pre> <h2 class="text-3xl mt-6 text-text" id="fuzzy-finder" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#fuzzy-finder">Fuzzy Finder</a></h2> <pre><code class="language-vim">Plug 'ctrlpvim/ctrlp.vim', { 'on': 'CtrlP' } </code></pre> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">The quickest way to jump to a file in your project is with a fuzzy finder.</strong> Similar experiences can be found in popular code editors like <a href="http://Atom.io" class="link">Atom.io</a> or Sublime. With vim the same experience can be achieved at <em class="italic text-green">lightning speeds when paired with Ag and NeoVim.</em> I’ve tried other fuzzy finders like fzf, but have found ctrlp to have the best experience and most reliable.</p> <pre><code class="language-vim">nnoremap &lt;Leader&gt;p :CtrlP&lt;CR&gt; nnoremap &lt;Leader&gt;t :CtrlP&lt;CR&gt; </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Space t</code> or <code>Space p</code> opens Fuzzy Finder</li> </ul> <h2 class="text-3xl mt-6 text-text" id="find-in-files" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#find-in-files">Find in Files</a></h2> <pre><code class="language-vim">Plug 'mhinz/vim-grepper' </code></pre> <p class="mb-4 text-text leading-7"><strong class="font-normal text-peach dark:text-yellow">Sometimes you just need to find some text somewhere in your project.</strong> The Silver Searcher, also known as Ag does just this and it does so very quickly. Grepper uses Ag’s speed combined with NeoVim’s async abilities to provide a fast way to find code anywhere in your project or buffers.</p> <pre><code class="language-vim">nnoremap &lt;Leader&gt;fp :Grepper&lt;Space&gt;-query&lt;Space&gt; nnoremap &lt;Leader&gt;fb :Grepper&lt;Space&gt;-buffers&lt;Space&gt;-query&lt;Space&gt;-&lt;Space&gt; </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Space f p</code> to type a search to find matches in entire <strong class="font-normal text-peach dark:text-yellow">p</strong>roject</li> <li class="text-subtext0"><code>Space f b</code> to type a search to find matches in current <strong class="font-normal text-peach dark:text-yellow">b</strong>uffers</li> </ul> <h2 class="text-3xl mt-6 text-text" id="project-as-file-tree" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#project-as-file-tree">Project as File Tree</a></h2> <pre><code class="language-vim">Plug 'Shougo/vimfiler.vim', { 'on': 'VimFiler' } </code></pre> <p class="mb-4 text-text leading-7">While <em class="italic text-green">not</em> my preferred way to navigate a project, it’s handy to have a file tree to see directory structure and browse for a file manually.</p> <pre><code class="language-vim">map ` :VimFiler -explorer&lt;CR&gt; map ~ :VimFilerCurrentDir -explorer -find&lt;CR&gt; </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>Space backtick</code> to toggle File Tree</li> <li class="text-subtext0"><code>Space ~</code> to open File Tree from current buffer’s directory</li> </ul> <h2 class="text-3xl mt-6 text-text" id="autocomplete" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#autocomplete">Autocomplete</a></h2> <pre><code class="language-vim">Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' } </code></pre> <p class="mb-4 text-text leading-7">A pretty standard feature of many code editors, an async dropdown tabbable suggestion menu as you type.</p> <pre><code class="language-vim">let g:deoplete#enable_at_startup = 1 inoremap &lt;expr&gt;&lt;tab&gt; pumvisible() ? &quot;\&lt;c-n&gt;&quot; : &quot;\&lt;tab&gt;&quot; </code></pre> <h2 class="text-3xl mt-6 text-text" id="linting" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#linting">Linting</a></h2> <pre><code class="language-vim">Plug 'w0rp/ale' </code></pre> <p class="mb-4 text-text leading-7">Async as you type code linting at its finest. Zero config needed.</p> <h2 class="text-3xl mt-6 text-text" id="sneaking-%E2%80%94-efficient-moving" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#sneaking-%E2%80%94-efficient-moving">Sneaking — Efficient Moving</a></h2> <pre><code class="language-vim">Plug 'justinmk/vim-sneak' </code></pre> <p class="mb-4 text-text leading-7">The secret to never needing to <code>wwwww</code>, or worse <code>lllll</code> is learning how to Sneak around your code. Efficient targeting comes from understanding where you want to jump to and pressing the appropriate sneak keys to get there. Key bindings listed below.</p> <pre><code class="language-vim">let g:sneak#s_next = 1 nmap f &lt;Plug&gt;Sneak_f nmap F &lt;Plug&gt;Sneak_F xmap f &lt;Plug&gt;Sneak_f xmap F &lt;Plug&gt;Sneak_F omap f &lt;Plug&gt;Sneak_f omap F &lt;Plug&gt;Sneak_F </code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><code>f &lt;key&gt;</code> to jump to next <code>&lt;key&gt;</code></li> <li class="text-subtext0"><code>F &lt;key&gt;</code> to jump to previous <code>&lt;key&gt;</code></li> <li class="text-subtext0"><code>f</code> to following match</li> <li class="text-subtext0"><code>s &lt;key&gt;&lt;key&gt;</code> to jump to next <code>&lt;key&gt;&lt;key&gt;</code></li> <li class="text-subtext0"><code>S &lt;key&gt;&lt;key&gt;</code> to jump to previous <code>&lt;key&gt;&lt;key&gt;</code></li> <li class="text-subtext0"><code>s</code> to following match</li> </ul> <h1 class="text-6xl mt-6 text-pink" id="language-specific" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#language-specific">Language Specific</a></h1> <p class="mb-4 text-text leading-7">The web is a very diverse space. I suggest searching <a href="http://vimawesome.com/" class="link">VimAwesome</a> for the languages you program in most often to find what plugins may assist you personally.</p> <h1 class="text-6xl mt-6 text-pink" id="what%E2%80%99s-next" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_2/#what%E2%80%99s-next">What’s Next</a></h1> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/a-modern-terminal-workflow-part-3-5" class="link">Part 3 will cover configuring Zsh</a></p> Tue, 24 Jan 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/a_modern_terminal_workflow_2/ A Modern Terminal Workflow — Part 1 / 5 https://gaiety.me/blog/a_modern_terminal_workflow_1/ <p class="mb-4 text-text leading-7">Perhaps you’re a tinkerer, a javascript ninja, or something else entirely it’s essential to have tools that help you do what you do best and look good doing it.</p> <p class="mb-4 text-text leading-7">This is an opinionated walkthrough using tools both new and old that are performant and work well together. Through a combination of Git, NeoVim, Zsh, Tmux and iTerm2 this article will take you step by step in writing a dotfiles repo to set up a MacOS programming environment.</p> <p class="mb-4 text-text leading-7">Optionally, skip ahead and <a href="https://github.com/hergaiety/modern-terminal-workflow" class="link">see the final result</a>.</p> <h2 class="text-3xl mt-6 text-text" id="what-is-a-dotfile%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#what-is-a-dotfile%3F">What is a Dotfile?</a></h2> <p class="mb-4 text-text leading-7">A dotfile is simply a file that begins with a <code>.</code> before the filename such as <code>.vimrc</code>. These are commonly program configurations and are <em class="italic text-green">often times hidden by default on Unix filesystems.</em></p> <h2 class="text-3xl mt-6 text-text" id="what-is-a-dotfiles-repo%3F" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#what-is-a-dotfiles-repo%3F">What is a Dotfiles repo?</a></h2> <p class="mb-4 text-text leading-7">Git can host dotfiles and setup scripts to set up a new machine with your tools configured exactly the way you want them. An ideal setup script can be run after a fresh clone of the git repo to symlink its configuration dotfiles with the host machine for a portable terminal workflow.</p> <h2 class="text-3xl mt-6 text-text" id="getting-started" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#getting-started">Getting Started</a></h2> <h3 class="text-2xl mt-4 text-text" id="updating-xcode" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#updating-xcode">Updating Xcode</a></h3> <p class="mb-4 text-text leading-7">Before we get started, ensure Xcode is up to date. It’s an easy step to miss and takes some time but is <em class="italic text-green">essential for NeoVim to build</em>.</p> <ol> <li class="text-subtext0">Update Xcode to the latest version using the appstore.</li> <li class="text-subtext0"><code>xcode-select --install</code> to install xcode’s cli tools.</li> </ol> <h3 class="text-2xl mt-4 text-text" id="creating-the-local-git-repo" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#creating-the-local-git-repo">Creating the local Git Repo</a></h3> <pre><code class="language-bash"><span class="hljs-built_in">mkdir</span> ~/dotfiles <span class="hljs-comment"># make a new dotfiles directory</span> <span class="hljs-built_in">cd</span> ~/dotfiles <span class="hljs-comment"># enter the new dotfiles directory</span> git init <span class="hljs-comment"># ready the directory for git version control</span> <span class="hljs-built_in">touch</span> init.sh zshrc tmux.conf vimrc <span class="hljs-comment"># creating the config files</span> <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="the-initialize-script" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#the-initialize-script">The Initialize Script</a></h2> <p class="mb-4 text-text leading-7">Like many Git projects a starting point is required. Through an init shell script a series of commands can be written in a way that can be reproduced on as many machines as desired.</p> <pre><code class="language-bash">vim init.sh <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="bash-script" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#bash-script">Bash Script</a></h3> <p class="mb-4 text-text leading-7">A shell script needs an interpreter. We will be installing Zsh later in this script, but MacOS will be running Bash out of the box and thus that is what we will set the interpreter as.</p> <pre><code class="language-bash"><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="installing-system-dependencies" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#installing-system-dependencies">Installing System Dependencies</a></h3> <p class="mb-4 text-text leading-7">Throughout this walkthrough we’ll be installing package managers of varying types. Luckily here we can leverage a MacOS built in tool called Brew which does just this. Brew knows how to find, download, and install CLI applications out of the box and with the addition of an additional tool called Cask it can install GUI applications as well.</p> <pre><code class="language-bash">brew install zsh tmux neovim/neovim/neovim python3 ag reattach-to-user-namespace brew tap caskroom/cask brew cask install iterm2 <span class="hljs-language-icon">bash</span></code></pre> <ul class="list-disc ml-4 mb-4 text-subtext0"> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Zsh</strong> is a powerful shell and an alternative to MacOS’s default Bash. This will be covered in more detail in part 3.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Tmux</strong> is a terminal multiplexer. Using some keyboard hotkeys you can use tabs and split panes for better multitasking.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">NeoVim</strong> is a modern alternative to Vim, a terminal based code editor with efficiency and code reading in mind. This will be covered in more detail in part 2. NeoVim has a strange path due to being in active development at the moment.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Python</strong> is installed to extend NeoVim’s plugin support.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Ag</strong> is a code-searching tool similar to Ack but faster. This will be covered more in part 2.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">Reattach-to-user-namespace</strong> is a MacOS Sierra fix to ensure the workflow has access to the clipboard so share copy and paste functionality as one would expect in the correct namespace.</li> <li class="text-subtext0"><strong class="font-normal text-peach dark:text-yellow">iTerm2</strong> is a terminal replacement with a great level of customizability and integration with Tmux.</li> </ul> <h3 class="text-2xl mt-4 text-text" id="upgrading-neovim-to-have-plugin-and-python-support" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#upgrading-neovim-to-have-plugin-and-python-support">Upgrading NeoVim to Have Plugin and Python Support</a></h3> <p class="mb-4 text-text leading-7">To make NeoVim a powerful enough tool to be a primary code editor some additional functionality is needed.</p> <p class="mb-4 text-text leading-7"><a href="https://github.com/junegunn/vim-plug" class="link">vim-plug</a> is installed as a package manager which will be leveraged in Part 2 to pull down user made plugins like themes, new movements, and ways to navigate the entire project. Some plugins rely on Python to work so a <code>pip3</code> command is ran to upgrade NeoVim to support it.</p> <pre><code class="language-bash">curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim pip3 install neovim <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="installing-fonts" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#installing-fonts">Installing Fonts</a></h2> <p class="mb-4 text-text leading-7">Brew’s Cask capability can be extended to allowing the installation of fonts to the filesystem.</p> <p class="mb-4 text-text leading-7">There are many programmer fonts available to choose from, but <em class="italic text-green">Fira Code has stolen my heart</em> to the point of it being used on this very blog article. Monospaced fonts are ideal for programming because every character is the same width meaning code naturally aligns vertically. Fira Code is designed with programming ligatures making commonly used operators combine together into a single symbol. =&gt; &lt;= <code>=&gt; =&lt;</code></p> <pre><code class="language-bash">brew tap caskroom/fonts brew cask install font-fira-code <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="setting-zsh-as-default-shell" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#setting-zsh-as-default-shell">Setting ZSH as Default Shell</a></h2> <pre><code class="language-bash">chsh -s /usr/local/bin/zsh <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="setting-configs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#setting-configs">Setting Configs</a></h2> <h3 class="text-2xl mt-4 text-text" id="removing-any-existing-configs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#removing-any-existing-configs">Removing Any Existing Configs</a></h3> <p class="mb-4 text-text leading-7">Some cleanup in case these files already exist.</p> <pre><code class="language-bash"><span class="hljs-built_in">rm</span> -rf ~/.vim ~/.vimrc ~/.zshrc ~/.tmux ~/.tmux.conf ~/.config/nvim 2&gt; /dev/null <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="creating-necessary-directories" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#creating-necessary-directories">Creating Necessary Directories</a></h3> <p class="mb-4 text-text leading-7">NeoVim expects a few directories to exist and so it’s best we add them now.</p> <pre><code class="language-bash"><span class="hljs-built_in">mkdir</span> -p ~/.config ~/.config/nvim <span class="hljs-language-icon">bash</span></code></pre> <h3 class="text-2xl mt-4 text-text" id="linking-configs" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#linking-configs">Linking Configs</a></h3> <p class="mb-4 text-text leading-7">Symlinks can allow the file system point from where configs are expected to be to this repo.</p> <pre><code class="language-bash"><span class="hljs-built_in">ln</span> -s ~/dotfiles/zshrc ~/.zshrc <span class="hljs-built_in">ln</span> -s ~/dotfiles/tmux.conf ~/.tmux.conf <span class="hljs-built_in">ln</span> -s ~/dotfiles/vimrc ~/.config/nvim/init.vim <span class="hljs-language-icon">bash</span></code></pre> <h2 class="text-3xl mt-6 text-text" id="wrapping-up" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#wrapping-up">Wrapping Up</a></h2> <ol> <li class="text-subtext0">Run your newly written <a href="http://init.sh" class="link">init.sh</a> with <code>bash init.sh</code> and then log out.</li> <li class="text-subtext0">Upon logging back in, launch iTerm2.</li> </ol> <p class="mb-4 text-text leading-7">We’re now running in Zsh and instead of vim we can use <code>nvim</code>.</p> <blockquote class="font-mono fancy-blockquote"> <p class="mb-4 text-text leading-7">Optionally <code>vim</code> can launch <code>nvim</code> if you add <code>alias vim=&quot;nvim&quot;</code> to your <a href="http://init.sh" class="link">init.sh</a></p> </blockquote> <h1 class="text-6xl mt-6 text-pink" id="what%E2%80%99s-next" tabindex="-1"><a class="header-anchor" href="https://gaiety.me/blog/a_modern_terminal_workflow_1/#what%E2%80%99s-next">What’s Next</a></h1> <p class="mb-4 text-text leading-7"><a href="https://gaiety.me/a-modern-terminal-workflow-part-2-5" class="link">Part 2 covers configuring NeoVim</a></p> Thu, 19 Jan 2017 24:00:00 GMT Ava Gaiety W. https://gaiety.me/blog/a_modern_terminal_workflow_1/