<?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>Forem: orangishcat</title>
    <description>The latest articles on Forem by orangishcat (@orangishcat).</description>
    <link>https://forem.com/orangishcat</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%2F3846821%2Fd9075f68-8e1e-4c61-9cfb-0e5499cc65ea.png</url>
      <title>Forem: orangishcat</title>
      <link>https://forem.com/orangishcat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/orangishcat"/>
    <language>en</language>
    <item>
      <title>Page Proxy v0.2.x: the boring 'polishing' work and why I think it matters</title>
      <dc:creator>orangishcat</dc:creator>
      <pubDate>Fri, 10 Apr 2026 22:48:12 +0000</pubDate>
      <link>https://forem.com/orangishcat/page-proxy-v02x-the-boring-polishing-work-and-why-i-think-it-matters-2cea</link>
      <guid>https://forem.com/orangishcat/page-proxy-v02x-the-boring-polishing-work-and-why-i-think-it-matters-2cea</guid>
      <description>&lt;p&gt;This is the second devlog for my Chrome/Firefox userscript manager extension, &lt;a href="https://orangishcat.github.io/page-proxy/" rel="noopener noreferrer"&gt;Page Proxy&lt;/a&gt;! Here I'm gonna cover v0.2.x, where I'm still trying to figure out what direction I'm planning to take the extension in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refining and QOL work
&lt;/h2&gt;

&lt;p&gt;This is what I would normally call "polishing" work. It gives the extension much-needed features and fixes long-standing bugs. This stage, I would say, comes after the "minimum viable product" stage, where you just need to get something working as idea validation.&lt;/p&gt;

&lt;p&gt;After you get your initial users who are interested in your idea, keeping them becomes very important. This is where usability comes in, and to make a product with good usability, it must have adequate features and minimal bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extension early stage
&lt;/h2&gt;

&lt;p&gt;At this point, I had a solid main idea of what I wanted the extension to do: turn page interactions into reusable userscripts.&lt;br&gt;
But the extension was lacking a lot of features, so I had to find the order which I wanted to implement them in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Website homepage&lt;/li&gt;
&lt;li&gt;Create tool:

&lt;ul&gt;
&lt;li&gt;Create a settings UI for your script (or any UI) easily&lt;/li&gt;
&lt;li&gt;Create components&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Settings page for the extension&lt;/li&gt;
&lt;li&gt;Multi-file scripts&lt;/li&gt;
&lt;li&gt;Local scripts&lt;/li&gt;
&lt;li&gt;Export to Tampermonkey userscript, CSS stylesheet, WXT extension&lt;/li&gt;
&lt;li&gt;Import/export with Figma&lt;/li&gt;
&lt;li&gt;Sync to cloud storage (Appwrite backend)&lt;/li&gt;
&lt;li&gt;Userscript discovery, sharing, and collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I had a good idea for what I wanted the extension to do.&lt;/p&gt;

&lt;p&gt;But for v0.2.x, I started with the missing features.&lt;/p&gt;
&lt;h2&gt;
  
  
  The inconvenience I wanted to solve
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;pq.selector&lt;/code&gt; could do a lot, sometimes it is simpler to just write CSS instead.&lt;/p&gt;

&lt;p&gt;Using JS would be a waste for doing things that CSS can do already. Worst of all would be using a JS &lt;code&gt;pq.selector&lt;/code&gt; just to inject styles on every matching element.&lt;/p&gt;

&lt;p&gt;So I made a CSS inspector!&lt;/p&gt;
&lt;h2&gt;
  
  
  CSS Inspector
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fq3qnuu3u4fesjt4kvhu4.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fq3qnuu3u4fesjt4kvhu4.jpg" alt=" " width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CSS Inspector (above) works similarly to the selector popup added in the previous version, but it directly allows you to apply CSS rules to a pregenerated selector for the element.&lt;/p&gt;

&lt;p&gt;And there's a nice dropdown that allows you to switch between this and the selector popup.&lt;/p&gt;

