<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Jatin's Website | RSS Feed]]></title><description><![CDATA[Software/Electronics engineer. This is my digital garden.]]></description><link>https://jatinshimpi.netlify.app</link><generator>GatsbyJS</generator><lastBuildDate>Mon, 23 Mar 2026 16:28:23 GMT</lastBuildDate><item><title><![CDATA[The Wild Oasis - Making It Responsive]]></title><description><![CDATA[why responsiveness matters after building the custom backend and refactoring both frontends, the wild oasis worked great — on desktop. but…]]></description><link>https://jatinshimpi.netlify.app/the-wild-oasis-responsive/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/the-wild-oasis-responsive/</guid><pubDate>Thu, 26 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;why-responsiveness-matters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-responsiveness-matters&quot; aria-label=&quot;why responsiveness matters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;why responsiveness matters&lt;/h2&gt;
&lt;p&gt;after building the custom backend and refactoring both frontends, the wild oasis worked great — on desktop. but try opening it on your phone and things got... ugly. elements overlapping, sidebar taking up the entire screen, tables completely unusable. you know the drill.&lt;/p&gt;
&lt;p&gt;so I sat down and made both the &lt;strong&gt;admin dashboard&lt;/strong&gt; and the &lt;strong&gt;customer website&lt;/strong&gt; fully responsive. the interesting part? they use completely different CSS approaches — styled-components on the admin side and tailwind on the customer side. same goal, two different playbooks.&lt;/p&gt;
&lt;h2 id=&quot;the-customer-website-tailwind-css&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-customer-website-tailwind-css&quot; aria-label=&quot;the customer website tailwind css permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;the customer website (tailwind CSS)&lt;/h2&gt;
&lt;p&gt;the customer-facing site is built with next.js and tailwind, so responsiveness here is all about mobile-first utility classes — &lt;code class=&quot;language-text&quot;&gt;sm:&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;md:&lt;/code&gt; prefixes that progressively enhance the layout as the screen gets bigger.&lt;/p&gt;
&lt;h3 id=&quot;home-page-hero&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#home-page-hero&quot; aria-label=&quot;home page hero permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;home page hero&lt;/h3&gt;
&lt;p&gt;the hero section needed to scale its typography and CTA button properly. the heading goes from &lt;code class=&quot;language-text&quot;&gt;text-4xl&lt;/code&gt; on mobile to &lt;code class=&quot;language-text&quot;&gt;text-8xl&lt;/code&gt; on desktop, and the button padding scales with &lt;code class=&quot;language-text&quot;&gt;sm:&lt;/code&gt; breakpoints.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/client-home-hero.png&quot; alt=&quot;Home Page - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;cabin-cards&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cabin-cards&quot; aria-label=&quot;cabin cards permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;cabin cards&lt;/h3&gt;
&lt;p&gt;the cabin cards were originally side-by-side (&lt;code class=&quot;language-text&quot;&gt;flex-row&lt;/code&gt;). on mobile they now stack vertically (&lt;code class=&quot;language-text&quot;&gt;flex-col sm:flex-row&lt;/code&gt;) with the image using &lt;code class=&quot;language-text&quot;&gt;aspect-video&lt;/code&gt; to maintain a clean ratio. the detail page also collapses to a single column.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/client-cabin-cards.png&quot; alt=&quot;Cabin Cards - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;about-page&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#about-page&quot; aria-label=&quot;about page permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;about page&lt;/h3&gt;
&lt;p&gt;the about page used a 5-column grid for its content layout. on mobile this collapses to a single column (&lt;code class=&quot;language-text&quot;&gt;grid-cols-1 md:grid-cols-5&lt;/code&gt;), with all &lt;code class=&quot;language-text&quot;&gt;col-span-*&lt;/code&gt; classes prefixed with &lt;code class=&quot;language-text&quot;&gt;md:&lt;/code&gt;. headings scale down to &lt;code class=&quot;language-text&quot;&gt;text-3xl&lt;/code&gt; and gaps are reduced.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/client-about-page.png&quot; alt=&quot;About Page - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;account-section--sidebar-to-tab-bar&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#account-section--sidebar-to-tab-bar&quot; aria-label=&quot;account section  sidebar to tab bar permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;account section — sidebar to tab bar&lt;/h3&gt;
&lt;p&gt;this was one of my favourite changes. the account sidebar with text links transforms into a &lt;strong&gt;horizontal icon-only tab bar&lt;/strong&gt; on mobile. the text labels get &lt;code class=&quot;language-text&quot;&gt;hidden md:inline&lt;/code&gt;, and the nav switches to &lt;code class=&quot;language-text&quot;&gt;justify-around&lt;/code&gt; with the border moving from the right side to the bottom.&lt;/p&gt;
&lt;p&gt;the sign out button follows the same pattern — icon only on mobile.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/client-account-tabbar.png&quot; alt=&quot;Account Tab Bar - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;reservation-layout&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reservation-layout&quot; aria-label=&quot;reservation layout permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;reservation layout&lt;/h3&gt;
&lt;p&gt;the calendar + reservation form grid changes from &lt;code class=&quot;language-text&quot;&gt;grid-cols-2&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;grid-cols-1 md:grid-cols-2&lt;/code&gt; — calendar stacks on top, form below. reservation cards also stack vertically and hide some date details on mobile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;live site:&lt;/strong&gt; &lt;a href=&quot;https://the-wild-oasis-client-jatin.netlify.app/&quot;&gt;the-wild-oasis-client-jatin.netlify.app&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-admin-dashboard-styled-components&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-admin-dashboard-styled-components&quot; aria-label=&quot;the admin dashboard styled components permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;the admin dashboard (styled-components)&lt;/h2&gt;
&lt;p&gt;the admin dashboard is a react + vite app using styled-components — so responsiveness here means writing &lt;code class=&quot;language-text&quot;&gt;@media&lt;/code&gt; queries inside template literals. different vibe, same results.&lt;/p&gt;
&lt;h3 id=&quot;sidebar--hamburger-menu&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sidebar--hamburger-menu&quot; aria-label=&quot;sidebar  hamburger menu permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;sidebar → hamburger menu&lt;/h3&gt;
&lt;p&gt;the biggest structural change. on desktop, the sidebar is always visible in a two-column grid. on mobile, it becomes a &lt;strong&gt;fixed-position overlay&lt;/strong&gt; that slides in from the left when you tap the ☰ button.&lt;/p&gt;
&lt;p&gt;I created a new &lt;code class=&quot;language-text&quot;&gt;SidebarContext&lt;/code&gt; to manage the toggle state, and added a backdrop overlay when the sidebar is open.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Desktop: [Sidebar | Main Content]  — sidebar always visible in grid
Mobile:  [Main Content] + overlay sidebar triggered by ☰ button&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/admin-sidebar-overlay.png&quot; alt=&quot;Admin Sidebar Overlay - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;dashboard-grid&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dashboard-grid&quot; aria-label=&quot;dashboard grid permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;dashboard grid&lt;/h3&gt;
&lt;p&gt;the dashboard stats grid goes from &lt;code class=&quot;language-text&quot;&gt;4 columns&lt;/code&gt; → &lt;code class=&quot;language-text&quot;&gt;2 columns&lt;/code&gt; at 1024px → &lt;code class=&quot;language-text&quot;&gt;1 column&lt;/code&gt; at 768px. the tricky part was the chart components — they had hard-coded grid spans like &lt;code class=&quot;language-text&quot;&gt;grid-column: 3 / span 2&lt;/code&gt; which reference columns that don&apos;t exist in a 1-column layout. all charts reset to &lt;code class=&quot;language-text&quot;&gt;1 / -1&lt;/code&gt; (full width) on mobile.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/admin-dashboard.png&quot; alt=&quot;Admin Dashboard - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;forms--header&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#forms--header&quot; aria-label=&quot;forms  header permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;forms &amp;#x26; header&lt;/h3&gt;
&lt;p&gt;modal forms switch from a 3-column grid layout to a single column on mobile, and the modal itself goes to &lt;code class=&quot;language-text&quot;&gt;95vw&lt;/code&gt; width. the header hides the username text and only shows the avatar circle, with the hamburger using &lt;code class=&quot;language-text&quot;&gt;margin-right: auto&lt;/code&gt; to keep the icons right-aligned.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/the-wild-oasis-responsive/admin-account-form.png&quot; alt=&quot;Admin Account Form - Mobile&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;tables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tables&quot; aria-label=&quot;tables permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;tables&lt;/h3&gt;
&lt;p&gt;rather than hiding columns or redesigning tables for mobile, I went with a practical approach: a &lt;code class=&quot;language-text&quot;&gt;min-width: 60rem&lt;/code&gt; on the table ensures it maintains its readable layout and scrolls horizontally inside an &lt;code class=&quot;language-text&quot;&gt;overflow-x: auto&lt;/code&gt; container.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;live site:&lt;/strong&gt; &lt;a href=&quot;https://adorable-gecko-dced13.netlify.app/&quot;&gt;adorable-gecko-dced13.netlify.app&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;patterns-that-worked&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#patterns-that-worked&quot; aria-label=&quot;patterns that worked permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;patterns that worked&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Where Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hamburger sidebar&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Admin — collapsible overlay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Icon-only nav&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Customer — account tab bar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Grid collapse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Both — &lt;code class=&quot;language-text&quot;&gt;grid-cols-1&lt;/code&gt; on mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flex-wrap&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Admin — Row, TableOperations, Filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Min-width + scroll&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Admin — Table component&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hidden text&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Both — UserAvatar, SideNavigation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Font scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Both — headings and buttons reduced&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;bug-fixes-along-the-way&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bug-fixes-along-the-way&quot; aria-label=&quot;bug fixes along the way permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;bug fixes along the way&lt;/h2&gt;
&lt;p&gt;responsiveness work has this funny side effect — you end up finding bugs you never noticed on desktop.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;isLoading1&lt;/code&gt; undefined&lt;/strong&gt; in DashboardLayout — missing destructuring alias&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;amp;mdash&lt;/code&gt; missing semicolon&lt;/strong&gt; in BookingRow — rendered as literal text instead of an em dash&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CORS blocking preflight&lt;/strong&gt; — &lt;code class=&quot;language-text&quot;&gt;cors()&lt;/code&gt; middleware was after &lt;code class=&quot;language-text&quot;&gt;helmet()&lt;/code&gt;, had to move it first&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rate limit too aggressive&lt;/strong&gt; — 100 requests/hour was choking development, bumped to 1000 in dev mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;conclusion&lt;/h2&gt;
&lt;p&gt;making two apps responsive with two different CSS approaches was a great exercise. styled-components gives you full control but you write more code. tailwind is faster but you need to think mobile-first from the start.&lt;/p&gt;
&lt;p&gt;the key takeaway: &lt;strong&gt;don&apos;t fight the grid&lt;/strong&gt;. if your desktop layout uses a 4-column grid, plan early for how it collapses. retroactively fixing grid spans that reference non-existent columns is not fun.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://github.com/jatinshimpi/the-wild-oasis-backend&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer Site:&lt;/strong&gt; &lt;a href=&quot;https://the-wild-oasis-client-jatin.netlify.app/&quot;&gt;the-wild-oasis-client-jatin.netlify.app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admin Panel:&lt;/strong&gt; &lt;a href=&quot;https://adorable-gecko-dced13.netlify.app/&quot;&gt;adorable-gecko-dced13.netlify.app&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[QLock UI Overhaul - Embracing the Pixel Art Aesthetic]]></title><description><![CDATA[The Need for a Facelift QLock started as a functional tool—a utility for timed MCQ practice. It did its job well, but visually, it felt a…]]></description><link>https://jatinshimpi.netlify.app/qlock-ui-overhaul/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/qlock-ui-overhaul/</guid><pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-need-for-a-facelift&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-need-for-a-facelift&quot; aria-label=&quot;the need for a facelift permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Need for a Facelift&lt;/h2&gt;
&lt;p&gt;QLock started as a functional tool—a utility for timed MCQ practice. It did its job well, but visually, it felt a bit... utilitarian. As I continued to use it and build upon it, I realized the interface needed some personality.&lt;/p&gt;
&lt;p&gt;old design &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/qlock-ui-overhaul/qlock-old-design.png&quot; alt=&quot;Old Design&quot;&gt;&lt;/p&gt;
&lt;p&gt;new design &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/qlock-ui-overhaul/qlock-new-design.png&quot; alt=&quot;New Design&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;shifting-the-color-scheme&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shifting-the-color-scheme&quot; aria-label=&quot;shifting the color scheme permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Shifting the Color Scheme&lt;/h2&gt;
&lt;p&gt;The original color scheme was functional but standard and looked very ai-generated because of thr heavy use of claude 4.5. I wanted something that felt more cohesive, modern and human made, yet retained a bit of retro charm to go with the new direction I was heading. I completely overhauled the palette, moving towards high-contrast, easier-on-the-eyes tones that make long study sessions less straining.&lt;/p&gt;
&lt;p&gt;specifically the following palette &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/qlock-ui-overhaul/qlock-ui-palette.png&quot; alt=&quot;New Color Palette&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;goodbye-emojis-hello-pixel-art&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#goodbye-emojis-hello-pixel-art&quot; aria-label=&quot;goodbye emojis hello pixel art permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Goodbye Emojis, Hello Pixel Art&lt;/h2&gt;
&lt;p&gt;One of the biggest changes in this update is the removal of standard emojis. While emojis are easy to use, they often look different across devices and can feel a bit &quot;generic.&quot;&lt;/p&gt;
&lt;p&gt;I wanted a consistent, retro-tech vibe. That&apos;s where &lt;strong&gt;pixel art&lt;/strong&gt; comes in.&lt;/p&gt;
&lt;p&gt;To implement this, I integrated &lt;a href=&quot;https://www.npmjs.com/package/@nsmr/pixelart-react&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;@nsmr/pixelart-react&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;@nsmr/pixelart-react&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^2.0.0&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This library allowed me to replace the standard emojis with pixelated icons that perfectly match the new aesthetic.&lt;/p&gt;
&lt;h2 id=&quot;why-pixel-art&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-pixel-art&quot; aria-label=&quot;why pixel art permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why Pixel Art?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; The icons look exactly the same on every device and browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aesthetic:&lt;/strong&gt; It gives the app a distinct &quot;indie game&quot; feel, which can make the potentially stressful task of timed practice feel a bit more engaging.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;whats-next&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#whats-next&quot; aria-label=&quot;whats next permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What&apos;s Next?&lt;/h2&gt;
&lt;p&gt;Adding settings modal to change the background and accent colour to few options to select from&lt;/p&gt;
&lt;p&gt;and most importantly&lt;/p&gt;
&lt;p&gt;With the visual foundation now solid, I&apos;m looking to add more security measures accross all platforms.&lt;/p&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[The Scrap Mini Amp]]></title><description><![CDATA[Introduction On my 20th birthday my father gave me enough money to buy an old rusty electric guitar, But after asking for an amp for it i…]]></description><link>https://jatinshimpi.netlify.app/scrap-mini-amp/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/scrap-mini-amp/</guid><pubDate>Mon, 16 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;On my 20th birthday my father gave me enough money to buy an old rusty electric guitar, But after asking for an amp for it i didnt get any, so i saved some money collected some scraps and hacked together a bedroom level guitar amp.&lt;/p&gt;
&lt;p&gt;On my summer break in 2024 i was home, and I went to my uncles for something and asked him if he had a speaker lying around he said i dont have a speaker BUT an old home theatre. I was like thats even better.&lt;/p&gt;
&lt;p&gt;I brought it to me dorm in pune and started making this, at firat i just hooked the guitar directly to the home theatre, it was very quiet but the sound was great&lt;/p&gt;
&lt;p&gt;So i researched abput it and found out there is a signal mismatch, the amp expects a line level signal but the guitar outputs a instrument level signal&lt;/p&gt;
&lt;p&gt;But the sound was very warm and i loved it, i found out later after i opened the amp after it got fried and found out on the main board there was a tube simulator circuit used as the preamp for all the signals coming in the. so all i needed was a overdrive circxuit to go with it and i was pretty much done but as i was going to order the parts the piece got fried.&lt;/p&gt;
&lt;h2 id=&quot;the-overdrive-circuit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-overdrive-circuit&quot; aria-label=&quot;the overdrive circuit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The overdrive circuit&lt;/h2&gt;
&lt;p&gt;I found this brilliant article by &lt;a href=&quot;https://www.wamplerpedals.com/blog/latest-news/2020/05/how-to-design-a-basic-overdrive-pedal-circuit/&quot;&gt;Wampler Pedals&lt;/a&gt; that walks through designing a basic overdrive pedal circuit. I used their schematic as the starting point and made some modifications to fit the components I had lying around.&lt;/p&gt;
&lt;p&gt;here&apos;s the original schematic I based mine on &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/scrap-mini-amp/overdrive-schematic.webp&quot; alt=&quot;Overdrive Schematic from Wampler Pedals&quot;&gt;&lt;/p&gt;
&lt;p&gt;and here&apos;s what my actual board looks like — hand-soldered on a perfboard &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/scrap-mini-amp/overdrive-circuit-front.jpeg&quot; alt=&quot;Overdrive Circuit - Front&quot;&gt;&lt;/p&gt;
&lt;p&gt;the back is a proper rat&apos;s nest of solder joints and wire bridges, but it works &gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/scrap-mini-amp/overdrive-circuit-back.png&quot; alt=&quot;Overdrive Circuit - Back&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-power-amp&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-power-amp&quot; aria-label=&quot;the power amp permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The power amp&lt;/h2&gt;
&lt;p&gt;The original plan was to use an old home theatre system for both the speakers and the power amplification. It worked for a while, but eventually the circuit got fried. So I replaced the internals with a &lt;strong&gt;TPA3118 PBTL&lt;/strong&gt; Class D power amp module I had bought online.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/scrap-mini-amp/power-amp.png&quot; alt=&quot;Class D Power Amp Module&quot;&gt;&lt;/p&gt;
&lt;p&gt;For power, I used an old laptop charger. It outputs around 19V which is more than enough for a tiny bedroom amp.&lt;/p&gt;
&lt;h2 id=&quot;how-it-sounds&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-it-sounds&quot; aria-label=&quot;how it sounds permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How it sounds&lt;/h2&gt;
&lt;p&gt;It&apos;s messy, it&apos;s not that loud, but it actually sounds pretty cool for something made of trash.&lt;/p&gt;
&lt;h3 id=&quot;clean-tone&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#clean-tone&quot; aria-label=&quot;clean tone permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Clean tone&lt;/h3&gt;
&lt;video width=&quot;100%&quot; controls&gt;
  &lt;source src=&quot;/images/scrap-mini-amp/clean-tone.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;h3 id=&quot;overdrive&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#overdrive&quot; aria-label=&quot;overdrive permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Overdrive&lt;/h3&gt;
