<?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: BuildAPlugin</title>
    <description>The latest articles on DEV Community by BuildAPlugin (@buildaplugin).</description>
    <link>https://dev.to/buildaplugin</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%2F4092492%2Fe2f41918-bd87-481f-a760-30f5136914d7.png</url>
      <title>DEV Community: BuildAPlugin</title>
      <link>https://dev.to/buildaplugin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/buildaplugin"/>
    <language>en</language>
    <item>
      <title>I wanted a REST client whose workflow was not hard-coded</title>
      <dc:creator>BuildAPlugin</dc:creator>
      <pubDate>Mon, 24 Aug 2026 19:01:26 +0000</pubDate>
      <link>https://dev.to/buildaplugin/i-wanted-a-rest-client-whose-workflow-was-not-hard-coded-55og</link>
      <guid>https://dev.to/buildaplugin/i-wanted-a-rest-client-whose-workflow-was-not-hard-coded-55og</guid>
      <description>&lt;p&gt;Most REST clients are excellent until the request succeeds.&lt;/p&gt;

&lt;p&gt;Then the surrounding work begins: add a header based on the current environment, validate a response, extract a value, expose the operation to somebody who should not need to understand the raw request, or repeat the same five clicks tomorrow.&lt;/p&gt;

&lt;p&gt;I kept seeing the same awkward choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep the workflow as tribal knowledge around a generic request;&lt;/li&gt;
&lt;li&gt;write a script that only its author understands; or&lt;/li&gt;
&lt;li&gt;build and maintain another internal web app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built &lt;strong&gt;BuildAPlugin&lt;/strong&gt; to explore a fourth option: keep the request inside a local REST client, but make the client itself programmable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A plugin should be inspectable
&lt;/h2&gt;

&lt;p&gt;The extension format is ordinary JavaScript. A minimal plugin declares what it intends to use and returns the request or response it changes:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request-marker&lt;/span&gt;&lt;span class="dl"&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;Request Marker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&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;requests.transform&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;beforeRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-Plugin&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="s2"&gt;enabled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;request&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;That explicit manifest matters. Extensibility becomes difficult to trust when behavior is invisible or when every extension implicitly receives the whole application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hooks are useful after the happy path
&lt;/h2&gt;

&lt;p&gt;The request hook is only the beginning. A response hook can inspect a result and update focused parts of the rendered workspace:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response-status&lt;/span&gt;&lt;span class="dl"&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;Response Status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&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;ui.transform&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;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;afterResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dollar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#responseStatus&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;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where a generic API request can become a small operational tool. The raw request remains available, but the everyday user can get a button, a form, validation, or a purpose-built response view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep local workflows local
&lt;/h2&gt;

&lt;p&gt;The app starts as a desktop REST client for macOS, Windows, and Linux. Requests, variables, response inspection, Postman-style collection import/export, and plugin data do not require turning every workflow into a hosted service.&lt;/p&gt;

&lt;p&gt;For workflows that are easier to express spatially, the same workspace includes a visual builder for connecting inputs, layout, logic, API actions, state, and device operations.&lt;/p&gt;

&lt;p&gt;The design goal is not to replace code with boxes. It is to let each part of a workflow live at the level where it is easiest to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question I am testing
&lt;/h2&gt;

&lt;p&gt;The interesting question is not whether another REST client can send a request. It is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What repeated API task deserves its own small interface, but does not deserve an entirely separate application?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have published a 24-second product walkthrough showing the request, response, plugin menu, and visual builder:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/oR_uE0Z6EP4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;BuildAPlugin is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://buildaplugin.com/download/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=channel_launch&amp;amp;utm_content=inspectable_plugins_launch" rel="noopener noreferrer"&gt;https://buildaplugin.com/download/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=channel_launch&amp;amp;utm_content=inspectable_plugins_launch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would genuinely like examples of the repeated API workflows you would turn into focused tools first.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>api</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
