<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Typing GIF Notes]]></title><description><![CDATA[Typing GIF Notes]]></description><link>https://ethanmoorenotes.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 30 Oct 2026 23:25:55 GMT</lastBuildDate><atom:link href="https://ethanmoorenotes.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[prefers-reduced-motion for text animations: what I actually turn off]]></title><description><![CDATA[Most "respect reduced motion" advice stops at wrapping everything in a media query and setting animation: none. For animated text that is often the wrong…]]></description><link>https://ethanmoorenotes.hashnode.dev/prefers-reduced-motion-for-text-animations-what-i-actually-turn-off</link><guid isPermaLink="true">https://ethanmoorenotes.hashnode.dev/prefers-reduced-motion-for-text-animations-what-i-actually-turn-off</guid><dc:creator><![CDATA[Ethan Moore]]></dc:creator><pubDate>Wed, 28 Oct 2026 23:00:47 GMT</pubDate><content:encoded><![CDATA[<p>Most "respect reduced motion" advice stops at wrapping everything in a media query and setting <code>animation: none</code>. For animated text that is often the wrong call, because the animation is carrying information: a word appearing, a status changing, a headline cycling through options.</p>
<p>Here is the checklist I use now.</p>
<p><strong>1. Keep the final state, drop the journey.</strong>
If a heading types itself out, reduced-motion users should get the finished heading immediately. Don't hide it, don't leave it at the first frame.</p>
<pre><code class="language-css">@media (prefers-reduced-motion: reduce) {
  .typing { animation: none; width: auto; border-right: 0; }
}
</code></pre>
<p><strong>2. Rotating words become a static list or one word.</strong>
A headline that cycles "fast / simple / free" should either show one representative word or the whole phrase ("fast, simple and free"). Cycling with a crossfade instead of a slide is still cycling.</p>
<p><strong>3. Blinking cursors go.</strong>
A blinking caret is pure decoration and it flickers. Remove it entirely rather than slowing it down.</p>
<p><strong>4. Fades are usually fine, movement is not.</strong>
Opacity changes under ~200ms rarely bother anyone. Translate, scale and parallax are what trigger vestibular issues. I keep short fades and remove motion.</p>
<p><strong>5. Autoplaying GIFs need a different answer.</strong>
CSS media queries can't pause a GIF. Options: swap to a static first-frame PNG with <code>&lt;picture&gt;</code> and a media query on the <code>source</code>, or use a short video with a poster and no autoplay.</p>
<pre><code class="language-html">&lt;picture&gt;
  &lt;source srcset="hero-static.png" media="(prefers-reduced-motion: reduce)"&gt;
  &lt;img src="hero.gif" alt="Headline typing out: Ship docs people read"&gt;
