<?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: Akbar Ali</title>
    <description>The latest articles on DEV Community by Akbar Ali (@akbrews).</description>
    <link>https://dev.to/akbrews</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%2F794441%2Ff731ca65-4e67-41c2-859c-1fc457169f43.jpeg</url>
      <title>DEV Community: Akbar Ali</title>
      <link>https://dev.to/akbrews</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akbrews"/>
    <language>en</language>
    <item>
      <title>True or false?</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:54:06 +0000</pubDate>
      <link>https://dev.to/akbrews/true-or-false-4c1a</link>
      <guid>https://dev.to/akbrews/true-or-false-4c1a</guid>
      <description>&lt;p&gt;Someone emailed me a signed contract, and I forwarded it to myself to test something.&lt;/p&gt;

&lt;p&gt;Outlook did what Outlook does. Re-saved the attachment on the way through. Same contract, same signatures, same everything a human would care about.&lt;/p&gt;

&lt;p&gt;Different bytes.&lt;/p&gt;

&lt;p&gt;My verifier, which at that point returned a boolean, looked at it and said &lt;strong&gt;invalid&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the moment I realised I had built a liar (a very confident one, which is worse).&lt;/p&gt;




&lt;h2&gt;
  
  
  The thing I got wrong
&lt;/h2&gt;

&lt;p&gt;I'm building &lt;a href="https://putmysign.com" rel="noopener noreferrer"&gt;Putmysign&lt;/a&gt;, a small app for sending PDFs out and collecting signatures. At the end of it there's a &lt;code&gt;/verify&lt;/code&gt; page: you drop a signed PDF on it, and it tells you whether the thing in your hands is real.&lt;/p&gt;

&lt;p&gt;The obvious design is a checkbox. Valid or not valid. Green or red.&lt;/p&gt;

&lt;p&gt;The obvious design is wrong, and it took a mail client to teach me why.&lt;/p&gt;

&lt;p&gt;Because "these are not the exact bytes I produced" and "this is a forgery" are &lt;em&gt;not the same sentence&lt;/em&gt;. I had been printing the second one every time I meant the first.&lt;/p&gt;

&lt;p&gt;If you tell someone holding a perfectly real contract that it's fake, you haven't built a security feature. You've built a way to ruin somebody's Tuesday.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two checks, not one
&lt;/h2&gt;

&lt;p&gt;So the verdict comes from two completely independent checks, which fail for completely different reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One.&lt;/strong&gt; Does the SHA-256 of this file match a document we finalized? That's the strongest answer there is: these are the exact bytes we made. This is the only check that needs a database row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two.&lt;/strong&gt; Is the certificate &lt;em&gt;inside&lt;/em&gt; the file authentically ours?&lt;/p&gt;

&lt;p&gt;That second one needs explaining. When a document is finalized, I stamp a small HMAC-signed payload into the PDF's &lt;code&gt;Keywords&lt;/code&gt; metadata. Who signed, when, the hash of the original, the document id. Base64url, because &lt;code&gt;Keywords&lt;/code&gt; is a flat PDF string and JSON's quotes and parentheses have to be escaped correctly by every reader that ever touches the file (one opaque token has nothing to get wrong).&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MANIFEST_PREFIX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;putmysign-certificate-v1:&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;function&lt;/span&gt; &lt;span class="nf"&gt;encodeManifest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CertificateManifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;manifestPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MANIFEST_PREFIX&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;signature&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;signature&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="dl"&gt;""&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The point of that: the document can speak for itself.&lt;/p&gt;

&lt;p&gt;My retention job deletes files on a schedule, by design. Someone downgrades, records age out, a mail client re-saves an attachment. In every one of those cases the byte-for-byte lookup finds nothing, and the only thing left in the world that can still say &lt;em&gt;we issued this, for this document, with these signers&lt;/em&gt; is the certificate riding along inside the file.&lt;/p&gt;

&lt;p&gt;A verifier that only recognises documents you still hold a row for will fail on everything you promised to delete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five outcomes
&lt;/h2&gt;

