<?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: Dharmendra Jagodana</title>
    <description>The latest articles on DEV Community by Dharmendra Jagodana (@dharmendra_jagodana).</description>
    <link>https://dev.to/dharmendra_jagodana</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%2F4000544%2F325a8f7c-d1d4-48bc-9c48-037b999a1f24.png</url>
      <title>DEV Community: Dharmendra Jagodana</title>
      <link>https://dev.to/dharmendra_jagodana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dharmendra_jagodana"/>
    <language>en</language>
    <item>
      <title>I made this cover image with one URL. Here's everything Imejis.io can do</title>
      <dc:creator>Dharmendra Jagodana</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:19:02 +0000</pubDate>
      <link>https://dev.to/dharmendra_jagodana/i-made-this-cover-image-with-one-url-heres-everything-imejisio-can-do-43b0</link>
      <guid>https://dev.to/dharmendra_jagodana/i-made-this-cover-image-with-one-url-heres-everything-imejisio-can-do-43b0</guid>
      <description>&lt;p&gt;The cover image on this post was not made in Figma.&lt;/p&gt;

&lt;p&gt;It's an &lt;strong&gt;Imejis.io&lt;/strong&gt; design: a few layers, with some of them marked &lt;em&gt;dynamic&lt;/em&gt;. If I change the JSON, I get a different image. Same design, two API calls:&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%2Fynoq2r3hjjmeikq9yoqt.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%2Fynoq2r3hjjmeikq9yoqt.png" alt="Same design, launch copy" width="800" height="336"&gt;&lt;/a&gt;&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%2Fez61dzd6dn4i8heehnig.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%2Fez61dzd6dn4i8heehnig.png" alt="Same design, weekly report copy" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The headline, subtitle, KPI, star rating, and bar chart all changed. I didn't open an editor.&lt;/p&gt;

&lt;p&gt;That's the idea behind Imejis: &lt;strong&gt;you design an image once, and it becomes an API.&lt;/strong&gt; Below is everything it can do.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 The core idea: dynamic fields
&lt;/h2&gt;

&lt;p&gt;Every layer in a design has a &lt;code&gt;key&lt;/code&gt;, like &lt;code&gt;headline&lt;/code&gt;, &lt;code&gt;avatar&lt;/code&gt;, or &lt;code&gt;price&lt;/code&gt;. Set &lt;code&gt;dynamic: true&lt;/code&gt; on a layer, and you can override any of its fields at render time with dot-paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;headline.text      → "Hello DEV 👋"
headline.color     → "#ff0055"
avatar.image       → "https://…/me.png"
revenue.value      → 92400
weekly_chart.data  → [12, 19, 15, 27]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule to remember: &lt;strong&gt;you always target a field, never the bare layer.&lt;/strong&gt; &lt;code&gt;?headline=Hi&lt;/code&gt; does nothing. &lt;code&gt;?headline.text=Hi&lt;/code&gt; works. Imejis returns a &lt;code&gt;warnings&lt;/code&gt; array when you get this wrong, so the mistake doesn't go unnoticed.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Rendering: GET or POST
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt; is good for &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags, emails, and anywhere else that only accepts a URL:&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;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR_RENDER_URL?headline.text=Hello%20DEV&amp;amp;format=webp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; is better for long text, many fields, or values you don't want showing up in logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMEJIS_RENDER_URL&lt;/span&gt;&lt;span class="s2"&gt;?format=png"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"dma-api-key: &lt;/span&gt;&lt;span class="nv"&gt;$IMEJIS_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "headline":     { "text": "Your weekly report, {{rendered live}}" },
    "revenue.value": 92400,
    "revenue.delta": -4,
    "weekly_chart.data": [48, 44, 39, 41, 36, 33, 30]
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; report.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nested (&lt;code&gt;{ "headline": { "text": … } }&lt;/code&gt;) and dot-path (&lt;code&gt;"headline.text"&lt;/code&gt;) forms do the same thing. Your API key can go in a header, a query param, or the POST body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Four output formats
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Use it for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lossless, transparency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jpeg&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Smallest photos, &lt;code&gt;?quality=1-100&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;webp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Modern web, transparency, tiny files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Vector&lt;/strong&gt; pages for print, certificates, invoices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Three delivery modes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bytes&lt;/strong&gt; (the default): the image comes back in the response.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;?delivery=hosted&lt;/code&gt;: you get a permanent public URL, which suits Slack blocks, webhooks, and CMSs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;?delivery=signed&amp;amp;expiresIn=60&lt;/code&gt;: you get a private link that expires, up to 7 days.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 27 components (it does far more than text on a rectangle)
&lt;/h2&gt;

