<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Palash Johri</title>
    <description>The latest articles on DEV Community by Palash Johri (@gulliblelamb).</description>
    <link>https://dev.to/gulliblelamb</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%2F555483%2F062e9530-139a-4c94-bbf2-f0b969364bbf.jpg</url>
      <title>DEV Community: Palash Johri</title>
      <link>https://dev.to/gulliblelamb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gulliblelamb"/>
    <language>en</language>
    <item>
      <title>Riffr - Create Photo Montages in the Browser with some ML Magic✨</title>
      <dc:creator>Palash Johri</dc:creator>
      <pubDate>Thu, 08 Dec 2022 23:48:11 +0000</pubDate>
      <link>https://dev.to/gulliblelamb/riffr-create-photo-montages-in-the-browser-with-some-ml-magic-5271</link>
      <guid>https://dev.to/gulliblelamb/riffr-create-photo-montages-in-the-browser-with-some-ml-magic-5271</guid>
      <description>&lt;h2&gt;
  
  
  🚀 What I Built (and What it Does)
&lt;/h2&gt;

&lt;p&gt;Riffr helps you make awesome, awesome montages! &lt;br&gt;
Okay, that's an oversimplification. Let me clarify how. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're allowed to choose up to 120 images(nice, right?), run face detection models on them &lt;/li&gt;
&lt;li&gt;Photos with faces detected are then configured around a specific face, zoom in/out levels &amp;amp; a frame rate, that is, how fast the images go by, is set.&lt;/li&gt;
&lt;li&gt;When you're done, the tool compiles these cached images and their configs and wraps it all up together in a neat little &lt;code&gt;webm&lt;/code&gt; or a &lt;code&gt;gif&lt;/code&gt; media file. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take this &lt;code&gt;gif&lt;/code&gt;, for example. (&lt;a href="https://riffr.tech/view/MoreElonGif-hOZ_H1ztJhbHvXcvf5kgi" rel="noopener noreferrer"&gt;in-app link&lt;/a&gt;)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.googleapis.com%2Friffr-gallery%2FMoreElonGif-hOZ_H1ztJhbHvXcvf5kgi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.googleapis.com%2Friffr-gallery%2FMoreElonGif-hOZ_H1ztJhbHvXcvf5kgi.gif" alt="Elon Montage" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It uses 26 images, cycled at 9 frames per second, and positioned around a specific face(Elon's, in this case).&lt;/p&gt;
&lt;h3&gt;
  
  
  🐱‍👤 Category Submission:
&lt;/h3&gt;