&lt;p&gt;So there are five, strongest first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;verified&lt;/code&gt;: the bytes match a document we finalized. Nothing has changed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;certified&lt;/code&gt;: the certificate is authentically ours, but the bytes aren't the ones we made. &lt;strong&gt;The signings happened. This particular file just isn't the artifact we issued.&lt;/strong&gt; This is my Outlook contract.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;self-signed&lt;/code&gt;: signed with the free browser-only tool. Nothing witnessed it, so the file's account of itself is all there is.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tampered&lt;/code&gt;: carries a certificate that does not check out.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unknown&lt;/code&gt;: no certificate, no matching record. Not one of ours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The middle three are the whole post. Collapsing any of them into "invalid" would be the wrong answer more often than the right one, and I have the receipts (one receipt, from my own inbox, but still).&lt;/p&gt;

&lt;p&gt;There's a smaller decision in there I'm oddly proud of. A certificate with &lt;em&gt;no signature at all&lt;/em&gt; is reported as &lt;code&gt;unknown&lt;/code&gt;, not &lt;code&gt;tampered&lt;/code&gt;, because that's what a document looks like when it was finalized while no signing key was configured. A signature that's present and wrong is a different matter entirely. Saying "forged" to someone holding a real contract is the worst mistake this endpoint could possibly make, so it only says it when it's actually sure.&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;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;signature&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;verdict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;certificateIsAuthentic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signature&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;verdict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tampered&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;certified&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;h2&gt;
  
  
  The self-signed one
&lt;/h2&gt;

&lt;p&gt;The free tool on the landing page signs a PDF entirely in the browser. The file never touches my server. That's the promise, and I'm not breaking it to make my verifier's life easier.&lt;/p&gt;

&lt;p&gt;Which means: nothing witnessed it. Nothing &lt;em&gt;could&lt;/em&gt; have witnessed it.&lt;/p&gt;

&lt;p&gt;I still write a certificate into it. Unsigned, marked &lt;code&gt;kind: "self"&lt;/code&gt;, and worth exactly nothing as proof.&lt;/p&gt;

&lt;p&gt;But it means &lt;code&gt;/verify&lt;/code&gt; can say "this was signed with Putmysign, by this name, on this date, and we were deliberately not involved", instead of reporting my own product's output as a stranger.&lt;/p&gt;

&lt;p&gt;A claim about a file isn't proof, but it beats a shrug.&lt;/p&gt;

&lt;p&gt;(The verify page keeps the same promise, by the way. Your PDF is read with &lt;code&gt;File.arrayBuffer()&lt;/code&gt; and never uploaded. What goes to the server is a 32-byte one-way digest and the certificate that was already in the file. Neither of those is content.)&lt;/p&gt;




&lt;h2&gt;
  
  
  The bit I'd do differently
&lt;/h2&gt;

&lt;p&gt;HMAC was the cheap choice. One environment variable, no key distribution, no ceremony.&lt;/p&gt;

&lt;p&gt;The cost is that the check has to run on my server. A sceptical counterparty, the exact person this feature exists for, cannot verify a certificate without asking me to confirm my own honesty, which is a hilarious thing to build into a trust product.&lt;/p&gt;

&lt;p&gt;A public key fixes it. That's the better end state and I haven't done it yet (I will, right after the eleven other things).&lt;/p&gt;




&lt;p&gt;Anyway. My actual take, one sentence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A verifier that can only say yes or no will spend most of its life saying the wrong one.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you had a boolean like this in your own code, a flag that quietly collapsed two very different failures into one answer? I'd genuinely like to hear about it, mostly so I feel less alone about the mail client thing.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>PDF Rendering in browsers</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Mon, 31 Aug 2026 14:02:55 +0000</pubDate>
      <link>https://dev.to/akbrews/pdf-rendering-in-browsers-1jfd</link>
      <guid>https://dev.to/akbrews/pdf-rendering-in-browsers-1jfd</guid>
      <description>&lt;h2&gt;
  
  
  Why was the certificate blank?
&lt;/h2&gt;

&lt;p&gt;A user sent me a screenshot of a signed document.&lt;/p&gt;

&lt;p&gt;The signature was there. The certificate page behind it was empty. Not broken, not garbled. Just a clean white page with nothing on it, like the PDF gave up halfway through.&lt;/p&gt;

&lt;p&gt;Worked fine on my machine, obviously. It always does.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the preview works
&lt;/h2&gt;