&lt;p&gt;On the right side of the CSS inspector is a properties list, similar to the one from the other selector. Placing the mouse caret over any part of the main CSS selector will provide documentation for what that CSS keyword does, which essentially acts like built-in documentation.&lt;/p&gt;

&lt;p&gt;As the tooltip says, you can also hold &lt;code&gt;z&lt;/code&gt; to highlight matching elements in lime or &lt;code&gt;x&lt;/code&gt; to preview styles applied in the editor.&lt;/p&gt;

&lt;p&gt;I also added a button that can bring you to the CSS inspector page directly from the Select Tool.&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.amazonaws.com%2Fuploads%2Farticles%2Fmpimc2fwdpb2fh8iotvr.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fmpimc2fwdpb2fh8iotvr.jpg" alt=" " width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's also some other features. Like, you can view the computed styles for the selected element! It's very similar to the computed styles in DevTools. If there are :nth-of-type selectors in the selector, a link appears to remove them easily. The CSS selector syncs with the &lt;code&gt;baseSelector&lt;/code&gt; field in the selector popup as well! Anything to avoid repetitive copying.&lt;/p&gt;

&lt;p&gt;Upon hitting &lt;code&gt;Save&lt;/code&gt;, it adds a &lt;code&gt;ps.injectCSS&lt;/code&gt; snippet into the editor, which will directly inject a style tag into the document head upon script run.&lt;/p&gt;
&lt;h2&gt;
  
  
  Other QOL features
&lt;/h2&gt;
&lt;h3&gt;
  
  
  run-on-page-load grant
&lt;/h3&gt;

&lt;p&gt;Before the update, the script wouldn't even be able to run on page load, and you'd have to click the run button manually every time. Fortunately, I added a &lt;code&gt;@grant&lt;/code&gt; field to the metadata. It only accepts one value as of now, &lt;code&gt;run-on-page-load&lt;/code&gt;, but it allows the script to execute automatically. A much needed feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @grant run-on-page-load&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon reload, it will create a dialog asking the user to grant permissions, like this:&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.amazonaws.com%2Fuploads%2Farticles%2Fwv15iop8m4ibzvtx64vn.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fwv15iop8m4ibzvtx64vn.jpg" alt=" " width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then it will ask the user to reload to apply updated permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Help tool
&lt;/h3&gt;

&lt;p&gt;Previously it was hardcoded into the extension. Now it fetches from the Github repository's HELP.md file, and rendered nicely in markdown.&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.amazonaws.com%2Fuploads%2Farticles%2Fxq2uencgmwnge6ml6yih.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fxq2uencgmwnge6ml6yih.jpg" alt=" " width="796" height="1127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  DevTools integration
&lt;/h3&gt;

&lt;p&gt;Added a wrench button in the select tool panel that appears when DevTools is open on the active tab. When clicking it, the selected element will match the selected element in DevTools. Highly useful for when the select tool can't select the element you want, like for example if its bounding box is covered by the bounding box of another element.&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.amazonaws.com%2Fuploads%2Farticles%2Fdatr888dux2r2lk64xjo.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fdatr888dux2r2lk64xjo.jpg" alt=" " width="796" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New APIs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;pa.moveNode to move a node elsewhere, such as to a parent node, or before or after another node.&lt;/li&gt;
&lt;li&gt;pv.pressKey to press keys programmatically using JS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Editor persistence
&lt;/h3&gt;

&lt;p&gt;Previously if a script was unsaved, switching to another tab without saving would cause you to lose your changes. Not anymore. Now a warning message appears and forces you to manually save before continuing.&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.amazonaws.com%2Fuploads%2Farticles%2Fs9l484r4pns5rzqhy3xy.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fs9l484r4pns5rzqhy3xy.jpg" alt=" " width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does not handle the extension sidepanel being closed, though, as there is no way to prevent it. The only solution in that case would be to autosave, which is risky as if there are bugs in the implementation someone's userscript can get overriden with the default script, causing them to lose it entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Selectors tool
&lt;/h3&gt;