&lt;/picture&gt;
</code></pre>
<p><strong>6. Test it for real.</strong>
macOS: System Settings &gt; Accessibility &gt; Display &gt; Reduce motion. Windows: Settings &gt; Accessibility &gt; Visual effects &gt; Animation effects off. DevTools can also emulate it under Rendering.</p>
<p>What I still haven't settled: whether a slow marquee of logos counts as essential. I've been removing it, but I'd like to hear how others handle it.</p>
]]></content:encoded></item><item><title><![CDATA[A Practical Checklist for a GitHub README That People Actually Read]]></title><description><![CDATA[When I ship a small web tool or open-source utility, I want other developers to evaluate it quickly, understand how to run it, and decide whether it solves…]]></description><link>https://ethanmoorenotes.hashnode.dev/a-practical-checklist-for-a-github-readme-that-people-actually-read</link><guid isPermaLink="true">https://ethanmoorenotes.hashnode.dev/a-practical-checklist-for-a-github-readme-that-people-actually-read</guid><category><![CDATA[GitHub]]></category><category><![CDATA[documentation]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[markdown]]></category><dc:creator><![CDATA[Ethan Moore]]></dc:creator><pubDate>Mon, 26 Oct 2026 14:20:11 GMT</pubDate><content:encoded><![CDATA[<p>When I ship a small web tool or open-source utility, I want other developers to evaluate it quickly, understand how to run it, and decide whether it solves their problem. Most developers give a repository only a quick glance before bouncing. If they hit a wall of dense text, broken images, or fifteen decorative badges, they move on.</p>
<p>After maintaining a handful of tiny utilities, I have settled on a disciplined approach to documentation. Here is the exact checklist I use to create clean, readable, and functional README files.</p>
<h2>Structure: The Inverted Pyramid</h2>
<p>I structure a README much like a news article: the most critical information sits right at the top, followed by progressively detailed instructions.</p>
<ol>
<li><strong>The One-Sentence Hook</strong>: Immediately under the repository title, write one clear sentence explaining what the tool does, who it is for, and how it differs from existing solutions.</li>
<li><strong>Visual Proof</strong>: Place a screenshot or a concise animation right below the hook. Showing the user interface or terminal output immediately anchors the mental model.</li>
<li><strong>Quick Start</strong>: Provide no more than three terminal commands to get running. If installation requires an API key or an extensive configuration file, show a minimal working default first.</li>
<li><strong>Core Features</strong>: Use a bulleted list of four to six points. Keep them focused on capabilities, not internal architecture.</li>
<li><strong>Configuration Options</strong>: Present flags, environment variables, or schema values in a Markdown table. Columns should be: Option, Type, Default, and Description.</li>
</ol>
<p>If setup instructions exceed two screens of scrolling, move the deep-dive documentation into a separate file inside a documentation directory.</p>
<h2>Badges: Practicing Ruthless Restraint</h2>
<p>A dense block of badges creates visual noise, and every badge adds another external image to load. I limit project badges to a maximum of four, arranged on a single line:</p>
<ul>
<li>Current build or test status (CI).</li>
<li>Latest package or release version.</li>
<li>Software license.</li>
<li>Test coverage percentage (only if the project actively maintains high coverage).</li>
</ul>
<p>Avoid badges for social media followers, arbitrary activity meters, or redundant framework logos. Every badge should convey actionable health metrics to someone deciding whether to depend on your code.</p>
<h2>Visuals and Animations: High Impact, Low Bandwidth</h2>
<p>Static images are almost always preferable to animations, but interactive tools often benefit from a quick demonstration of state changes or CLI output. </p>
<p>When you do use motion, keep the file tiny. A multi-megabyte GIF loaded over a mobile connection drags the entire page down.</p>
<h3>Video and Animation Rules</h3>
<ul>
<li><strong>Duration</strong>: Keep animations between 4 and 8 seconds. Loop seamlessly if possible.</li>
<li><strong>Framerate</strong>: Cap animations at 12 to 15 frames per second. Smooth 60 fps capture is unnecessary for user interfaces and text prompts.</li>
<li><strong>Resolution</strong>: Keep widths around 600px to 800px. GitHub scales wider images down to fit the README column anyway, so extra pixels mostly add bytes.</li>
<li><strong>Target Size</strong>: Aim for under 1.5 MB for animations, and under 150 KB for static screenshots.</li>
</ul>
<p>To convert a screen recording into a small, clean GIF without proprietary apps, I run this single <code>ffmpeg</code> command:</p>
<pre><code class="language-bash">ffmpeg -i input.mov -vf "fps=12,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse=dither=bayer" -loop 0 output.gif
</code></pre>
<p>Limiting <code>max_colors</code> to 128 usually trims file size while keeping simple UI text readable; raise it back to 256 if you see banding. For static PNG screenshots, I run <code>pngquant</code> to strip bloat before committing:</p>
<pre><code class="language-bash">pngquant --quality=80-90 --strip --skip-if-larger screenshot.png --output screenshot-opt.png
</code></pre>
<p>Never commit raw, unoptimized screen captures straight from your operating system's default screenshot utility; a full-resolution desktop grab on a high-DPI screen can easily run to several megabytes.</p>
<h2>Accessibility: Don't Skip Alt Text</h2>
<p>Visuals should never be the only way to understand your tool. Screen readers rely on the alt text in your Markdown image syntax, and users on constrained networks depend on it while assets load.</p>
<p>Avoid placeholder descriptions:</p>
<ul>
<li><strong>Poor</strong>: <code>![demo](assets/demo.gif)</code></li>
<li><strong>Better</strong>: <code>![Animated demonstration of entering a CSS selector and seeing matching DOM elements highlight in real time](assets/demo.gif)</code></li>
</ul>
<p>When sharing a terminal session, write a brief, copy-pasteable text block directly beneath the image. This helps developers using screen readers follow along, while letting sighted developers copy commands without retyping them from an image.</p>
<h2>The Final Review Checklist</h2>
<p>Before pushing changes to my default branch, I run through this fast verification:</p>
<ul>
<li><input disabled type="checkbox" /> Title and one-sentence explanation are visible without scrolling.</li>
<li><input disabled type="checkbox" /> Badges occupy no more than one clean horizontal row.</li>
<li><input disabled type="checkbox" /> Quick start requires three or fewer commands to reach a running state.</li>
<li><input disabled type="checkbox" /> Visual assets reside within the repository or release assets, optimized under 1.5 MB.</li>
<li><input disabled type="checkbox" /> All images have descriptive alt text.</li>
<li><input disabled type="checkbox" /> Code blocks specify the language identifier for syntax highlighting (for example, <code>bash</code> or <code>typescript</code> after the opening fence).</li>
<li><input disabled type="checkbox" /> Markdown renders properly with zero broken formatting tags on mobile widths.</li>
</ul>
<p>A disciplined README does not need to be exhaustive. Its real job is to take someone from zero context to a working mental model as quickly as possible.</p>
]]></content:encoded></item><item><title><![CDATA[Animated Release Banners for GitHub Releases and CHANGELOG.md]]></title><description><![CDATA[GitHub releases and project changelogs serve a straightforward utility: they tell developers what changed, what broke, and what improved. Yet, most release…]]></description><link>https://ethanmoorenotes.hashnode.dev/animated-release-banners-for-github-releases-and-changelog-md</link><guid isPermaLink="true">https://ethanmoorenotes.hashnode.dev/animated-release-banners-for-github-releases-and-changelog-md</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Devops]]></category><category><![CDATA[markdown]]></category><dc:creator><![CDATA[Ethan Moore]]></dc:creator><pubDate>Sun, 25 Oct 2026 09:31:27 GMT</pubDate><content:encoded><![CDATA[<p>GitHub releases and project changelogs serve a straightforward utility: they tell developers what changed, what broke, and what improved. Yet, most release feeds blend into an identical wall of plain text, standard issue commit hashes, and nested bullet points. Adding a lightweight visual anchor at the top of an announcement provides immediate context before the reader dives into the detailed pull requests.</p>
<p>Generating an <a href="https://typinggif.com/github-readme-typing-gif">animated typing GIF for GitHub</a> allows maintainers to headline a release with a focused, dynamic banner—such as <code>v2.4.0 — faster cold starts</code>—without relying on heavy video production software or manual asset design workflows. Done cleanly, an animated header adds polish to releases and documentation while preserving repository performance.</p>
<h2>Drafting a Focused, Single-Line Message</h2>
<p>An animated release banner should never try to replace the release notes themselves. Its purpose is to deliver the single most important takeaway of the release in a couple of seconds. </p>
<p>Keep your copy restricted to a single phrase that pairs the version number with the headline feature or bug fix:</p>
<ul>
<li><code>v1.8.0 — zero-config ESM builds</code></li>
<li><code>v2.4.0 — faster cold starts and leaner runtime</code></li>
<li><code>v3.0.0-rc.1 — breaking: new config schema</code></li>
</ul>
<p>When preparing the copy, aim well below the hard limit of 280 characters. Keeping the text short ensures that the animation remains punchy and completes its cycle quickly. If your text exceeds 280 characters, the generation tool warns instead of silently truncating the input, but long sentences degrade readability on smaller screens anyway. Treat this copy like a commit title: clear, direct, and focused on the primary delta.</p>
<h2>Selecting Presets and Typography</h2>
<p>Rather than dealing with complex keyframe editors, you can choose from three targeted animation presets depending on your repository's aesthetic:</p>
<ul>
<li><strong>Typewriter</strong>: Emulates classic sequential character entry. This works well for general open-source tools and libraries.</li>
<li><strong>Terminal</strong>: Emulates a command-line interface entry, complete with a terminal cursor. It fits CLI tools, devops infrastructure, and system utilities.</li>
<li><strong>Word-by-word</strong>: Displays the message word by word rather than character by character. This preset is ideal for longer messages because readers process full tokens faster, reducing overall playback friction.</li>
</ul>
<p>Pair your chosen preset with a font that mirrors your project's ecosystem. Four typography options cover the spectrum of developer documentation:</p>
<ul>
<li><strong>Inter</strong>: A clean, contemporary sans-serif suited for web frameworks and user-facing utilities.</li>
<li><strong>Space Grotesk</strong>: A proportional sans-serif with geometric, tech-forward accents.</li>
<li><strong>JetBrains Mono</strong>: A structured monospace typeface designed specifically for code clarity.</li>
<li><strong>IBM Plex Mono</strong>: An industrial monospace font with a distinct engineering pedigree.</li>
</ul>
<p>Because the tool is not a keyframe editor, you do not need to manage frame easing, spatial coordinates, or entry curves. You simply configure the preset and typography, check the preview, and produce an asset that carries no watermark.</p>
<h2>Timing, Limits, and Browser-Side Rendering</h2>
<p>Animated banners must respect viewer attention. The GIF loops continuously, so the total animation duration should stay under 10 seconds. Anything longer becomes distracting if a user leaves the release page open while reading detailed upgrade steps.</p>
<p>On the free tier, GIF output is generated up to an 800px longest edge at 15 fps, with a maximum length of 10 seconds. This framerate and resolution balance crisp text rendering with minimal bandwidth consumption. File size is also protected by a ceiling: output is capped at 50 MiB, though short text banners will typically render well below this threshold.</p>
<p>Privacy and data boundary considerations are straightforward. The rendering process executes in the browser on the user's device, meaning your unreleased version strings and internal feature descriptions are never uploaded to an external server during export.</p>
<h2>Storage Architecture: Repo Commits vs. Release Assets</h2>
<p>Once the banner is generated, you must decide where to host the asset: inside the Git repository itself, or hosted externally via the GitHub release editor.</p>
<h3>Approach A: Drag-and-Drop into the GitHub Release Editor</h3>
<p>When drafting a new release in the GitHub UI, you can drag your generated GIF directly into the release description field. GitHub uploads the file to its user asset storage (typically on <code>github-production-user-asset-6210df.s3.amazonaws.com</code> or similar CDN endpoints) and outputs a permanent Markdown image link:</p>
<pre><code class="language-markdown">![v2.4.0 Banner](https://github.com/user-attachments/assets/example-uuid)

## What's Changed
...
</code></pre>
<p><em>Advantages</em>: Zero impact on your <code>.git</code> repository size; releases remain independent.<br /><em>Disadvantages</em>: The image URL is managed outside your version control tree, making local previewing in an offline <code>CHANGELOG.md</code> less reliable.</p>
<h3>Approach B: Committing to the Repository</h3>
<p>If you maintain a <code>CHANGELOG.md</code> file within the repository, storing assets within a dedicated folder (such as <code>.github/assets/releases/</code>) ensures that documentation rendered locally in an IDE looks identical to GitHub's rendered web view.</p>
<p>When referencing assets in <code>CHANGELOG.md</code>, always use relative paths:</p>
<pre><code class="language-markdown"># Changelog

## [2.4.0] - 2024-03-15

![v2.4.0 — faster cold starts](.github/assets/releases/v2.4.0.gif)

### Performance
* Optimized container boot sequence.
</code></pre>
<p>Relative paths ensure that the image renders correctly across branches, forks, and local documentation servers.</p>
<h2>Writing Accessible Alt Text</h2>
<p>Screen readers and accessibility scanners cannot parse text baked into a raster GIF. Leaving alt text empty or setting it to a generic label like <code>image</code> creates an accessibility barrier and weakens search indexing.</p>
<p>Always include the explicit version number and headline within the alt text:</p>
<pre><code class="language-markdown">&lt;!-- Bad --&gt;
![](./banner.gif)
![Banner](./banner.gif)

&lt;!-- Good --&gt;
![Release banner: v2.4.0 — faster cold starts](./assets/v2.4.0.gif)
</code></pre>
<p>If an enterprise proxy or slow connection blocks GIF loading, the alt text preserves the exact meaning intended by the visual banner.</p>
<h2>Avoiding Repository Bloat</h2>
<p>Git tracks binary file changes inefficiently. Every time you commit a modified GIF under the same filename, Git stores the entire binary blob again, expanding the repository history.</p>
<p>To prevent unnecessary bloat:</p>
<ol>
<li><strong>Name files explicitly by version</strong>: Store assets as <code>v2.4.0.gif</code>, <code>v2.5.0.gif</code>, etc., rather than continuously overwriting a single <code>latest-release.gif</code>. This clarifies asset mapping over time.</li>
<li><strong>Prune past release assets if necessary</strong>: For high-velocity repositories releasing multiple times a week, consider keeping only the latest banner in the repository tree and relying on release editor uploads for historical logs.</li>
<li><strong>Keep durations short</strong>: Sticking close to 3–5 seconds keeps frame counts low, yielding compact files that add negligible weight to clones.</li>
</ol>
<h2>When to Use Silent MP4 Instead</h2>
<p>While GIFs offer universal inline rendering in Markdown image tags, GitHub's release notes editor also accepts video uploads directly. </p>
<p>You can export a silent MP4 at 720p30 up to 10 seconds as an alternative format. Consider using silent MP4 files when:</p>
<ul>
<li><strong>Frame pacing requires higher fluidity</strong>: MP4 outputs render at 30 fps (versus 15 fps for GIF), yielding smoother cursor motions and character reveals.</li>
<li><strong>Bandwidth efficiency is critical</strong>: The H.264 video codec compresses solid backgrounds and static typographic regions far more efficiently than the older LZW-compressed GIF format, often reducing file footprint significantly at equal resolution.</li>
<li><strong>Publishing exclusively to GitHub Releases</strong>: If you do not need the banner to render inside plain <code>CHANGELOG.md</code> files where HTML5 video tags are stripped or unsupported, dragging an MP4 directly into the release notes UI provides an optimal visual result.</li>
</ul>
<p>By keeping banners under 10 seconds, choosing typography that reflects your project, and managing your asset storage deliberately, animated release headers turn routine maintenance logs into engaging milestones.</p>
<p><em>GitHub is a trademark of its owner; not affiliated.</em></p>
]]></content:encoded></item></channel></rss>