&lt;p&gt;You can't hand a browser a raw PDF and call it a day (not when the file is private and every page needs an access check). So each page gets rendered on the server into a JPEG.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pdftoppm&lt;/code&gt; does the render. One page, scaled to a fixed width, quality 82, into a temp dir that gets torn down in a finally block. The result goes into object storage under a cache key, and that write is best effort. If the cache write fails you still get your page.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cached&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;getObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&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;cached&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;cached&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;pdf&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;fetchPdfAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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;jpeg&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;renderPageWithPoppler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pdf&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple enough. That part was never the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem was Alpine
&lt;/h2&gt;

&lt;p&gt;PDFs have fourteen "base" fonts. Helvetica, Times, Courier and friends. The spec says every viewer must have them, so writing tools don't bother embedding them. Why ship a font everyone already has?&lt;/p&gt;

&lt;p&gt;Everyone, except a &lt;code&gt;node:24-alpine&lt;/code&gt; container.&lt;/p&gt;

&lt;p&gt;Alpine ships with basically no fonts (that's the whole point of Alpine). So &lt;code&gt;pdftoppm&lt;/code&gt; opens the PDF, reads "draw this in Helvetica", goes looking for something to substitute with, finds absolutely nothing, and draws nothing at all. Correctly, by its own logic.&lt;/p&gt;

&lt;p&gt;No error. No warning. Exit code &lt;code&gt;0&lt;/code&gt;. A perfectly successful render of a blank page.&lt;/p&gt;

&lt;p&gt;That's the worst kind of bug. It didn't fail. It agreed with me.&lt;/p&gt;

&lt;p&gt;The fix is one line in the Dockerfile: install Liberation fonts. They're metric compatible with the base-14 families, so nothing shifts around.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other font problem
&lt;/h2&gt;

&lt;p&gt;While I was in there I found something worse, and this one didn't crash either.&lt;/p&gt;

&lt;p&gt;The app shows typed signatures in Dancing Script, the loopy face that reads like handwriting. The generated PDF was drawing them in Helvetica Oblique.&lt;/p&gt;

&lt;p&gt;So you type your name, watch it appear in nice script, click sign, download the file, and get slanted Helvetica. Not wrong exactly. Just not what you agreed to.&lt;/p&gt;

&lt;p&gt;For an app whose entire pitch is "the document is exactly what you saw", that's not a cosmetic bug.&lt;br&gt;
So Dancing Script got vendored into the repo and embedded straight into the PDF with fontkit, subsetted so only the glyphs you actually used come along for the ride.&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;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;embedSignatureFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PDFFont&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerFontkit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fontkit&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;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;subset&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The font is inlined as a data URI at build time instead of read off disk. The production image only copies &lt;code&gt;build/&lt;/code&gt;, so a runtime file read would have found nothing (the blank page bug again, wearing a different hat).&lt;br&gt;
Embedding fixed both ends at once. The download matches the screen now, and the renderer doesn't need the font installed anywhere, because the font is sitting inside the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually learned
&lt;/h2&gt;

&lt;p&gt;Fonts are a deployment concern. I'd have filed them under "design" on any list you handed me, right up until a container with no fonts quietly produced legal documents with nothing written on them.&lt;/p&gt;

&lt;p&gt;And a renderer that exits &lt;code&gt;0&lt;/code&gt; will lie to you. Check the pixels, not the exit code.&lt;/p&gt;

&lt;p&gt;The certificate page got rebuilt in the same pass. Three big signer cards became compact rows, seven to a page, readable timestamps, a pointer to &lt;code&gt;/verify&lt;/code&gt; at the bottom. It's the page almost nobody opens, right until the one day somebody really needs it.&lt;/p&gt;

&lt;p&gt;That's most of what building &lt;a href="//putmysign.com"&gt;Putmysign&lt;/a&gt; has been, honestly. Polishing things people will hopefully never have to look at.&lt;/p&gt;

&lt;p&gt;Anyone else been bitten by a slim base image quietly dropping something? I want to hear the worse ones.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I built an e-signature app that charges you for storage, not signatures</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Sat, 22 Aug 2026 14:06:54 +0000</pubDate>
      <link>https://dev.to/akbrews/i-built-an-e-signature-app-that-charges-you-for-storage-not-signatures-23g4</link>
      <guid>https://dev.to/akbrews/i-built-an-e-signature-app-that-charges-you-for-storage-not-signatures-23g4</guid>
      <description>&lt;h2&gt;
  
  
  The bill that made no sense
&lt;/h2&gt;

&lt;p&gt;A signature is about 400 bytes of JSON and a hash.&lt;/p&gt;

&lt;p&gt;Every big e-signature product will charge you somewhere between $1 and $4 to store those 400 bytes. They call it an "envelope". Run out of envelopes on the 22nd of the month and your deal waits until the 1st. I have watched a real contract sit still because a counter hit zero.&lt;/p&gt;

&lt;p&gt;The expensive part is the other thing. A 4 MB PDF sitting in storage for seven years, backed up and replicated, costs real money every month. That part is free. It is a checkbox on the feature list.&lt;/p&gt;

&lt;p&gt;So the pricing is backwards. It charges for the cheap thing and gives away the expensive one.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://putmysign.com" rel="noopener noreferrer"&gt;Putmysign&lt;/a&gt; the other way around. Unlimited documents, unlimited recipients, unlimited signatures, on every plan. You only pay if you want the files kept.&lt;/p&gt;

&lt;p&gt;Free keeps your PDFs for 5 days. Pro is $19 a month and keeps them forever. The audit trail is kept forever on both, because it is a few kilobytes and it is the whole point of the product.&lt;/p&gt;

&lt;p&gt;That one pricing decision shaped almost every technical choice underneath. That is the interesting part.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Deleting files is a feature, so it has to actually happen
&lt;/h2&gt;

&lt;p&gt;If I promise free files are gone in 5 days, "we will get to it eventually" is not good enough. A scheduled job walks every document past its expiry date and removes the file from storage, along with every cached page image made from it.&lt;/p&gt;

&lt;p&gt;But it deletes the file, not the record. The row stays. The audit trail stays. The hashes stay:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// signatures applied, certificate page added&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So five days later the PDF is gone from my storage and I still cannot lie about what happened. If you kept your own copy, you can hash it and check it against a record I cannot quietly change.&lt;/p&gt;

&lt;p&gt;Throwing away the file while keeping the proof turned out to be a nice property. I did not design it. It fell out of the pricing.&lt;/p&gt;

&lt;p&gt;The worst bug in this area was a quiet one. A signing link can outlive the file it points to. The recipient clicks a link that is perfectly valid, and lands on nothing. So link expiry is capped to the retention window:&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="cm"&gt;/**
 * A share link must never outlive the file it points to, otherwise a recipient
 * opens a valid token and finds nothing to sign.
 */&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;MAX_EXPIRY_DAYS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PLAN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retentionDays&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two separate clocks on the same object will drift apart sooner or later. Make one of them depend on the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Recipients never make an account
&lt;/h2&gt;

&lt;p&gt;Unlimited recipients means a recipient cannot be a user record I charge for.&lt;/p&gt;

&lt;p&gt;A signup wall in the middle of someone else's contract is the biggest reason paperwork stalls. It mostly exists so vendors can count seats.&lt;/p&gt;

&lt;p&gt;So the signing link is the login. It is an HMAC over the document and the recipient, built from a server-only secret. Only the hash of the token is stored:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&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;SIGNING_TOKEN_SECRET&lt;/span&gt; &lt;span class="o"&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;SESSION_SECRET&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;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;must be at least 32 characters&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="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&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;Store the hash, not the token. If my database leaks tomorrow, nobody gets a working signing link out of it. Same idea as hashing passwords, applied to a URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. One row per document
&lt;/h2&gt;

&lt;p&gt;A signing session is a burst of tiny writes. Opened. Viewed page 3. Signed field 2. IP recorded. All of it against one document that is only ever read as a whole.&lt;/p&gt;

&lt;p&gt;Splitting that across six tables buys me joins I never run. So each document is one JSONB column holding everything, with the fields I actually filter on copied out into real indexed columns: owner, status, updated date, expiry date, purge date. A GIN index on the JSON handles signing-link and "shared with me" lookups.&lt;/p&gt;

&lt;p&gt;The real risk with a single row is two people signing at the same moment. Last write wins, one signature disappears. I fixed it the boring way, with &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; inside a transaction.&lt;/p&gt;

&lt;p&gt;Postgres has been a fine document database for years, and it still hands you row locks when you need them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Thumbnails without a thumbnail service
&lt;/h2&gt;

&lt;p&gt;Page previews come from &lt;code&gt;pdftoppm&lt;/code&gt;, part of poppler. It is a 25 year old C program. I shell out to it, render the page when someone asks for it, and cache the image back into the bucket next to the PDF. Delete the PDF and the cached pages go with it.&lt;/p&gt;

&lt;p&gt;No render service, no queue, no third party API with a per page price on it. Storage is what I charge for, so anything that turns compute into a monthly bill works against the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack, quickly
&lt;/h2&gt;

&lt;p&gt;React Router 7, TypeScript, Postgres with Prisma, any S3 compatible bucket (MinIO locally, so the whole thing runs on a laptop with one &lt;code&gt;docker compose up&lt;/code&gt;), Firebase Auth for owners only, Resend for email with bounce handling, Paddle for billing.&lt;/p&gt;

&lt;p&gt;Nothing fancy. The interesting decisions are all about what is missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things worth stealing
&lt;/h2&gt;

&lt;p&gt;You do not have to care about e-signatures to use any of this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Charge for what actually costs you money.&lt;/strong&gt; If your pricing unit and your cost are different things, people feel it as unfair long before they can explain why.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete the file, keep the proof.&lt;/strong&gt; Hashes and audit rows are tiny. They let you delete aggressively and still stay accountable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two clocks on one object will drift.&lt;/strong&gt; Derive one from the other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A signup wall in someone else's workflow is a tax on your own customer.&lt;/strong&gt; They pay it in deals that stall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSONB, plus a few copied-out indexed columns, plus &lt;code&gt;FOR UPDATE&lt;/code&gt;&lt;/strong&gt; covers a lot of "we need a document database" situations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is live at &lt;strong&gt;&lt;a href="https://putmysign.com" rel="noopener noreferrer"&gt;putmysign.com&lt;/a&gt;&lt;/strong&gt;. Free tier, no card. Upload a PDF you already have and send it to someone who will never make an account.&lt;/p&gt;

&lt;p&gt;If you can break the signing link logic, I would genuinely like to hear about it in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What is the most backwards pricing unit you have run into? I will start: per seat pricing on a read only viewer.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>postgres</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Translate apps in one command</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Wed, 13 Aug 2025 06:04:17 +0000</pubDate>
      <link>https://dev.to/akbrews/translate-apps-in-one-command-3mll</link>
      <guid>https://dev.to/akbrews/translate-apps-in-one-command-3mll</guid>
      <description>&lt;p&gt;Check out the package first:&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/@pulimoodan/localiser" rel="noopener noreferrer"&gt;@pulimoodan/localiser&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Translate i18n locales with one command&lt;/li&gt;
&lt;li&gt;Translate only required languages (only the ones we changed)&lt;/li&gt;
&lt;li&gt;Translate only the required namespaces (yeah, same as above: only the ones we changed)&lt;/li&gt;
&lt;li&gt;Translate any language, with any iso codes: like pt or pt-BR (because, we're using AI. Not a flex btw)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concerns to be addressed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Optimise the Open AI requests with the only the required keys, instead of whole json file&lt;/li&gt;
&lt;li&gt;An init command to generate the project configuration &lt;/li&gt;
&lt;li&gt;Doesn't support different types of folder structures, only: lang/namespace.json&lt;/li&gt;
&lt;li&gt;Configure different types of models&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Contribute (or detract)
&lt;/h2&gt;

&lt;p&gt;If you've got an idea to improve or play around with this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fork the repo &lt;/li&gt;
&lt;li&gt;Work your magic, cook well&lt;/li&gt;
&lt;li&gt;Slam a PR&lt;/li&gt;
&lt;li&gt;And I will think about it (kidding, we need those contributions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Link to GitHub repo: &lt;a href="https://github.com/pulimoodan/localiser" rel="noopener noreferrer"&gt;Localiser&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Code pollution</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Sun, 03 Aug 2025 06:04:11 +0000</pubDate>
      <link>https://dev.to/akbrews/code-pollution-49fp</link>
      <guid>https://dev.to/akbrews/code-pollution-49fp</guid>
      <description>&lt;p&gt;The list of &lt;code&gt;PR&lt;/code&gt;s to be reviewed, getting long and long each day in numbers.&lt;/p&gt;

&lt;p&gt;The dashboard, looking at me with that weird devil laugh every time I open the Github.&lt;/p&gt;

&lt;p&gt;It's not me, being lazy and stubborn to keep reviewing everything consistently (maybe).&lt;/p&gt;

&lt;p&gt;It's some dry dreaded lines of waste, of code changes being written in those files that make the stubborn I am.&lt;/p&gt;

&lt;p&gt;The AI slop, waiting on those changes to get refuge in our codebases are becoming a nightmare day by day.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cause
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers being lazy to write code. They're not here for passion (or they lost it), just for money.&lt;/li&gt;
&lt;li&gt;They don't care about what they (or the agent) write, they're just focused on completing the task due to work pressure.&lt;/li&gt;
&lt;li&gt;They're not good at this, maybe they're some product managers who focus on the app but not technology under the hood. &lt;/li&gt;
&lt;li&gt;The FOMO of using AI to get tasks move quickly and wasting time (most of the medias are responsible for this, the me before a few months would assure this).&lt;/li&gt;
&lt;li&gt;People being developers instead of poets (The art of beautiful code is long gone).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Review PRs effectively (I used to rewrite some my own, instead of educating the PR author)&lt;/li&gt;
&lt;li&gt;Talk to your teammates and motivate them (there had been one of my friends who quoted about a fellow's code: I got goosebumps reading it)&lt;/li&gt;
&lt;li&gt;As a developer, think about a problem before asking it to the agent. Share your thoughts and get feedback.&lt;/li&gt;
&lt;li&gt;Try to use AI for automation, not to be dumb day by day (The ability to think will fade away, aware of that).&lt;/li&gt;
&lt;li&gt;Proofread the code written by the agent, and instruct how to make it well written.&lt;/li&gt;
&lt;li&gt;Sometimes writing with your own hands feels like greatness being achieved (don't listen to the FOMO creators).&lt;/li&gt;
&lt;li&gt;Learn to code or learn to prompt (be good at it, sometimes it is easier to express in code than in natural language).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I could have become a project manager 20 years ago if I didn’t care to write code myself and I just wanted outcomes.&lt;br&gt;
-- DHH&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Common JS library import in ES Module</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Mon, 21 Jul 2025 07:15:13 +0000</pubDate>
      <link>https://dev.to/akbrews/common-js-library-import-in-es-module-57i7</link>
      <guid>https://dev.to/akbrews/common-js-library-import-in-es-module-57i7</guid>
      <description>&lt;p&gt;Spent a lot of time debugging this.&lt;/p&gt;

&lt;p&gt;I was using react color library from NPM in a project and my project was in ES module scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;reactColor&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;react-color&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cannot&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nf"&gt;undefined &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;displayName&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;h2&gt;
  
  
  Fix
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;reactColor&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;react-color&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;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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SketchPicker&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reactColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>react</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Prisma: Could not parse schema engine response</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Thu, 19 Dec 2024 08:13:48 +0000</pubDate>
      <link>https://dev.to/akbrews/prisma-could-not-parse-schema-engine-response-4502</link>
      <guid>https://dev.to/akbrews/prisma-could-not-parse-schema-engine-response-4502</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Recently encountered this error while deploying our app to production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Could not parse schema engine response: SyntaxError: Unexpected token E in JSON at position 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no more explanation why this occurred, just this line. In the recent merge commit we had only changed a couple of locale keywords, that's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Figuring out
&lt;/h2&gt;

&lt;p&gt;Searched all over the internet and found nothing.&lt;/p&gt;

&lt;p&gt;Then, I noticed a warning a couple lines of above the error, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prisma:warn Prisma failed to detect the libssl/openssl version to use, and may not work as expected. Defaulting to "openssl-1.1.x".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I searched about this on GitHub and found this:&lt;br&gt;
&lt;a href="https://github.com/prisma/prisma/issues/19729" rel="noopener noreferrer"&gt;Prisma fails to find openssl 3.0.x on new bookworm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I realised that for some reasons, the new version of the alpine docker image I was using doesn't come with the openssl package - Which was required for Prisma engine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The issue discussion I shared above said that use node version 18.5.something and we can temporarily resolve this or use a different docker image.&lt;/p&gt;

&lt;p&gt;But, I don't have to use a different version of node and make conflicts to other packages.&lt;/p&gt;

&lt;p&gt;So, I should install the package manually.&lt;/p&gt;

&lt;p&gt;This is the docker image I was using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18-alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added these lines to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# install openssl
RUN apk update &amp;amp;&amp;amp; apk upgrade
RUN apk add --no-cache openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, that solved the problem.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Importing from GitLab to GitHub</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Fri, 17 May 2024 07:19:17 +0000</pubDate>
      <link>https://dev.to/akbrews/importing-from-gitlab-to-github-3bcd</link>
      <guid>https://dev.to/akbrews/importing-from-gitlab-to-github-3bcd</guid>
      <description>&lt;h2&gt;
  
  
  In GitLab:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Profile -&amp;gt; Preferences -&amp;gt; Access tokens -&amp;gt; Add new token&lt;/li&gt;
&lt;li&gt;Name it, select all permission that apply, click create. &lt;/li&gt;
&lt;li&gt;Now you get a token, copy it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  In GitHub
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create new repository. &lt;/li&gt;
&lt;li&gt;On the create page, right below the heading there is a text saying &lt;code&gt;import a repository&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Click it, copy the repo url from Gitlab and paste it there.&lt;/li&gt;
&lt;li&gt;Add your gitlab username and the access token. &lt;/li&gt;
&lt;li&gt;Name the repository. &lt;/li&gt;
&lt;li&gt;Click &lt;code&gt;begin import&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It will take some time, sit tight.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Object memory reference in JS</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Tue, 12 Mar 2024 20:05:52 +0000</pubDate>
      <link>https://dev.to/akbrews/object-memory-reference-in-js-2ne7</link>
      <guid>https://dev.to/akbrews/object-memory-reference-in-js-2ne7</guid>
      <description>&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;person1&lt;/span&gt; &lt;span class="o"&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;Alex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toronto&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;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What would be the output of the above code?&lt;/p&gt;

&lt;p&gt;Does that look like this:&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;address:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Toronto"&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;You're wrong. It would look like this:&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;address:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Toronto"&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;Yes, that's the correct output. But that was not what we ought to do. We need the name of the person1 to stay like whatever it was before. We changed the name of person2.&lt;/p&gt;

&lt;p&gt;Then, where did it go wrong?&lt;/p&gt;

&lt;p&gt;The problem is with the JavaScript's object memory reference. We only assigned the &lt;code&gt;person1&lt;/code&gt; variable to the &lt;code&gt;person2&lt;/code&gt; variable. Javascript keeps the memory reference of the variable in the place for both of them. That's why when we changed the name of &lt;code&gt;person2&lt;/code&gt;, it affected &lt;code&gt;person1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How to overcome this bug?&lt;/p&gt;

&lt;p&gt;Even, I had spent a full day debugging a commercial app and banged my keyboards due to frustration to find out it's just a memory reference bug.&lt;/p&gt;

&lt;p&gt;Here's a solution:&lt;br&gt;
&lt;strong&gt;Spread operator&lt;/strong&gt;&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;person1&lt;/span&gt; &lt;span class="o"&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;Alex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toronto&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;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we are spreading the &lt;code&gt;person1&lt;/code&gt; variable to create a new one. Now it would work fine as we expected. But, it has an exception.&lt;/p&gt;

&lt;p&gt;What if our code was like this:&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;person1&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Telles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toronto&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;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&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 our expected output:&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="err"&gt;name:&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="err"&gt;first:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;last:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Telles"&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="err"&gt;address:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Toronto"&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;But, what we get:&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="err"&gt;name:&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="err"&gt;first:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;last:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Telles"&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="err"&gt;address:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Toronto"&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;The &lt;code&gt;person1&lt;/code&gt; also got changed even if we used spread operation to create a new object. &lt;/p&gt;

&lt;p&gt;This is because, the spread operator only affects the first level properties and it won't clone the deep level key values. So, the &lt;code&gt;first&lt;/code&gt; in the &lt;code&gt;name&lt;/code&gt; property still has the memory reference to its parent.&lt;/p&gt;

&lt;p&gt;Here is the solution to deep clone JS objects:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON stringify&lt;/strong&gt;&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;person2&lt;/span&gt; &lt;span class="o"&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;parse&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;person1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting the object to string and then into JSON resolves the problem.&lt;/p&gt;

&lt;p&gt;But still, we have a problem.&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;function&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a Test&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Telles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Toronto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;f&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;person2&lt;/span&gt; &lt;span class="o"&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;parse&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;person1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will return an error saying &lt;code&gt;TypeError: person2.f is not a function&lt;/code&gt;. This is because, we had a memory reference to the function in the parent object and when we converted it into string for cloning, that reference got lost. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;thanks to &lt;a class="mentioned-user" href="https://dev.to/efpage"&gt;@efpage&lt;/a&gt; for the feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, there are some ways to overcome this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using loadash&lt;/strong&gt;&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a Test&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person1&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Telles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;XYZ&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;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lodash library has a cloneDeep function which will help to deep clone object with all memory reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structured clone function&lt;/strong&gt;&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;person2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;structuredClone&lt;/code&gt; function will be available in the new version of JavaScript and it will deep copy the parent object.&lt;/p&gt;

&lt;p&gt;Hope this articles helped you. Drop your feedbacks in comments.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>This or that?</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Wed, 06 Dec 2023 09:07:49 +0000</pubDate>
      <link>https://dev.to/akbrews/this-or-that-162j</link>
      <guid>https://dev.to/akbrews/this-or-that-162j</guid>
      <description>&lt;p&gt;Have you ever ended up in a situation where you have many images of something but hard to choose the perfect one?&lt;/p&gt;

&lt;p&gt;Like, if we have two images, it's easy to choose the best one. But when it's 5 or 10 or 50 images, the process becomes more difficult. &lt;/p&gt;

&lt;p&gt;The solution is to take the first two pictures, find the best one. Now take the third picture and cross check with the best one and it continues.&lt;/p&gt;

&lt;p&gt;I made a simple web app which helps to do this. Simply, we upload a bunch of images and click start. The program shows us a pair of images and we have to choose the best one. It repeats until the best one finally being found. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pulimoodan/dot-poll" rel="noopener noreferrer"&gt;Dot-poll&lt;/a&gt; is a simple web app with basic html and js which delivers this solution. See the live version here: &lt;a href="https://pulimoodan.github.io/dot-poll/" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a lot of features we can add to this app and I am looking for developers who are interested working on this. Leave a comment or a pull request if you find this worth a try.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>An alternative for Render?</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Tue, 05 Dec 2023 09:17:32 +0000</pubDate>
      <link>https://dev.to/akbrews/an-alternative-for-render-3l8o</link>
      <guid>https://dev.to/akbrews/an-alternative-for-render-3l8o</guid>
      <description>&lt;p&gt;I have been using &lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Render&lt;/a&gt; for hosting my side projects. It's flawless, easy to connect GitHub projects and deploy with just a click.&lt;/p&gt;

&lt;p&gt;I switched to render because I was fed up with the hard and weird deployment process of Heroku. Render has some amazing features and easy to use.&lt;/p&gt;

&lt;p&gt;But recently, I faced this problem of services getting suspended if they are in free tier. Somehow, it's hard to afford some side projects in a paid plan. I share my side projects with my friends and they say it's not loading. I ask them to wait for couple of minutes and they usually stop trying after some time.&lt;/p&gt;

&lt;p&gt;Currently, I am searching for a better alternative which provide full time serving of the web app we deploy. I really liked the workflow of &lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Render&lt;/a&gt; and hope to find something similar.&lt;/p&gt;

</description>
      <category>hosting</category>
      <category>webdev</category>
      <category>github</category>
    </item>
    <item>
      <title>A platform to share jokes</title>
      <dc:creator>Akbar Ali</dc:creator>
      <pubDate>Mon, 04 Dec 2023 09:00:39 +0000</pubDate>
      <link>https://dev.to/akbrews/a-platform-to-share-jokes-8mp</link>
      <guid>https://dev.to/akbrews/a-platform-to-share-jokes-8mp</guid>
      <description>&lt;p&gt;I was totally inspired by the dev.to and twitter platforms due to their engagements and user interactions.&lt;/p&gt;

&lt;p&gt;So, sharing jokes and reacting to them is a pretty entertaining medium and thought about building a platform for that.&lt;/p&gt;

&lt;p&gt;I am planning to add more interactive features to the app and expecting more public opinions.&lt;/p&gt;

&lt;p&gt;Feel free to try the app here: &lt;a href="https://chali.onrender.com/" rel="noopener noreferrer"&gt;Chali App&lt;/a&gt; and share your feedbacks.&lt;/p&gt;

&lt;p&gt;View the source code if you are interested to know how I built it: &lt;a href="https://github.com/pulimoodan/Chali" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, I am trying to work on the android and IOS apps.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>react</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