&lt;p&gt;I gave it functionality by displaying highlighted elements upon hover.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error handling
&lt;/h3&gt;

&lt;p&gt;Errors are less likely to be silently swallowed now, and surface more clearly. It still needs a bit of work though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving on to v0.3.x
&lt;/h3&gt;

&lt;p&gt;v0.2.x added some much needed polish and a crucial CSS Inspector. It wasn't much, and ended up only being three versions, v0.2.0 to v0.2.2. That just means there were less features.&lt;/p&gt;

&lt;p&gt;Oh and I also changed the storage format, which ended up causing some scripts to be lost. It was okay as I still don't have that many users, but I definitely need to be more careful with that next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I think it's okay to be still figuring things out, and not just for your project either, this probably could work as life advice too. Changing directions in software development or in general is perfectly okay, and it allows one to refine and test their designs, and also throw out ideas that just don't quite work.&lt;/p&gt;

&lt;p&gt;Of course, I definitely could have planned my features more thoroughly. The CSS Inspector as the main feature in v0.2.x is probably fine, but the rest of the polish would probably make more sense to be done in v0.1.x. Like having a method to inject CSS (&lt;code&gt;ps.injectCSS&lt;/code&gt;) should have been like one of the main features of the custom pp-api. And making a breaking change to the storage format was definitely not a good idea. Could have used some planning beforehand.&lt;/p&gt;

&lt;p&gt;Also, I started to use AI for coding a lot for this project. My AI setup is just Codex and some basic skills like &lt;code&gt;superpowers&lt;/code&gt;, but it works pretty well. AI-generated code certainly isn't as clean as handwritten code, but it handles edge cases pretty well. Previously I found myself spending a lot more time passing states between components and fixing type objects, than spending time implementing actual functionality. So it's nice that AI allows me to go back to focusing on features, rather than type errors.&lt;/p&gt;

&lt;p&gt;But the great thing about agentic engineering is that the product is still the output of &lt;em&gt;my&lt;/em&gt; creative work. All the designs, the raw flow chart, and all my ideas are all me, and I've documented them in the Figma file and my devlogs. AI is just speeding up the implementation of those ideas, in a controlled manner.&lt;/p&gt;

&lt;p&gt;The landing page is still looking pretty barren... definitely need to do that earlier next time.&lt;/p&gt;

&lt;p&gt;I think that's it for this devlog. If you want to stick around, maybe I'll see you for v0.3.x?&lt;/p&gt;

&lt;p&gt;Try out &lt;a href="https://orangishcat.github.io/page-proxy/" rel="noopener noreferrer"&gt;Page Proxy&lt;/a&gt;, and maybe give me some feedback? I'd also be interested to hear about your thoughts on AI and whatnot.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>browser</category>
      <category>extensions</category>
      <category>typescript</category>
    </item>
    <item>
      <title>I built a GUI-powered Userscript manager to turn page interactions into userscripts!</title>
      <dc:creator>orangishcat</dc:creator>
      <pubDate>Sat, 04 Apr 2026 04:04:56 +0000</pubDate>
      <link>https://forem.com/orangishcat/i-built-a-gui-powered-userscript-manager-for-faster-userscript-creation-ebb</link>
      <guid>https://forem.com/orangishcat/i-built-a-gui-powered-userscript-manager-for-faster-userscript-creation-ebb</guid>
      <description>&lt;p&gt;I made &lt;a href="https://orangishcat.github.io/page-proxy/" rel="noopener noreferrer"&gt;Page Proxy&lt;/a&gt;, a Chrome and Firefox extension that converts page interactions into reusable code via Userscripts.&lt;/p&gt;

&lt;p&gt;This is my first project I've ever released. Please try it out and give feedback! Would be really appreciated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;I've always found messing around with userscript managers like Tampermonkey quite fun; I could fix websites and change their behavior to my liking. But it took me roughly 15 minutes to go from idea to code, then 30 minutes to an hour just to debug and polish the script.&lt;/p&gt;