&lt;p&gt;This is the part that surprised me most. On top of the basics, Imejis renders &lt;strong&gt;real data visualizations&lt;/strong&gt; into images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basics:&lt;/strong&gt; &lt;code&gt;text&lt;/code&gt; · &lt;code&gt;image&lt;/code&gt; · &lt;code&gt;rect&lt;/code&gt; · &lt;code&gt;circle&lt;/code&gt; · &lt;code&gt;line&lt;/code&gt; · &lt;code&gt;shape&lt;/code&gt; (any SVG path)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codes:&lt;/strong&gt; &lt;code&gt;qr&lt;/code&gt; (URLs, coupons, Wi-Fi) · &lt;code&gt;barcode&lt;/code&gt; (Code 128, EAN-13, UPC-A, ITF-14, GS1-128, and more)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scores and KPIs:&lt;/strong&gt; &lt;code&gt;rating&lt;/code&gt; (stars, hearts, or a custom emoji, with half fills) · &lt;code&gt;progress&lt;/code&gt; (bar, ring, or gauge) · &lt;code&gt;metric&lt;/code&gt; (a KPI tile with an up/down delta and a sparkline)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Charts:&lt;/strong&gt; &lt;code&gt;chart&lt;/code&gt; (bar, line, area, waterfall, lollipop, step, slope, and combo with a second axis) · &lt;code&gt;pie&lt;/code&gt;/donut · &lt;code&gt;waffle&lt;/code&gt; · &lt;code&gt;funnel&lt;/code&gt; · &lt;code&gt;bullet&lt;/code&gt; · &lt;code&gt;dumbbell&lt;/code&gt; · &lt;code&gt;radar&lt;/code&gt; · &lt;code&gt;scatter&lt;/code&gt; (with a trend line) · &lt;code&gt;candlestick&lt;/code&gt; (OHLC) · &lt;code&gt;treemap&lt;/code&gt; (market heatmap) · &lt;code&gt;calendar&lt;/code&gt; (GitHub-style contribution grid) · &lt;code&gt;sankey&lt;/code&gt; · &lt;code&gt;chord&lt;/code&gt; · &lt;code&gt;gantt&lt;/code&gt; · &lt;code&gt;table&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maps:&lt;/strong&gt; &lt;code&gt;map&lt;/code&gt;, which draws choropleth or bubble maps of the world, US states, or provinces and states of Canada, Germany, Australia, Brazil, and India. You key the data by ISO code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sales_map.data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;310&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of these is dynamic. Push new &lt;code&gt;.data&lt;/code&gt; with each render, and a daily dashboard screenshot becomes a single API call.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✍️ Typography goes deep
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;500+ fonts&lt;/strong&gt; built in, and you can upload your own.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;autoResize&lt;/code&gt; with min and max font sizes, so long titles don't overflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline patterns&lt;/strong&gt;: write &lt;code&gt;Save {{40%}} today&lt;/code&gt; and only the &lt;code&gt;{{…}}&lt;/code&gt; part gets its own color, pill background, or size.&lt;/li&gt;
&lt;li&gt;Gradient text fills, stacked outlines in the "sticker" style, text shadows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curved text&lt;/strong&gt; on an arched baseline, which is great for personalized book covers.&lt;/li&gt;
&lt;li&gt;RTL support, letter spacing, text transforms, and highlight backgrounds.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📐 One design, every size
&lt;/h2&gt;

&lt;p&gt;A design can carry &lt;strong&gt;variations&lt;/strong&gt;: a 1080×1080 master, plus a 1080×1920 Story, a 1200×630 OG image, a 1280×720 YouTube thumbnail, and so on.&lt;/p&gt;

