<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mohit Yadav</title>
    <description>The latest articles on Forem by Mohit Yadav (@just_moh_it).</description>
    <link>https://forem.com/just_moh_it</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F824670%2Fb5861ff3-dc14-4ae0-952f-e582a90c3cef.png</url>
      <title>Forem: Mohit Yadav</title>
      <link>https://forem.com/just_moh_it</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/just_moh_it"/>
    <language>en</language>
    <item>
      <title>PeopleNotes - Release notes for People!</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:48:41 +0000</pubDate>
      <link>https://forem.com/just_moh_it/peoplenotes-release-notes-for-people-56i4</link>
      <guid>https://forem.com/just_moh_it/peoplenotes-release-notes-for-people-56i4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mux-2025-12-03"&gt;DEV's Worldwide Show and Tell Challenge Presented by Mux&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://player.mux.com/cHBVSO9xA01kbcgdGOz5iV2T53DJijMHdhgNJFgb3Qys?metadata-video-title=PeopleNotes&amp;amp;video-title=PeopleNotes" rel="noopener noreferrer"&gt;https://player.mux.com/cHBVSO9xA01kbcgdGOz5iV2T53DJijMHdhgNJFgb3Qys?metadata-video-title=PeopleNotes&amp;amp;video-title=PeopleNotes&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h2&gt;
  
  
  My Pitch Video
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  The Story Behind It
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Technical Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use of Mux (Additional Prize Category Participants Only)
&lt;/h3&gt;

</description>
      <category>devchallenge</category>
      <category>muxchallenge</category>
      <category>showandtell</category>
      <category>video</category>
    </item>
    <item>
      <title>Introducing ✨ Relano - Create beautiful "What's new" videos and automate your project's social media!</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Tue, 23 May 2023 23:55:57 +0000</pubDate>
      <link>https://forem.com/just_moh_it/introducing-relano-create-beautiful-whats-new-videos-and-automate-your-projects-social-media-cp2</link>
      <guid>https://forem.com/just_moh_it/introducing-relano-create-beautiful-whats-new-videos-and-automate-your-projects-social-media-cp2</guid>
      <description>&lt;h2&gt;
  
  
  ✨ What is Relano?
&lt;/h2&gt;

&lt;p&gt;Relano is a GitHub action you could add to your repository to automatically create 'what's new' videos as soon as you publish a release! &lt;/p&gt;

&lt;p&gt;Just add the GitHub action to your workflow, pass in the &lt;code&gt;openai-api-key&lt;/code&gt; and the &lt;code&gt;release-notes&lt;/code&gt; variable, and publish a release. Relano uses OpenAI to come up with a summary of all the changes in the published release, and passes it to our renderer for creating a beautiful video!&lt;/p&gt;

&lt;h2&gt;
  
  
  📸 Example Output
&lt;/h2&gt;