&lt;p&gt;The first issue: juggling with DevTools windows, copy-pasting CSS selectors, and debugging my scripts was incredibly tedious.&lt;br&gt;
I'd mostly have to rely on print debugging, then I would have to reload the page every time and search through the console for errors.&lt;/p&gt;

&lt;p&gt;So I wanted a way to quickly generate CSS selectors and code. I wanted something similar to DevTools, but has integration with code and selector generation to speed up userscript development.&lt;/p&gt;

&lt;p&gt;Second of all, there were many reoccurring patterns in all of my scripts. For example:&lt;/p&gt;

&lt;p&gt;Do something on key press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;ev&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;altKey&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;KeyV&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="nf"&gt;runFunction&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press a key using JS (e.g. Escape):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;escEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Escape&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;which&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bubbles&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="na"&gt;cancelable&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="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;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;escEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I wanted to make an API that included all of these common usage patterns out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  My philosophy
&lt;/h2&gt;

&lt;p&gt;The product should solve:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GUI tools for userscript creation to make it less tedious&lt;/li&gt;
&lt;li&gt;API covering common use cases and code patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The product must remain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accessibility: The extension can be complicated, but it should be easy to use. Add help docs (or links to them) everywhere.&lt;/li&gt;
&lt;li&gt;Break-resistant: If a website's CSS classes change, the script should still work or at least be easy to migrate.&lt;/li&gt;
&lt;li&gt;Integration: The extension should not replace any other tools. Keep Tampermonkey compatibility, integrate with DevTools.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Planning and design
&lt;/h2&gt;

&lt;p&gt;Note: this was the first ever design sketch of the project. The extension has probably strayed quite far from it now.&lt;/p&gt;

&lt;p&gt;I learned how to use Figma and some common design patterns. Designing my own UI has always been a goal of mine as a programmer, so I'm glad I was able to do that for this project.&lt;/p&gt;

&lt;p&gt;Plus, I really disliked the overused blue-and-purple palette signature of AI website design. So using &lt;a href="https://www.realtimecolors.com/" rel="noopener noreferrer"&gt;Realtime Colors&lt;/a&gt;, I chose a simple orange and lime color palette.&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.amazonaws.com%2Fuploads%2Farticles%2Foa1lgab0pr1usrp0cq14.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.amazonaws.com%2Fuploads%2Farticles%2Foa1lgab0pr1usrp0cq14.png" alt=" " width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're interested, here's a raw, unedited flow chart of the features I wanted in Page Proxy that I threw up in an hour or so.&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.amazonaws.com%2Fuploads%2Farticles%2Fcqhqlb956v4a1sv2dnzp.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.amazonaws.com%2Fuploads%2Farticles%2Fcqhqlb956v4a1sv2dnzp.png" alt=" " width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial design
&lt;/h3&gt;

&lt;p&gt;I originally wanted to make Page Proxy a web app, mainly so it would "be unique". I quickly realized that unique does not always mean that it's good.&lt;/p&gt;

&lt;p&gt;From a technical standpoint, the web app quickly became a terrible idea. Websites won't function due to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP" rel="noopener noreferrer"&gt;CSP&lt;/a&gt;, and they certainly won't keep cookies, rendering pretty much all content behind a login screen completely inaccessible.&lt;/p&gt;

&lt;p&gt;Besides, it just didn't make sense at all. It would be much more convenient to create an extension side panel, allowing it to be easily accessed, like DevTools.&lt;/p&gt;

&lt;p&gt;Old design:&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.amazonaws.com%2Fuploads%2Farticles%2Ff5krgfsr8n3r65iirahq.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Ff5krgfsr8n3r65iirahq.webp" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  New extension design
&lt;/h3&gt;

