<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pease Ernest</title>
    <description>The latest articles on DEV Community by Pease Ernest (@pease_ernest_e356419ec4a6).</description>
    <link>https://dev.to/pease_ernest_e356419ec4a6</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3671214%2Ff1e3af8b-c684-412f-8d09-17956f0d52d4.jpg</url>
      <title>DEV Community: Pease Ernest</title>
      <link>https://dev.to/pease_ernest_e356419ec4a6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pease_ernest_e356419ec4a6"/>
    <language>en</language>
    <item>
      <title>Is bun really fast or maybe nope</title>
      <dc:creator>Pease Ernest</dc:creator>
      <pubDate>Tue, 05 May 2026 11:25:11 +0000</pubDate>
      <link>https://dev.to/pease_ernest_e356419ec4a6/is-bun-really-fast-or-maybe-nope-55a1</link>
      <guid>https://dev.to/pease_ernest_e356419ec4a6/is-bun-really-fast-or-maybe-nope-55a1</guid>
      <description>&lt;p&gt;so i have been wondering is bun really fast or this is another marketing claim that seems just too good to be true here I am going to summarize this and say bun is not fast it just caches to look fast why because for those that don't know bun caches your library in your machine then when you re-install it  just fetches it from your machine that is just good caching but that is not fast &lt;br&gt;
i do a deeper breakdown of this great topic in &lt;br&gt;
&lt;a href="https://nothing-browser-docs.pages.dev/blog/bun/buninstallmess" rel="noopener noreferrer"&gt;readhere&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bunjs</category>
    </item>
    <item>
      <title>Built an Amazon Scraper API in 50 Lines of TypeScript (And You Can Too)</title>
      <dc:creator>Pease Ernest</dc:creator>
      <pubDate>Fri, 24 Apr 2026 19:33:03 +0000</pubDate>
      <link>https://dev.to/pease_ernest_e356419ec4a6/built-an-amazon-scraper-api-in-50-lines-of-typescript-and-you-can-too-1ld1</link>
      <guid>https://dev.to/pease_ernest_e356419ec4a6/built-an-amazon-scraper-api-in-50-lines-of-typescript-and-you-can-too-1ld1</guid>
      <description>&lt;h1&gt;
  
  
  I Built an Amazon Scraper API in 50 Lines of TypeScript
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;No stealth plugins. No fingerprint hacks. No 47-line setup. Just a browser that actually works.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've been scraping Amazon for years. Every time I thought I had it figured out, something broke:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puppeteer? &lt;code&gt;navigator.webdriver = true&lt;/code&gt; → blocked.&lt;/li&gt;
&lt;li&gt;Playwright? Same problem, different package.&lt;/li&gt;
&lt;li&gt;curl_cffi? Great TLS fingerprint, but no browser JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built something different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Nothing Browser Piggy
&lt;/h2&gt;

&lt;p&gt;Piggy is a headless browser library that doesn't leak automation signals. Real BoringSSL TLS. No CDP overhead. Built-in fingerprint spoofing that runs at &lt;strong&gt;DocumentCreation&lt;/strong&gt; — before any page JavaScript can detect it.&lt;/p&gt;

&lt;p&gt;Here's an Amazon scraper API in 50 lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePiggy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nothing-browser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;writeFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;headful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;amazon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://www.amazon.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actHuman&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;amazon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;usePiggy&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;amazon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;amazon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;term&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mattress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;amazon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://www.amazon.com/s?k=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;amazon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;amazon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-asin]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;asin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-asin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h2 span&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.a-price .a-offscreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.a-icon-alt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img.s-image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;pageResults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`./amazon-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search Amazon products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mattress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;integer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. One command starts an API server with OpenAPI docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes This Different
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. No Stealth Plugin Nightmares
&lt;/h3&gt;

&lt;p&gt;Puppeteer needs &lt;code&gt;puppeteer-extra-plugin-stealth&lt;/code&gt;. Playwright needs... something. Piggy has anti-detection &lt;strong&gt;built in&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This just works. No extra imports.&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;piggy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;actHuman&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Real Browser, Real TLS
&lt;/h3&gt;

&lt;p&gt;Piggy uses Qt6 WebEngine with real BoringSSL — same as Chrome. The TLS fingerprint is identical. No patched OpenSSL.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Built-in API Server
&lt;/h3&gt;