&lt;p&gt;Choose Your Own Adventure&lt;/p&gt;
&lt;h3&gt;
  
  
  🐱‍🏍 App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://riffr.tech" rel="noopener noreferrer"&gt;https://riffr.tech&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  😏 Background: Some Context
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;(What made you decide to build this particular app? What inspired you?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Time for a trip down the memory lane. &lt;br&gt;
Remember this 🔽 video from &lt;em&gt;wayyy&lt;/em&gt; back, in 2017?&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/65nfbW-27ps"&gt;
&lt;/iframe&gt;
&lt;br&gt;
For long, I had been really captivated by how the dedicated Youtuber &lt;strong&gt;Hugo Cornellier&lt;/strong&gt;, who took photos in front of a camera every day for 9 years, and ended up making a time-lapse collection of over 2500 photos, placed perfectly around himself. This video spoke to me, as it probably did to you. It showed a person's journey - of growth, of being a kid, of going through phases, and finally, finding love.&lt;/p&gt;

&lt;p&gt;However, it turns out, capturing this together was a painstakingly slow and difficult process. Aligning along a specific face, resizing images, and compiling these to make a meaningful video. It took Hugo 50+ hours just to make this!&lt;/p&gt;

&lt;p&gt;Being inspired by his pain, I decided to lend a hand and put out a tool that can automate all this configuration, detect and cycle between faces, and generate a video with it all!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Psst...&lt;/strong&gt;With this app, a user doesn't even have to click photos repeatedly at the same place or in the same position - the ML model adjusts all sorts of photos together 🤭&lt;/p&gt;

&lt;p&gt;Sounds easy enough to implement, right? &lt;br&gt;
Spoiler Alert: It was &lt;em&gt;not&lt;/em&gt; easy at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwjm92lmpl8rqj71erpx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwjm92lmpl8rqj71erpx.gif" alt="Ummmm" width="480" height="325"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🛠 How I Built It
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;(How did you utilize MongoDB Atlas? Did you learn something new along the way? Pick up a new skill?)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Since my first implementation (nearer to the beginning of the Atlas hackathon) was focused on preserving user privacy, I went for a pre-trained ML model that was loaded right into the browser, and compiled using the native &lt;code&gt;MediaRecorder&lt;/code&gt; Web API. Additionally, I learned how to cache images in the browser using &lt;code&gt;Web Workers&lt;/code&gt; and draw them blazing-fast onto the canvas with &lt;code&gt;ImageBitmap&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt; - For more details, check out my write-up on that earlier implementation that I published on Devpost (&lt;a href="https://devpost.com/software/riffr" rel="noopener noreferrer"&gt;here&lt;/a&gt;) &amp;amp; submitted to another hackathon.&lt;/p&gt;

&lt;p&gt;Nevertheless, the limitations caught up, and while various bug fixes ensured good quality (using &lt;code&gt;VP8&lt;/code&gt; media codecs) and speed, on mobile devices, it was just too much sometimes, and they'd just freeze due to large memory &amp;amp; computing requirements and start burning up!&lt;/p&gt;

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

&lt;p&gt;After a while, I decided to overcome this by using the power of &lt;code&gt;Tensorflow-Node&lt;/code&gt; in a custom Node.js backend, one that I could fully manage and let users share, upload and detect without worries about their phones. The compilation is still done on the front end, though, since it is easier there, in both &lt;code&gt;gif&lt;/code&gt; &amp;amp; &lt;code&gt;webm&lt;/code&gt; formats. Even though it might seem like a privacy-performance trade-off, I have structured the application in such a way with MongoDB that it's really easy to maintain privacy.&lt;/p&gt;

&lt;p&gt;Plus, now it's as easy as toggling a button to switch between in-browser and on-server ML detection!&lt;/p&gt;

&lt;p&gt;Lastly, the VueUse library made it so easier to tackle memory heap allocation debugging, QR Code generation, color picking, web workers etc.&lt;/p&gt;
&lt;h4&gt;
  
  
  💪 Using MongoDB Atlas
&lt;/h4&gt;

&lt;p&gt;I learned the Mongoose ODM to integrate with Atlas, and used it as a back end database (with possible future search functionalities) to create 2 collections, &lt;code&gt;Montages&lt;/code&gt; &amp;amp; &lt;code&gt;Users&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;The server generates unique, secret urls that are inherently public but as secure &amp;amp; private as &lt;code&gt;uuid&lt;/code&gt; using the &lt;code&gt;nanoid&lt;/code&gt; module, and storea them publicly in both the database and storage solution. This way, fetching is easier, data can be aggregated in one place or distributed accordingly, and indexes for search purposes can be generated, too!&lt;/p&gt;
&lt;h3&gt;
  
  
  📸 Screenshots &amp;amp; Details
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Signup/Signin &amp;amp; Onboarding Processes
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
     &lt;td&gt;Landing Page with Signup/Signin&lt;/td&gt;
     &lt;td&gt;Onboarding Intro&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FtcX17yy%2FScreenshot-2022-12-09-041341.png" width="800" height="450"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FchqQwZL%2FScreenshot-2022-12-09-042432.png" width="800" height="450"&gt;&lt;/td&gt;

  &lt;/tr&gt;
  &lt;tr&gt;
     &lt;td&gt;Onboarding Avatar &amp;amp; Email Verification&lt;/td&gt;
     &lt;td&gt;Onboarding Details&lt;/td&gt;
  &lt;/tr&gt;

  &lt;tr&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F0YqMKKv%2FScreenshot-2022-12-09-042537.png" width="800" height="450"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F0DwLx5r%2FScreenshot-2022-12-09-042607.png" width="800" height="450"&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h4&gt;
  
  
  Pick, Edit &amp;amp; Compile
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
     &lt;td&gt;User Aggregated Dashboard&lt;/td&gt;
     &lt;td&gt;Add your pictures, choose output &amp;amp; model&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F8zgKLpv%2FScreenshot-2022-12-09-042643.png" width="800" height="450"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FQcP1FXh%2FScreenshot-2022-12-09-042727.png" width="800" height="400"&gt;&lt;/td&gt;

  &lt;/tr&gt;
  &lt;tr&gt;
     &lt;td&gt;Select the right faces, frame rate, zoom, background&lt;/td&gt;
     &lt;td&gt;Compile, and Voila! Your montage is ready&lt;/td&gt;
  &lt;/tr&gt;

  &lt;tr&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fnnv8R5G%2FScreenshot-2022-12-09-042854.png" width="800" height="450"&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F48x8tyf%2FScreenshot-2022-12-09-042947.png" width="800" height="450"&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h4&gt;
  
  
  Viewer Page (with Publicly Accessible Links)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu0jzlnl6knl7tsveclh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu0jzlnl6knl7tsveclh.png" alt="Viewer" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  👨‍💻 Tech Stack
&lt;/h3&gt;

&lt;p&gt;Basically a MEVN stack web application. However, there are additionally a large number of APIs used, too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Front End - &lt;a href="https://quasar.dev/" rel="noopener noreferrer"&gt;Quasar Framework&lt;/a&gt; built on top of Vue 3.&lt;/li&gt;
&lt;li&gt;Back End - &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt; &amp;amp; &lt;a href="https://www.mongodb.com/atlas/database" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Important APIs - &lt;a href="https://ml5js.org/" rel="noopener noreferrer"&gt;ml5&lt;/a&gt; for in-browser detection, &lt;a href="https://github.com/vladmandic/face-api" rel="noopener noreferrer"&gt;face-api&lt;/a&gt; that uses &lt;code&gt;tensorflow-node&lt;/code&gt; to accelerate on-server detection. &lt;a href="https://vueuse.org/" rel="noopener noreferrer"&gt;VueUse&lt;/a&gt; for a bunch of useful component tools like the &lt;code&gt;QR Code&lt;/code&gt; generator. Yahoo's &lt;a href="https://github.com/yahoo/gifshot" rel="noopener noreferrer"&gt;Gifshot&lt;/a&gt; for creating &lt;code&gt;gif&lt;/code&gt; files in-browser etc.&lt;/li&gt;
&lt;li&gt;Storage Vendor - &lt;a href="https://console.cloud.google.com/storage/" rel="noopener noreferrer"&gt;Google Cloud Storage&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hosting - &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Azure&lt;/a&gt; Virtual Machine for the &lt;code&gt;Express&lt;/code&gt; server, and &lt;a href="https://vercel.app/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; for &lt;code&gt;Quasar&lt;/code&gt; build.&lt;/li&gt;
&lt;li&gt;Transactional - &lt;a href="https://www.mailgun.com/" rel="noopener noreferrer"&gt;Mailgun&lt;/a&gt; to send verification emails&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🔗 Link to Source Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/holy-script" rel="noopener noreferrer"&gt;
        holy-script
      &lt;/a&gt; / &lt;a href="https://github.com/holy-script/riffr" rel="noopener noreferrer"&gt;
        riffr
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Riffr is a great tool to literally 'riff' through a bunch of images and create photo montages around a centered face
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Riffr - Montage Time! (riffr)&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Riffr helps you literally 'riff' through images - centered around a face and creating a photo montage.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;A bit more detail about Riffr&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;You're allowed to choose up to 120 images(nice, right?), run the detection on them, and then you edit photos with faces detected and size them up accordingly. Also, you choose a frame rate, that is, how fast the images go by, and you can play and pause the editor to check out a preview with those settings. When you're done, the tool compiles these cached images and their configs and wraps it all up together in a neat little video.&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tbody&gt;
&lt;tr&gt;
     &lt;td&gt;Add your pictures&lt;/td&gt;
     &lt;td&gt;Select the right faces, frame rate, zoom&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/84567489/202893519-a20faac7-9b2f-4913-8d6d-a6bda7cac3cf.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F84567489%2F202893519-a20faac7-9b2f-4913-8d6d-a6bda7cac3cf.png" width="500"&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/84567489/202893560-b765257c-8b85-48a5-9110-d0df31e6bcad.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F84567489%2F202893560-b765257c-8b85-48a5-9110-d0df31e6bcad.png" width="500"&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
     &lt;td&gt;Compile&lt;/td&gt;
     &lt;td&gt;Voila! your montage&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/84567489/202893566-460c9cd0-4f42-4c18-8a1a-eb907193ebdb.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F84567489%2F202893566-460c9cd0-4f42-4c18-8a1a-eb907193ebdb.png" width="500"&gt;&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/84567489/202893572-2158d810-48b7-402d-a61c-857be6784dcc.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F84567489%2F202893572-2158d810-48b7-402d-a61c-857be6784dcc.png" width="500"&gt;&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;The final product will be something like this&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/84567489/202893757-a2c5772f-e729-4b61-941c-52c9f40bc2fc.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F84567489%2F202893757-a2c5772f-e729-4b61-941c-52c9f40bc2fc.gif" width="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Do you want to spin this up locally and experiement with it?&lt;/h3&gt;
&lt;/div&gt;

  Installation Guide
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install the dependencies&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/holy-script/riffr" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  📃 Permissive License
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;MIT License&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🤫 Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;Riffr's original submission page (on &lt;a href="https://devpost.com/software/riffr" rel="noopener noreferrer"&gt;Devpost&lt;/a&gt;) that won 1st spot 🏆 in an MLH Weekend Hackathon.&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>SpaceBin: The Minimalist Rich Text &amp; Image Storage with Unique URLs</title>
      <dc:creator>Palash Johri</dc:creator>
      <pubDate>Thu, 12 May 2022 23:59:36 +0000</pubDate>
      <link>https://dev.to/gulliblelamb/spacebin-the-minimalist-rich-text-image-storage-with-unique-urls-540e</link>
      <guid>https://dev.to/gulliblelamb/spacebin-the-minimalist-rich-text-image-storage-with-unique-urls-540e</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;This application is a PasteBin concept evolved and modernized with rich-text support, image media storage and a more comprehensive &amp;amp; simplistic UI/UX.&lt;/p&gt;

&lt;p&gt;I was starting out with using both Quasar(a Vue 3 Framework) and Appwrite😍, so I decided on something simple yet showcase-worthy. It wasn't too difficult to wrap my head around Appwrite, and although I tinkered with the realtime database, I ended up using just the basic storage for now.&lt;/p&gt;

&lt;p&gt;The application is easily understandable, so I hope you find it fun, calming and useful!&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category: Wacky Wildcards
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/holy-script"&gt;
        holy-script
      &lt;/a&gt; / &lt;a href="https://github.com/holy-script/spacebin"&gt;
        spacebin
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A rich text and image storage with unique publish urls.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
SpaceBin (spacebin)&lt;/h1&gt;
&lt;p&gt;A rich text and image storage with unique publish urls.&lt;/p&gt;
&lt;h2&gt;
Install the dependencies&lt;/h2&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
npm install&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
Start the app in development mode (hot-code reloading, error reporting, etc.)&lt;/h3&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;quasar dev&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
Lint the files&lt;/h3&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn lint
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
npm run lint&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
Format the files&lt;/h3&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;yarn format
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
npm run format&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
Build the app for production&lt;/h3&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;quasar build&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
Customize the configuration&lt;/h3&gt;
&lt;p&gt;See &lt;a href="https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js" rel="nofollow"&gt;Configuring quasar.config.js&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/holy-script/spacebin"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GUBoxFhA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5s38ff5t630dxmjasqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GUBoxFhA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5s38ff5t630dxmjasqv.png" alt="Home Screen" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4k6TLHLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xmks00ykkue4j72gxxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4k6TLHLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xmks00ykkue4j72gxxp.png" alt="Editor Screen" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GH-07sCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/57dxzcoa6fa4nepuqmvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GH-07sCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/57dxzcoa6fa4nepuqmvp.png" alt="Viewer Screen" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Site
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://spacebin.tech/"&gt;SpaceBin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>appwritehack</category>
    </item>
  </channel>
</rss>