&lt;p&gt;An example from the &lt;code&gt;remotion-dev/remotion&lt;/code&gt; release version &lt;code&gt;3.3.93&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mkGqYsmVpHc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(Video not loading? Click here: &lt;a href="https://youtu.be/mkGqYsmVpHc" rel="noopener noreferrer"&gt;youtu.be/mkGqYsmVpHc&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This video was created automatically without any other inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ How it works
&lt;/h2&gt;

&lt;p&gt;A very simple explanation of how to use the Relano and how it works:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/D7udTbnKAP8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(Video not loading? Click here: &lt;a href="https://youtu.be/D7udTbnKAP8" rel="noopener noreferrer"&gt;youtu.be/mkGqYsmVpHc&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  🤩 Use this action in your GitHub Projects
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92hhpipufggfy8iq42a9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92hhpipufggfy8iq42a9.png" alt="Github Action for Relano–Marketplace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💫 Background, and why I created it
&lt;/h2&gt;

&lt;p&gt;I saw a lot of open source maintainers struggline with community management. For example, popular open source projects like plaiceholder are run by people who have a day-job, and don't necessarily have the time to keep their community informed about what's new!&lt;/p&gt;

&lt;h3&gt;
  
  
  🧓🏼 How it all started
&lt;/h3&gt;

&lt;p&gt;When I was talking with &lt;a href="https://twitter.com/JNYBGR" rel="noopener noreferrer"&gt;Jonny Burger&lt;/a&gt; (the creator of &lt;a href="https://remotion.dev/" rel="noopener noreferrer"&gt;Remotion&lt;/a&gt;) about the challenges small open source projects face and how it becomes harder for individual maintainers who work because of their goodwill to carry their project forward, I did not realize the conversation would give birth to the idea of Relano.&lt;/p&gt;

&lt;p&gt;It all started on a discord chat, when I was casually talking with Jonny. We somehow got to the topic of what it is like being an open source maintainer. Though I knew Jonny had a team behind Remotion to help manage the day-to-day operations of open source, I soon realized it would have been hard for individual contributors to do open-source part-time, just as well as Jonny and his team did, without the resources they had.&lt;/p&gt;

&lt;h3&gt;
  
  
  🥷🏼 The Hidden Challenges
&lt;/h3&gt;

&lt;p&gt;Maintainers pour countless hours into coding, debugging, and ensuring their project's stability. However, there's always this one aspect that eludes their attention – community management. In the midst of programming, fixing issues, and creating roadmaps, finding the time to engage with the community, communicate updates effectively, and provide the necessary documentation became a big problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  🥲 Struggles of a Solo Maintainer
&lt;/h3&gt;

&lt;p&gt;Solo maintainers or small teams have to cope up with so much for open source projects, and it becomes clear that keeping the community informed about latest releases often falls through the cracks.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤩 Relano bridges the gap
&lt;/h3&gt;

&lt;p&gt;I'm pretty well versed with react and Remotion, and there's a new opportunity to tackle, I thought to myself. That's when the idea for Relano materialized – a tool that would empower maintainers to effortlessly create captivating "What's New" videos for their projects' latest releases.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑🏼‍🔧 How it works under the hood
&lt;/h2&gt;

&lt;p&gt;Converting an idea to reality was one of the most interesting parts of the process! No matter the outcome, the learning experience has to be worth it! Let me take you through the journey of how I created Relano, and how it works!&lt;/p&gt;

&lt;h3&gt;
  
  
  🤌🏼 Publishing a release triggers the action
&lt;/h3&gt;

&lt;p&gt;The action listens for the &lt;code&gt;release&lt;/code&gt; event, and gets triggered when a new release is published, or an existing release is edited.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky3lkiss4rg8kndk88k2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky3lkiss4rg8kndk88k2.png" alt="Triggers"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;starts the video-creator job&lt;/strong&gt;, using the suitable environment which has the secrets:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmoqy4c8i2c3yt5g04t0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmoqy4c8i2c3yt5g04t0.png" alt="Jobs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of the few steps required to run Relano, one of the steps is the Relano action. It takes 4 inputs relating to the current repository, and uses them to create a video.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh44o46w4eyqovmfviafu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh44o46w4eyqovmfviafu.png" alt="Relano step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 OpenAI for summarization
&lt;/h3&gt;

&lt;p&gt;The release notes are passed down to OpenAI to extract the most useful information, which is finally used to create the video.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xng0sxnd0eu08lsoxz9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xng0sxnd0eu08lsoxz9.gif" alt="Openai Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this, we use the chat mode, since it has a better interface for defining instructions and content. The OpenAI prompt reads something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqi5bunj5ql9ncmmquur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqi5bunj5ql9ncmmquur.png" alt="OpenAI Playground screenshot showing system and user message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This creates yaml with the following format:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzqh4ouc2c3wvuvjudt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzqh4ouc2c3wvuvjudt4.png" alt="GPT-chat Response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This yaml is then converted to json using &lt;a href="https://npmjs.com/package/yaml" rel="noopener noreferrer"&gt;an open source library–yaml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn83cq378yz6hy1e6nxht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn83cq378yz6hy1e6nxht.png" alt="Yaml to converted JSON"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🤯 Rendering the video
&lt;/h3&gt;

&lt;p&gt;After the OpenAI command completes, we get to the actual video creation step. Here's where &lt;strong&gt;GitHub actions&lt;/strong&gt; really &lt;strong&gt;shines&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91r4vt9t9xi1btkeklil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91r4vt9t9xi1btkeklil.png" alt="Github Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The input from OpenAI as JSON is passed onto the &lt;a href="https://github.com/Just-Moh-it/Relano/tree/main/remotion/BaseComp" rel="noopener noreferrer"&gt;Remotion Composition&lt;/a&gt; as input props! These parameters are what constitute the information for the final video! &lt;/p&gt;

&lt;p&gt;You could even copy the parameters over, clone the Relano repository, and paste them as props to the composition, and you'd be able to preview the video in the Remotion UI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F898flbx2s40zetp6n8zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F898flbx2s40zetp6n8zq.png" alt="Remotion previewer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remotion converts the videos to chunks, then renders them multithreaded on GitHub Actions runners!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9m6l34ytow3rx8niy0h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh9m6l34ytow3rx8niy0h.gif" alt="Remotion Distributed Rendering"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To learn more about how remotion renders videos on the server, checkout the docs: &lt;a href="https://www.remotion.dev/docs/ssr" rel="noopener noreferrer"&gt;remotion.dev/docs/ssr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The video is finally available, uploaded as an artifact after the workflow run!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qsj9s4y4e2i41hqtvk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qsj9s4y4e2i41hqtvk3.png" alt="Artifact on github action run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ Posting to social media!
&lt;/h3&gt;

&lt;p&gt;Keeping users informed about the latest changes is one of the best things a maintainer could do to keep the community thriving and exited! After downloading the video, upload it to your &lt;strong&gt;project's social media&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgvim50rqz7lkyh2nful.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgvim50rqz7lkyh2nful.png" alt="Uploading to twitter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💁🏼‍♂️ Additional Resources/Info
&lt;/h2&gt;

&lt;p&gt;I took inspiration from the following sections to create the video:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.remotion.dev/showcase#d2SvbrhHvyJZb2EmSv441M601UBy1dfEYfToKGqDpV01Y" rel="noopener noreferrer"&gt;Reanimated update video&lt;/a&gt; on remotion showcase page - design inspiration&lt;/li&gt;
&lt;li&gt;William Candillon's &lt;a href="https://youtu.be/PfCQEA72ljU" rel="noopener noreferrer"&gt;Song of bloom&lt;/a&gt; for &lt;a href="https://youtu.be/e1htZET1j2Y" rel="noopener noreferrer"&gt;audio&lt;/a&gt; inspiration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📂 Category Submission:
&lt;/h2&gt;

&lt;p&gt;The project fits into the following categories. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wacky Wildcards&lt;/strong&gt; - Pretty wild what Relano is using GitHub actions for!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maintainer Must-Haves&lt;/strong&gt;: This makes the life of maintainers easier and lets them focusing on the thing they do best–creating awesome open-source tools! Relano assists in the community management part!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The source code lives here: &lt;a href="https://github.com/Just-Moh-it/Relano" rel="noopener noreferrer"&gt;https://github.com/Just-Moh-it/Relano&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Checkout the GitHub Action on the marketplace: &lt;a href="https://github.com/marketplace/actions/relano-automated-what-s-new-videos" rel="noopener noreferrer"&gt;https://github.com/marketplace/actions/relano-automated-what-s-new-videos&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;See this GitHub action being battle-tested over on Remotion's Discord server: &lt;a href="https://discord.com/channels/809501355504959528/994527481598070815" rel="noopener noreferrer"&gt;https://discord.com/channels/...&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💼 Permissive License
&lt;/h2&gt;

&lt;p&gt;The workflow is licensed under the MIT license. Use however you want! 🔥 &lt;a href="https://github.com/remotion-dev/remotion/blob/main/LICENSE.md" rel="noopener noreferrer"&gt;Remotion's license&lt;/a&gt; applies to mid-to-large-size commercial organizations using the action.&lt;/p&gt;

</description>
      <category>githubhack23</category>
      <category>github</category>
      <category>githubactions</category>
      <category>community</category>
    </item>
    <item>
      <title>How to serve *any* website from your own domain (for free!)</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Sat, 13 Aug 2022 23:10:00 +0000</pubDate>
      <link>https://forem.com/just_moh_it/how-to-serve-any-website-from-your-own-domain-for-free-44l9</link>
      <guid>https://forem.com/just_moh_it/how-to-serve-any-website-from-your-own-domain-for-free-44l9</guid>
      <description>&lt;p&gt;Have you ever wanted to white-label a website, like display it on your own domain? Or have you wanted to remove a watermark from a website that asks for premium (for edu. purposes ofc.)?&lt;/p&gt;

&lt;p&gt;Well, this guide contains everything you need to know to proxy a website/webpage on your custom domain/subdomain! Let's just get into it! 😃&lt;/p&gt;

&lt;h3&gt;
  
  
  🔥 The Backstory (reading optional)
&lt;/h3&gt;

&lt;p&gt;A few months ago, I got my own domain from Google, and have been putting up things on it for a long time. Though, when it comes to social media, I wanted to show a links-in-bio page, not my personal portfolio page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro1hvvruq70nxmh1dv9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro1hvvruq70nxmh1dv9f.png" alt="Google Domains"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I looked into some solutions. Found a few websites like short.io that allow you to shorten links and make them visible on your domain base, but they're paid and provide little room for customization. And the ones that did provide awesome features were mostly paid.&lt;/p&gt;

&lt;p&gt;So I was left with no choice but to go with the standard-solution: mainstream websites like &lt;a href="https://bio.link" rel="noopener noreferrer"&gt;bio.link&lt;/a&gt; or Linktree[&lt;a href="https://linktr.ee" rel="noopener noreferrer"&gt;https://linktr.ee&lt;/a&gt;]. I got my links up on it, customized it to just how I wanted, and it looked really cool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmn3hogd19rz2tfpzsb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmn3hogd19rz2tfpzsb3.png" alt="My Bio-Link Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But since I consider myself somewhat of a perfectionist (an understatement, sometimes), and like to bring something unique to the table, I thought about a way to serve the bio-link page on my own domain. &lt;/p&gt;

&lt;h3&gt;
  
  
  ⚖️ But why? A few pros and cons
&lt;/h3&gt;

&lt;p&gt;There are a few 👍 &lt;strong&gt;pros&lt;/strong&gt; to hosting a domain! Just to name a few, for me, it was to ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes your link-in-bio page &lt;strong&gt;look unique&lt;/strong&gt;: Unlike pages that are bio.link/username, the custom-domain page looks very professional, just like how your portfolio on &lt;code&gt;youdomain.dev&lt;/code&gt; looks better as compared to &lt;code&gt;3p-domain.vercel.app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Have total control over anything served over the domain&lt;/strong&gt;: Remove watermarks or modify existing content pretty easily!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloudflare Workers' specific pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt; - Cloudflare tracks every request through its proxy, so you could have a direct idea about where your domain visits are coming from, and how they're reaching your website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching (Faster loads)&lt;/strong&gt; - Cloudflare also caches every request that goes through its DNS proxy, so a slow SPA could easily benefit on subsequent requests from the same user, right out of the box (though it's disabled by default)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased Uptime&lt;/strong&gt;, even when the &lt;strong&gt;source is down&lt;/strong&gt;: In case the source website goes down for a short time, the content served over the domain would still work flawlessly, given that it was recently cached.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt; - You could randomly fetch from 2-3 different sources and get a very basic version of load balancing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypass account's free limits&lt;/strong&gt; - For example, if you have 2-3 accounts on Vercel hosting the same exact website, you could easily modify the worker's code to randomly fetch from any one of them. This way, you could evenly distribute the data usage between the accounts and not hit the free-account limit on the source website (though this might be against the fair use policy).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👎 &lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's important to note the downsides of this as well&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Might not work on every website&lt;/strong&gt; - Well-engineered web-apps like Google's auth platform could easily detect if the receiver (in this case, Cloudflare's servers), are the end users of the request. 
This way, they could prevent kind-of man-in-the-middle attacks. But 99% of the websites won't have problems like these.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adds an extra layer&lt;/strong&gt; - Though this is pretty unnoticeable, since the responses are un-cached, but basically, since all the data goes through a third-party (Cloudflare), the resource per request usage also increases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Could get pretty expensive (sometimes)&lt;/strong&gt;: If your usage stats are out of the roof, and you get more than 100k request per day, subsequent users could face errors if you're on the free plan, till the quota gets reset.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But hey, for light usage and very typical use-cases, chances are that these cons won't matter. In fact, with features like caching and simple analytics, the pros would certainly outweigh the cons.&lt;/p&gt;

&lt;h3&gt;
  
  
  🙋‍♂️ But what is 'Cloudflare Workers'?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2F48NWaLkDcME%2Fmaxresdefault.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2F48NWaLkDcME%2Fmaxresdefault.jpg" alt="Cloudflare workers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Glad you asked! According to &lt;a href="https://developers.cloudflare.com/workers/" rel="noopener noreferrer"&gt;Workers' docs&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;'Cloudflare Workers' provides a  &lt;a href="https://www.cloudflare.com/learning/serverless/what-is-serverless/" rel="noopener noreferrer"&gt;serverless&lt;/a&gt;  execution environment that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's basically a way to run serverless functions, just like AWS Lambda or Google Cloud Run, but with a few small differences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost&lt;/strong&gt;: At the time of writing this article, it has around &lt;strong&gt;100k free requests per day&lt;/strong&gt; (more than enough, even for very famous webpages).&lt;/p&gt;

&lt;h3&gt;
  
  
  🚶‍♀️ A Step-by-Step Guide
&lt;/h3&gt;

&lt;p&gt;This guide assumes you have no/little prior knowledge about Cloudflare and Cloudflare Workers. Though if you're pretty experienced, this guide doesn't compromise on quality over simplicity. 🙃&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create your Cloudflare account and add a domain (optional)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf9r0clpz1fotle10adx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf9r0clpz1fotle10adx.png" alt="Add a new domain to your Cloudflare account"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Follow the usual instructions on configuring the domain's nameservers, as illustrated in their &lt;a href="https://developers.cloudflare.com/fundamentals/get-started/setup/add-site/" rel="noopener noreferrer"&gt;'adding a site' docs&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;If you aren't managing your DNS through Cloudflare, point the domain to Cloudflare's servers. Read their docs for more info.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add your Cloudflare worker Route&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1a5ongkcl2nzer8xcoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1a5ongkcl2nzer8xcoo.png" alt="Cloudflare Worker add route"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the catch-all domain/sub-domain&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcchwrcekwmy30r0o2xse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcchwrcekwmy30r0o2xse.png" alt="Add the domain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "Manage Workers", and create a new worker Service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbeip3u5loanhjxtxr9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbeip3u5loanhjxtxr9b.png" alt="Create a new Worker Service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the second option (HTTP Router) when creating the worker, since we don't just want to send a simple response&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3w5svx6ms3oy21z4pfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3w5svx6ms3oy21z4pfr.png" alt="Select HTTP Router 2nd option"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the web code-editor to quickly edit the Cloudflare Worker logic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8w9mn22bz203ciixntz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8w9mn22bz203ciixntz.png" alt="Open the code-editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit/Paste the code, and preview&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmea6bu6yazrxexjezi4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmea6bu6yazrxexjezi4.png" alt="Edit the domain and Preview!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit the default code snippet that's already in the editor, or add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt; 

&lt;span class="cm"&gt;/**
* Many more examples available at:
* https://developers.cloudflare.com/workers/examples
* @param {Request} request
* @returns {Promise&amp;lt;Response&amp;gt;}
*/&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://justmohit.bio.link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Assign the custom domain to your worker&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yda5vcr4yiaeaj3lkmz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yda5vcr4yiaeaj3lkmz.png" alt="Assign the custom domain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it!&lt;/p&gt;

&lt;h3&gt;
  
  
  🎉 Reap the Benefits: Analytics, Caching &amp;amp; Custom Domains
&lt;/h3&gt;

&lt;p&gt;We can now access the contents of &lt;a href="https://justmohit.bio.link" rel="noopener noreferrer"&gt;justmohit.bio.link&lt;/a&gt; at &lt;a href="https://links.mohitya.dev" rel="noopener noreferrer"&gt;links.mohitya.dev&lt;/a&gt;. Heck, we even get simple analytics, without the option being enabled by the bio.link team!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfopv15jn86jd7qg5dl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfopv15jn86jd7qg5dl5.png" alt="Domain changed image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, get instant feedback on anything the server sends, including status codes, requests, etc. and the data is persisted for weeks at end in the free tier!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6pufl59o5an3a1hm596.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6pufl59o5an3a1hm596.png" alt="Screenshot of analytics"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  😱 Taking it to the next level: Edit response HTML
&lt;/h3&gt;

&lt;p&gt;We could change the Cloudflare Workers code in order to change the response that is displayed to the end user!&lt;/p&gt;

&lt;p&gt;For example, we could use it to our advantage (for educational purposes only, of course) by removing a watermark on a website that requires a premium subscription to remove it.&lt;/p&gt;

&lt;p&gt;You could find more info on how to modify response content using Cloudflare Workers on their &lt;a href="https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/" rel="noopener noreferrer"&gt;HTML Rewriter docs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🙈 A few Alternatives
&lt;/h3&gt;

&lt;p&gt;Though I'm not fond of paying for a webpage with such a low view count, I'd still like to highlight some alternatives:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paid&lt;/strong&gt;: &lt;em&gt;&lt;a href="https://ablyhost.com/?utm_campaign=mohits-blog&amp;amp;utm_source=devto-workers-blog" rel="noopener noreferrer"&gt;Ably.host&lt;/a&gt;&lt;/em&gt; - Host any website on your subdomain within a few minutes (no-code alternative)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzxx8f6fjvh1fc9vj9ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzxx8f6fjvh1fc9vj9ng.png" alt="Ably Host"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt;: &lt;em&gt;Self-hosted Nginx&lt;/em&gt; - (If you want to manage everything)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtweohl2qd2ztbah0ue2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdtweohl2qd2ztbah0ue2.png" alt="Nginx logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nginx could be easily used as a reverse proxy, for routing both internal, and external traffic! &lt;a href="https://phoenixnap.com/kb/nginx-reverse-proxy" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  👋 That's it!
&lt;/h3&gt;

&lt;p&gt;Thanks for reading along! Let me know how/what you're using this for, if you've tried to follow along! Till then, see you later...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xf76tsrt2ng234mzj0q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3xf76tsrt2ng234mzj0q.gif" alt="Bye Bye"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Accidental post</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Thu, 12 May 2022 16:30:56 +0000</pubDate>
      <link>https://forem.com/just_moh_it/how-to-cr-59l7</link>
      <guid>https://forem.com/just_moh_it/how-to-cr-59l7</guid>
      <description>&lt;p&gt;Ah, I was just trying posting stuff from different mediums, so here's this article and turns out, there isn't a delete button in here 😆 #ForeverSufferings.&lt;/p&gt;

&lt;p&gt;Btw, if you're here, thanks for checking out my profile since I'm sure you didn't get this in your recommendations and I don't know how to get rid of this post lol bye buddy&lt;/p&gt;

</description>
      <category>doessomeoneevenread</category>
      <category>accidentalpost</category>
    </item>
    <item>
      <title>Introducing 🕷 Spitey-Sense: Simulate conversations with Spider-Man using 🪄 GPT-3 and Deepgram ☘️</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Mon, 11 Apr 2022 23:49:29 +0000</pubDate>
      <link>https://forem.com/just_moh_it/introducing-spitey-sense-simulate-conversations-with-spider-man-using-gpt-3-and-deepgram-1ph2</link>
      <guid>https://forem.com/just_moh_it/introducing-spitey-sense-simulate-conversations-with-spider-man-using-gpt-3-and-deepgram-1ph2</guid>
      <description>&lt;h3&gt;
  
  
  🚀 Introduction
&lt;/h3&gt;

&lt;p&gt;Hey there! 👋 Have you ever wanted to talk with your favorite superheroes, but either they're they're unreachable, or they're too busy shooting for their next blockbuster?&lt;/p&gt;

&lt;p&gt;Well, with 🕷 Spitey-Sense, you could interact with a simulated version of Peter-Parker! The idea is simple; OpenAI's GPT-3 was trained (or fine-tuned) using scripts from various Spider-Man movies, and the AI was able to learn from Peter Parker's personality. At the end, it was able to predict exactly what Peter Parker would have said if he was asked something. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj68am5261h88stp3mxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj68am5261h88stp3mxv.png" alt="Open AI"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For example, GPT-3 classifies Peter's personality to be having a sense of soft humor, and a feeling of responsibility. Therefore, the AI would generate responses to your conversations exactly/mostly like how Peter Parker would have.&lt;/p&gt;

&lt;p&gt;The goal of this project was to create an interface to seamlessly communicate with the AI engine and show responses to statements in real time, using web-sockets, along with training the model to act in the required way.&lt;/p&gt;

&lt;h3&gt;
  
  
  🪄 Demo
&lt;/h3&gt;

&lt;p&gt;As soon as the user opens up the website, they're greeted with this &lt;strong&gt;landing page&lt;/strong&gt;, from where they could open up the menu, or dive right into the fun part (talking)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq21e9ql8nwtlk9s8x6qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq21e9ql8nwtlk9s8x6qb.png" alt="Home Page"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Upon navigating the &lt;code&gt;/chat&lt;/code&gt; route, users are asked to give microphone permission to the app so that they could interact with the AI. A web-socket connection is created with the backend, and the audio is constantly monitored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm34n2ufe3zjjrabdxkg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm34n2ufe3zjjrabdxkg.gif" alt="Demo"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If the user doesn't speak for a few moments, the conversation till now is sent to the OpenAI model, and the AI replies exactly how Peter Parker/Spider-Man would have.&lt;/p&gt;

&lt;h3&gt;
  
  
  🏋️‍♀️ Training/Fine-Tuning the AI Model
&lt;/h3&gt;

&lt;p&gt;As for the model, I used the &lt;code&gt;Text-DaVinci-001&lt;/code&gt; model, since it is the most powerful General Purpose Artificial Intelligence model out there, and has the highest number of parameters. Also, it's pretty expensive, but is worth it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpageqjxjtb1snry3mor.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpageqjxjtb1snry3mor.jpeg" alt="Fine-Tuning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the data, I scoured the internet for scripts, tried fruitlessly to extract information from the PDF script files I got from movie databases, however, it was a nightmare to classify and sort the data according to the requirements. The number of space, tabs, etc. had to be considered, and they often overlapped. Therefore, I continued my search for a better solution.&lt;/p&gt;

&lt;h4&gt;
  
  
  💿 Getting access to a dataset
&lt;/h4&gt;

&lt;p&gt;After visiting many movie-db sites, I saw an article where someone created a character-simulation using a dataset from Kaggle. I just found what I needed... I quickly downloaded the dataset, and it contained script data for around hundreds of titles. Once I found a super-hero movie, it was time to extract the data from &lt;code&gt;.csv&lt;/code&gt; data format.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjaugvjqys5e475chkmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjaugvjqys5e475chkmb.png" alt="Kaggle Files Structure"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For this purpose, I used 🐼 pandas, and loaded the data from the multiple files, which were partitioned like a relational-database, with unique and foreign keys for each movie, character, etc. I sourced the conversations file, then extracted the plain text lines along with the people speaking those, and finally, fed them into the model. At the end, I was able to finally get around 80-90 lines which had either Peter Parker, or Spider-Man as an active speaker.&lt;/p&gt;

&lt;p&gt;I fed them into the model, and though the waiting time was around a few hours, I was finally able to get the custom-model up and running.&lt;/p&gt;

&lt;h3&gt;
  
  
  🏆 Deepgram's Role
&lt;/h3&gt;

&lt;p&gt;Deepgram plays an essential role in the whole lifecycle of the app. From providing the first medium of contact with the app, Deepgram seamlessly transcribes audio in real time with almost unnoticeable latency, along with quotations, punctuations, etc. so that the AI model could analyze the tone of the sentence.&lt;/p&gt;

&lt;p&gt;Therefore, Deepgram is an integral and irreplaceable part of the app due to its various awesome features.&lt;/p&gt;

&lt;h3&gt;
  
  
  ☘️ Submission Category
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Analytics Ambassador&lt;/strong&gt;: Because the app uses Deepgram to analyse expressions in users' voices (inhances inputs with puntuations) and also makes it accessible for people with low-vision/motor disabilites to interact with the AI without typing a word. The recording is sent in real time and the backend analyses it to convert it to a textual transcript.&lt;/p&gt;

&lt;h3&gt;
  
  
  🥳 Useful Links
&lt;/h3&gt;

&lt;p&gt;Here are some useful links you may want to access:&lt;/p&gt;

&lt;p&gt;🏖 Main Links&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project Demo Link: &lt;a href="https://spity-sense.mohitya.dev/" rel="noopener noreferrer"&gt;Web Demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NextJS Web Interface + API Source Code: &lt;a href="https://github.com/Just-Moh-it/Spity-Sense" rel="noopener noreferrer"&gt;On GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🦾 AI Links&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source Code for training data: &lt;a href="https://github.com/Just-Moh-it/Spity-Sense-Training" rel="noopener noreferrer"&gt;On GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fine-Tuning GPT-3 Instructions for DIY: &lt;a href="https://beta.openai.com/docs/guides/fine-tuning" rel="noopener noreferrer"&gt;OpenAI Guides&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🏡 Miscellaneous Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source Dataset: &lt;a href="https://www.kaggle.com/datasets/Cornell-University/movie-dialog-corpus?select=movie_lines.tsv" rel="noopener noreferrer"&gt;From Cornell University&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Design Inspiration: &lt;a href="https://dribbble.com/shots/17566833-Spider-man-movie-landing-page-concept" rel="noopener noreferrer"&gt;From Dribbble&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hackwithdg</category>
      <category>deepgram</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Top 7 VS Code extensions 🤓 almost nobody knows about</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Mon, 07 Mar 2022 18:14:32 +0000</pubDate>
      <link>https://forem.com/just_moh_it/top-7-vs-code-extensions-almost-nobody-knows-about-56ld</link>
      <guid>https://forem.com/just_moh_it/top-7-vs-code-extensions-almost-nobody-knows-about-56ld</guid>
      <description>&lt;p&gt;As a developer, you're most probably using Visual Studio Code on a daily basis. But did you know that there are tons of extensions out there that can make your life a lot easier and take your productivity to another level?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645502895927%2FO7oK0JOsL.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645502895927%2FO7oK0JOsL.webp" alt="never gets easier.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have a lot of VS Code extensions. Some are indispensable, some are good to have, and some become irrelevant because I'm no longer learning the language I downloaded it for.&lt;/p&gt;

&lt;p&gt;Today, I'm going to list my top 7 extensions that I think are underrated and unknown to most developers.😍&lt;/p&gt;

&lt;h2&gt;
  
  
  Top Unknown VS Code extensions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;: At the end, there is a bonus extension, so be sure to check it out.&lt;/p&gt;

&lt;p&gt;Now, starting off with the 7th one,&lt;/p&gt;

&lt;h3&gt;
  
  
  7: &lt;a href="https://marketplace.visualstudio.com/items?itemName=p42ai.refactor" rel="noopener noreferrer"&gt;P42 JavaScript Assistant&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp42.ai%2Fimage%2Fvscode%2Fvscode-intro.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fp42.ai%2Fimage%2Fvscode%2Fvscode-intro.gif" alt="Preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the website says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The P42 JavaScript Assistant adds 68 automated refactorings and quick fixes for JavaScript, TypeScript, and React to Visual Studio Code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's another demo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FubkdmM0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FubkdmM0.gif" alt="Demo 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's also a sidebar, so you could see the refactors your poor code needs, all in one place!&lt;/p&gt;

&lt;h3&gt;
  
  
  6: &lt;a href="https://marketplace.visualstudio.com/items?itemName=cweijan.vscode-office" rel="noopener noreferrer"&gt;Office Viewer&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;"Show me the demo first!" Here you go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsockpd86skxv1t3710is.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsockpd86skxv1t3710is.gif" alt="Office Viewer"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;A really helpful but annoying extension that allows you to view major office format like: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excel: .xls, .xlsx, .csv&lt;/li&gt;
&lt;li&gt;Svg: .svg&lt;/li&gt;
&lt;li&gt;Pdf: .pdf&lt;/li&gt;
&lt;li&gt;Font: .ttf, .otf, .woff&lt;/li&gt;
&lt;li&gt;Markdown: .md&lt;/li&gt;
&lt;li&gt;HttpRequest: .http&lt;/li&gt;
&lt;li&gt;PlantUml: .puml, .plantuml&lt;/li&gt;
&lt;li&gt;Windows Reg: .reg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that's crazy. But you may want to disable this for certain file types (like &lt;code&gt;.md&lt;/code&gt;), read the extension description to know more.&lt;/p&gt;

&lt;h3&gt;
  
  
  5: &lt;a href="https://marketplace.visualstudio.com/items?itemName=sandipchitale.vscode-indent-line" rel="noopener noreferrer"&gt;Indent line&lt;/a&gt; (5k downloads)
&lt;/h3&gt;

&lt;p&gt;This extension fixes all indentation issues with a single shortcut. What is better than seeing it for yourself? Here's a demo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fsandipchitale%2Fvscode-indent-line%2Fraw%2Fmaster%2Fimages%2Findent-line-demo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fsandipchitale%2Fvscode-indent-line%2Fraw%2Fmaster%2Fimages%2Findent-line-demo.gif" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But why need it when you have prettier? There's a reason. As far as I know, prettier does not format python code, but this extension supports many languages that prettier does not.&lt;/p&gt;

&lt;h3&gt;
  
  
  4: &lt;a href="https://marketplace.visualstudio.com/items?itemName=pnp.polacode" rel="noopener noreferrer"&gt;Polacode&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Ever wanted to present your code to someone or some platform, but it looks ugly? A great alternative to &lt;a href="https://carbon.now.sh/" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;, it automatically detects the language, highlighting, etc. and presents a picture-perfect version of your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foctref%2Fpolacode%2Fraw%2Fmaster%2Fdemo%2Fusage.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foctref%2Fpolacode%2Fraw%2Fmaster%2Fdemo%2Fusage.gif" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't use it to share your company's code though :)&lt;/p&gt;

&lt;h3&gt;
  
  
  3: &lt;a href="https://marketplace.visualstudio.com/items?itemName=BriteSnow.vscode-toggle-quotes" rel="noopener noreferrer"&gt;Toggle Quote&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Ever typed a string with &lt;code&gt;"&lt;/code&gt; and wanted to convert it to a template literal with &lt;code&gt;`&lt;/code&gt;  or to &lt;code&gt;'&lt;/code&gt;? Why move your cursor back and forth? Just press a simple keyboard shortcut to toggle through these quotes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645501577361%2FdsEThH6bF.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645501577361%2FdsEThH6bF.gif" alt="Toggle.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you get the idea. This is pretty useful for me personally, since I mistakenly write the &lt;code&gt;"&lt;/code&gt; and then remember to use &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2: &lt;a href="https://marketplace.visualstudio.com/items?itemName=viablelab.bracket-padder" rel="noopener noreferrer"&gt;Bracket Padder&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A simple package that provides smart whitespace padding and closing of bracket pairs: &lt;code&gt;() [] {}&lt;/code&gt;. Even though prettier does it automatically, it also supports languages like python, go, etc. which prettier does not support. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F6108538%2F22630998%2F56e3f60e-ec05-11e6-8e5b-53c99e36f46c.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F6108538%2F22630998%2F56e3f60e-ec05-11e6-8e5b-53c99e36f46c.gif" alt="Preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A must-have to increase readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  1: &lt;a href="https://marketplace.visualstudio.com/items?itemName=ryanlaws.toggle-case" rel="noopener noreferrer"&gt;Toggle Case&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is one of the most useful extensions on the list. The thing it does might sound very basic, but combined with VS Code's awesome features, it could save a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F2899448%2F10712456%2F3c5e29b6-7a9c-11e5-9ce4-7eb944889696.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F2899448%2F10712456%2F3c5e29b6-7a9c-11e5-9ce4-7eb944889696.gif" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It becomes awesome when dealing with multi-cursor text, where it could convert case for multiple instances to ones, saving a lot of time. It also converts text like &lt;code&gt;foo bar&lt;/code&gt; to paths like &lt;code&gt;foo/bar&lt;/code&gt;. A must-have for every programmer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus! &lt;a href=""&gt;Hot dog stand&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Get the joke?&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645499475560%2FcxGX1iXSb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645499475560%2FcxGX1iXSb.png" alt="hot dog.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, let's start the pitching.&lt;/p&gt;

&lt;p&gt;Have you ever wanted to &lt;strong&gt;burn your eyeballs within seconds&lt;/strong&gt;!? Well now, you can! With ho... Oh, wait. No one in their healthy minds would want that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! If you are looking to take your VS Code experience to the next level, be sure to check out some of these extensions. Also, I'm going to post about a really cool project soon, so stay tuned. &lt;/p&gt;

&lt;p&gt;You know the drill. If you found this post helpful, please share it with your friends and followers. And if you have any questions or comments, please feel free to leave them below.&lt;/p&gt;

&lt;p&gt;Until then, happy coding!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645503093621%2FVbybySt7w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645503093621%2FVbybySt7w.gif" alt="Bye.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;sup&gt;(This post was cross posted from my trending &lt;a href="https://blog.mohityadav.codes/top-vs-code-extensions-only-5-people-know-about" rel="noopener noreferrer"&gt;Hashnode Blog&lt;/a&gt;, so sorry if you've already read this, and I took up some part of your feed real-estate 😅)&lt;/sup&gt;&lt;/p&gt;

</description>
      <category>ide</category>
      <category>extensions</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing Pckd - The most powerful 💪 URL shortener</title>
      <dc:creator>Mohit Yadav</dc:creator>
      <pubDate>Thu, 03 Mar 2022 12:01:45 +0000</pubDate>
      <link>https://forem.com/just_moh_it/introducing-pckd-the-most-powerful-url-shortener-obk</link>
      <guid>https://forem.com/just_moh_it/introducing-pckd-the-most-powerful-url-shortener-obk</guid>
      <description>&lt;h2&gt;
  
  
  Overview of My Submission
&lt;/h2&gt;

&lt;p&gt;This month, I saw the Azure + Dev.to Hackathon 🤩 and immediately knew I found the excuse to spend my time bringing my prolonged idea to life.&lt;/p&gt;

&lt;h2&gt;
  
  
  What exactly is 🔗 &lt;a href="https://pckd.mohityadav.codes/devto-demo/" rel="noopener noreferrer"&gt;Pckd&lt;/a&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646134353427%2FXxF1QtA0N.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646134353427%2FXxF1QtA0N.gif" alt="Intro Video"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever wanted to share a long link with a friend, but it seems way too long to send through a message (maybe it's a base-64 image URI), so you might turn towards URL shorteners, nothing special?&lt;/p&gt;

&lt;p&gt;But try to imagine, along with the shortening functionality, what if you could have a lot more. I mean, track all the clicks (or hits) on the URL that you shortened and get very-deep insights about the person who clicked it, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Their 💻 device information, including model, operating system, etc.&lt;/li&gt;
&lt;li&gt;Their 👩‍💻 browser name and version&lt;/li&gt;
&lt;li&gt;Their 🌎 IP location, along with their ISP name, their city, rough coordinates, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And much more! 🤯&lt;/p&gt;

&lt;p&gt;And to add the cherry on the top, you could host it yourself on your custom domain! In fact, it was created to be self-hosted, for people on the &lt;a href="https://www.reddit.com/r/selfhosted/" rel="noopener noreferrer"&gt;self-hosted community&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doesn't that sound like the time to switch from Bitly and stop paying &lt;a href="https://bitly.com/pages/pricing" rel="noopener noreferrer"&gt;the premium&lt;/a&gt;, or being limited by 100 links/month?&lt;/p&gt;

&lt;h2&gt;
  
  
  Submission Category
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Computing Captains&lt;/strong&gt;: Since this app is hosted on an azure virtual machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creation process 👩‍🎨
&lt;/h2&gt;

&lt;p&gt;The creation process was undoubtedly the most fun part of the project. I solved many new challenges, learnt a lot, and finally came up with an application I was proud of! Here is how I pulled it off...&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing 🎨
&lt;/h3&gt;

&lt;p&gt;Usually when I create a pet project, I just use the designing from the previous projects I was working on, since they won't get noticed anyway. But with this one, I wanted it to reach to the top of the list of open source URL shorteners. I had self-doubts about whether I would be able to reach the goal with my experience, but you are &lt;a href="https://pckd.mohityadav.codes/devto-demo" rel="noopener noreferrer"&gt;free to judge&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inspiration ✨
&lt;/h4&gt;

&lt;p&gt;So, I started by looking for inspiration. The best place for this was &lt;a href="https://dribbble.com" rel="noopener noreferrer"&gt;Dribbble&lt;/a&gt;. I went to the inspiration tab. Many people would create the best design they could without any inspiration, but as Pablo Picasso (may have) said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good artists create, great artists steal&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's one way to put it, but the point is: with the amount of design experience and the height of the goals I had, I just wasn't going to be able to create a good-enough design overnight if I started from scratch. Hence, the searching.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646102675914%2FEhT8sPZ-Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646102675914%2FEhT8sPZ-Q.gif" alt="Dribbble.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After endless scrolling, similar-sounding keywords and hard-to-make choices, I decided to go with &lt;a href="https://dribbble.com/shots/15223174-Project-Management-Dashboard-UI-Exploration" rel="noopener noreferrer"&gt;this design&lt;/a&gt;, because it just looked great for the purpose I was looking for. There were many fancy ones too, but they just weren't practical, or too flashy for the typical programmer that was going to host it (if Pckd was even going to be successful).&lt;/p&gt;

&lt;h4&gt;
  
  
  Customizing 🍕
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://dribbble.com/shots/15223174-Project-Management-Dashboard-UI-Exploration" rel="noopener noreferrer"&gt;original design from Dribbble&lt;/a&gt; was good, but it wanted something more, like the colour customization, planning out exactly where everything would go, and creating an exact mock-up of how the app would look and much more. Therefore, everything was already planned out before I touched any code.&lt;/p&gt;

&lt;p&gt;I find this approach very useful, because you don't have to scratch your head over minor details that would otherwise go unnoticed while planning, and you have to go to the sketch board all over again if you've started coding.&lt;/p&gt;

&lt;h5&gt;
  
  
  Dashboard 💾
&lt;/h5&gt;

&lt;p&gt;I again went on to Dribbble to find some dashboard designs. I got some that caught my attention. After that, I went to Figma and started laying out the design&lt;/p&gt;

&lt;p&gt;After endless scratching of heads, I got this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645203739109%2FVz2jIS6iP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645203739109%2FVz2jIS6iP.png" alt="dashboard.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(One of my proudest creations 😎)&lt;/p&gt;

&lt;h5&gt;
  
  
  Other pages 🗞
&lt;/h5&gt;

&lt;p&gt;As for the other pages, I created the homepage out of just my imagination. Here's how it looked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645205140834%2FZTdNk6J4bS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645205140834%2FZTdNk6J4bS.png" alt="home.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the signup pages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645205192611%2FffTQwK1Zn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1645205192611%2FffTQwK1Zn.png" alt="signup.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The designs looked good in my opinion, and I was dead-set to implement the most design-accurate version of this with react and try to not mess up the margins or paddings somewhere. This marked the end of the designing and planning part of the app. &lt;br&gt;
Not bad, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the backend 🧩
&lt;/h3&gt;

&lt;p&gt;For the backend, I started out by forking a &lt;a href="https://github.com/Just-Moh-it/grapqhl-nextjs-template" rel="noopener noreferrer"&gt;backend template repo&lt;/a&gt; (made by me ;), because it contains a file-based structure, just like NextJS, but for the backend. It also has authentication baked in, so one doesn't have to go through the hassle of setting everything up.&lt;/p&gt;

&lt;h4&gt;
  
  
  The database schema 💾
&lt;/h4&gt;

&lt;p&gt;OK, I want to have a &lt;code&gt;hits&lt;/code&gt; table, a &lt;code&gt;user&lt;/code&gt; table, and..., and that's it. Oh! Forgot the &lt;code&gt;pckd&lt;/code&gt; table, the main one! After all these thoughts back and forth in my mind, I was ready with the following database schema&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646105302582%2Fism9BSqmU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646105302582%2Fism9BSqmU.png" alt="structure.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created the database through the &lt;a href="https://prisma.io" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; schema, and it ended up working great.&lt;/p&gt;

&lt;h4&gt;
  
  
  The file structure 📁
&lt;/h4&gt;

&lt;p&gt;This is how the finished file structure looked like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646101860667%2FoeGiAjkMt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646101860667%2FoeGiAjkMt.png" alt="Screenshot 2022-03-01 at 8.00.42 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding a new route was just as easy as creating a new file in the directory, like for the &lt;code&gt;user&lt;/code&gt; type, &lt;code&gt;api/User/index.graphql&lt;/code&gt; file needed to be created. This is how it looked like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

type User {
  id: ID!
  pckds: [pckd!]
  name: String!
  email: String!
  createdAt: String!
  updatedAt: String!
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And For the resolving the users' &lt;code&gt;pckd&lt;/code&gt; logic, in the &lt;code&gt;api/User/index.js&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pckds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pckds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pckd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pckds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As simple as creating an export file. You should definitely try this method of creating backends out. Little boilerplate, powerful APIs. 😃💪&lt;/p&gt;

&lt;h4&gt;
  
  
  Achieving this functionality ⛽
&lt;/h4&gt;

&lt;p&gt;For combining the files and graphql schemas, and create a single instance of &lt;code&gt;typeDef&lt;/code&gt; and &lt;code&gt;resolvers&lt;/code&gt;, I used the following code&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadFilesSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graphql-tools/load-files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mergeTypeDefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mergeResolvers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graphql-tools/merge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;makeExecutableSchema&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graphql-tools/schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadFilesSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/**/*.graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadFilesSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/**/*.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schemaWithResolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeExecutableSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;mergeTypeDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;mergeResolvers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schemaWithResolvers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This would combine all the files ending with the &lt;code&gt;.js&lt;/code&gt; and &lt;code&gt;.graphql&lt;/code&gt; extension from the &lt;code&gt;api&lt;/code&gt; and it's sub-folder into a single &lt;code&gt;typedef&lt;/code&gt; and &lt;code&gt;resolvers&lt;/code&gt; variable, and export them as &lt;code&gt;schema&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Querying the backend 💬
&lt;/h3&gt;

&lt;p&gt;For those who are new to GraphQL or haven't used apollo GraphQL before, Apollo provides a great interface for testing and creating queries, just like postman, but for Graphs, and much more powerful.&lt;/p&gt;

&lt;p&gt;And creating APIs with GraphQL never gets easier&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646104502429%2F3Z3YJd5HV.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1646104502429%2F3Z3YJd5HV.webp" alt="never gets easier.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the frontend ⚛
&lt;/h3&gt;

&lt;p&gt;For the frontend, I used React with the Create-react-app template, because it was easiest to work with, and I didn't use NextJS because the app didn't have much about SEO.&lt;/p&gt;

&lt;p&gt;Along with react, I used Redux, and Apollo-graphql-client to query the backend, because the global state was shared across multiple components. Also, I wanted to learn Redux, and what other way to learn than to implement it yourself. (But it turned out to be an overkill 😅).&lt;/p&gt;

&lt;p&gt;The typical React development pattern continues... At the end, I had a polished URL-shortener application that was fully customizable (upto the name) and ready to be deployed. Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting it
&lt;/h2&gt;

&lt;p&gt;For hosting the web app, I used azure VMs, as per the instructions. I created a B2s virtual machine, installed nginx, MySQL, NodeJS, NPM and cert bot, then ran the NodeJS server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxqlt5ul8qynqkf9cx6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxqlt5ul8qynqkf9cx6f.png" alt="Azure Portal Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The React frontend was built to a static file, which the backend served itself. I only had to set up a nginx proxy pass to redirect internet traffic from external port 80/443 (the web traffic port) to internal port 4000 (NodeJS server port).&lt;/p&gt;

&lt;p&gt;Here is how my &lt;code&gt;default&lt;/code&gt; configuration file looked like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:4000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_pass_header&lt;/span&gt;  &lt;span class="s"&gt;Set-Cookie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;Host&lt;/span&gt;               &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;X-Real-IP&lt;/span&gt;          &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt;  &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt;    &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(The SSL part is not included). Then I exposed the ports 80 and 443 from the azure portal, and the app was open for the world to access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Here are some useful links you would need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 Project Demo - &lt;a href="https://pckd.mohityadav.codes/devto-demo" rel="noopener noreferrer"&gt;https://pckd.mohityadav.codes/devto-demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐱 GitHub Repo - &lt;a href="https://github.com/Just-Moh-it/pckd" rel="noopener noreferrer"&gt;https://github.com/Just-Moh-it/pckd&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you liked the blog. If you did, please leave your thoughts in the comments. It would make my day.&lt;/p&gt;

&lt;p&gt;Till then, happy 💻 coding! 🍿&lt;/p&gt;

</description>
      <category>azuretrialhack</category>
      <category>node</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