&lt;p&gt;One line: &lt;code&gt;await piggy.serve(3000)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-generated OpenAPI docs at &lt;code&gt;/openapi&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Caching with &lt;code&gt;ttl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Middleware support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. TypeScript First
&lt;/h3&gt;

&lt;p&gt;Full type safety. And &lt;code&gt;usePiggy&amp;lt;T&amp;gt;()&lt;/code&gt; gives you autocomplete for registered sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;Running this scraper on a mattress search (5 pages):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Products scraped&lt;/td&gt;
&lt;td&gt;~200 per search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time per page&lt;/td&gt;
&lt;td&gt;~3 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blocked by Amazon&lt;/td&gt;
&lt;td&gt;0% (tested 50+ runs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lines of code&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
bun add nothing-browser

&lt;span class="c"&gt;# Download the binary from GitHub Releases&lt;/span&gt;
&lt;span class="c"&gt;# Place nothing-browser-headless in your project root&lt;/span&gt;

&lt;span class="c"&gt;# Run&lt;/span&gt;
bun run amazon-scraper.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then visit &lt;code&gt;http://localhost:3000/openapi&lt;/code&gt; — interactive API docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API reverse engineers&lt;/strong&gt; — capture every request/responses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price monitoring&lt;/strong&gt; — check competitor prices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO researchers&lt;/strong&gt; — analyze product rankings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data nerds&lt;/strong&gt; — build datasets without getting blocked&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Honest Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Windows support is coming (native build in progress)&lt;/li&gt;
&lt;li&gt;Google/Facebook may still block you (they block everything non-Chrome)&lt;/li&gt;
&lt;li&gt;Amazon CAN ban your IP if you go too fast (add delays, use proxies)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;I built Piggy because I was tired of the same 47-line setup file copied between projects. It's open source (MIT), it's fst, and it passes Cloudflarer where other tols fail.&lt;/p&gt;

&lt;p&gt;Try it. Break it. Send a PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/BunElysiaReact/nothing-browser" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nothing-browser.pages.dev" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/TUxBVQ7y" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webscraping</category>
      <category>api</category>
      <category>bunjs</category>
      <category>elysia</category>
    </item>
    <item>
      <title>BERTUI NEXT BURNER FEATURE</title>
      <dc:creator>Pease Ernest</dc:creator>
      <pubDate>Sat, 03 Jan 2026 04:37:26 +0000</pubDate>
      <link>https://dev.to/pease_ernest_e356419ec4a6/bertui-next-burner-feature-c6d</link>
      <guid>https://dev.to/pease_ernest_e356419ec4a6/bertui-next-burner-feature-c6d</guid>
      <description>&lt;p&gt;Bertui is soon to introduce zig transpiled icons the first super fast icons library in the bertui family &lt;br&gt;
our icons will still have the same syntax as all lucide children i.e lucide-react and many more &lt;br&gt;
it will be called bertui-icons if you do not know what bertui is visit our docs at &lt;a href="https://bertui-docswebsite.vercel.app/" rel="noopener noreferrer"&gt;https://bertui-docswebsite.vercel.app/&lt;/a&gt;&lt;br&gt;
and learn more about it &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I migrated from vite to bertui after they lauched server islands today</title>
      <dc:creator>Pease Ernest</dc:creator>
      <pubDate>Tue, 23 Dec 2025 09:28:23 +0000</pubDate>
      <link>https://dev.to/pease_ernest_e356419ec4a6/i-migrated-from-vite-to-bertui-after-they-lauched-server-islands-today-35o2</link>
      <guid>https://dev.to/pease_ernest_e356419ec4a6/i-migrated-from-vite-to-bertui-after-they-lauched-server-islands-today-35o2</guid>
      <description>&lt;h1&gt;
  
  
  I Migrated from Vite to BertUI After They Launched Server Islands Today
&lt;/h1&gt;

&lt;p&gt;I've been building React apps with Vite for the past year. It's been solid—fast dev server, decent build times, and a massive ecosystem. But today, BertUI dropped Server Islands in v1.1.0, and I spent the afternoon migrating my docs site. Here's what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Even Considered Switching
&lt;/h2&gt;

&lt;p&gt;BertUI has been on my radar since their 1.0 release. The performance claims seemed wild:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;494ms dev server startup vs Vite's 713ms&lt;/li&gt;
&lt;li&gt;265ms production builds vs Vite's 4.7s&lt;/li&gt;
&lt;li&gt;Zero configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly? I dismissed it as "just fast Vite." Cool speeds, but missing the killer feature I needed: &lt;strong&gt;SEO&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then Server Islands dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Server Islands?
&lt;/h2&gt;

&lt;p&gt;Server Islands are BertUI's answer to the "client-only React" problem. You add one line to any page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And BertUI generates static HTML at build time. No SSR server. No complex setup. Just pure HTML that search engines can index immediately.&lt;/p&gt;

&lt;p&gt;Here's the magic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (Vite):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- What search engines see --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (BertUI with Server Islands):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Full content immediately --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My Awesome Docs&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;Full content here!&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"app.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The kicker? You choose which pages get this treatment. Landing page needs SEO? Add the line. Dashboard needs full React state? Skip it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Backup Everything
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-vite-project
bunx migrate-bertui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BertUI's migration tool automatically backs up everything to &lt;code&gt;.bertmigrate/&lt;/code&gt; before touching anything. Smart move.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Convert Routes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vite routing (React Router):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.jsx&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Home&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;About&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/blog/:slug"&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BlogPost&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;BertUI file-based routing:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/pages/index.jsx        → /
src/pages/about.jsx        → /about
src/pages/blog/[slug].jsx  → /blog/:slug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No router config. Just files. Took me 10 minutes to restructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Update Imports
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (Vite)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// After (BertUI)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bertui/router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find and replace. Done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Add Server Islands
&lt;/h3&gt;

&lt;p&gt;This is where it got interesting. I added &lt;code&gt;export const render = "server";&lt;/code&gt; to my landing page, about page, and changelog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/pages/changelog.jsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Changelog - BertUI&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Complete history of BertUI releases&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Changelog&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;BertUI Changelog&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... content ... */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Build and Deploy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;265ms build time.&lt;/strong&gt; I thought it was broken. Ran it again. Still 265ms.&lt;/p&gt;

&lt;p&gt;My Vite builds were taking 4.7s. This felt like a bug, but the output was perfect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Changed
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Good
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Build Speed is Ridiculous&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite: 4.7s production builds&lt;/li&gt;
&lt;li&gt;BertUI: 265ms production builds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;18x faster&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For CI/CD pipelines, this is massive. My GitHub Actions went from 45s to 12s.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Dev Server Actually Feels Instant&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite: 713ms startup (already fast)&lt;/li&gt;
&lt;li&gt;BertUI: 494ms startup&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not a huge difference, but noticeable&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real win? HMR feels snappier. Changes reflect in ~30ms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. SEO Problem: Solved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I ran a quick test with &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://my-site.vercel.app/changelog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Vite output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;BertUI output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"changelog-page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;BertUI Changelog&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- FULL CONTENT HERE --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Search engines see everything. No JavaScript required. This is what I needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Zero Config is Real&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;vite.config.js&lt;/code&gt; was 50 lines of plugins and aliases. BertUI? No config file at all. Just works.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Trade-offs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. No TypeScript Support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BertUI is JavaScript-first by design. They explicitly don't plan to add &lt;code&gt;.tsx&lt;/code&gt; support.&lt;/p&gt;

&lt;p&gt;For my docs site? Not a problem. For a complex app with a team? This could be a dealbreaker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Smaller Ecosystem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vite has plugins for everything. BertUI is new. If you need niche tooling, you might be stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Bun-Only&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BertUI requires Bun. If your company is locked into Node.js, this won't work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. No Multi-Framework Support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vite supports Vue, Svelte, etc. BertUI is React-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Comparison (My Machine)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;BertUI&lt;/th&gt;
&lt;th&gt;Vite&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dev Server&lt;/td&gt;
&lt;td&gt;494ms&lt;/td&gt;
&lt;td&gt;713ms&lt;/td&gt;
&lt;td&gt;BertUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production Build&lt;/td&gt;
&lt;td&gt;265ms&lt;/td&gt;
&lt;td&gt;4.7s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;BertUI (18x)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundle Size&lt;/td&gt;
&lt;td&gt;100KB&lt;/td&gt;
&lt;td&gt;220KB&lt;/td&gt;
&lt;td&gt;BertUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG Support&lt;/td&gt;
&lt;td&gt;✅ YES&lt;/td&gt;
&lt;td&gt;❌ NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;BertUI&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  When Should You Actually Use BertUI?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Use BertUI if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're building content sites (docs, blogs, landing pages)&lt;/li&gt;
&lt;li&gt;You need fast builds for CI/CD&lt;/li&gt;
&lt;li&gt;You want per-page control over SSG&lt;/li&gt;
&lt;li&gt;You're okay with JavaScript (no TypeScript)&lt;/li&gt;
&lt;li&gt;You can use Bun&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Stick with Vite if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need TypeScript&lt;/li&gt;
&lt;li&gt;You're using Vue/Svelte&lt;/li&gt;
&lt;li&gt;You need a mature plugin ecosystem&lt;/li&gt;
&lt;li&gt;You can't use Bun&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Use Next.js if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need full SSR (real-time server rendering)&lt;/li&gt;
&lt;li&gt;You need advanced features like ISR&lt;/li&gt;
&lt;li&gt;You have complex data requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Honest Take
&lt;/h2&gt;

&lt;p&gt;BertUI isn't "just fast Vite" anymore. Server Islands genuinely solve a problem Vite can't—instant SEO without complexity.&lt;/p&gt;

&lt;p&gt;The speed is nice, but the killer feature is &lt;strong&gt;per-page SSG with one line of code&lt;/strong&gt;. That's unique. Next.js has SSG, but it's more complex. Vite has no SSG at all.&lt;/p&gt;

&lt;p&gt;Would I recommend it for every project? No. If you need TypeScript or multi-framework support, look elsewhere.&lt;/p&gt;

&lt;p&gt;But for React-first projects that need blazing speed and perfect SEO? BertUI is now a serious option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Checklist
&lt;/h2&gt;

&lt;p&gt;If you're considering the switch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Check if your project needs TypeScript (dealbreaker if yes)&lt;/li&gt;
&lt;li&gt;[ ] Verify you can use Bun in your environment&lt;/li&gt;
&lt;li&gt;[ ] Identify which pages need SEO (use Server Islands)&lt;/li&gt;
&lt;li&gt;[ ] Back up your project (or use &lt;code&gt;bunx migrate-bertui&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;[ ] Convert routes to file-based structure&lt;/li&gt;
&lt;li&gt;[ ] Update router imports&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;export const render = "server";&lt;/code&gt; to SEO pages&lt;/li&gt;
&lt;li&gt;[ ] Test build and deploy&lt;/li&gt;
&lt;li&gt;[ ] Verify SEO with &lt;code&gt;curl&lt;/code&gt; or view-source&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://bertui-docswebsite.vercel.app/" rel="noopener noreferrer"&gt;BertUI Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bertui-docswebsite.vercel.app/server-islands" rel="noopener noreferrer"&gt;Server Islands Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/BunElysiaReact/BERTUI" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/migrate-bertui" rel="noopener noreferrer"&gt;Migration Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Migrated from Vite to BertUI after they launched Server Islands. Got 18x faster builds and perfect SEO with zero config. Trade-off: no TypeScript support. Worth it for content sites.&lt;/p&gt;

&lt;p&gt;questions about it are allowed &lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a React Framework in 2025 - Here's What I Learned</title>
      <dc:creator>Pease Ernest</dc:creator>
      <pubDate>Fri, 19 Dec 2025 19:28:10 +0000</pubDate>
      <link>https://dev.to/pease_ernest_e356419ec4a6/i-built-a-react-framework-in-2025-heres-what-i-learned-34n9</link>
      <guid>https://dev.to/pease_ernest_e356419ec4a6/i-built-a-react-framework-in-2025-heres-what-i-learned-34n9</guid>
      <description>&lt;h2&gt;
  
  
  Why I Built It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create React App is deprecated&lt;/li&gt;
&lt;li&gt;Vite felt too complex for simple projects&lt;/li&gt;
&lt;li&gt;Wanted to learn Bun's native APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bun.Transpiler for JSX/TSX&lt;/li&gt;
&lt;li&gt;Elysia for dev server&lt;/li&gt;
&lt;li&gt;Bun.build for production&lt;/li&gt;
&lt;li&gt;Zero plugins, zero config&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;bertui builds pages depending on website size a small 2 to 5 pages website dev server will load in less tha  a second 1st build will take about 2 to 5 seconds and the rest lessa time&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;Learn bun's api perfectly because i knew about bun and a week later i had this idea dn i started making it which made it hard to know what to use and when to use it&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;bunx create-bertui my-app&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a framework taught me more about React tooling than years of using frameworks.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