&lt;p&gt;Variations are &lt;em&gt;linked&lt;/em&gt; to the master. Each size stores only what's different at that size, and when you add a size, Imejis &lt;strong&gt;automatically reflows&lt;/strong&gt; the layout onto it. Then you render the size you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?variation=instagram-story
?variation=og-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dynamic data is shared across sizes, so &lt;strong&gt;one payload fills a whole social media kit.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Bulk export and carousels
&lt;/h2&gt;

&lt;p&gt;You can render up to &lt;strong&gt;25 images in one call&lt;/strong&gt;, and each one comes back as a stored URL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the same design in every size&lt;/li&gt;
&lt;li&gt;the same design with 25 different data rows (personalized cards, A/B copy)&lt;/li&gt;
&lt;li&gt;several different designs together&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;a carousel&lt;/strong&gt;, because the results keep their order and the array &lt;em&gt;is&lt;/em&gt; the slide sequence. Make each item a PDF and you get a PDF carousel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If one item fails, the others still render, and you're only billed for the successful ones.&lt;/p&gt;




&lt;h2&gt;
  
  
  🕰️ Versioning that protects what's public
&lt;/h2&gt;

&lt;p&gt;This is where Imejis acts like a developer tool and not a design toy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every publish creates a &lt;strong&gt;numbered, labeled version&lt;/strong&gt;, and you can &lt;strong&gt;roll back&lt;/strong&gt; to any of them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share links&lt;/strong&gt; (a public page, no account needed) and &lt;strong&gt;templates&lt;/strong&gt; are &lt;em&gt;pinned&lt;/em&gt; to a specific version. Editing the design doesn't change what the public sees until you sync.&lt;/li&gt;
&lt;li&gt;If a bad edit went live, you can point the public page at an older version immediately and fix the design afterwards.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎨 Templates and gallery
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The public gallery has &lt;strong&gt;200+ templates&lt;/strong&gt;: LinkedIn carousels, quote cards, wellness slides, business covers, and more.&lt;/li&gt;
&lt;li&gt;You can turn any of your designs into a &lt;strong&gt;workspace template&lt;/strong&gt; so your team starts from on-brand layouts.&lt;/li&gt;
&lt;li&gt;You can submit a template to the public gallery, where an admin reviews it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 It works with AI agents too
&lt;/h2&gt;

&lt;p&gt;Imejis has an &lt;strong&gt;MCP server&lt;/strong&gt;, so assistants like Claude can create, edit, preview, and export designs directly. The cover of this post was made that way: the agent read the component guide, built the layers, previewed the result, and exported all three variants above in one bulk call.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What I'd build with it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto OG images&lt;/strong&gt; for every blog post, generated at build time from the frontmatter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificates&lt;/strong&gt; with the name, course, date, and a QR code, exported as vector PDFs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekly KPI cards&lt;/strong&gt; posted to Slack with real charts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce banners&lt;/strong&gt; with the price, rating, and barcode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub-style streak cards&lt;/strong&gt; with the &lt;code&gt;calendar&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event tickets&lt;/strong&gt; with a seat number and a scannable code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localized ads&lt;/strong&gt;: one design, with the copy swapped for each language&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A quick OG image in Node
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// build-og.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IMEJIS_RENDER_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?format=png&amp;amp;delivery=hosted`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;dma-api-key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IMEJIS_API_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;Content-Type&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;application/json&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;body&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title.text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;author.text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avatar.image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorAvatar&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;}&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// drop `url` into &amp;lt;meta property="og:image"&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧾 TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🖼️ Design once&lt;/td&gt;
&lt;td&gt;Visual editor plus 200+ templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔌 Render anywhere&lt;/td&gt;
&lt;td&gt;GET/POST, one URL per image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📊 Real data&lt;/td&gt;
&lt;td&gt;27 components, including charts, maps, QR codes, and barcodes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📐 Every size&lt;/td&gt;
&lt;td&gt;Linked variations with auto-reflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📦 At scale&lt;/td&gt;
&lt;td&gt;25 images per bulk call, ordered carousels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 Safe to ship&lt;/td&gt;
&lt;td&gt;Versions, rollback, pinned share links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🤖 Agent-ready&lt;/td&gt;
&lt;td&gt;MCP server for AI assistants&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you've ever opened Figma just to change one line of text on an image, try &lt;strong&gt;&lt;a href="https://www.imejis.io" rel="noopener noreferrer"&gt;imejis.io&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What would you automate first? Let me know in the comments 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>automation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I rebuilt the same SaaS backend five times. So I turned it into one SDK.</title>
      <dc:creator>Dharmendra Jagodana</dc:creator>
      <pubDate>Thu, 09 Jul 2026 14:20:32 +0000</pubDate>
      <link>https://dev.to/dharmendra_jagodana/i-rebuilt-the-same-saas-backend-five-times-so-i-turned-it-into-one-sdk-bok</link>
      <guid>https://dev.to/dharmendra_jagodana/i-rebuilt-the-same-saas-backend-five-times-so-i-turned-it-into-one-sdk-bok</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I build SaaS products with my brother. After shipping five of them, I realized I'd rebuilt the exact same backend (auth, Stripe, multi-tenancy, workflows, email, webhooks) five separate times. So I extracted it into one SDK for React/Next.js. It now runs all five products in production. This is the honest version, including what it still can't do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The fifth time I sat down to write sign-up and login, I stopped.&lt;/p&gt;