&lt;p&gt;After some designing, I came up with this:&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.amazonaws.com%2Fuploads%2Farticles%2Fw8y2im9tkx2b4mbgp2jl.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.amazonaws.com%2Fuploads%2Farticles%2Fw8y2im9tkx2b4mbgp2jl.png" alt=" " width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I finally loved the design. It was significantly cleaner, and I also was incredibly proud of myself that I could make my color palette work so well.&lt;/p&gt;

&lt;p&gt;It's similar to DevTools, but I kept the top toolbar as buttons. This fits the design very well, keeping the UI large-scale and with self-explanatory icons.&lt;/p&gt;

&lt;p&gt;I liked this design for its simplicity. While DevTools, for example, was feature rich, it also had quite a steep learning curve, and a very dense, packed UI. I wanted to do the opposite; with the features I am planning, I wanted to prioritize ease of use, and I had no need for such densely packed features.&lt;/p&gt;

&lt;p&gt;So the natural next question was: what tools do I want to add?&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Select tool: Similar to DevTools' inspect element, but provides additional information like selectors, attributes, and more.&lt;/li&gt;
&lt;li&gt;Create tool: Create components (like in web frameworks like React and Svelte) in scripts&lt;/li&gt;
&lt;li&gt;Selectors tool: List CSS selectors and their properties&lt;/li&gt;
&lt;li&gt;Help tool: Help links and stuff&lt;/li&gt;
&lt;li&gt;Export tool: Export the script in a variety of different formats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now for the bottom half of the sidepanel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code editor
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;JS code editor&lt;/li&gt;
&lt;li&gt;Has highlighting and autocomplete&lt;/li&gt;
&lt;li&gt;Inspiration: Tampermonkey editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total time spent in design phase: 10 days. Probably only a few hours overall, but designing kinda felt like a chore since I was so new to it, which is why I didn't have the motivation to spend much time on it per day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;I split the monorepo into web and extension directories.&lt;/p&gt;

&lt;p&gt;Some library choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Package manager: &lt;code&gt;bun&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Web framework: &lt;code&gt;Svelte&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extension framework: &lt;code&gt;WXT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Components: &lt;code&gt;bits-ui&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;CSS: &lt;code&gt;tailwindcss&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Icons: &lt;code&gt;lucide-svelte&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Network: &lt;code&gt;axios&lt;/code&gt; (no I was not affected by the breach, because I update my packages like once a month)&lt;/li&gt;
&lt;li&gt;Test: &lt;code&gt;vitest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Code editor: &lt;code&gt;CodeMirror&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Actual coding
&lt;/h3&gt;

&lt;p&gt;And implementation began. It was a bit rough at the start; the first implementation did not look good.&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.amazonaws.com%2Fuploads%2Farticles%2F70m7986ac5fhyj1u3nje.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F70m7986ac5fhyj1u3nje.webp" alt=" " width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Along with the selector panel, I added a popup centered on the main page that provides element information and a selector builder. This helped identifying elements &lt;em&gt;much&lt;/em&gt; easier, as unlike DevTools, all the selector information was all laid out already for me to convert into code.&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.amazonaws.com%2Fuploads%2Farticles%2Fnkdvh0yxggkpa9b4ch46.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fnkdvh0yxggkpa9b4ch46.webp" alt=" " width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The API
&lt;/h3&gt;

&lt;p&gt;Original API layout (changed now):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pq&lt;/code&gt;: stands for &lt;code&gt;pp-query&lt;/code&gt;, contains methods related to querying and traversing through DOM elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ps&lt;/code&gt;: &lt;code&gt;pp-style&lt;/code&gt;: A module for style helpers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pv&lt;/code&gt;: &lt;code&gt;pp-event&lt;/code&gt;: A module for callback-based event selectors
For the methods that were added, view the &lt;a href="https://orangishcat.github.io/page-proxy/docs/0.1.x/" rel="noopener noreferrer"&gt;old documentation&lt;/a&gt;, there's too many for me to list here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The three files was placed in the extension directory, serving as a library containing the modules.&lt;/p&gt;

