<?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: 梦醒时雨刚停</title>
    <description>The latest articles on DEV Community by 梦醒时雨刚停 (@wac0623).</description>
    <link>https://dev.to/wac0623</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4186861%2F87edecae-d31e-489b-9770-06bee13a210e.jpg</url>
      <title>DEV Community: 梦醒时雨刚停</title>
      <link>https://dev.to/wac0623</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wac0623"/>
    <language>en</language>
    <item>
      <title>I Built a DSH Plugin That Renders SPAs and Logged-In Pages for web_fetch</title>
      <dc:creator>梦醒时雨刚停</dc:creator>
      <pubDate>Thu, 15 Oct 2026 13:20:31 +0000</pubDate>
      <link>https://dev.to/wac0623/i-built-a-dsh-plugin-that-renders-spas-and-logged-in-pages-for-webfetch-56h</link>
      <guid>https://dev.to/wac0623/i-built-a-dsh-plugin-that-renders-spas-and-logged-in-pages-for-webfetch-56h</guid>
      <description>&lt;p&gt;DSH's built-in &lt;code&gt;web_fetch&lt;/code&gt; returns raw server HTML. That's fine for static pages, but it breaks for anything client-rendered or behind a login. I kept hitting this wall, so I built a plugin to fix it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;moli_fetch&lt;/code&gt; — renders pages in a headless browser, returns text / markdown / html / screenshot / pdf. Supports CSS selector extraction so you don't dump the entire page into context.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;moli_probe&lt;/code&gt; — environment probing and browser engine installation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plugin itself is 26 kB. The browser engine is ~101 MB and installed separately. Works on Windows / macOS / Linux.&lt;/p&gt;

&lt;p&gt;Why I built this&lt;br&gt;
If you've used DSH's web_fetch on a React or Vue app, you know the problem: you get a shell of a page with empty divs. The actual content is rendered client-side, so it's never in the HTML response. Same issue with anything behind a login wall.&lt;/p&gt;

&lt;p&gt;I wanted something that would render the page first, then let me grab what I need — without pulling the entire DOM into context.&lt;/p&gt;

&lt;p&gt;How moli_fetch works&lt;br&gt;
The tool launches a headless browser, waits for the page to finish rendering, then returns the result in the format you specify:&lt;/p&gt;

&lt;p&gt;text — plain text extraction&lt;/p&gt;

&lt;p&gt;markdown — useful for feeding into an LLM context&lt;/p&gt;

&lt;p&gt;html — full rendered HTML if you need the structure&lt;/p&gt;

&lt;p&gt;screenshot — PNG of the rendered page&lt;/p&gt;

&lt;p&gt;pdf — full page export&lt;/p&gt;

&lt;p&gt;You can also pass a CSS selector to extract only a specific element. If you just need one field from a page, you don't have to dump the whole thing.&lt;/p&gt;

&lt;p&gt;Two Windows sandbox traps I ran into&lt;br&gt;
The most time-consuming part of this project was dealing with two Windows-specific issues that only show up in sandboxed environments.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Pipe capture fails&lt;br&gt;
In the Windows sandbox, child processes can't open inherited named pipes. When you set stdio: 'pipe' on a spawn call, you get status=null and zero bytes back. The workaround was to redirect output to a temp file instead of relying on pipes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PowerShell UTF-16 byte pollution&lt;br&gt;
When you use PowerShell's &amp;gt; redirection on native program output, PowerShell re-encodes it as UTF-16, inserting a 00 byte after every single byte. This corrupts binary output completely — PNGs come out unreadable. The fix was to bypass PowerShell redirection entirely and use Node's own file streams.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both of these are documented in the README and in the code comments, in case anyone else hits them.&lt;/p&gt;

&lt;p&gt;What's in the box&lt;br&gt;
The plugin is intentionally small (26 kB) because the browser engine is a separate ~101 MB download. moli_probe handles the installation, checks for existing installations, and reports what it finds.&lt;/p&gt;

&lt;p&gt;The README covers:&lt;/p&gt;

&lt;p&gt;Install paths for Windows, macOS, and Linux&lt;/p&gt;

&lt;p&gt;Failure diagnostics and troubleshooting&lt;/p&gt;

&lt;p&gt;Why the engine isn't bundled (size, licensing, platform differences)&lt;/p&gt;

&lt;p&gt;TLS handling and why insecureTls defaults to true in some environments&lt;/p&gt;

&lt;p&gt;Links&lt;br&gt;
GitHub: &lt;a href="https://github.com/27painter/dsh-moli" rel="noopener noreferrer"&gt;https://github.com/27painter/dsh-moli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;README: full install guide and troubleshooting&lt;/p&gt;

&lt;p&gt;If you've been fighting with web_fetch on SPA or auth-gated pages, give it a shot. Feedback and issues welcome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe33pfls35jzsa1oh5g00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe33pfls35jzsa1oh5g00.png" alt=" " width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
dsh plugin --profile web add github:27painter/dsh-moli
# then call moli_probe action=install for the browser engine


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

&lt;/div&gt;

</description>
      <category>javascript</category>
      <category>plugin</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