&lt;p&gt;It wasn't hard. That was the problem. I'd done it four times already, and I could see the next three weeks laid out in front of me like a checklist I'd memorized: auth, then Stripe, then workspaces, then roles and permissions, then usage limits, then transactional emails, then webhooks. Weeks of plumbing before I could touch the one feature that was the actual reason I started the project.&lt;/p&gt;

&lt;p&gt;I build software with my brother. Five of our products are live right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imejis&lt;/strong&gt; - a template-based image-generation API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AgentCenter&lt;/strong&gt; - mission control for AI agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PlugNode&lt;/strong&gt; - a visual AI workflow builder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RemoteWait&lt;/strong&gt; - a virtual queue system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkTracer&lt;/strong&gt; - creator analytics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five completely different products. Every single one needed the exact same backend before it could do anything interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The backend tax
&lt;/h2&gt;

&lt;p&gt;There's a tax you pay on every SaaS product before you write a single line of the thing that makes it special.&lt;/p&gt;

&lt;p&gt;Users, so you build auth - and not just email/password, but social login, magic links, sessions, resets. Revenue, so you wire up Stripe, including a whole metering layer if you're doing anything usage-based. Teams, so you build workspaces, roles, invitations. Then email. Then feature flags. Then webhooks.&lt;/p&gt;

&lt;p&gt;None of it is novel. All of it is necessary. And all of it stands between you and the actual idea.&lt;/p&gt;

&lt;p&gt;The first time, it's fun, you're learning. By the third time, you're copy-pasting from your last repo and quietly resenting it. By the fifth, you're maintaining five slightly different versions of the same bugs.&lt;/p&gt;

&lt;p&gt;The first rebuild feels like progress. The fifth one feels like a warning.&lt;/p&gt;

&lt;h2&gt;
  
  
  From copy-paste to a platform
&lt;/h2&gt;

&lt;p&gt;After the third product, I stopped copy-pasting and started extracting - pulling the shared pieces into their own package with a hard boundary between what was truly generic and what was product-specific.&lt;/p&gt;

&lt;p&gt;After the fourth, the package had opinions. It knew how billing should attach to a workspace. It knew each org should get its own physically isolated database. It had a workflow engine, because I was tired of gluing cron jobs and automation tools together just to send a welcome sequence.&lt;/p&gt;

&lt;p&gt;After the fifth, it wasn't a package anymore. It was a platform, running all five products in production every day.&lt;/p&gt;

&lt;p&gt;That's BuildBase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;The whole SaaS backend for React and Next.js, in one SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @buildbase/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not just auth. Nineteen integrated modules that actually talk to each other, because they were built together for real products rather than stitched together from a marketplace of disconnected services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auth&lt;/strong&gt; - email/password, magic link, passkeys (WebAuthn), Google, GitHub, Microsoft, LinkedIn, plus a full OAuth 2.0 authorization server so your app can become an identity provider&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Billing&lt;/strong&gt; - Stripe with your own account, usage-based metering, quota enforcement, credits, seats, multi-currency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tenancy&lt;/strong&gt; - an isolated workspace and isolated database per org, with RBAC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt; - a real event-driven engine (triggers, actions, conditions), queue-backed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication&lt;/strong&gt; - email through your own sender (SMTP, Google, Microsoft, Mailgun) plus event-driven Slack alerts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growth&lt;/strong&gt; - feature flags, audience/CRM, short links, webhooks, analytics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global&lt;/strong&gt; - i18n across 8 locales and 22 currencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headless&lt;/strong&gt; - an API layer, so you can use any of it without our UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point isn't the length of the list. It's that these pieces work as one system. Billing knows about your workspaces. Workflows can read your audience. Feature flags can target a plan. That coherence is the part you can't copy-paste from five different vendors.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it actually runs
&lt;/h2&gt;

