<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preload" as="image" href="https://bytes.dev/images/bytes-banner-rounded.png">
<link rel="preload" as="image" href="https://bytes.dev/images/content/eyes.png">
<link rel="preload" as="image" href="https://bytes.dev/images/content/white-monster.jpg">
<link rel="preload" as="image" href="https://bytes.dev/images/fb-share-icon.png">
<link rel="preload" as="image" href="https://bytes.dev/images/li-share-icon.png">
<link rel="preload" as="image" href="https://bytes.dev/images/tw-share-icon.png">
<link rel="preload" as="image" href="https://bytes.dev/images/em-share-icon.png">
<link rel="preload" as="image" href="https://bytes.dev/images/content/coderabbit-logo.png">
<link rel="preload" as="image" href="https://bytes.dev/images/content/liam-neeson.jpg">
<link rel="preload" as="image" href="https://bytes.dev/images/content/spot-the-bug.png">
<link rel="preload" as="image" href="https://bytes.dev/images/content/cool-bits.png">
<link rel="preload" as="image" href="https://bytes.dev/images/bytes-icon.png">
<title>Bytes: TypeScript Can Read Your Weird Files</title>
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono&family=Outfit:wght@400;500;700;900&family=Paytone+One" rel="stylesheet">
<style>@media (prefers-color-scheme: dark) {
.email-wrapper {
color: #F9F4DA !important;
background-color: #0F0D0E !important;
}
hr {
border-color: #262422 !important;
}
mark {
background-color: #231F20 !important;
color: #F9F4DA !important;
}
pre {
background-color: #231F20 !important;
border: 1px solid #231F20 !important;
color: #F9F4DA !important;
}
.bg-alt {
background-color: #231F20 !important;
}
.unsubscribe-link {
color: #504C48 !important;
}
.token.punctuation {
color: #f9f4da !important;
}
}
@media screen and (min-width: 600px) {
.mobile-break {
display: none;
}
}</style>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<table class="email-wrapper" border="0" cellspacing="0" width="100%" style="background-color: #FFF; border-collapse: collapse; color: #231F20; font-family: Outfit, sans-serif; font-size: 18px; width: 100%;"><tbody><tr>
<td style="border-collapse: collapse !important; word-break: normal;"></td>
<td width="600px" style="border-collapse: collapse !important; width: 600px; word-break: normal;"><div style="max-width:600px;padding-top:80px">
<div style="text-align:center"><img width="600" style="max-width: 100%; padding-bottom: 40px;" src="https://bytes.dev/images/bytes-banner-rounded.png" alt="Bytes"></div>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;"><strong style="font-weight: 600;">Today’s issue:</strong> JPEG’s new t-shirt size, a TypeScript pregnancy test, and a classic case of bundle phobia.</p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">Welcome to <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/reh8h9umpwl60nu2h6/aHR0cHM6Ly9ieXRlcy5kZXYvYXJjaGl2ZXMvNTMz" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682828">#533</a>.</p>
<hr style="border: 0; border-bottom: 5px solid; border-color: #f5f5f5; margin-bottom: 100px; margin-top: 100px;">
<div style="text-align:center;margin-bottom:36px">
<img width="80" src="https://bytes.dev/images/content/eyes.png" alt="Eyeballs logo" style="max-width: 100%;"><h2 style="font-family: Paytone One, sans-serif; font-size: 28px; margin-top: 10px; text-transform: uppercase;">The Main Thing</h2>
</div>
<div class="bg-alt" style="background-color: #f5f5f5; border-radius: 16px; margin-bottom: 40px; max-width: 100%; padding: 24px; padding-bottom: 12px;">
<img src="https://bytes.dev/images/content/white-monster.jpg" alt="White-haired man in sunglasses holds up a can of white Monster Energy" width="600" style="border-radius: 5px; max-width: 100%;"><p style="font-family: Outfit, sans-serif; font-size: 17px; font-style: italic; line-height: 1; margin: 0; padding-bottom: 4px; padding-left: 24px; padding-right: 24px; padding-top: 10px; text-align: center;">Nectar of the gods<!-- --> </p>
</div>
<h3 style="font-size: 24px; margin-bottom: 0; padding-left: 24px; padding-right: 24px;">TypeScript Can Read Your Weird Files:</h3>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">What happens when you give a bunch of millennial JavaScript developers White Monsters, gas station Tornados, and access to the internet? They’re going to try and stick their JavaScript into every imaginable type of file, which explains why <code style="font-size: 15px;">.jsx</code>, <code style="font-size: 15px;">.mdx</code>, <code style="font-size: 15px;">.astro</code>, <code style="font-size: 15px;">.svelte</code>, and <code style="font-size: 15px;">.vue</code> exist.</p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">But as we “matured” into TypeScript developers, this created a bunch of problems. In order to type check these random file types, you either needed to wrap the compiler and ship something like <code style="font-size: 15px;">vue-tsc</code> or use a project like <code style="font-size: 15px;">@volar/typescript</code> to build a language server for your project. That was until <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/8ghqh3uo8q6rlzbkh9/aHR0cHM6Ly9kZXZibG9ncy5taWNyb3NvZnQuY29tL3R5cGVzY3JpcHQvYW5ub3VuY2luZy10eXBlc2NyaXB0LTctMS1iZXRhLw==" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682830">TypeScript 7.1 beta shipped this past week</a>, which introduced a new feature called Content Mappers.</p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;"><strong style="font-weight: 600;">What are content mappers?</strong></p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">Content mappers are a new type of plugin that teaches TypeScript how to translate an arbitrary file type into a virtual TypeScript file that the type checker can use. It’s what powers <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/vqh3hmuo6e9wp0hghl/aHR0cHM6Ly9yZXlsby5kZXYv" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682831"><code style="font-size: 15px;">reylo</code></a>’s type inference for <code style="font-size: 15px;">.sql</code> files.</p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;"><em>Here’s how they work:</em></p>
<ul>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><strong style="font-weight: 600;">Register a mapper:</strong> Content mappers are added via <code style="font-size: 15px;">tsconfig.json</code> and specify the file extensions they are designed to handle. They are then executed by running <code style="font-size: 15px;">tsc --runExternalCode</code>.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><strong style="font-weight: 600;">Transform the source:</strong> The mapper converts matching files into virtual TypeScript files with references to the original source. If you’re code curious, <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/l2heh6ulp6mx37u6h0/aHR0cHM6Ly9naXRodWIuY29tL0RhbmllbFJvc2Vud2Fzc2VyL2NvbnRlbnQtbWFwcGVyLXNhbXBsZS9ibG9iL21haW4vZGh0bWwtY29udGVudC1tYXBwZXIvc3JjL2h0bWwudHM=" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682832">here’s an example for HTML</a>.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><strong style="font-weight: 600;">Check the types:</strong> TypeScript checks the virtual files and uses span mappings to report errors at the correct locations in your original file. These mappings also enable code completions, hover hints, and click-to-definition navigation (if anyone still uses their IDE).</p>
</li>
</ul>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;"><strong style="font-weight: 600;">Bottom Line:</strong> Content mappers are TypeScript’s midlife crisis marathon: you atone for the sins of your past, but it’s maybe a few years too late for it to really matter <span role="img" aria-label="">🫠</span>.</p>
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse; margin-top: 40px; text-align: center;"><tbody><tr><td style="border-collapse: collapse !important; padding-top: 12px; word-break: normal;">
<a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/m2h7h6u3xm648pimhq/aHR0cHM6Ly9mYWNlYm9vay5jb20vc2hhcmVyL3NoYXJlci5waHA_dT1odHRwcyUzQSUyRiUyRmJ5dGVzLmRldiUyRmFyY2hpdmVzJTJGNTMz" rel="noopener" style="color: #12b5e5; font-weight: 600; padding-left: 5px; text-decoration: none;" target="_blank" url-id="1898682833"><img alt="" style="display: inline-block; max-width: 100%; width: 32px;" width="25" src="https://bytes.dev/images/fb-share-icon.png"></a><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/dphehmuex89p09imh4/aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL3NoYXJpbmcvc2hhcmUtb2Zmc2l0ZS8_dXJsPWh0dHBzJTNBJTJGJTJGYnl0ZXMuZGV2JTJGYXJjaGl2ZXMlMkY1MzM=" rel="noopener" style="color: #12b5e5; font-weight: 600; padding-left: 5px; text-decoration: none;" target="_blank" url-id="1898682834"><img alt="" style="display: inline-block; max-width: 100%; width: 32px;" width="25" src="https://bytes.dev/images/li-share-icon.png"></a><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/e0hph0u7zq3r08u8h2/aHR0cHM6Ly90d2l0dGVyLmNvbS9pbnRlbnQvdHdlZXQvP3RleHQ9SlBFRyVFMiU4MCU5OXMlMjBuZXclMjB0LXNoaXJ0JTIwc2l6ZSUyQyUyMGElMjBUeXBlU2NyaXB0JTIwcHJlZ25hbmN5JTIwdGVzdCUyQyUyMGFuZCUyMGElMjBjbGFzc2ljJTIwY2FzZSUyMG9mJTIwYnVuZGxlJTIwcGhvYmlhLiZ1cmw9aHR0cHMlM0ElMkYlMkZieXRlcy5kZXYlMkZhcmNoaXZlcyUyRjUzMw==" rel="noopener" style="color: #12b5e5; font-weight: 600; padding-left: 5px; text-decoration: none;" target="_blank" url-id="1898682835"><img alt="" style="display: inline-block; max-width: 100%; width: 32px;" width="25" src="https://bytes.dev/images/tw-share-icon.png"></a><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/7qh7h2u9ew2nonizh6/bWFpbHRvOj9zdWJqZWN0PVlvdSUyMGxpa2UlMjBjb3JuYnJlYWQlM0YmYm9keT1UaG91Z2h0JTIweW91JTI3ZCUyMGxvdmUlMjB0aGlzJTIwd2VlayUyN3MlMjBCeXRlcyUwQS0tLSUwQUpQRUclRTIlODAlOTlzJTIwbmV3JTIwdC1zaGlydCUyMHNpemUlMkMlMjBhJTIwVHlwZVNjcmlwdCUyMHByZWduYW5jeSUyMHRlc3QlMkMlMjBhbmQlMjBhJTIwY2xhc3NpYyUyMGNhc2UlMjBvZiUyMGJ1bmRsZSUyMHBob2JpYS4lMEFodHRwcyUzQSUyRiUyRmJ5dGVzLmRldiUyRmFyY2hpdmVzJTJGNTMz" rel="noopener" style="color: #12b5e5; font-weight: 600; padding-left: 5px; text-decoration: none;" target="_blank" url-id="1898682836"><img alt="" style="display: inline-block; max-width: 100%; width: 32px;" width="25" src="https://bytes.dev/images/em-share-icon.png"></a>
</td></tr></tbody></table>
<hr style="border: 0; border-bottom: 5px solid; border-color: #f5f5f5; margin-bottom: 100px; margin-top: 100px;">
<div style="text-align:center;margin-bottom:36px">
<img width="150" src="https://bytes.dev/images/content/coderabbit-logo.png" alt="CodeRabbit logo" style="max-width: 100%;"><h2 style="font-family: Paytone One, sans-serif; font-size: 28px; margin-top: 10px; text-transform: uppercase;"><span>Our Friends <br class="mobile-break">(With Benefits)</span></h2>
</div>
<div class="bg-alt" style="background-color: #f5f5f5; border-radius: 16px; margin-bottom: 40px; max-width: 100%; padding: 24px; padding-bottom: 12px;">
<img src="https://bytes.dev/images/content/liam-neeson.jpg" alt="Liam Neeson holds a phone to his ear with a stern expression" width="600" style="border-radius: 5px; max-width: 100%;"><p style="font-family: Outfit, sans-serif; font-size: 17px; font-style: italic; line-height: 1; margin: 0; padding-bottom: 4px; padding-left: 24px; padding-right: 24px; padding-top: 10px; text-align: center;">When you have someone with a "particular set of skills" watching over your codebase<!-- --> </p>
</div>
<h3 style="font-size: 24px; margin-bottom: 0; padding-left: 24px; padding-right: 24px;"><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/owhkhwuwegmqr0hvhr/aHR0cHM6Ly9jb2RlcmFiYml0LmxpbmsvYnl0ZXMtMDE4" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682837">Fewer findings. Only real risks.</a></h3>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">AI-generated code can introduce vulnerabilities that are easy to miss in a pull request. CodeRabbit Security continuously reviews your codebase for complex bugs and security risks, using full-codebase context to follow data flows, dependencies, and patterns beyond the latest diff.</p>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;"><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/owhkhwuwegmqr0hvhr/aHR0cHM6Ly9jb2RlcmFiYml0LmxpbmsvYnl0ZXMtMDE4" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682837">Run CodeRabbit Security on your own repositories today</a></p>
<hr style="border: 0; border-bottom: 5px solid; border-color: #f5f5f5; margin-bottom: 100px; margin-top: 100px;">
<div style="text-align:center;margin-bottom:36px">
<img width="110" src="https://bytes.dev/images/content/spot-the-bug.png" alt="Spot the Bug logo" style="max-width: 100%;"><h2 style="font-family: Paytone One, sans-serif; font-size: 28px; margin-top: 10px; text-transform: uppercase;">Spot the Bug</h2>
<div class="section-presenter" style="margin-bottom:50px;margin-top:15px">
<h4 style="font-size: 20px; margin-bottom: 0; padding-left: 24px; padding-right: 24px;">Spot the Bug – Sponsored by <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/z2hgh7uezp2l3zsph0/aHR0cHM6Ly9qYW0uZGV2L21hYz91dG1fY2FtcGFpZ249bWFjLWxhdW5jaCZ1dG1fc291cmNlPWJ5dGVz" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682838">Jam</a>
</h4>
<p style="font-family: Outfit, sans-serif; font-size: 18px; line-height: 1.5; margin-top: 5px; padding-left: 24px; padding-right: 24px;"><em>Make your team’s bug reports easier to solve than this challenge we’re sponsoring. Use <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/z2hgh7uezp2l3zsph0/aHR0cHM6Ly9qYW0uZGV2L21hYz91dG1fY2FtcGFpZ249bWFjLWxhdW5jaCZ1dG1fc291cmNlPWJ5dGVz" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682838">Jam’s new Mac app</a> to record your screen with Chrome, Safari or Electron logs so devs and agents fix stuff fast.</em></p>
</div>
</div>
<pre class="language-js" style="-moz-hyphens: none; -moz-tab-size: 2; -ms-hyphens: none; -o-tab-size: 2; -webkit-hyphens: none; background-color: #f9f9f9; border: 1px solid #f9f9f9; border-radius: 8px; box-sizing: border-box; color: #c0c5ce; direction: ltr; font-family: 'Fira Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 15px; hyphens: none; line-height: 1.5; max-width: 100%; overflow: auto; overflow-wrap: anywhere; padding: 24px; tab-size: 2; text-align: left; white-space: pre-wrap; word-spacing: normal;"><code class="language-js" style="-moz-hyphens: none; -moz-tab-size: 2; -ms-hyphens: none; -o-tab-size: 2; -webkit-hyphens: none; color: #c0c5ce; direction: ltr; font-family: 'Fira Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 15px; hyphens: none; line-height: 1.5; overflow-wrap: anywhere; tab-size: 2; text-align: left; white-space: pre-wrap; word-spacing: normal;"><span class="token keyword" style="color: #f38ba3; font-size: 15px;">function</span> <span class="token function" style="color: #9d7dce; font-size: 15px;">buildSearchUrl</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token parameter" style="color: #f38ba3; font-size: 15px;">tags</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span> <span class="token punctuation" style="color: #231F20; font-size: 15px;">{</span>
<span class="token keyword" style="color: #f38ba3; font-size: 15px;">const</span> params <span class="token operator" style="color: #12b5e5; font-size: 15px;">=</span> <span class="token keyword" style="color: #f38ba3; font-size: 15px;">new</span> <span class="token class-name" style="color: #12b5e5; font-size: 15px;">URLSearchParams</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
tags<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">forEach</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token parameter" style="color: #f38ba3; font-size: 15px;">tag</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span> <span class="token operator" style="color: #12b5e5; font-size: 15px;">=></span> params<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">set</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token string" style="color: #f99157; font-size: 15px;">"tag"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">,</span> tag<span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
<span class="token keyword" style="color: #f38ba3; font-size: 15px;">return</span> <span class="token template-string" style="font-size: 15px;"><span class="token template-punctuation string" style="color: #f99157; font-size: 15px;">`</span><span class="token string" style="color: #f99157; font-size: 15px;">/search?</span><span class="token interpolation" style="color: #12b5e5; font-size: 15px;"><span class="token interpolation-punctuation punctuation" style="color: #231F20; font-size: 15px;">${</span>params<span class="token interpolation-punctuation punctuation" style="color: #231F20; font-size: 15px;">}</span></span><span class="token template-punctuation string" style="color: #f99157; font-size: 15px;">`</span></span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
<span class="token punctuation" style="color: #231F20; font-size: 15px;">}</span>
console<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">log</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token function" style="color: #9d7dce; font-size: 15px;">buildSearchUrl</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">[</span><span class="token string" style="color: #f99157; font-size: 15px;">"js"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">,</span> <span class="token string" style="color: #f99157; font-size: 15px;">"ts"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">]</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
</code></pre>
<hr style="border: 0; border-bottom: 5px solid; border-color: #f5f5f5; margin-bottom: 100px; margin-top: 100px;">
<div style="text-align:center;margin-bottom:36px">
<img width="110" src="https://bytes.dev/images/content/cool-bits.png" alt="Cool Bits logo" style="max-width: 100%;"><h2 style="font-family: Paytone One, sans-serif; font-size: 28px; margin-top: 10px; text-transform: uppercase;">Cool Bits</h2>
</div>
<ol>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Tanner <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/p8hehqu4egwqzvhqh3/aHR0cHM6Ly90YW5zdGFjay5jb20vYmxvZy9pbnRyb2R1Y2luZy10YW5zdGFjay1yZWRhY3Q=" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682839">released the well-named <code style="font-size: 15px;">redact</code></a>, a smaller, synchronous version of React, for those of you who still suffer from bundle phobia.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Jeff Lindsay created <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/x0hph3uem9vqe8b5hl/aHR0cHM6Ly9naXRodWIuY29tL3RyYWN0b3JkZXYvd2ViZnJhbWU=" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682840"><code style="font-size: 15px;">webframe</code>, a tool that lets you run browser-dependent scripts from the command line</a>.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Equip your AI on <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/6qhehoul4n89lkuohk/aHR0cDovL2FwaWZ5LmNvbS9hcGlmeS9lLWNvbW1lcmNlLXNjcmFwaW5nLXRvb2w_ZnByPWZpcmVzaGlwLWJ5dGVz" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682841">Apify</a> for Black Friday and get live prices, availability, and ratings from Amazon, Walmart, eBay, or any other online store. Use code BYTES for $25 in credits. [sponsored]</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Remix <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/e0hph0u7zq3r7lt8h2/aHR0cHM6Ly9naXRodWIuY29tL3JlbWl4LXJ1bi9yZW1peC9yZWxlYXNlcy90YWcvcmVtaXglNDAzLjEuMA==" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682842">released version 3.1</a>, patching up some post-launch issues and making it faster so now it’s really actually ready… probably.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Jake Archibald explains <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/7qh7h2u9ew2n98fzh6/aHR0cHM6Ly9qYWtlYXJjaGliYWxkLmNvbS8yMDI2L2pwZWcteGwtdnMtYXZpZi8=" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682843">when to use JPEG XL rather than AVIF</a> in his latest blog post. JPEG is also wearing size XL? The post-COVID years have been rough for all of us.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">James Long <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/owhkhwuwegmqwlavhr/aHR0cHM6Ly9qYW1lc2JveC5leGUueHl6L2FydGlmYWN0cy9ydW5lLXZzLW1hY29zLXRleHQv" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682844">compared Rune’s text render to macOS text rendering, pixel by pixel</a>. Developers with OCD are the best.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/z2hgh7uezp2le8tph0/aHR0cHM6Ly9oeXBlcmFnZW50LmNvbS9maXJlc2hpcDEwMA==" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682845">Hyperagent</a> lets you hire AI staff to take on roles across your business. They run in the cloud with their own browser, shell, and file system, connect to your tools, and hand work off to each other. Your whole team can work with the same agents—not just the person who set them up. [sponsored]</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Shu Ding, inspired by Cheng Lou’s latest wizardry, <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/p8hehqu4egwq47aqh3/aHR0cHM6Ly9jYWxjdWx1cy1vZi1pbnRlcmZhY2VzLnZlcmNlbC5hcHAv" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682846">compiled a dashboard UI into a single math function</a> giving new meaning to the trope <code style="font-size: 15px;">UI = fn(state)</code>.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/x0hph3uem9vqens5hl/aHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9Nb3ppbGxhL0ZpcmVmb3gvUmVsZWFzZXMvMTU5" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682847">Firefox 159 is out</a>, which means <code style="font-size: 15px;">scroll-driven-animations</code> are now supported in all major browsers. I <em>think</em> this is a good thing.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Your code has bugs. <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/6qhehoul4n89l7bohk/aHR0cHM6Ly9zZW50cnkuaW8vcmVzb3VyY2VzL2F1dG9tYXRlZC1kZWJ1Z2dpbmcvP3V0bV9zb3VyY2U9Ynl0ZXMmdXRtX21lZGl1bT1wYWlkLWNvbW11bml0eSZ1dG1fY2FtcGFpZ249YXV0b21hdGVkZGVidWdnaW5nLWZ5MjdxMy1ldmVyZ3JlZW4mdXRtX2NvbnRlbnQ9bmV3c2xldHRlci1yZXNvdXJjZS1odWItbGVhcm5tb3Jl" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682848">Sentry finds them, figures out what caused them, and helps your agents fix them</a>. [sponsored]</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;">Vercel Labs created <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/kkhmh2unp60xnnulh7/aHR0cHM6Ly9naXRodWIuY29tL3ZlcmNlbC1sYWJzL3d0ZXJtLw==" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682849">wterm</a>, a terminal emulator for the web that renders DOM so text selection actually works <span role="img" aria-label="smiling face with tear">🥲</span>.</p>
</li>
<li>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5;"><a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/58hvh8ugwkd6gki6h4/aHR0cHM6Ly9naXRodWIuY29tL3p6ajM3MjAvdHN0c3Q=" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682850"><code style="font-size: 15px;">tsts</code> is another slopfork of the TypeScript compiler</a>, but this time it’s running inside TypeScript’s own type system? I think this is the equivalent of Doom running inside of a pregnancy test.</p>
</li>
</ol>
<hr style="border: 0; border-bottom: 5px solid; border-color: #f5f5f5; margin-bottom: 100px; margin-top: 100px;">
<div style="text-align:center;margin-bottom:36px">
<img width="110" src="https://bytes.dev/images/content/spot-the-bug.png" alt="Spot the Bug logo" style="max-width: 100%;"><h2 style="font-family: Paytone One, sans-serif; font-size: 28px; margin-top: 10px; text-transform: uppercase;">Spot the Bug: Solution</h2>
<div class="section-presenter" style="margin-bottom:50px;margin-top:15px"><h4 style="font-size: 20px; margin-bottom: 0; padding-left: 24px; padding-right: 24px;">Spot the Bug – Sponsored by <a href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/z2hgh7uezp2l3zsph0/aHR0cHM6Ly9qYW0uZGV2L21hYz91dG1fY2FtcGFpZ249bWFjLWxhdW5jaCZ1dG1fc291cmNlPWJ5dGVz" style="color: #12b5e5; font-weight: 600; text-decoration: underline;" url-id="1898682838">Jam</a>
</h4></div>
</div>
<p style="font-family: Outfit, sans-serif; font-size: 19px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">The URL only contains <code style="font-size: 15px;">tag=ts</code>. <code style="font-size: 15px;">URLSearchParams.set()</code> replaces the previous value for a key, so the second tag overwrites the first. Use <code style="font-size: 15px;">append()</code> to keep both values:</p>
<pre class="language-js" style="-moz-hyphens: none; -moz-tab-size: 2; -ms-hyphens: none; -o-tab-size: 2; -webkit-hyphens: none; background-color: #f9f9f9; border: 1px solid #f9f9f9; border-radius: 8px; box-sizing: border-box; color: #c0c5ce; direction: ltr; font-family: 'Fira Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 15px; hyphens: none; line-height: 1.5; max-width: 100%; overflow: auto; overflow-wrap: anywhere; padding: 24px; tab-size: 2; text-align: left; white-space: pre-wrap; word-spacing: normal;"><code class="language-js" style="-moz-hyphens: none; -moz-tab-size: 2; -ms-hyphens: none; -o-tab-size: 2; -webkit-hyphens: none; color: #c0c5ce; direction: ltr; font-family: 'Fira Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 15px; hyphens: none; line-height: 1.5; overflow-wrap: anywhere; tab-size: 2; text-align: left; white-space: pre-wrap; word-spacing: normal;"><span class="token keyword" style="color: #f38ba3; font-size: 15px;">function</span> <span class="token function" style="color: #9d7dce; font-size: 15px;">buildSearchUrl</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token parameter" style="color: #f38ba3; font-size: 15px;">tags</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span> <span class="token punctuation" style="color: #231F20; font-size: 15px;">{</span>
<span class="token keyword" style="color: #f38ba3; font-size: 15px;">const</span> params <span class="token operator" style="color: #12b5e5; font-size: 15px;">=</span> <span class="token keyword" style="color: #f38ba3; font-size: 15px;">new</span> <span class="token class-name" style="color: #12b5e5; font-size: 15px;">URLSearchParams</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
tags<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">forEach</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token parameter" style="color: #f38ba3; font-size: 15px;">tag</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span> <span class="token operator" style="color: #12b5e5; font-size: 15px;">=></span> params<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">append</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token string" style="color: #f99157; font-size: 15px;">"tag"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">,</span> tag<span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
<span class="token keyword" style="color: #f38ba3; font-size: 15px;">return</span> <span class="token template-string" style="font-size: 15px;"><span class="token template-punctuation string" style="color: #f99157; font-size: 15px;">`</span><span class="token string" style="color: #f99157; font-size: 15px;">/search?</span><span class="token interpolation" style="color: #12b5e5; font-size: 15px;"><span class="token interpolation-punctuation punctuation" style="color: #231F20; font-size: 15px;">${</span>params<span class="token interpolation-punctuation punctuation" style="color: #231F20; font-size: 15px;">}</span></span><span class="token template-punctuation string" style="color: #f99157; font-size: 15px;">`</span></span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
<span class="token punctuation" style="color: #231F20; font-size: 15px;">}</span>
console<span class="token punctuation" style="color: #231F20; font-size: 15px;">.</span><span class="token function" style="color: #9d7dce; font-size: 15px;">log</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token function" style="color: #9d7dce; font-size: 15px;">buildSearchUrl</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">(</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">[</span><span class="token string" style="color: #f99157; font-size: 15px;">"js"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">,</span> <span class="token string" style="color: #f99157; font-size: 15px;">"ts"</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">]</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">)</span><span class="token punctuation" style="color: #231F20; font-size: 15px;">;</span>
</code></pre>
<div style="text-align:center;padding-bottom:80px;padding-top:80px">
<div class="bg-alt" style="background-color: #f5f5f5; border-radius: 16px; margin-bottom: 40px; padding: 24px;"><div style="margin-top:-40px">
<img src="https://bytes.dev/images/bytes-icon.png" alt="Bytes" width="55px" style="max-width: 100%; width: 55px;"><h5 style="font-size:18px;font-weight:400;margin-bottom:24px">Want us to say nice things <br> about your company?</h5>
<div style="margin-bottom:16px"><a style="background-color: #FCBA28; border: 1px solid #231F20; border-radius: 100px; color: #231F20; font-size: 14px; font-weight: 600; padding: 8px 14px; text-decoration: none;" href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/25h2h9u3x4pm3di3h4/aHR0cHM6Ly9ieXRlcy5kZXYvYWR2ZXJ0aXNl" url-id="1898682851">Sponsor Bytes</a></div>
<div style="margin-bottom:20px"><a style="color: #FCBA28; font-size: 14px; font-weight: 600; text-decoration: underline;" href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/qvh8h8ud3omkdqulhk/aHR0cHM6Ly9ieXRlcy5kZXYvc2hhcmU=" url-id="1898682852">or share it</a></div>
<p style="font-family: Outfit, sans-serif; font-size: 14px; line-height: 1.5; padding-left: 24px; padding-right: 24px;">Built with ❤️ by<!-- --> <a style="color: #ed203d; font-weight: 600; text-decoration: underline;" href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/g3hnhwum268qmgbrh9/aHR0cHM6Ly9maXJlc2hpcC5kZXY=" url-id="1898682853">Fireship</a></p>
</div></div>
<p style="font-family: Outfit, sans-serif; font-size: 14px; line-height: 1.5; opacity: 0.5; padding-left: 24px; padding-right: 24px;">50 W Broadway Ste 333 PMB 51647 Salt Lake City, Utah 84101</p>
<div style="font-family:Papyrus, cursive"><a class="unsubscribe-link" href="https://c5e21242.click.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o/9qhzhdud8zv5d0f9h3/aHR0cHM6Ly9ieXRlcy5kZXYvdW5zdWJzY3JpYmU=" style="color: #9B9890;" url-id="1898682854">Unsubscribe from Bytes</a></div>
</div>
</div></td>
<td style="border-collapse: collapse !important; word-break: normal;"></td>
</tr></tbody></table>
<span style="display: none"><a href="https://c5e21242.unsubscribe.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o">Unsubscribe</a></span>
<!-- -->
<img src="https://c5e21242.open.convertkit-mail.com/v8u5q54200irh42xr36hghvv2p3moi9hq32o" alt="">
</body>
</html>