&lt;p&gt;Also at the top of each userscript, there must be metadata. Similar to Tampermonkey, it had &lt;code&gt;@title&lt;/code&gt;, &lt;code&gt;@website&lt;/code&gt;, and &lt;code&gt;@description&lt;/code&gt; to describe the script, and it is autogenerated upon new script creation but is very much editable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ==Page Proxy==&lt;/span&gt;
&lt;span class="c1"&gt;// @title Page Proxy&lt;/span&gt;
&lt;span class="c1"&gt;// @website&lt;/span&gt;
&lt;span class="c1"&gt;// @description&lt;/span&gt;
&lt;span class="c1"&gt;// ==/Page Proxy==&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The editor
&lt;/h3&gt;

&lt;p&gt;Looking at the above screenshot, the editor looked, well, not great. Code syntax highlighting broke often, and required a lot of maintenance. There were no line numbers. The entire container was offset for some reason. It was overall a huge pain to fix.&lt;/p&gt;

&lt;p&gt;So I switched to &lt;a href="https://microsoft.github.io/monaco-editor/" rel="noopener noreferrer"&gt;Monaco&lt;/a&gt; editor, the same editor that powers VSCode. The extension instantly became a few MB heavier, but it was definitely worth it. Monaco editor was extremely powerful, with all the standard editor features such as renaming variables, syntax highlighting, and more just out of the box. I'm so glad I didn't have to implement any of that myself, yet it's available for everyone to use.&lt;/p&gt;

&lt;p&gt;For autocomplete, I eventually hacked together a solution that generated type stubs from the API and passed it into Monaco editor. That temporary solution is still being used today. If it ain't broke, I ain't fixing it. It's probably staying in the codebase for good.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nearly two months of coding later
&lt;/h3&gt;

&lt;p&gt;The extension looks much more polished now. It was also functional enough that I was able to actually make and run userscripts on it.&lt;br&gt;
I had spent way longer than expected on the project, and decided to cut some features for the initial release.&lt;br&gt;
The select tool was finished fully, but the create tool was marked "Coming soon", and I settled on a simple display for the selectors tool.&lt;br&gt;
At this point, I just needed to publish it and get some initial validation.&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.amazonaws.com%2Fuploads%2Farticles%2Fq1xetab42507vwh7b76j.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fq1xetab42507vwh7b76j.webp" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo website
&lt;/h2&gt;

&lt;p&gt;It was quite plain, and didn't even have a feature list. I struggled a lot to explain the premise of the system in just 1-2 sentences. Even after publishing, the landing page remained incomplete for another two months.&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.amazonaws.com%2Fuploads%2Farticles%2Fgqqf12r6cgwujsy28czo.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fgqqf12r6cgwujsy28czo.webp" alt=" " width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final polishes
&lt;/h2&gt;

&lt;p&gt;Oh... no one could figure out how to use the extension. I've already tried to make the extension pretty self-explanatory, but I guess I still need to write some documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;I used &lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt; to host my documentation website. Although it used &lt;code&gt;mdx&lt;/code&gt; (based on React) while the rest of my website was using Svelte, there just wasn't a solution that worked nearly as well out of the box. There I made some basic tutorials and wrote documentation for the API.&lt;/p&gt;

&lt;p&gt;It was very primitive, but it got the job done, and eventually it was good enough for publish.&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.amazonaws.com%2Fuploads%2Farticles%2Fd51x4m6m8ykmloyrlg15.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fd51x4m6m8ykmloyrlg15.webp" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bugs
&lt;/h3&gt;

&lt;p&gt;I initially used script injection to run user JS in the page content, but that would be blocked by CSP on certain websites, rendering them completely inaccessible for userscripts. This was fixed easily by migrating to the UserScript API, but now users will have to enable permissions to run scripts on the main page.&lt;/p&gt;

&lt;p&gt;Also, there were annoying Firefox-specific bugs that I had to fix, but they overall weren't too important.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end of v0.1.x
&lt;/h2&gt;

