<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Anlisha Maharjan on Medium]]></title>
        <description><![CDATA[Stories by Anlisha Maharjan on Medium]]></description>
        <link>https://medium.com/@anlishamaharjan?source=rss-47753a60808d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*RQl0kAcA1jeE9sgSIWrAow.jpeg</url>
            <title>Stories by Anlisha Maharjan on Medium</title>
            <link>https://medium.com/@anlishamaharjan?source=rss-47753a60808d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 15 May 2026 08:44:16 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@anlishamaharjan/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Deploy Laravel with GitHub Actions on Shared Hosting]]></title>
            <link>https://towardsdev.com/deploy-laravel-with-github-actions-on-shared-hosting-9a984adfea29?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/9a984adfea29</guid>
            <category><![CDATA[ssh-keys]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Mon, 09 Jan 2023 03:46:54 GMT</pubDate>
            <atom:updated>2023-01-09T13:14:28.456Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/610/1*UJPor9gS35BuSxsxlI27Tg.png" /></figure><p>Let’s see the process to deploy Laravel app on shared hosting with SSH GitHub Action.</p><p><strong>Prerequisites:</strong></p><ul><li>Set up SSH keys in the server.</li><li>Set up Laravel project in GitHub.</li></ul><p>Let’s start!</p><p><strong>Create Deployment Script:</strong></p><p>Run the command below in the root of the project directory. A deploy.sh file is created inside the scripts folder. Paste the code snippet below into the deploy.sh file.</p><pre>mkdir .scripts/ <br>touch .scripts/deploy.sh</pre><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/019df2b657c3d8e14698928b017b8216/href">https://medium.com/media/019df2b657c3d8e14698928b017b8216/href</a></iframe><p><strong>Setup GitHub Actions:</strong></p><p>Option 1:</p><p>Run the command below in the root of the project directory. A ci.yml file is created inside the workflows folder, the file can have any name but it should end with a .yml extension. Write the configuration code snippet below into the ci.yml file.</p><pre>mkdir .github/ <br>mkdir .github/workflows/ <br>touch .github/workflows/ci.yml</pre><p>Option 2:</p><p>In the GitHub repository, click on <strong>Actions &gt; set up a workflow yourself</strong> and write the configuration code snippet below into the ci.yml file. The file can have any name but it should end with a .yml extension.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/61cd3527572f08570e40e9a66e8b1e92/href">https://medium.com/media/61cd3527572f08570e40e9a66e8b1e92/href</a></iframe><p>Let me explain what each section does.</p><pre>name: Deploy on push master</pre><p>Just specifying a name for the workflow.</p><pre>on:<br>  push:<br>    branches:<br>      - master</pre><p>The above snippet triggers the workflow when one pushes to the <em>master</em> branch.</p><pre>jobs:<br>  web-deploy:<br>    name: Deploy<br>    runs-on: ubuntu-latest</pre><p><em>jobs</em> — Group all the jobs that run in the workflow. Specifying and setting up a<em> web-deploy</em> job.</p><p><em>runs-on: ubuntu-latest</em> — Configures to run the workflow using the latest version of Ubuntu.</p><pre>steps:<br>    - name: 🚚 Get latest code<br>        uses: actions/checkout@v2</pre><p><em>steps</em> — Group all the steps that run in the <em>web-deploy</em> job.</p><p><em>uses: actions/checkout@v2</em> — Check-out repository so the workflow can access it.</p><pre>- name: 📂 Deploy to server via ssh<br>        uses: appleboy/ssh-action@v0.1.7<br>        with:<br>          host: ${{ secrets.HOST }}<br>          username: ${{ secrets.USERNAME }}<br>          password: ${{ secrets.PASSWORD }}<br>          port: ${{ secrets.PORT }}<br>          script: &quot;cd /var/www/html &amp;&amp; sh ./.scripts/deploy.sh&quot;</pre><p>Using appleboy/ssh-action; any ssh commands can be remotely executed to the shared hosting server with SSH username/password provided.</p><p><strong>Add GitHub Secrets:</strong></p><p>Goto <strong>Settings</strong> tab on the GitHub repository, click on <strong>Secrets</strong> &gt; <strong>Actions</strong> &gt; <strong>New Repository Secret </strong>to add the server host, ssh username, password, and port.</p><p>For example: For Server host: <strong>HOST</strong> as Name and <strong>your server IP address</strong> as Value. For SSH port: <strong>PORT</strong> as Name and <strong>your ssh port</strong> as Value. <strong>22</strong> is the default ssh port. For example: For SSH username: <strong>USERNAME</strong> as Name and<strong> run whoami on your server and use the result </strong>as Value.</p><p>To access variables in the pipeline use the format below:</p><pre>${{ secrets.HOST }}<br>${{ secrets.USERNAME }}<br>${{ secrets.PASSWORD }}<br>${{ secrets.PORT }}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fbwo3SKpw6LkJP56.png" /></figure><p>Now anytime one pushes to the master branch, the pipeline starts running a <em>web-deploy</em> job that deploys the Laravel app.</p><p>Goto <strong>Actions</strong> tab to monitor whether it’s running, successfully deployed or failed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*v92-RbUmzGssyrXq.png" /></figure><p>This concludes a CI/CD pipeline for Laravel on GitHub. Thanks for reading!</p><p><em>Originally published at </em><a href="https://anlisha.com.np/blog/deploy-laravel-with-github-actions-on-shared-hosting/"><em>https://anlisha.com.np</em></a><em> on January 9, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9a984adfea29" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/deploy-laravel-with-github-actions-on-shared-hosting-9a984adfea29">Deploy Laravel with GitHub Actions on Shared Hosting</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy React with GitHub Actions on Shared Hosting]]></title>
            <link>https://javascript.plainenglish.io/deploy-react-with-github-actions-on-shared-hosting-d950fcf27685?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/d950fcf27685</guid>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <category><![CDATA[shared-hosting]]></category>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[reactjs]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Wed, 28 Dec 2022 13:41:00 GMT</pubDate>
            <atom:updated>2023-01-03T11:51:39.830Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/610/1*JEJHNlJc1PsuQ3P7G4MY-Q.png" /></figure><p>Let’s see the process to deploy React app on shared hosting with FTP Deploy GitHub Action.</p><p><strong>Prerequisites:</strong></p><ul><li>Set up an FTP account in cPanel.</li><li>Setup React Project in GitHub.</li></ul><p>Let’s start!</p><p><strong>Setup GitHub Actions:</strong></p><p>Option 1:</p><p>Run the command below in the root of the project directory. A ci.yml file is created inside the workflows folder, the file can have any name but it should end with a .yml extension. Write the configuration code snippet below into the ci.yml file.</p><pre>mkdir .github/ <br>mkdir .github/workflows/ <br>touch .github/workflows/ci.yml</pre><p>Option 2:</p><p>In the GitHub repository, click on <strong>Actions &gt; set up a workflow yourself</strong> and write the configuration code snippet below into the ci.yml file. The file can have any name but it should end with a .yml extension.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e692f70c193ec301be2789462e5d92ab/href">https://medium.com/media/e692f70c193ec301be2789462e5d92ab/href</a></iframe><p>Let me explain what each section does.</p><pre>name: 🚀 Deploy on push master</pre><p>Just specifying a name for the workflow.</p><pre>on: <br>  push:<br>    branches:    <br>      - master</pre><p>The above snippet triggers the workflow when one pushes to the <em>master</em> branch.</p><pre>jobs:<br>  web-deploy:<br>    name: 🎉 Deploy<br>    runs-on: ubuntu-latest</pre><p><em>jobs</em> — Group together all the jobs that run in the workflow. Specifying and setting up a<em> web-deploy</em> job.</p><p><em>runs-on: ubuntu-latest</em> — Configures to run the workflow using the latest version of Ubuntu.</p><pre>strategy:<br>      matrix:<br>        node-version: [16.x]</pre><p>The <em>matrix</em> accompanied by the node-version tells the workflow to run <em>web-deploy</em> on the specified node version.</p><pre>steps:<br>    - name: 🚚 Get latest code<br>      uses: actions/checkout@v2</pre><p><em>steps</em> — Group together all the steps that run in the <em>web-deploy</em> job.</p><p><em>uses: actions/checkout@v2</em> — Check-out repository so the workflow can access it.</p><pre> - name: Use Node.js ${{ matrix.node-version }}<br>      uses: actions/setup-node@master<br>      with:<br>        node-version: ${{ matrix.node-version }}</pre><p><em>uses: actions/setup-node@master</em> — Installs the specified node version(16) in the CI environment.</p><pre>- name: Copy .env.prod.example to .env<br>      run: cp .env.prod.example .env</pre><p><em>run: cp .env.prod.example .env</em> — Creates a .env with required environment variables. (Important because .env is always added to .gitignore).</p><pre>- name: 🔨 Build Project <br>      run: |<br>        npm install<br>        npm run build</pre><p><em>run: npm install</em> — Using npm to install the package node dependencies.</p><p><em>run: npm run build</em> — Builds React project.</p><pre>- name: 📂 Sync files<br>      uses: SamKirkland/FTP-Deploy-Action@4.3.3<br>      with:<br>        server: ${{ secrets.SERVER }}<br>        username: ${{ secrets.FTP_USERNAME }}<br>        password: ${{ secrets.FTP_PASSWORD }}<br>        local-dir: build/</pre><p>Transfers files from the <em>build</em> folder to the shared hosting server using FTP credentials.</p><p><strong>Add GitHub Secrets:</strong></p><p>Goto <strong>Settings</strong> tab on the GitHub repository, click on <strong>Secrets</strong> &gt; <strong>Actions</strong> &gt; <strong>New Repository Secret </strong>to add the FTP server, account username, and password.</p><p>For example, for FTP username: <strong>FTP_USERNAME</strong> as Name and <strong>zon@zon.com</strong> as Value.</p><p>To access variables in the pipeline use the format below:</p><pre>${{ secrets.SERVER }} <br>${{ secrets.FTP_USERNAME }} <br>${{ secrets.FTP_PASSWORD }}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wM9VhGelPG7XqvHw.png" /></figure><p>Now anytime one pushes to the master branch, the pipeline starts running <em>web-deploy</em> job which builds and deploys the react app.</p><p>Goto <strong>Actions</strong> tab to monitor whether it’s running, successfully deployed or failed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Fg2fFeKYSWB8XYNn.png" /></figure><p>This concludes a CI/CD pipeline on GitHub. Thanks for reading!</p><p><em>Originally published at </em><a href="https://anlisha.com.np/blog/deploy-react-with-github-actions-on-shared-hosting/"><em>https://anlisha.com.np</em></a><em> on December 28, 2022.</em></p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>.</em></p><p><em>Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><strong><em>, </em></strong><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><strong><em>, and</em></strong><em> </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><strong><em>.</em></strong></p><p><strong><em>Looking to scale your software startup</em></strong><em>? Check out </em><a href="https://circuit.ooo/?utm=publication-post-cta"><strong><em>Circuit</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d950fcf27685" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/deploy-react-with-github-actions-on-shared-hosting-d950fcf27685">Deploy React with GitHub Actions on Shared Hosting</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Yup.array validate object property is unique with Formik in React.]]></title>
            <link>https://anlishamaharjan.medium.com/yup-array-validate-object-property-is-unique-with-formik-in-react-162fd1aff25c?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/162fd1aff25c</guid>
            <category><![CDATA[yup]]></category>
            <category><![CDATA[formik]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Tue, 29 Nov 2022 08:24:28 GMT</pubDate>
            <atom:updated>2022-11-29T09:03:21.095Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*EEnILWwg2uGf0kRF2MycOQ.png" /></figure><p>The requirement is to validate objects in <strong>users</strong> array has unique <strong>name</strong> property.</p><p>Define a custom method in Yup using <strong>Yup.addMethod</strong>. Yup.js provides this function to conveniently reuse test functions. Function has to either return <strong>true</strong> or <strong>false</strong> to indicate if testing has failed or not respectively, or a new <strong>ValidationError</strong> created through <strong>this.createError()</strong>.</p><pre>Yup.addMethod(Yup.array, &quot;unique&quot;, function (message, path) { return this.test(&quot;unique&quot;, message, function (list) { const mapper = (x) =&gt; get(x, path); const set = [...new Set(list.map(mapper))]; const isUnique = list.length === set.length; if (isUnique) { return true; } const idx = list.findIndex((l, i) =&gt; mapper(l) !== set[i]); return this.createError({path: `users[${idx}].${path}`,message}); }); });</pre><p>With Yup, we create a Yup formatted object that resembles our intended schema for an object.</p><pre>const schema = Yup.object().shape({ users: Yup.array().of( Yup.object().shape({ name: Yup.string().required(&quot;Name is required&quot;), })).unique(&quot;Duplicate user&quot;, &quot;name&quot;) });</pre><p>Formik has a special config option / prop for Yup object schemas called validationSchema which will automatically transform Yup’s validation errors into a pretty object whose keys match values and touched. Set the validationSchema option to the schema created above.</p><p>Use &lt;FieldArray/&gt; that helps with common array/list manipulations. Pass it a name property <strong>name=”users”</strong>. &lt;FieldArray/&gt; will give access to array helper methods via render props.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2735afd80eef6b5de046c61f2a2ed90d/href">https://medium.com/media/2735afd80eef6b5de046c61f2a2ed90d/href</a></iframe><p>Note on line 57, <strong>arrayHelpers.push</strong> add a value to the end of an array. Similarly, <strong>arrayHelpers.remove</strong> on line 104 remove an element at an index of an array and return it.</p><p>&lt;Field/&gt; hooks up inputs to Formik. Note the name attribute on line 82; it uses to match up with Formik state.</p><p>Thank you for reading!</p><p><em>Originally published at </em><a href="https://anlisha.com.np/blog/yup-array-validate-object-property-is-unique-with-formik-in-react/"><em>https://anlisha.com.np</em></a><em> on November 29, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=162fd1aff25c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Setup Bitbucket CI/CD for React]]></title>
            <link>https://towardsdev.com/setup-bitbucket-ci-cd-for-react-bfe42e396d98?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/bfe42e396d98</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[deployment-pipelines]]></category>
            <category><![CDATA[bitbucket-pipelines]]></category>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Tue, 25 Oct 2022 17:42:32 GMT</pubDate>
            <atom:updated>2022-11-14T12:08:41.712Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/610/1*vlBmvGGY-u-YUAt-boUFqg.png" /><figcaption>CI/CD</figcaption></figure><p>Continuous integration (CI) validates all the stages of the development process from merging codes to testing builds while optimizing the code release cycles. Continuous deployment (CD) focuses on setting up a bundled artifact into a production environment in the fastest way possible which automates the whole deployment process.</p><p>Here is a set of steps to integrate the Bitbucket CI/CD pipeline with React application; assuming that you have already set up React application repository in Bitbucket.</p><h3>Enable bitbucket pipelines</h3><p>Go to Repository settings → Pipelines settings. Enable the CI/CD pipeline by clicking on the Enable Pipelines button.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/789/1*1IuhS1HzJkcngs0q5fZWUw.png" /></figure><h3>Generate SSH keys</h3><p>Generate a new SSH key pair (recommended):<br>Go to Repository settings → SSH keys → Generate keys to generate public key and private key.</p><p>Add an existing key pair:</p><p>Go to Repository settings → SSH keys → Use my own keys and paste the private and public key into the provided fields, then Save.</p><p>Install the public key on the remote host before Pipelines can authenticate with that host.</p><p>For EC2; paste the public key to file: /home/ec2-user/.ssh/authorized_keys</p><p>I prefer to add a one-liner description such as: #Bitbucket CI/CD Pipeline</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/919/1*OyWc2SM37mm7DrSdBBTXoA.png" /></figure><h3>Setup known hosts</h3><p>Pipelines provide a way to store, and inspect, the fingerprint of a remote host, along with the host address; for the sole reason to verify that the public key presented by a remote host actually matches the identity of that host, to help you detect spoofing and man-in-the-middle attacks.<br>Go to Repository settings → SSH keys and enter the server IP address and select the Fetch button to see the host&#39;s fingerprint.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/1*j-SUCv0eOILxeZjJrknKfg.png" /></figure><h3>Add .env.prod.example in React JS repository</h3><p>Copy .env to .env.prod.example. Setup .env.prod.example with necessary values. For example: REACT_APP_API_URL=(Your Production API Url)</p><h3>Add bitbucket-pipeplines.yml in React JS application</h3><p>Add the bitbucket-pipelines.yml file below to the root directory of the React repository to run the CI/CD pipeline.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8e0566565724aae161ea1a82bd7b35dd/href">https://medium.com/media/8e0566565724aae161ea1a82bd7b35dd/href</a></iframe><p>In the yml file; When pull requests are merged in master branch the first step “Build React (Prod Server)” scripts are executed. This step mainly focus on installing latest npm packages and building the React application. Next step “Deployment (Prod Server)” focus on deploying the build folder to the server. <br>Note the $PROD_USER, $PROD_SERVER variables.</p><h3>Add repository variables</h3><p>Go to Repository settings → Repository variables<br>Pipelines variables added at the repository level can be accessed from the bitbucket-pipelines.yml file or any script in the following way: $PROD_USER where PROD_USER is the name of the variable. <br>For EC2; Set the values of variables as follows:<br>PROD_USER - ubuntu<br>PROD_SERVER - (Your Server IP Address)<br>PROD_BUILD_FOLDER - build<br>PROD_REMOTE_DESTINATION_PATH - (Your Server Path)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/981/1*9h1GtdTARb0Wnxf3Pp39-w.png" /></figure><h3>CI/CD pipeline process</h3><p>Go to Pipelines to see the list of all pipeline processes. Now when pull requests are merged into the master branch, the pipeline will run. A pipeline process runs all the scripts defined in the bitbucket-pipelines.yml file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K16egMAzyqaWW39FGkfctA.png" /></figure><p>And that’s it. Happy Reading!!</p><p><em>Originally published at </em><a href="https://anlisha.com.np/blog/bitbucket-ci-cd/"><em>https://anlisha.com.np</em></a><em> on October 25, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bfe42e396d98" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/setup-bitbucket-ci-cd-for-react-bfe42e396d98">Setup Bitbucket CI/CD for React</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Google Maps API Directions Service in React — Plot efficient route on map with total distance and…]]></title>
            <link>https://anlishamaharjan.medium.com/google-maps-api-directions-service-in-react-plot-efficient-route-on-map-with-total-distance-and-40f84efe9fc7?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/40f84efe9fc7</guid>
            <category><![CDATA[directions-api]]></category>
            <category><![CDATA[formik]]></category>
            <category><![CDATA[google-map-api]]></category>
            <category><![CDATA[reactjs]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Wed, 24 Aug 2022 04:15:59 GMT</pubDate>
            <atom:updated>2022-08-25T05:12:40.812Z</atom:updated>
            <content:encoded><![CDATA[<h3>Google Maps API Directions Service in React — Plot efficient route on map with total distance and duration.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NWTcQzt5MTu6SgfgAAJcFQ.jpeg" /></figure><p><strong>Use Case:</strong></p><ul><li>One can enter source and destination address; For the address field, google places autocomplete is implemented.</li><li>One can also add multiple way-points/stops between source and destination address.</li><li>On change in any address field, The Map and the Directions service is initialized to plot the driving directions and route on map and display the total distance and total duration.</li></ul><p><strong>Final Demo!</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*f8yXqxMSQwiI0lEc.png" /></figure><p><strong>Step1 — Enable Directions API for Google Maps API key</strong></p><p>If you are new to Google Maps API key, I recommend you to have a look at it <a href="https://developers.google.com/maps/documentation/directions/cloud-setup">here</a>.</p><p><strong>Step2 — Start Basic CRA</strong> <strong>and Install packages</strong></p><pre>npx create-react-app axon <br>cd axon <br>npm install @mui/material @emotion/react @emotion/styled</pre><p>This will create a basic CRA. We also installed MUI 5 for creating UI components.</p><pre>npm install @react-google-maps/api use-places-autocomplete formik moment</pre><p>This will install react-google-maps/api and use-places-autocomplete packages required.</p><p><strong>Step3 — Include Maps JavaScript Library</strong></p><p>Include the google maps client-side library in public/index.html</p><pre>&lt;script type=&quot;text/javascript&quot; src=&quot;https://maps.googleapis.com/maps/api/js?key [YOUR_API_KEY]&amp;libraries=places&quot;&gt;&lt;/script&gt;</pre><p><strong>Step4 — Setup App.js</strong></p><p>Initialize Formik with empty initial values of address fields. Formik is the most popular open source form library for React.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/010b3daf24c39b8b5dfceb0ff1df9bc9/href">https://medium.com/media/010b3daf24c39b8b5dfceb0ff1df9bc9/href</a></iframe><p><strong>Step5 — Create source and destination address field with multiple way-points</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3123144150b9d903bf2e32a40d01a7bf/href">https://medium.com/media/3123144150b9d903bf2e32a40d01a7bf/href</a></iframe><p>The GoogleAutocomplete field used is a custom google places autocomplete. You can find it <a href="https://github.com/anlisha-maharjan/react-google-directions-service/blob/master/src/components/autocomplete.js">here</a>.</p><p><strong>Step6 — Configure Request to Direction Service</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d43b6b5369b5230b515ef5d31a9dd0a/href">https://medium.com/media/9d43b6b5369b5230b515ef5d31a9dd0a/href</a></iframe><p>On line 9, an instance of the DirectionsService Object is created.<br>On line 13, the route() called takes directions request JavaScript object (with required query parameters origin, destination and travelMode) as an argument. Also waypoints parameter is included to consider all the stops between origin and destination.</p><p>The second argument of route() method which is a response callback function returns directionsResult and directionsStatus.</p><p>And that concludes it!</p><p><strong>Source Code!</strong></p><p>The full source code is available here — <a href="https://github.com/anlisha-maharjan/react-google-directions-service">https://github.com/anlisha-maharjan/react-google-directions-service</a></p><p>Happy Learning! Feel free to give this article a clap and follow to stay up to date with more articles!</p><p><em>Originally published at </em><a href="https://anlisha.com.np/blog/google-maps-api-directions-service-in-react-plot-efficient-route-on-map-with-total-distance-and-duration/"><em>https://anlisha.com.np</em></a><em> on August 24, 2022.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=40f84efe9fc7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build a custom time picker React component]]></title>
            <link>https://anlishamaharjan.medium.com/build-a-custom-time-picker-react-component-8a78059546d8?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/8a78059546d8</guid>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[time-picker]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Thu, 30 Jun 2022 17:58:15 GMT</pubDate>
            <atom:updated>2022-07-01T05:57:58.336Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jRnrAg7OzChQcUqE4mY-Qw.png" /><figcaption>custom-time-picker</figcaption></figure><p>In this article, we’ll create a custom time picker component combining react-datetime and react-input-mask packages.</p><h3>Step1 — Start Basic CRA</h3><pre>npx create-react-app axon</pre><h3>Step2 — Install react-datetime and react-input-mask packages</h3><pre>cd axon <br>npm i react-datetime react-input-mask moment</pre><h3>Step3 — Setup time picker component</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5ced987ad06d9824a8c7d33675a75aa1/href">https://medium.com/media/5ced987ad06d9824a8c7d33675a75aa1/href</a></iframe><h3>Step4 — Style time picker component</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/46c9948b70f94228aa827b584a5486a9/href">https://medium.com/media/46c9948b70f94228aa827b584a5486a9/href</a></iframe><h3>Step5 — Import CustomTimePicker component in App.js</h3><pre>import React from &quot;react&quot;;<br>import CustomTimePicker from &quot;./custom-time-picker&quot;;<br>import &#39;./custom-time-picker.scss&#39;;<br>function App() {<br>  return (<br>    &lt;div<br>      style={{<br>        display: &quot;flex&quot;,<br>        flexDirection: &quot;column&quot;,<br>        justifyContent: &quot;center&quot;,<br>        alignItems: &quot;center&quot;,<br>        width: &quot;100vw&quot;,<br>        height: &quot;100vh&quot;,<br>      }}<br>    &gt;<br>      &lt;CustomTimePicker name=&quot;time&quot; label=&quot;Time&quot; /&gt;<br>    &lt;/div&gt;<br>  );<br>}<br>export default App;</pre><p>And that’s it!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8a78059546d8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Introduction to Absolute Imports in React Native]]></title>
            <link>https://javascript.plainenglish.io/react-native-absolute-imports-quick-easy-5e3b60897f34?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/5e3b60897f34</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[tsconfig]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Fri, 06 May 2022 09:59:20 GMT</pubDate>
            <atom:updated>2022-05-18T00:43:41.038Z</atom:updated>
            <content:encoded><![CDATA[<h4>React Native Absolute imports — made easy for beginners.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*dwHbDTAFUnbWLeRtu7LWfA.jpeg" /><figcaption>React Native Absolute Imports Quick &amp; Easy!</figcaption></figure><p>Absolute imports help to simplify the paths and better organize the project as it grows. Also with absolute imports, it&#39;s easier to copy-paste the code with imports into another file in the project and not have to tinker with import paths. 😆</p><p>When the project’s folder structure is complex, we are going to have long relative imports in the project like this:</p><pre>import Input from ‘../../../components/form/input’;</pre><p>It can be pretty hard to refactor and looks messy. The solution is to convert relative imports to absolute imports.</p><p><strong>Step 1 — Install </strong><strong>babel-plugin-module-resolver plugin</strong></p><pre>$ npm install --save-dev babel-plugin-module-resolver</pre><p>Or</p><pre>$ yarn add --dev babel-plugin-module-resolver</pre><p><strong>Step 2 — Update </strong><strong>babel.config.js</strong></p><p>Add the following code snippet in babel.config.js</p><pre>module.exports = {<br>  plugins: [<br>    [<br>      &#39;module-resolver&#39;,<br>      {<br>        alias: {<br>          &#39;@app&#39;: &#39;./src&#39;,<br>        },<br>      },<br>    ],<br>  ],<br>}</pre><p>Note: @app is an alias one can give whatever one wants.</p><p><strong>Step 3 — Setup </strong><strong>jsconfig.json or </strong><strong>tsconfig.json</strong></p><p><strong>Using JavaScript</strong></p><p>Create/open jsconfig.json file (in the root directory of the project) and add baseUrl and paths setting inside compilerOptions as shown in the snippet below:</p><pre>{<br>  &quot;compilerOptions&quot;: {<br>    &quot;baseUrl&quot;: &quot;.&quot;,<br>    &quot;paths&quot; : {<br>      &quot;@app/*&quot;: [&quot;src/*&quot;]<br>    }<br>  }<br>}</pre><p><strong>Using TypeScript</strong></p><p>If you’re using TypeScript in React Native project, update tsconfig.json file (in the root directory of the project) and add the same setting inside compilerOptions as JavaScript.</p><pre>{<br>  &quot;compilerOptions&quot;: {<br>    &quot;baseUrl&quot;: &quot;.&quot;,<br>    &quot;paths&quot; : {<br>      &quot;@app/*&quot;: [&quot;src/*&quot;]<br>    }<br>  }<br>}</pre><p><strong>Step 4 — Implement Absolute Import</strong></p><p>Absolute imports setting is now successfully configured with src folder as a custom base directory and we can import an input component located at src/components/form/input.js from like so:</p><pre>import Input from &#39;@app/components/form/input&#39;;</pre><p>Happy Learning! Feel free to give this article a clap and follow to stay up to date with more articles!</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a><em> and </em><a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>. Check out our </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Community Discord</em></strong></a><em> and join our </em><a href="https://inplainenglish.pallet.com/talent/welcome"><strong><em>Talent Collective</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5e3b60897f34" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/react-native-absolute-imports-quick-easy-5e3b60897f34">An Introduction to Absolute Imports in React Native</a> was originally published in <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[LinkedIn API — OAuth 2.0 Access Token]]></title>
            <link>https://anlishamaharjan.medium.com/linkedin-api-oauth-2-0-access-token-12760694012a?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/12760694012a</guid>
            <category><![CDATA[oauth2]]></category>
            <category><![CDATA[linkedin-api]]></category>
            <category><![CDATA[linkedin]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Fri, 22 Apr 2022 15:12:22 GMT</pubDate>
            <atom:updated>2022-04-22T15:12:22.874Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>LinkedIn </strong>API — OAuth 2.0 Access Token</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qkdBlC628i4PRd_VciSYxg.jpeg" /><figcaption>LinkedIn API — OAuth 2.0 Access Token</figcaption></figure><p>Hi, on a recently worked project, we needed to fetch shares (posts) of company in LinkedIn. Thus, I write this step by step guide to access LinkedIn API.</p><p>The LinkedIn API uses OAuth 2.0 for user authorization and API authentication. Since we need access to Marketing APIs to fetch posts of company, we’ll follow Authorization Code Flow (3-legged authorization).</p><p><strong>Step 1 — Register application in the LinkedIn Developer Portal</strong></p><p>Create a new app in <a href="https://www.linkedin.com/developers/apps/new"><em>Developer Portal</em></a>, specify App name, enter the LinkedIn Page of the company which will be associated with the application, upload logo and publish.</p><p><em>Note: It is required to associate the app with a LinkedIn Company Page. The company selected will function as the publisher of the app.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N-A0W3QXp04nyUWQGva0sA.png" /><figcaption>Register application in the LinkedIn Developer Portal</figcaption></figure><p><strong>Step 2 — Request Application Verification</strong></p><p>Go to <em>Settings</em> tab, select <em>Verify</em> button next to the company associated with the app. Click the <em>Generate URL</em> button in the Company Verification pop-up. Copy the URL and send it to the Page admin for verification.</p><p>Page admin has 30 days to verify the app with the unique URL. Once the Page admin approves the request, the app will show <em>Verified</em> in <em>Settings</em> tab. The link will only expire earlier than 30 days if Page admin clicks <em>Deny</em> in the request.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MbzL73g3TVBBcDwLtw2h1g.png" /><figcaption>Verify the application</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qUw-Vex-ehICKd3pxBI2tQ.png" /><figcaption>Verify Company</figcaption></figure><p><strong>Step 3— Verify Application Request</strong></p><p>As a Page admin when a unique URL is received requesting approval to associate the app with company Page; Clicking the URL will navigate to the Developer Portal. Sign in and the landing page will feature the request details; company page information, app information, and the requestor’s name. The request can either be approved or denied.</p><p>Once verification is complete, it cannot be undone. If the link is accessed after 30 days, the landing page will showcase an expired message and a new unique URL link must be generated.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*K854eeZZWFA6NzHTydmnNg.png" /><figcaption>Verify Application Request</figcaption></figure><p><strong>Step 4— Application Credentials and Redirect URL</strong></p><p>Next click the <em>Auth</em> tab to view application credentials i.e <em>Client ID</em> and <em>Client Secret</em>.</p><p>Under <em>OAuth 2.0 settings, </em>we need to specify <em>Authorized redirect URLs</em>. Since we’re using Postman to get access token, we’ll add the Postman callback URL ‘<em>https://oauth.pstmn.io/v1/callback</em>’ to the list.</p><p><em>Note: Please note Client ID</em> and <em>Client Secret for later use.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UHbOMcnb8zm4HnRAZ8YKJQ.png" /><figcaption>Application Credentials and Redirect URL</figcaption></figure><p><strong>Step 5— Setup OAuth 2.0 scopes</strong></p><p>To fetch data through LinkedIn API we requires access to proper OAuth 2.0 scopes such as r_basicprofile, r_organization_social. These scopes are based on the products added in the application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/773/1*RFeyZs1OqagAuKgdh3CTDQ.png" /><figcaption>OAuth 2.0 scopes</figcaption></figure><p>Click the <em>Products</em> tab and apply to <em>Marketing Developer Platform</em>, <em>Share on LinkedIn</em> and <em>Sign in with LinkedIn</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*80ZRFYXRRy5R4guGYko5gg.png" /><figcaption>Products</figcaption></figure><p>Complete the <em>MDP</em> access form under <em>Products &gt; Marketing Developer Platform</em>. A confirmation email is received when the application has been reviewed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Gw2JFbr1N0xlg0n8IVjmMA.png" /><figcaption>MDP</figcaption></figure><p>Check the OAuth 2.0 scopes for the application now that products are added. <em>Sign in with LinkedIn</em> product gives access to r_liteprofile and r_emailaddress scopes. <em>Share on LinkedIn</em> product gives access to w_member_social scope. Remaining scopes are obtained from <em>Marketing Developer Platform </em>product<em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QhSGKTwwxpS0tHHCaBC8OQ.png" /><figcaption>OAuth 2.0 scopes</figcaption></figure><p><strong>Step 6— Get Access Token via Postman</strong></p><p>Open <em>Postman, </em>Create <em>New Request </em>and<em> </em>Click <em>Authorization</em> Tab. Select <em>Type</em> as <em>OAuth 2.0</em>. Fill in the given details:</p><ul><li>Token Name : <em>{provide token name}</em></li><li>Grant Type : <em>Authorization Code</em></li><li>Callback URL: <em>https://oauth.pstmn.io/v1/callback</em></li><li>Auth URL : <em>https://www.linkedin.com/oauth/v2/authorization</em></li><li>Access Token URL : <em>https://www.linkedin.com/oauth/v2/accessToken</em></li><li>Client ID : <em>{provide Client ID}</em></li><li>Client Secret : <em>{provide Client Secret}</em></li><li>Scope : <em>r_basicprofile, r_liteprofile, r_emailaddress, w_member_social, r_organization_social, rw_organization_admin, w_organization_social</em></li><li>State : <em>{provide a unique string value}</em></li><li>Client Authentication: <em>Send client credentials in body</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wPQ1XzsDGtn5vFMwac4gUg.png" /><figcaption>Access Token via Postman</figcaption></figure><p>Click on <em>Get New Access Token. </em>Postman will take us to the LinkedIn authorization page, where it is prompted to log into LinkedIn. Click <em>Allow</em> to authorize the request. The prompt on the authorization page is dictated by the requested scopes in the previous step.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/421/1*4d6Vqv7ikLwcaB-d8Q2utA.png" /><figcaption><em>Get New Access Token</em></figcaption></figure><p>Postman will display the access token to be used for testing. Choose <em>Use Token</em> button to set this token.</p><p><strong>Step 7— LinkedIn Find Shares By Owner API</strong></p><p>Our application can now retrieve the collection of shares (posts) owned by a specific organization for which the authenticated member is an <em>Admin</em>.</p><p>API Endpoint:</p><p>GET https://api.linkedin.com/v2/shares?q=owners&amp;owners=urn:li:company:{id}&amp;sortBy=LAST_MODIFIED&amp;sharesPerOwner=1000&amp;count=50&amp;start=0&amp;oauth2_access_token={ACCESS_TOKEN}</p><p>LinkedIn Company ID is a unique 6 to 9 digits long string of numbers. To find Company ID as a LinkedIn Page Admin, navigate to the Admin View of the LinkedIn Page from the All Pages or Home tab. The LinkedIn company ID is the numbers after “/company/” in the URL. For example, if the Admin URL for the LinkedIn Page is <em>https://www.linkedin.com/company/8681905/admin/</em>, the company ID is 8681905.</p><p><strong>And this is it!</strong></p><p>If you need to fetch shares (posts) of LinkedIn Company Page that doesn’t belong to you, then the Admin of that Company Page must add you as <em>Content admin</em> role. Skip these steps if not required.</p><p>As a Page Admin, access your LinkedIn Company Page Admin view. Click the <em>Admin tools</em> dropdown at the top of the page and select <em>Manage Admins</em>. Click the <em>Add admin</em> button. Search the authenticated member and assign role as <em>Content admin</em> and Save.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p0mrpCPVPpn-M8TA9cqmWg.png" /><figcaption>Manage Page Admins</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/540/1*e1_8s3D2yNU1Tdr77G3sqQ.png" /><figcaption>Add Page Admin</figcaption></figure><p><strong>Dependencies:</strong></p><ul><li>For each company, the authenticated user must have a <em>Admin</em> role in the company’s LinkedIn Page to fetch shares (posts) of the organization.</li><li>The app must have access to <em>Marketing Developer Platform</em> product and its scopes.</li></ul><p><strong>References:</strong></p><p><a href="https://docs.microsoft.com/en-us/linkedin/shared/authentication/getting-access">Getting Access to LinkedIn APIs - LinkedIn</a></p><p>If you enjoyed learning about LinkedIn API access flow then feel free to give this article a clap and follow to stay up to date with more articles! Thanks for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=12760694012a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tailwind CSS in HTML starter via NPM]]></title>
            <link>https://towardsdev.com/tailwind-css-in-html-starter-via-npm-ec43a5144001?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/ec43a5144001</guid>
            <category><![CDATA[tailwind]]></category>
            <category><![CDATA[html-css]]></category>
            <category><![CDATA[tailwind-css-tutorial]]></category>
            <category><![CDATA[tailwind-ui]]></category>
            <category><![CDATA[tailwind-css]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Mon, 28 Mar 2022 16:42:55 GMT</pubDate>
            <atom:updated>2022-04-01T11:39:38.585Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TEkIQ5DzoZjaL0qrzAxzqw.jpeg" /><figcaption>tailwindcss</figcaption></figure><p>Tailwind CSS is a utility-first CSS framework. This article includes steps to install Tailwind CSS in HTML via package manager and how to properly process Tailwind CSS. Although it requires a bit more setup, it is definitely the best way to make use of all of the features that Tailwind CSS can provide.</p><p><strong>Step 1 — Initialize package.json</strong></p><pre>npm init -y</pre><p><em>Note: The -y flag will say yes to all questions</em></p><p><strong>Step 2— Install Tailwind CSS</strong></p><pre>npm install -D tailwindcss@latest</pre><p><em>-D option if to save package to peerDependencies</em></p><p><strong>Step 3— Include Tailwind CSS directives</strong></p><p>Now that Tailwind CSS is installed, the next step is creating a tailwind.css file and add the following code to inject the Tailwind CSS directives.</p><pre>@tailwind base;<br>@tailwind components;<br>@tailwind utilities;</pre><p><strong>Step 4— Setup Tailwind configuration file</strong></p><p>The configuration file makes it easy to customize the classes in Tailwind CSS by changing any fonts, color, spacing, etc.</p><pre>npx tailwindcss init</pre><p>A minimal configuration file named tailwind.config.js is generated.</p><pre>module.exports = {<br> content: [&quot;./index.html&quot;], // Paths to all template files<br> theme: {<br>  extend: {},<br> },<br> plugins: [],<br>}</pre><p><strong>Step 5— Processing Tailwind CSS</strong></p><p>We’ll be using TailwindCSS CLI to build the CSS. In the following command ./assets/scss/tailwind.css is the input, and the built-css output will be placed in ./assets/css/tailwind.css.</p><pre>npx tailwindcss -i ./assets/scss/tailwind.css -o ./assets/css/tailwind.css --watch</pre><p>Also we can add the following script into package.json to easily build CSS with command npm run dev .</p><pre>&quot;scripts&quot;: {<br>&quot;dev&quot;: &quot;tailwindcss -i ./assets/scss/tailwind.css -o ./assets/css/tailwind.css --watch&quot;,<br>}</pre><p><strong>Step 6— Link Tailwind CSS into HTML</strong></p><p>Create an index.html file; Add the following code in HTML template head section.</p><pre>&lt;!-- index.html --&gt;</pre><pre>&lt;link rel=&quot;stylesheet&quot; href=&quot;./assets/css/tailwind.css&quot; /&gt;</pre><p><strong>And This is it. Enjoy!</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ec43a5144001" width="1" height="1" alt=""><hr><p><a href="https://towardsdev.com/tailwind-css-in-html-starter-via-npm-ec43a5144001">Tailwind CSS in HTML starter via NPM</a> was originally published in <a href="https://towardsdev.com">Towards Dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fabric.js in React — Draw bounding box in webcam preview using canvas events.]]></title>
            <link>https://anlishamaharjan.medium.com/fabric-js-in-react-draw-bounding-box-in-webcam-preview-using-canvas-events-3504c8a919ba?source=rss-47753a60808d------2</link>
            <guid isPermaLink="false">https://medium.com/p/3504c8a919ba</guid>
            <category><![CDATA[bounding-box]]></category>
            <category><![CDATA[reactjs]]></category>
            <category><![CDATA[fabricjs]]></category>
            <dc:creator><![CDATA[Anlisha Maharjan]]></dc:creator>
            <pubDate>Tue, 15 Mar 2022 10:21:44 GMT</pubDate>
            <atom:updated>2022-03-15T11:05:20.829Z</atom:updated>
            <content:encoded><![CDATA[<h3>Fabric.js in React — Draw bounding box in webcam preview using canvas events.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KYtFaxQAlAX9LeVlFQs-xw.png" /><figcaption>Fabric.js</figcaption></figure><p>Fabric.js is a JavaScript library for HTML5 canvas. Using Fabric.js one can create object/shapes on canvas. We’ll be incorporating canvas events to draw bounding box over webcam component.</p><p><strong>Step1 — Install Fabric.js &amp; react-html5-camera-photo</strong></p><pre>npm i fabric react-html5-camera-photo</pre><p><strong>Step2 — Create canvas &amp; camera element</strong></p><pre>&lt;Camera onTakePhoto={(uri) =&gt; {}} /&gt;</pre><pre>&lt;canvas id=&quot;fabricEl&quot; width=&quot;720&quot; height=&quot;348&quot;&gt;&lt;/canvas&gt;</pre><p><strong>Step3 — Initialize fabric.Canvas</strong></p><pre>import React, { useEffect, useState } from &quot;react&quot;;<br>import Camera from &quot;react-html5-camera-photo&quot;;<br>import { fabric } from &quot;fabric&quot;;</pre><pre>const [canvas, setCanvas] = useState(&quot;&quot;);</pre><pre>const initCanvas = () =&gt;<br> new fabric.Canvas(&quot;fabricEl&quot;, {<br>  selection: false,<br>  stateful: true,<br>});</pre><pre>useEffect(() =&gt; {<br> setCanvas(initCanvas());<br>}, []);</pre><p>Note that initCanvas function returns a fabric.Canvas object; invoked upon initial rendering of the DOM.</p><p><strong>Step4 — Draw bounding box with canvas mouse events</strong></p><p>Fabric supports a number of events to allow for interactivity and extensibility. In order to subscribe to events for a canvas we use the on method.</p><pre>useEffect(() =&gt; {<br> if (canvas) {<br>  var rectangle;<br>  canvas.on(&quot;mouse:down&quot;, function (e) {<br>    var pointer = canvas.getPointer(e.e);<br>    rectangle = new fabric.Rect({<br>     id: 1,<br>     top: pointer.y,<br>     left: pointer.x,<br>     width: 0,<br>     height: 0,<br>     originX: &quot;left&quot;,<br>     originY: &quot;top&quot;,<br>     fill: &quot;rgba(255,0,0,0.3)&quot;,<br>     stroke: &quot;rgba(255,0,0,1)&quot;,<br>     strokeWidth: 2,<br>     hasControls: true,<br>     hasRotatingPoint: true,<br>     hasBorders: true,<br>     transparentCorners: false,<br>     selectable: true,<br>     cornerSize: 10,<br>     cornerColor: &quot;rgba(255,0,0,1)&quot;,<br>     borderColor: &quot;rgba(255,0,0,1)&quot;,<br>     cornerStrokeColor: &quot;rgba(255,0,0,1)&quot;,<br>     cornerStyle: &quot;rect&quot;,<br>    });<br>    canvas.add(rectangle);<br>  });<br> }<br>}, [canvas]);</pre><p>On mouse:down event of canvas we create a fabric.Rect object and add it to the canvas via canvas.add() method.</p><p><strong>Final Code!</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/310f30b963559e909398f717b2f47fb8/href">https://medium.com/media/310f30b963559e909398f717b2f47fb8/href</a></iframe><p>Note on line 95, canvas.renderAll() re-renders both the upper and lower canvas layers on the DOM. The object:moving event is to restrict the bounding box rectangle within canvas boundary. The object:modified event calculates bounding box center x, center y, width and height.</p><p><strong>Demo!</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v9dOJvw0CwbcCOvQSCUngg.png" /><figcaption>demo</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3504c8a919ba" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>