&lt;p&gt;Under the hood it's MongoDB + Redis + Docker. The defining architectural choice is &lt;strong&gt;a physically isolated database per organization&lt;/strong&gt; - not a shared table with a &lt;code&gt;tenant_id&lt;/code&gt; column, but real per-org isolation. That's the single biggest cost driver, which is also why the pricing is per-app rather than per-seat (more on that below).&lt;/p&gt;

&lt;p&gt;Being honest about the tradeoff: per-org isolation is great for data separation and terrible if you pretend it scales infinitely. It doesn't yet. There's a known connection-pool ceiling I'm not going to hand-wave past, so I'm not making big scale claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three decisions I care most about
&lt;/h2&gt;

&lt;p&gt;A feature list tells you what a product does. These tell you what it believes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Bring your own Stripe, and I take 0% of it.&lt;/strong&gt; Your customers pay you, directly, into your own Stripe account. I never sit in the middle of your revenue. The norm in this space is that your bill climbs as &lt;em&gt;you&lt;/em&gt; grow. I built the opposite on purpose, because I've been the founder watching that line item climb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. You own your data, three ways to run it.&lt;/strong&gt; Shared (isolated DB per app on our infra), Dedicated (dedicated infra per app), or Self-hosted (run our Docker images on your own servers with your own MongoDB and Redis). No lock-in by design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Per-app pricing.&lt;/strong&gt; One app = one org = one isolated database. You pay for what you actually run, not per-seat and not per-MAU. Three plans: Launch, Grow, Scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let me be straight about where it stands
&lt;/h2&gt;

&lt;p&gt;This is the part I'd want to read first, so here it is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React and Next.js only, today.&lt;/strong&gt; No Vue, Svelte, or native mobile SDK yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not open source.&lt;/strong&gt; I know this matters most to this crowd, so I'm not going to bury it. Self-hosting means running our &lt;em&gt;compiled&lt;/em&gt; Docker images on your own infrastructure - you don't get the source code. What you get instead is no vendor lock-in: your infra, your database, your Stripe. I'm not going to dress up "self-hostable" as "open source," because it isn't, and you'd catch it in five minutes anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Early and bootstrapped.&lt;/strong&gt; It's me and my brother. The SDK is young (0.x). But it isn't a landing page with a waitlist - five real products depend on it in production every day. When something breaks, it breaks for me first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who it's for
&lt;/h2&gt;

&lt;p&gt;Solo founders, indie hackers, and small teams building SaaS on React or Next.js who are sick of wiring the same backend together for the tenth time and want those weeks back for the product that actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, or tear it apart
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://www.buildbase.app" rel="noopener noreferrer"&gt;https://www.buildbase.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://demo.buildbase.app/" rel="noopener noreferrer"&gt;https://demo.buildbase.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://docs.buildbase.app/introduction" rel="noopener noreferrer"&gt;https://docs.buildbase.app/introduction&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-host starter:&lt;/strong&gt; &lt;a href="https://github.com/buildbase-app/self-hosted-starter" rel="noopener noreferrer"&gt;https://github.com/buildbase-app/self-hosted-starter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The feedback I most want, especially from this audience: what would make you trust a backend SDK enough to build your next SaaS on it? And what's the one thing missing for your stack?&lt;/p&gt;

&lt;p&gt;Reach me anytime at &lt;a href="mailto:dharmendra@buildbase.app"&gt;dharmendra@buildbase.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I built this because I got tired of paying the backend tax. If it saves you even one of those rebuilds, it did its job.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>nextjs</category>
      <category>buildinpublic</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