&lt;video width=&quot;100%&quot; controls&gt;
  &lt;source src=&quot;/images/scrap-mini-amp/bheegi-bheegi-overdrive.mp4&quot; type=&quot;video/mp4&quot;&gt;
&lt;/video&gt;
&lt;h2 id=&quot;what-i-learned&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-i-learned&quot; aria-label=&quot;what i learned permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What I learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;reading schematics and actually building them on a perfboard are very different skills&lt;/li&gt;
&lt;li&gt;soldering is surprisingly meditative once you get the hang of it&lt;/li&gt;
&lt;li&gt;constraint breeds creativity — not having money for a real amp forced me to actually understand how amps work&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Total cost? about &lt;strong&gt;₹500&lt;/strong&gt;. I learned a lot about electronics and guitar amps while building this. It was a fun project and i would recommend it to anyone who is interested in electronics and music.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&quot;Constraint breeds creativity&quot;&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Circuit Reference:&lt;/strong&gt; &lt;a href=&quot;https://www.wamplerpedals.com/blog/latest-news/2020/05/how-to-design-a-basic-overdrive-pedal-circuit/&quot;&gt;Wampler Pedals — How to Design a Basic Overdrive Pedal Circuit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[Idea: Teensy 4.1 Guitar Interface]]></title><description><![CDATA[The Idea I want to build a digital guitar effects processor using a Teensy 4.1 microcontroller. The idea is to write code that manipulates…]]></description><link>https://jatinshimpi.netlify.app/teensy-guitar-interface/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/teensy-guitar-interface/</guid><pubDate>Mon, 16 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-idea&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-idea&quot; aria-label=&quot;the idea permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Idea&lt;/h2&gt;
&lt;p&gt;I want to build a digital guitar effects processor using a &lt;strong&gt;Teensy 4.1 microcontroller&lt;/strong&gt;. The idea is to write code that manipulates the audio signal in real-time — applying delay, reverb, distortion, etc. — directly on the chip.&lt;/p&gt;
&lt;p&gt;I can also record the audio, I would have to use a powerful audio codec with it so that i can stream the data live&lt;/p&gt;
&lt;h2 id=&quot;why-teensy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-teensy&quot; aria-label=&quot;why teensy permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why Teensy?&lt;/h2&gt;
&lt;p&gt;Teensy 4.1 is a beast for audio processing. It has a fast clock speed and great libraries for audio. Plus, coding my own effects sounds like a fun way to combine music and programming.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(More details coming when I actually start building this...)&lt;/em&gt;&lt;/p&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[QLock - MCQ Timer App]]></title><description><![CDATA[How it started one day I was talking with my roommate and i asked him hows his study going he said hes using an spp for timed questions so…]]></description><link>https://jatinshimpi.netlify.app/qlock-story/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/qlock-story/</guid><pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;how-it-started&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-it-started&quot; aria-label=&quot;how it started permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How it started&lt;/h2&gt;
&lt;p&gt;one day I was talking with my roommate and i asked him hows his study going he said hes using an spp for timed questions so he can record how much time is taken for each question, he&apos;s a GATE aspirant. he was also saying that most of the apps lack basic features or the UX is painful to use when you&apos;re trying to simulate real exam conditions.&lt;/p&gt;
&lt;p&gt;I was like — wait, I can build this.&lt;/p&gt;
&lt;p&gt;so we sat down, brainstormed features, discussed what he actually needed vs what existing apps were giving him. and that&apos;s how QLock was born. he was basically my user 0, my first real client. we&apos;re still adding features to it honestly, the list keeps growing.&lt;/p&gt;
&lt;h2 id=&quot;what-it-does&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-it-does&quot; aria-label=&quot;what it does permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What it does&lt;/h2&gt;
&lt;p&gt;QLock is built for students appearing for JEE, NEET, GATE and other competitive exams where time management is everything. it supports MCQ, MSQ, and NAT question types — because different exams use different formats and most apps just ignore that.&lt;/p&gt;
&lt;p&gt;you can set timers per question or for the entire session, practice under real exam pressure, and track how you&apos;re doing over time. the whole point is to make practice feel like the real thing.&lt;/p&gt;
&lt;h2 id=&quot;the-tech-stack&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-tech-stack&quot; aria-label=&quot;the tech stack permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The tech stack&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;React&lt;/td&gt;
&lt;td&gt;Web Frontend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;Mobile App (Android)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust / Axum&lt;/td&gt;
&lt;td&gt;Backend API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expo&lt;/td&gt;
&lt;td&gt;Mobile Tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;the-jetpack-compose-disaster&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-jetpack-compose-disaster&quot; aria-label=&quot;the jetpack compose disaster permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The jetpack compose disaster&lt;/h2&gt;
&lt;p&gt;The first mistake i did was making the webapp first and then going on to make the mobile app&lt;/p&gt;
&lt;p&gt;so when I decided to build the mobile app, I wanted a pixel-to-pixel clone of the web version. so naturally I asked claude — &quot;hey I want to make an exact clone of my web app for android, what should I use?&quot;&lt;/p&gt;
&lt;p&gt;claude said jetpack compose.&lt;/p&gt;
&lt;p&gt;so I blindly followed it. started building in kotlin, jetpack compose, the whole android native setup. and oh man, it was a nightmare. trying to replicate a React web UI in jetpack compose is like trying to write a novel in a language you barely speak. the paradigms are completely different, the styling system is nothing like CSS, and I was spending more time fighting the framework than actually building features.&lt;/p&gt;
&lt;p&gt;after a few painful days I stepped back and thought — wait, why am I doing this to myself? I already know React. the web app is in React. why not just use React Native?&lt;/p&gt;
&lt;p&gt;switched to React Native with Expo and things immediately clicked. the component structure was familiar, I could reuse a lot of the logic, and the styling was close enough to CSS that I wasn&apos;t losing my mind anymore. lesson learned — don&apos;t blindly follow AI suggestions without thinking about your own context first.&lt;/p&gt;
&lt;h2 id=&quot;why-rust-for-the-backend&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#why-rust-for-the-backend&quot; aria-label=&quot;why rust for the backend permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why Rust for the backend&lt;/h2&gt;
&lt;p&gt;I could&apos;ve just used express and called it a day. but I wanted to learn Rust, and building a real project is the best way to do that. Axum turned out to be a great choice — it&apos;s fast, the type system catches bugs at compile time, and honestly once you get past the borrow checker it&apos;s pretty satisfying to write.&lt;/p&gt;
&lt;h2 id=&quot;where-were-at-now&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#where-were-at-now&quot; aria-label=&quot;where were at now permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Where we&apos;re at now&lt;/h2&gt;
&lt;p&gt;the web version is live and working. the android app is built and functional — we&apos;re holding off on publishing to the Play Store until we finish a security audit. I don&apos;t want to ship something to real users without making sure auth, data handling, and all that stuff is solid.&lt;/p&gt;
&lt;p&gt;we still have a bunch of features on the roadmap that my roommate and I keep brainstorming. it&apos;s one of those projects that just keeps evolving because we&apos;re actually using it.&lt;/p&gt;
&lt;h2 id=&quot;what-i-learned&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-i-learned&quot; aria-label=&quot;what i learned permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What I learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;build for a real user.&lt;/strong&gt; having my roommate as user 0 made every feature decision easier. no guessing, just &quot;does this actually help him practice better?&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;don&apos;t blindly follow AI.&lt;/strong&gt; claude is great but it doesn&apos;t know your context. jetpack compose was the &quot;correct&quot; answer technically, but react native was the right answer for me.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rust is worth the pain.&lt;/strong&gt; the learning curve is steep but once it clicks, you write more confident code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cross-platform is hard but doable.&lt;/strong&gt; porting from React to React Native isn&apos;t a copy-paste job, but the mental model transfers really well.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://github.com/jatinshimpi/mcq-timer&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[Mini Redis - Rust]]></title><description><![CDATA[Introduction RivetDB is a mini Redis implementation written in Rust, built as a hands-on learning project to dive deep into systems…]]></description><link>https://jatinshimpi.netlify.app/rivetDB-story/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/rivetDB-story/</guid><pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;RivetDB&lt;/strong&gt; is a mini Redis implementation written in Rust, built as a hands-on learning project to dive deep into systems programming concepts like memory management, concurrency, and network protocols.&lt;/p&gt;
&lt;h2 id=&quot;motivation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#motivation&quot; aria-label=&quot;motivation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Motivation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Understand how in-memory databases work under the hood&lt;/li&gt;
&lt;li&gt;Learn Rust&apos;s ownership model and concurrency primitives in a real-world context&lt;/li&gt;
&lt;li&gt;Explore the RESP (Redis Serialization Protocol) and TCP networking&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tech-stack&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tech-stack&quot; aria-label=&quot;tech stack permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tech Stack&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Core Implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tokio&lt;/td&gt;
&lt;td&gt;Async Runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;Network Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;key-features&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#key-features&quot; aria-label=&quot;key features permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Key Features&lt;/h2&gt;
&lt;h3 id=&quot;core-data-structures&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#core-data-structures&quot; aria-label=&quot;core data structures permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Core Data Structures&lt;/h3&gt;
&lt;p&gt;Implemented fundamental Redis data structures including strings, sorted sets, and key-value storage with expiration support.&lt;/p&gt;
&lt;h3 id=&quot;async-networking&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#async-networking&quot; aria-label=&quot;async networking permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Async Networking&lt;/h3&gt;
&lt;p&gt;Built on Tokio for high-performance asynchronous I/O, handling multiple concurrent client connections efficiently.&lt;/p&gt;
&lt;h3 id=&quot;command-parsing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#command-parsing&quot; aria-label=&quot;command parsing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Command Parsing&lt;/h3&gt;
&lt;p&gt;A RESP-compatible command parser that handles standard Redis commands like &lt;code class=&quot;language-text&quot;&gt;GET&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;SET&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;DEL&lt;/code&gt;, and more.&lt;/p&gt;
&lt;h2 id=&quot;challenges--learnings&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#challenges--learnings&quot; aria-label=&quot;challenges  learnings permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Challenges &amp;#x26; Learnings&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Wrestling with Rust&apos;s borrow checker while implementing concurrent data structures was challenging but incredibly educational. It forces you to think about data ownership in ways other languages don&apos;t.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building a Redis clone from scratch is one of the best ways to learn systems programming. This project provided deep insights into how databases manage memory, handle concurrency, and communicate over the network.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://github.com/jatinshimpi/rivetDB&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[The Wild Oasis - Custom Backend]]></title><description><![CDATA[The supabase problem so here's what happened — I had the wild oasis project running on supabase's free tier for a while. it was working fine…]]></description><link>https://jatinshimpi.netlify.app/the-wild-oasis-story/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/the-wild-oasis-story/</guid><pubDate>Wed, 01 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-supabase-problem&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-supabase-problem&quot; aria-label=&quot;the supabase problem permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The supabase problem&lt;/h2&gt;
&lt;p&gt;so here&apos;s what happened — I had the wild oasis project running on supabase&apos;s free tier for a while. it was working fine, until one day my project just... expired. the free tier just kills your project if it&apos;s inactive for too long. classic.&lt;/p&gt;
&lt;p&gt;at first I was annoyed, but then I thought wait — this is actually a great excuse to build something real. instead of just re-deploying on supabase or switching to another BaaS, why not build the entire backend myself? learn how stuff actually works under the hood.&lt;/p&gt;
&lt;p&gt;and that&apos;s exactly what I did.&lt;/p&gt;
&lt;h2 id=&quot;the-inspiration--youtube-twitter-backend&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-inspiration--youtube-twitter-backend&quot; aria-label=&quot;the inspiration  youtube twitter backend permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The inspiration — youtube-twitter backend&lt;/h2&gt;
&lt;p&gt;I had already gone through hitesh choudhary&apos;s youtube-twitter backend project, and I really liked the patterns he used there. proper industry standard stuff — structured error handling, consistent API responses, clean separation of concerns. so I took that as my base and adapted it for the wild oasis.&lt;/p&gt;
&lt;p&gt;the core idea was simple: if I&apos;m going to build a backend, I&apos;m going to do it the right way. scalable, secure, and maintainable.&lt;/p&gt;
&lt;h2 id=&quot;project-structure&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#project-structure&quot; aria-label=&quot;project structure permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Project structure&lt;/h2&gt;
&lt;p&gt;here&apos;s how the project is organized:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;the-wild-oasis-backend/
├── src/
│   ├── app.js              # express app setup + middleware
│   ├── index.js             # server entry point
│   ├── constants.js
│   ├── swagger.js           # API docs config
│   ├── controllers/
│   │   ├── bookings.controller.js
│   │   ├── cabins.controller.js
│   │   ├── guests.controller.js
│   │   ├── settings.controller.js
│   │   └── user.controller.js
│   ├── models/
│   │   ├── bookings.model.js
│   │   ├── cabins.model.js
│   │   ├── guest.model.js
│   │   ├── settings.model.js
│   │   └── user.model.js
│   ├── routes/
│   │   ├── bookings.routes.js
│   │   ├── cabins.routes.js
│   │   ├── guests.routes.js
│   │   ├── settings.routes.js
│   │   └── user.routes.js
│   ├── middlewares/
│   │   ├── auth.middleware.js
│   │   └── multer.middleware.js
│   ├── utils/
│   │   ├── ApiError.js
│   │   ├── ApiResponse.js
│   │   ├── asyncHandler.js
│   │   └── cloudinary.js
│   ├── db/
│   │   └── index.js
│   └── scripts/
│       └── seed.js
├── public/
└── package.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;clean MVC-ish pattern. controllers handle the logic, models define the data, routes wire everything up. nothing fancy, just solid structure that scales.&lt;/p&gt;
&lt;h2 id=&quot;the-utils--where-the-magic-lives&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-utils--where-the-magic-lives&quot; aria-label=&quot;the utils  where the magic lives permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The utils — where the magic lives&lt;/h2&gt;
&lt;p&gt;this is straight from the hitesh choudhary playbook and honestly it&apos;s one of the best patterns I&apos;ve picked up.&lt;/p&gt;
&lt;h3 id=&quot;apierror&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#apierror&quot; aria-label=&quot;apierror permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ApiError&lt;/h3&gt;
&lt;p&gt;custom error class that gives you consistent error responses across the entire app:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiError&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    statusCode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;something went wrong&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    stack &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statusCode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; statusCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;error &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stcak &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stack&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      Error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;captureStackTrace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;constructor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;now whenever something goes wrong in any controller, I just throw &lt;code class=&quot;language-text&quot;&gt;new ApiError(404, &quot;cabin not found&quot;)&lt;/code&gt; and the global error handler catches it. no more scattered &lt;code class=&quot;language-text&quot;&gt;res.status().json()&lt;/code&gt; calls everywhere.&lt;/p&gt;
&lt;h3 id=&quot;apiresponse&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#apiresponse&quot; aria-label=&quot;apiresponse permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ApiResponse&lt;/h3&gt;
&lt;p&gt;same idea but for success responses:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiResponse&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;statusCode&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statusCode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; statusCode&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; statusCode &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;every successful response looks the same — &lt;code class=&quot;language-text&quot;&gt;statusCode&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;data&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;message&lt;/code&gt;, and a &lt;code class=&quot;language-text&quot;&gt;success&lt;/code&gt; boolean. the frontend always knows what to expect.&lt;/p&gt;
&lt;h3 id=&quot;asynchandler&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#asynchandler&quot; aria-label=&quot;asynchandler permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;asyncHandler&lt;/h3&gt;
&lt;p&gt;this tiny wrapper saved me from writing try-catch in every single controller:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;asyncHandler&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;requestHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;requestHandler&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;wraps any async function and forwards errors to express&apos;s error handler automatically. simple but super effective.&lt;/p&gt;
&lt;h2 id=&quot;security-and-middleware&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#security-and-middleware&quot; aria-label=&quot;security and middleware permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;security and middleware&lt;/h2&gt;
&lt;p&gt;I went all in on security for this one. the &lt;code class=&quot;language-text&quot;&gt;app.js&lt;/code&gt; is loaded with production-grade middleware:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Security HTTP Headers&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;helmet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Rate limiting&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; limiter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rateLimit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;windowMs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Too many requests from this IP, please try again in an hour!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/api&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; limiter&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Data sanitization against NoSQL query injection&lt;/span&gt;
app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mongoSanitize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;helmet&lt;/strong&gt; — sets a bunch of security HTTP headers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rate limiting&lt;/strong&gt; — 100 requests per hour per IP, no one&apos;s DDoS-ing my hotel API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mongo sanitize&lt;/strong&gt; — prevents NoSQL injection attacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CORS&lt;/strong&gt; — configured for both the admin dashboard (vite on 5173) and the customer website (next.js on 3000)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;swagger&lt;/strong&gt; — full API documentation at &lt;code class=&quot;language-text&quot;&gt;/api-docs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactoring-the-frontends&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#refactoring-the-frontends&quot; aria-label=&quot;refactoring the frontends permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;refactoring the frontends&lt;/h2&gt;
&lt;p&gt;this was honestly the hardest part. the original wild oasis project by jonas uses supabase directly from the frontend — no API layer at all. so when I built this custom backend, I had to refactor both the admin dashboard and the customer-facing website to talk to my API instead.&lt;/p&gt;
&lt;p&gt;every supabase call had to be ripped out and replaced with fetch/axios calls to my express API. the data shapes were different too since I&apos;m using mongoose models now instead of supabase&apos;s postgres tables. lots of mapping and adapting.&lt;/p&gt;
&lt;p&gt;but it was worth it. now the frontends are properly decoupled from the database, which is how it should be in production anyway.&lt;/p&gt;
&lt;h2 id=&quot;tech-stack&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tech-stack&quot; aria-label=&quot;tech stack permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;tech stack&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;technology&lt;/th&gt;
&lt;th&gt;purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;express.js&lt;/td&gt;
&lt;td&gt;API framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mongodb + mongoose&lt;/td&gt;
&lt;td&gt;database + ODM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JWT + bcrypt&lt;/td&gt;
&lt;td&gt;auth + password hashing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cloudinary&lt;/td&gt;
&lt;td&gt;image/media storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;helmet&lt;/td&gt;
&lt;td&gt;security headers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;swagger&lt;/td&gt;
&lt;td&gt;API documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;multer&lt;/td&gt;
&lt;td&gt;file upload handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;zod&lt;/td&gt;
&lt;td&gt;request validation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;what-i-learned&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-i-learned&quot; aria-label=&quot;what i learned permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;what I learned&lt;/h2&gt;
&lt;p&gt;building this backend taught me way more than any tutorial could. some takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BaaS is convenient, but knowing how to build your own backend is invaluable.&lt;/strong&gt; when supabase expired, I didn&apos;t panic — I just built my own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;consistent error handling patterns make everything cleaner.&lt;/strong&gt; the ApiError/ApiResponse pattern from hitesh&apos;s project is something I now use in every backend I build.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;security isn&apos;t optional.&lt;/strong&gt; rate limiting, helmet, sanitization — these are table stakes for any production API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;refactoring is where the real learning happens.&lt;/strong&gt; tearing out supabase and wiring up a custom API forced me to understand every data flow in the app.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;conclusion&lt;/h2&gt;
&lt;p&gt;what started as a &quot;damn, supabase killed my project&quot; moment turned into one of the best learning experiences I&apos;ve had. the project is now fully self-hosted, scalable, and doesn&apos;t depend on any third-party BaaS that could expire on me again.&lt;/p&gt;
&lt;p&gt;if you&apos;re sitting on a project that uses supabase or firebase and you want to level up — try building the backend yourself. it&apos;s painful at first but it&apos;s worth every line of code.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://github.com/jatinshimpi/the-wild-oasis-backend&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item><item><title><![CDATA[YouTube - Twitter Backend]]></title><description><![CDATA[Introduction This project is a backend implementation inspired by the architectures of YouTube and Twitter, built as a learning exercise in…]]></description><link>https://jatinshimpi.netlify.app/youtube-twitter-backend-story/</link><guid isPermaLink="false">https://jatinshimpi.netlify.app/youtube-twitter-backend-story/</guid><pubDate>Mon, 01 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This project is a backend implementation inspired by the architectures of &lt;strong&gt;YouTube&lt;/strong&gt; and &lt;strong&gt;Twitter&lt;/strong&gt;, built as a learning exercise in production-grade backend development. Guided by Hitesh Choudhary&apos;s teachings, it covers essential patterns for building scalable APIs.&lt;/p&gt;
&lt;h2 id=&quot;motivation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#motivation&quot; aria-label=&quot;motivation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Motivation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Learn production backend patterns and best practices&lt;/li&gt;
&lt;li&gt;Understand how large-scale social platforms structure their APIs&lt;/li&gt;
&lt;li&gt;Practice building robust authentication, file uploads, and data modeling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tech-stack&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tech-stack&quot; aria-label=&quot;tech stack permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tech Stack&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Express.js&lt;/td&gt;
&lt;td&gt;API Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudinary&lt;/td&gt;
&lt;td&gt;Media Storage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;key-features&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#key-features&quot; aria-label=&quot;key features permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Key Features&lt;/h2&gt;
&lt;h3 id=&quot;user-authentication&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#user-authentication&quot; aria-label=&quot;user authentication permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;User Authentication&lt;/h3&gt;
&lt;p&gt;Complete authentication flow with JWT tokens, refresh tokens, and secure password hashing.&lt;/p&gt;
&lt;h3 id=&quot;video-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#video-management&quot; aria-label=&quot;video management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Video Management&lt;/h3&gt;
&lt;p&gt;Upload, stream, and manage video content with cloud-based media storage via Cloudinary.&lt;/p&gt;
&lt;h3 id=&quot;social-features&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#social-features&quot; aria-label=&quot;social features permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Social Features&lt;/h3&gt;
&lt;p&gt;Tweet-like posting, likes, comments, subscriptions, and a personalized feed — modeled after real-world social platforms.&lt;/p&gt;
&lt;h3 id=&quot;aggregation-pipelines&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#aggregation-pipelines&quot; aria-label=&quot;aggregation pipelines permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Aggregation Pipelines&lt;/h3&gt;
&lt;p&gt;Complex MongoDB aggregation pipelines for channel statistics, watch history, and subscriber analytics.&lt;/p&gt;
&lt;h2 id=&quot;challenges--learnings&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#challenges--learnings&quot; aria-label=&quot;challenges  learnings permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Challenges &amp;#x26; Learnings&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Understanding how to structure a backend for scale — from data modeling to middleware chains — was the most valuable takeaway from this project.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#conclusion&quot; aria-label=&quot;conclusion permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This project bridges the gap between tutorial-level backends and production-ready systems. It covers authentication, media handling, and complex querying patterns that are essential for any backend engineer.&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://github.com/jatinshimpi/youtube-twitter-backend&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>shimpijatin@gmail.com</author></item></channel></rss>