&lt;p&gt;For the rest of v0.1.x I just did some chores, bug fixes, and small features. I had made a basic sandbox for the userscript using &lt;code&gt;@endojs/lockdown&lt;/code&gt;, but it didn't really work as it was extremely easy to bypass. I wanted to add functions, network access controls, etc., but it couldn't be done reliably without OS-native controls so I removed it in the last version of v0.1.x.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial validation
&lt;/h2&gt;

&lt;p&gt;I published to Hack Club, and everyone who viewed my project thought it was pretty cool :D&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Whew! This is probably the longest piece of media I have written in my entire life. Evidently I have a lot to learn.&lt;/p&gt;

&lt;p&gt;I'm ending the devlog at v0.1.x because as my first post ever, this took me like 3-4 hours to write. I've already added way more features in v0.2.x and v0.3.x, but I will get around to writing about them another time.&lt;/p&gt;

&lt;p&gt;I learned a lot over this journey. This was my first introduction to multiple new webdev (and also non-webdev) concepts I had never interacted with before.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Figma&lt;/code&gt;: Probably my biggest reward from seeing the project through. I used to never plan out my projects, working things out as I go. Terrible idea. I eventually lost track of where I was going, leading me to lose motivation, and it's much easier to change a wireframe or Figma design than website code. Without UI planning, the UI doesn't look good and is quite clunky. I definitely also wanted to avoid the AI-generated UI look, so rolling my own would be a great learning process and would also look decent.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Svelte&lt;/code&gt;: I used React for a project once, but I hated it. I eventually became trapped in &lt;code&gt;useEffect&lt;/code&gt; hell and gave up. Svelte gave me way less trouble; it handled all the dependencies and states easily without me ever needing to use a &lt;code&gt;$effect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WXT&lt;/code&gt;: Last time I tried making a Chrome extension, I gave up because Chrome refused to recognize my manifest no matter what I tried. WXT allows me to build extensions that are not only cross-browser using a unified API, but simplify the configuration as well. WXT gets a glowing recommendation from me.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Docusaurus&lt;/code&gt;: Not much else to say, other than it is insanely cool and works very well for hosting documentation.&lt;/li&gt;
&lt;li&gt;GitHub actions: I learned to set up Actions workflows for basically whatever I wanted. I wrote build, check, deploy to GitHub Pages workflows using myself and some AI.&lt;/li&gt;
&lt;li&gt;Dependency management: I configured Renovate to check for package updates. After all the package breaches that have been happening lately, I probably won't be updating any packages until they're each at least three days old.&lt;/li&gt;
&lt;li&gt;Search Engine Optimization: I learned to add some basic metadata to the website for SEO.&lt;/li&gt;
&lt;li&gt;Coding with AI: I learned to code alongside AI (no, letting the AI do everything didn't work) and speed up development, while I reviewed the code and kept the code quality as best as I could.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And as of v0.1.x, am I following my original goals for the project?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GUI tools: yes&lt;/li&gt;
&lt;li&gt;API for common use cases: yes&lt;/li&gt;
&lt;li&gt;Accessibility: yes&lt;/li&gt;
&lt;li&gt;Break-resistant: no, not really; there were matchers based on other attributes like inner text, but CSS selectors were still much better&lt;/li&gt;
&lt;li&gt;Integration: no, there's not much integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But this is just the beginning, so I'd say this is a great starting point. I still have a lot of blogging to do for v0.2.x and v0.3.x.&lt;/p&gt;

&lt;p&gt;If you think my extension is interesting, you can &lt;a href="https://orangishcat.github.io/page-proxy/" rel="noopener noreferrer"&gt;give it a try&lt;/a&gt; and maybe stick around as I devlog more of my journey!&lt;/p&gt;

&lt;p&gt;This being my first project, I've probably never even written a blog post before, so I'm still figuring things out. Any feedback you have would be greatly appreciated!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>browser</category>
      <category>extensions</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
