<?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 Sbasken on Medium]]></title>
        <description><![CDATA[Stories by Sbasken on Medium]]></description>
        <link>https://medium.com/@sbasken?source=rss-f9df6996e355------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*yQ_cf_TZ8mnKNhjRFpiPyg.jpeg</url>
            <title>Stories by Sbasken on Medium</title>
            <link>https://medium.com/@sbasken?source=rss-f9df6996e355------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 03 Apr 2026 22:07:55 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sbasken/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[Understanding VPC Endpoints vs VPN: A Quick Guide for AWS Networking Beginners]]></title>
            <link>https://blog.stackademic.com/understanding-vpc-endpoints-vs-vpn-a-quick-guide-for-aws-networking-beginners-f4ccc2589311?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/f4ccc2589311</guid>
            <category><![CDATA[amazon]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[amazon-web-services]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Wed, 09 Oct 2024 18:28:37 GMT</pubDate>
            <atom:updated>2024-10-10T11:07:35.981Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bza2ZhUEsPvYGsBt" /><figcaption>Photo by <a href="https://unsplash.com/@nasa?utm_source=medium&amp;utm_medium=referral">NASA</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>I am studying for AWS Solutions Architect Associate exam right now and I found some concepts confusing as I am fairly new to networking. I am writing down key points here for myself and for others who are also learning AWS Networking for review.</p><h4><strong>VPC Endpoints</strong></h4><ul><li>Allow <strong>private connection</strong> between your VPC and AWS services (e.g., S3, DynamoDB) without using the public internet.</li></ul><p><strong>Use Case Scenario</strong></p><p>Imagine you have an application hosted on EC2 instances inside a VPC that needs to access files stored in an S3 bucket. Without a VPC Endpoint, your EC2 instances would have to go through the public internet to reach S3.</p><ul><li><strong>Solution</strong>: Create a <strong>VPC Gateway Endpoint</strong> for S3. This allows your EC2 instances to communicate directly with S3 over the AWS private network, enhancing security and reducing latency since the data never leaves the AWS network.</li></ul><h4>VPN (Virtual Private Network)</h4><ul><li>Securely connect your <strong>on-premises network</strong> or other cloud networks to your AWS VPC.</li></ul><p><strong>Use Case Scenario</strong></p><p>Suppose your company has a data center on-premises and you want to securely connect your data center network to your AWS VPC to transfer data or run hybrid cloud applications.</p><ul><li><strong>Solution</strong>: Set up an <strong>AWS Site-to-Site VPN</strong> connection. This creates an encrypted tunnel over the internet between your on-premises data center and your AWS VPC, enabling secure communication between your on-premises servers and AWS resources.</li></ul><h4>How About Route tables, Network ACLs, and Security Groups?</h4><p>Route tables, Network ACLs, and Security Groups <strong>control traffic within the VPC</strong> and between subnets, but they <strong>cannot establish private connectivity</strong> to AWS services (like S3 or DynamoDB) outside your VPC. VPC Endpoints are needed because they enable <strong>private connections to AWS services</strong> using the AWS network, without exposing traffic to the public internet.</p><p>AWS services like S3, DynamoDB, and SNS are <strong>global AWS services</strong> and do not reside inside a specific VPC by default.</p><p>For connecting to services in another <strong>VPC (even your own)</strong>, you would use <strong>VPC Peering</strong> or <strong>Transit Gateway</strong>, not VPC Endpoints.</p><h4>Important Points to Remember</h4><ul><li>AWS services like S3, DynamoDB, and SNS are <strong>global AWS services</strong> and do not reside inside a specific VPC by default.</li><li>For connecting to resources in <strong>another VPC (even your own)</strong>, you would use <strong>VPC Peering</strong> or <strong>Transit Gateway</strong>, not VPC Endpoints.</li></ul><h3>Stackademic 🎓</h3><p>Thank you for reading until the end. Before you go:</p><ul><li>Please consider <strong>clapping</strong> and <strong>following</strong> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/stackademic"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/c/stackademic"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a></li><li>Visit our other platforms: <a href="https://plainenglish.io/"><strong>In Plain English</strong></a> | <a href="https://cofeed.app/"><strong>CoFeed</strong></a> | <a href="https://differ.blog/"><strong>Differ</strong></a></li><li>More content at <a href="https://stackademic.com/"><strong>Stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f4ccc2589311" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/understanding-vpc-endpoints-vs-vpn-a-quick-guide-for-aws-networking-beginners-f4ccc2589311">Understanding VPC Endpoints vs VPN: A Quick Guide for AWS Networking Beginners</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Keeping Your Full-Stack App Responsive: Prevent Slow Startups Even on Free Instances on Render]]></title>
            <link>https://blog.stackademic.com/keeping-your-full-stack-app-responsive-prevent-slow-startups-even-on-free-instances-on-render-093b260037a3?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/093b260037a3</guid>
            <category><![CDATA[full-stack]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[codingbootcamp]]></category>
            <category><![CDATA[deployment]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Wed, 22 Nov 2023 12:17:11 GMT</pubDate>
            <atom:updated>2023-11-29T16:22:42.938Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9MY85EE9u5F36V0l" /><figcaption>Photo by <a href="https://unsplash.com/@mike_van_den_bos?utm_source=medium&amp;utm_medium=referral">Mike van den Bos</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Introduction</h3><p>In the fast-paced world of web applications, responsiveness is key. Users expect quick and seamless interactions, but often, full-stack applications, especially those hosted on platforms like Render, can experience slow startups after periods of inactivity. In this blog, we delve into a practical solution to keep your full-stack application always ready and responsive. Whether you’re using React for the front end and Flask/Python for the backend like me or any other technology stack, this guide will walk you through the steps to ensure that your application on Render stays active and avoids the dreaded slow launch. This enhances user experience and maintains consistent performance. Note that syntax and modules might differ, but the concept should remain the same.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ESAAII0OQwf-n-Lje2zRLg.png" /><figcaption>Reference: <a href="https://render.com/docs/free">https://render.com/docs/free</a></figcaption></figure><p>On Render, if your website doesn’t receive any request for 15 minutes, next time someone accesses it, it can take 30 seconds or more to load the website. (Yes, it’s longer than the few seconds mentioned in their documentation, unfortunately.)</p><p>Most of my work stuff is live on paid hosts but I still have few projects from my coding bootcamp using free tier service on Render. Initially, I thought I had to just accept the slow performance. So I ended up filming a demo video to share on social media and added that to my resume, along with the link to the live website, because I knew the link would be slow to access.</p><p>Luckily, there is an easy and quick solution to that problem 🙌</p><h3>Option 1: Frontend Approach</h3><p>You can send a request every 15 minutes to your backend. In my case, I could use setInterval function in React that sends a simple GET request to your Flask backend every 15 minutes. This could be for a lightweight endpoint like /pingin your backend app, just to receive the request and keep the website active.</p><p>The catch is that this approach relies on the user keeping the browser tab open. If the tab is closed, the requests will stop. So for a portfolio project, this might not be very effective because these sites don’t have a steady stream of visitors.</p><h3>Option 2: Backend Approach</h3><p>A much better and more reliable approach would be to set up a similar mechanism in the backend, as it doesn’t rely on user activity in the browser.</p><p>In my case, I used Flask/Python for the backend (You would need a WSGI environment to run Flask app) and it was super simple to set up a background task. You can install BackgroundScheduler from apscheduler.schedulers.background and requests module and have that run your HTTP requests on schedule on your behalf! Pretty neat, isn’t it?</p><p>Run pip install apscheduler and pip install requests and add the below code to your app.py.</p><pre>from apscheduler.schedulers.background import BackgroundScheduler<br>import requestspy</pre><p>Here is what my code looks like using the above modules for one of the projects.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jrUdLepejWGRZw5dgrGkyw.png" /><figcaption>app.py in server directory</figcaption></figure><p>I added an endpoint called ‘/ping’ that simply returns a response {“status”: “alive”}, 200 for this task.</p><p>I then added a function keep_alive() that tries to send HTTP request to the /ping endpoint with an exception handling to capture the error messages.</p><p>I saved BackgroundSchedule() to a variable scheduler and used that to run the keep_alive() function, setting intervals of <strong>15 minutes</strong> so it will run automatically at this frequency.</p><p>After that, I ran pip freeze &gt; ../requirements.txt to update my requirements.txt as I installed new modules. Then I pushed to my deploy branch on Github and Render automatically re-deployed my application with the new set up.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vMDUaHJOOx787_FiqjmPtw.png" /></figure><p>You can check the log on Render to see if it is actually sending requests every 15 minutes. It seems pretty consistent but as you can see, sometimes it is 16 minutes or 14 minutes. So you can set the interval to 13 minutes or less just to make sure that it is responsive at all times. Check out my website below and see if you can access it right away!</p><p><a href="https://property-panda-app.onrender.com/">Property Panda 🐼</a></p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=093b260037a3" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/keeping-your-full-stack-app-responsive-prevent-slow-startups-even-on-free-instances-on-render-093b260037a3">Keeping Your Full-Stack App Responsive: Prevent Slow Startups Even on Free Instances on Render</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Protecting Your API Keys: A Guide for Website Deployment]]></title>
            <link>https://blog.stackademic.com/protecting-your-api-keys-a-guide-for-website-deployment-1e43d61f333a?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/1e43d61f333a</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[website]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Fri, 10 Nov 2023 18:01:03 GMT</pubDate>
            <atom:updated>2023-11-13T00:55:03.562Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CC-OnFb4Sibkfxhi" /><figcaption>Photo by <a href="https://unsplash.com/@nickmorrison?utm_source=medium&amp;utm_medium=referral">Nick Morrison</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4>Never expose your API keys to the public</h4><p>You might know that when developing a website, you shouldn’t have your API keys out in the public. Keeping API keys secure within your project is essential to prevent potential security risks.</p><h4>Storing API Keys in a Secure .env File</h4><p>You can safely keep your API keys in the .env file. Additionally, you should include the .env file in your project&#39;s .gitignore to prevent it from being pushed to your remote repository on platforms like GitHub. This practice ensures that sensitive information remains hidden from public view.</p><p>Here’s an example of how you can access API keys from the .env file in your code from my React application:</p><pre>const { isLoaded } = useLoadScript({<br>googleMapsApiKey: process.env.REACT_APP_GOOGLEMAPS_KEY,<br>libraries,<br>});</pre><p>But what happens when you deploy your website? How does your app have access to your API keys if they are saved on your local computer?</p><h4>The Importance of Hiding API Keys</h4><p>Exposing API keys is a recipe for disaster, and here’s why:</p><p>1. <strong>Unauthorized Usage: </strong>Unauthorized individuals might exploit your keys, resulting in unexpected financial charges.<br>2. <strong>Credibility Issues: </strong>Misuse of your API keys could tarnish your reputation with the API provider, potentially leading to service restrictions.<br>3. <strong>Data Breaches: </strong>Depending on the type of API, this could lead to data breaches, as malicious actors may gain access to sensitive information through unauthorized API requests.<br>4. <strong>Reputation Damage: </strong>And all of these can cause reputation damage to your website and yourself.</p><h4>Protecting API Keys After Deployment</h4><p>Luckily, it is fairly simple to hide your API keys even after deploying your website. In my case with React and Flask full-stack application that I deployed on render.com, it only took me a few minutes to do so. The basic concept should be fairly similar for other web hosts but the code might need to be modified accordingly depending on their setup.</p><p>Follow these steps to protect your API keys after deployment ⬇️</p><ol><li><strong>Copy API Key Information:</strong> Begin by copying the API key information from your .env file.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F0vydmk3GKYF-iLMDXoOlQ.png" /><figcaption>.env file where the API Keys are saved</figcaption></figure><p>In my project, I used EmailJS and Google Maps.</p><p>2. <strong>Configure Environment Variables: </strong>Navigate to the Environment Variables on render.com and add the information there:</p><figure><img alt="Environmentl Variable section on Render.com" src="https://cdn-images-1.medium.com/max/1024/1*5hnla1YrClv-FTuJc05O4A.png" /></figure><p>Make sure you use the same key value pairs as in yourgitignore file for each API key.</p><p>3. <strong>Re-Deploy Your Application: </strong>Once you’ve saved the environment variables, your application should automatically re-deploy. You should now be able to see the components of your website using the protected API keys.</p><p>In my case, I was still using trial account so when I added the API keys on render’s environment variables, I still had an issue with generating Google Maps saying For development purposes only right on the Map but I just needed to go to the Google API console and activate my account. To use API after delopying, make sure you have full account access. To do so, you might have to add a billing information.</p><p>Happy coding, and keep those keys safe! 🚀</p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e43d61f333a" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/protecting-your-api-keys-a-guide-for-website-deployment-1e43d61f333a">Protecting Your API Keys: A Guide for Website Deployment</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Emulator Hacks: Revealing console.log() Output for Seamless Debugging]]></title>
            <link>https://blog.stackademic.com/emulator-hacks-revealing-console-log-output-for-seamless-debugging-a1b3ef343615?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1b3ef343615</guid>
            <category><![CDATA[debugging]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[startup]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Thu, 19 Oct 2023 20:24:51 GMT</pubDate>
            <atom:updated>2024-10-04T16:45:14.783Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="cellphone image" src="https://cdn-images-1.medium.com/max/1024/0*JGXeSyP_UHFzVumT" /><figcaption>Photo by <a href="https://unsplash.com/@williamtm?utm_source=medium&amp;utm_medium=referral">William Hook</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3><em>App Localization with TUO</em></h3><p>I did app localization for <a href="https://www.thetuolife.com/">TUO</a>, a startup specializing in circadian lighting. For their Ionic/Capacitor application, I could simply use ionic serve command to launch a server on localhost, and test on a browser just like I would for web applications.</p><p>But it turns out that many app plugins and certain features may not show up when run on a server, especially if they rely on hardware-specific components or system resources that may not be available on a server environment. That’s when the trusty emulator or an actual test device comes to the rescue!</p><h4>Where’s my Console?</h4><p>In my latest project involving a review prompt using Android Studio, I hit a little roadblock. Unlike the familiar Console in Chrome Inspect for web applications, Android Studio didn’t offer an equivalent feature right out of box.</p><p>After a thorough online quest, I stumbled upon something called ‘logcat’ in Android Studio. Exciting, right? Well, not so fast! It didn’t quite display what I needed from console.log() in the code.</p><h4>Chrome Inspect: Guiding the Way Through Debugging Puzzles</h4><p>Thankfully, a solution wasn’t far off. Once your application is up and running on an emulator, simply type chrome://inspect in the browser&#39;s URL. Chrome Inspect will seamlessly identify the application for you, providing a vital tool for debugging.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vBVpISaxMQRek4IThuwo_A.png" /></figure><p>You can then hit inspect below your device details and a new browser with a Console pops up like below 🙌</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mCzObwQWmkCwM0WCJCAXHw.png" /></figure><p>I must admit, I never thought I’d be this excited to see a Console. But here I am, enthusiastic about the prospect of enhanced debugging on my mobile app development journey. 📱🥂</p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1b3ef343615" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/emulator-hacks-revealing-console-log-output-for-seamless-debugging-a1b3ef343615">Emulator Hacks: Revealing console.log() Output for Seamless Debugging</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Take Home Assignment Insights: My Journey and Learnings]]></title>
            <link>https://medium.com/@sbasken/take-home-assignment-insights-my-journey-and-learnings-a25f4ce83562?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/a25f4ce83562</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[interview]]></category>
            <category><![CDATA[junior-developer]]></category>
            <category><![CDATA[bootcamp]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Sat, 14 Oct 2023 20:00:50 GMT</pubDate>
            <atom:updated>2023-10-17T16:27:25.861Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vD7myIoREVPISxLB" /><figcaption>Photo by <a href="https://unsplash.com/@mrthetrain?utm_source=medium&amp;utm_medium=referral">Joshua Hoehne</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Exploring the Take-Home Assignment</h3><p>I recently had the chance to dive into an interview process for a position that had me buzzing with excitement. I went to the third round of interview which was a take home assignment. The fourth one would’ve been the final round. I was given a simple design and was asked to create a website using React but was given a liberty to add as much features as I felt fit. I was so excited but, long story short, the job ultimately slipped through my fingers.</p><h4>The Rush to Completion: Lessons in Patience</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GU-0oWZJXuPBhtv5" /><figcaption>Photo by <a href="https://unsplash.com/@slelham?utm_source=medium&amp;utm_medium=referral">Steven Lelham</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Now, let’s talk about the mad dash I made to complete the assignment. Given a generous week to work my magic, I decided to channel all my energy into a day and a half of intense, I mean INTENSE, creativity, hitting submit next. I literally put everything else on hold. Looking back, I can’t help but cringe a little. If I could hop into a time machine and give past-me a piece of advice, it would be this: “Wait until the last day. Exhaust all your resources, let your ideas simmer, revisit them with fresh eyes, seek input from mentors, refine them, and then, and only then, hit submit.”</p><p>Hindsight is a funny thing; what once seemed like a brilliant move now strikes me as a rush of excitement that obscured my vision of the project as a website, not just an assignment.</p><h3>A Moment of Clarity</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1TWAGR1TpIQ0jOHr" /><figcaption>Photo by <a href="https://unsplash.com/@lephunghia?utm_source=medium&amp;utm_medium=referral">Nghia Le</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>For a few weeks after the rejection, I’ll admit, I was baffled. I couldn’t figure out why I had been turned down. I wished I could see other candidates’ submissions so I could learn from them. After all, I felt quite content with what I had submitted.</p><p>Yet, giving up isn’t my style. I really believed that the position was a perfect match for me, both technically and in terms of cultural fit. Instead of viewing this setback as a mere failure, I saw it as an invaluable learning opportunity. It was then that I decided to reach out to my mentor, who graciously guided me through my thought process.</p><p>That conversation led to a series of realizations:</p><ol><li><strong>I had approached the project as an assignment rather than treating it like a genuine website.</strong></li><li><strong>I got caught up in trying to mirror the design, thinking of the extra features I added as icing on the cake. Turns out, I ended up throwing in functionalities that wouldn’t really fly in the real world.</strong></li><li><strong>I failed to grasp the subtle message embedded in the instructions.</strong></li></ol><p>When you’re granted creative freedom, it’s likely intended to see not just what you did, but why you did it, or at the very least, to ensure your choices are intuitively clear.</p><p>In hindsight, I realize that providing a brief note on the reasoning behind the features I included would have been invaluable. After all, the assignment isn’t just about showcasing technical skills, but also about revealing one’s approach to problem-solving.</p><h3>Turning Setbacks into Stepping Stones</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BqrqaeS2hHrNwbsx" /><figcaption>Photo by <a href="https://unsplash.com/@helloimnik?utm_source=medium&amp;utm_medium=referral">Nik</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Reflecting on this experience, I’ve come to appreciate the valuable lessons learned. What initially felt like a setback has turned into a powerful stepping stone for personal and professional growth. It’s shown me the importance of seeing beyond the surface, of treating each project as an opportunity to create something meaningful and functional.</p><p>As I move forward, I feel more prepared for the next assignment I may have in the future thanks to this opportunity. I’ll remember that it’s not just about what you create, but why and how you create it. I’ll embrace setbacks as chances to learn, improve, and ultimately, to excel.</p><p>And most importantly, having a mentor is gold. (Thanks, Amy! 💚)</p><p>Thank you for joining me on this journey of self-discovery and growth. Here’s to taking on new challenges with confidence and a determination to continuously better ourselves.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a25f4ce83562" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating Custom Admonitions in Docusaurus React App]]></title>
            <link>https://blog.stackademic.com/creating-custom-admonitions-in-docusaurus-react-app-cbe00c39339b?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/cbe00c39339b</guid>
            <category><![CDATA[docusaurus]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[documentation]]></category>
            <category><![CDATA[markdown]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Thu, 07 Sep 2023 18:19:18 GMT</pubDate>
            <atom:updated>2023-09-10T13:27:42.313Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AA3kpIQFvSG37sGrwH7ebA.jpeg" /></figure><h3>What is Docusaurus?</h3><p>Docusaurus is a static-site generator to help build a documentation site quickly to let users focus on its contents rather than the technical parts, through text editors like VSCode or <strong>Content Management Systems (CMS)</strong> such as WordPress, Strapi, and Netlify CMS.</p><p>Content writers can use those tools and save contents in markdown files and it has a lot of out-of-the-box features to fit your needs.</p><h4>Customizing Docusaurus</h4><p>Customizing features on Docusaurus can be a headache at first for that reason though: there are a lot of out-of-the-box-features!</p><p>But once you understand how things work with Docusaurus, I’ve actually come to enjoy it. A lot of people didn’t even think React was that good when it first came out and now it is the most popular JS framework in the world, right? (I wasn’t a dev back then but <a href="https://www.youtube.com/watch?v=8pDqJVdNa44">this React documentary</a> was so interesting, I got my husband to watch it with me. 🍿 It turns out that our friend was in the documentary but that’s a story for another day…)</p><h4>What is Swizzling…?</h4><p><strong>Swizzling</strong> is a special-term in Docusaurus: a feature that allows you to customize built-in components and features to better suit your specific needs.</p><h3>Admonitions</h3><p><strong>Admonitions </strong>in markdown look like below ⬇️</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_6znWnWc0N6JOGXeHyuBQA.png" /><figcaption>Example of info admonition</figcaption></figure><p>The code for the above looks like this ⬇️</p><pre>:::info title goes here<br>content goes here<br>:::</pre><h3>Custom Admonitions</h3><p>In Docusaurus, there are <strong>5</strong> built-in admonitions: ‘<strong>note</strong>’, ‘<strong>tip</strong>’, ‘<strong>info</strong>’, ‘<strong>caution</strong>’, and ‘<strong>danger</strong>’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3jATAvKUPKfR9HyYBAGHBw.png" /></figure><p>To add custom admonitions, follow the steps below 🏁</p><p><strong>Step 1️⃣ </strong>Add words to the array of keywords in docusaurus.config.js</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x5zqMebWXYTfE5k78b3V_Q.png" /><figcaption>docusaurus.config.js</figcaption></figure><p>These keywords will be used to call the admonitions.<br>Here, <strong>question</strong>, <strong>podcast</strong>, <strong>newletter</strong>, <strong>company</strong>, <strong>contribute</strong>, and <strong>book</strong> were added.</p><p><strong>Step</strong> 2️⃣ Add custom css in src/theme/Admonition/styles.module.css</p><blockquote>If the file is not there yet, you need to swizzle the component. (See <a href="https://docusaurus.io/docs/swizzling">here</a> for more info on swizzling)</blockquote><p>To add a custom css to the new admonition, you simply use the keyword as a selector. For example, for ‘podcast’, it would be .podcast.</p><pre>.podcast {<br>  border-left: 5px solid yellow;<br>  background-color: rgb(250, 250, 234);<br>}</pre><p><strong>Step </strong>3️⃣ Add keywordIcon function to src/theme/Admonition/index.js</p><pre>import { MdPodcasts } from &#39;react-icons/md&#39;<br><br>function PodcastIcon() {<br>  return (<br>    &lt;MdPodcasts<br>      title=&quot;Podcast Icon&quot;<br>      style=&quot;&quot;<br>    /&gt;<br>  )<br>}</pre><p>I’m using <a href="https://react-icons.github.io/react-icons/">react-icons</a> so in this case, I’m importing the icon from the library and then use that to create PodcastIcon()function which simply returns the icon with the title.</p><p><strong>Step</strong> 4️⃣ Add keyword to the object AdmonitionConfigs in index.js</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OtuggeJknm5FDrmhpUbksQ.png" /><figcaption>src/theme/Admonition/index.js</figcaption></figure><p>For other keywords, simply change where is says podcast to others.</p><p>Step 5️⃣ Add the new ones to Admonition() in index.js</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5Ize2mz3RUzEJBB7yx0xFA.png" /></figure><p>For podcast, I added const isPodcastAdmonition = type === ‘podcast’; and [styles.podcast]: isPodcastAdmonition to the admonitionClassName variable and did the same for other keywords.</p><p><strong>Step</strong> 5️⃣ Test 🚀</p><p>Once all the above is done, add admonition code (:::keyword title content :::) to any markdown file where you want to test and you should be able to see your custom admonitions with your keywords and icons like below 🎉</p><blockquote>caveat: don’t forget to re-start the server as we made changes to the config file!</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L9vGVj452b33j0rpOz-AJA.png" /></figure><p><em>Examples were from my experience at the </em><a href="https://www.climatetechhandbook.com"><em>Climate Tech Handbook</em></a><em>.</em></p><p><em>Please give them a follow on </em><a href="https://www.linkedin.com/company/climate-tech-handbook/"><em>LinkedIn</em></a><em>!</em></p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Following us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X</em></strong>)</a>, <a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a>, and <a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visiting </em><a href="http://stackademic.com"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cbe00c39339b" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/creating-custom-admonitions-in-docusaurus-react-app-cbe00c39339b">Creating Custom Admonitions in Docusaurus React App</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mastering Truncation: A Guide to Implementing Reusable React Component with Text Truncation]]></title>
            <link>https://blog.stackademic.com/mastering-truncation-a-guide-to-implementing-reusable-react-component-with-text-truncation-276bf927ebab?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/276bf927ebab</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[open-source]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[docusaurus]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Mon, 21 Aug 2023 18:39:14 GMT</pubDate>
            <atom:updated>2023-09-10T21:53:44.666Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="React logo" src="https://cdn-images-1.medium.com/max/730/1*CEcpYBx81colOtpMnIV5HA.jpeg" /></figure><p>For t<a href="https://www.linkedin.com/company/climate-tech-handbook/">he Climate Tech Handbook</a>, the open source project that I’ve been contributing to for the last few months, I got to make a reusable react component called <strong>ImageCards</strong> to generate cards in markdown files using<strong> Docusaurus</strong>.</p><p><strong>Docusaurus</strong> is a static site generator like <strong>Nextra.js (</strong>Next. js Static Site Generator framework<strong>) </strong>and it allows content writers to use simple markdown files via softwares like notion but also takes in mdx which allows us to use reusable react components in those files.</p><p>With that, we can generate static sites with react components like below:</p><figure><img alt="Markdown Sector page with solutions listed with reusable react component" src="https://cdn-images-1.medium.com/max/1024/1*rHtMSpblRSLDvR4NIT99jA.png" /></figure><blockquote>Live site <a href="https://www.climatetechhandbook.com/sector-electricity">here</a> <br>Github Repo <a href="https://github.com/climate-tech-handbook/climate-tech-handbook">here</a></blockquote><p>This is not limited to .mdx files but when a component is used multiple times in a single page or across pages, it is hard to keep everything looking nice and clean. For example in the above, cards are used to list climate solutions for each sector. The problem here is that word/ character count for each image’s description varies.</p><p>For the above ImageCards component, I had the below code originally in typescript:</p><pre>import React from &#39;react&#39;<br>import styles from &quot;./ImageCard.module.css&quot;;<br>import clsx from &quot;clsx&quot;;<br>import Link from &quot;@docusaurus/Link&quot;;<br>import { AiOutlineArrowRight } from &#39;react-icons/ai&#39;;<br>import { useHistory } from &#39;react-router-dom&#39;;<br><br>    interface CardProps {<br>        title: string;<br>        description: string;<br>        imageUrl: string;<br>        linkUrl: string;<br>    }<br><br>    const ImageCard: React.FC&lt;CardProps&gt; = ({<br>        title,<br>        description,<br>        imageUrl,<br>        linkUrl,<br>    }) =&gt; {<br><br>    const history = useHistory();<br><br>    const handleClick = () =&gt; {<br>        history.push(linkUrl);<br>      };<br><br>    return (<br>        &lt;div className={clsx(&quot;cardContainer&quot;, styles.cardContainer)} onClick={handleClick}&gt;<br>            &lt;img className={clsx(&quot;img&quot;, styles.cardImg)} src={imageUrl} alt={title} /&gt;<br>            &lt;div className={clsx(&quot;content&quot;, styles.content)}&gt;<br>                &lt;h2&gt;{title}&lt;/h2&gt;<br>                &lt;p&gt;{description}<br>                    &lt;Link<br>                        to={linkUrl}<br>                        className={clsx(<br>                            styles.cardButton,<br>                        )}<br>                    &gt; &lt;AiOutlineArrowRight /&gt;<br>                    &lt;/Link&gt;<br>                &lt;/p&gt;<br>                <br>            &lt;/div&gt;<br>        &lt;/div&gt;<br>    )<br>}<br><br>export default ImageCard </pre><p>In order to make sure that the description fits in the card and doesn’t look like below, we can <strong>truncate </strong>the text.</p><figure><img alt="Test overflowing in the card" src="https://cdn-images-1.medium.com/max/1024/1*uEvnmkx-pedZR6Ynh9Mwcw.png" /></figure><p>First, we need to set the character limit. For this, I started with 100 characters and then adjusted it to 80 to make sure it works with our content.</p><p>After that, I created a variable called <strong>truncatedDescription</strong> and set it to description that gets passed by writers as <strong>props </strong>in markdown files.</p><p>Next step is to check the length of the description and if the length is smaller than the limit set above, we want to show it as is, otherwise, we need to truncate it.</p><p>But we don’t want to cut off description in the middle of a word just because it is over the character limit. We want to add ... to the last word if the description is too long to indicate to the reader that it continues.</p><p>To do so, I created another variable called <strong>lastSpaceIndex </strong>and save the index of the last white space using a method called <strong>.lastIndexOf</strong>.</p><p>If the <strong>lastSpaceIndex </strong>equals to -1, which is the end of the description, we have a complete word right before so we just need to add ... at the end but if it doesn’t, it means at character 80, it is in the middle of a word so we have to go back to the last white space and add ... there instead.</p><p>Here is the code for the above:</p><pre>const characterLimit = 80;<br>    let truncatedDescription = description;<br>    if (truncatedDescription.length &gt; characterLimit) {<br>        const lastSpaceIndex = truncatedDescription.lastIndexOf(&#39; &#39;, characterLimit);<br>        if (lastSpaceIndex !== -1) {<br>            truncatedDescription = truncatedDescription.substring(0, lastSpaceIndex) + &#39;...&#39;;<br>        } else {<br>            truncatedDescription = truncatedDescription.substring(0, characterLimit) + &#39;...&#39;;<br>        }<br>    }</pre><p>Once this is added to the typescript file and the JSX is changed from {description} to {truncatedDescription}, everything should fit perfectly in the image cards like below 🎉</p><figure><img alt="Text fits in the card" src="https://cdn-images-1.medium.com/max/1024/1*6O4kXgKvpJkKLsYbiak2-w.png" /></figure><p><em>Thank you for reading until the end. Please consider following the writer and this publication. Visit </em><a href="https://stackademic.com/"><strong><em>Stackademic</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=276bf927ebab" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/mastering-truncation-a-guide-to-implementing-reusable-react-component-with-text-truncation-276bf927ebab">Mastering Truncation: A Guide to Implementing Reusable React Component with Text Truncation</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[So, Is React Translated Yet?]]></title>
            <link>https://medium.com/@sbasken/so-is-react-translated-yet-e1b4640ffae3?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/e1b4640ffae3</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[translation]]></category>
            <category><![CDATA[localization]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Fri, 09 Jun 2023 23:59:58 GMT</pubDate>
            <atom:updated>2023-06-09T23:59:58.818Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kVfRl8WV1j44yp966EUTgA.jpeg" /></figure><h3><strong>React Conf in 2019</strong></h3><p>I just watched this <a href="https://www.youtube.com/watch?v=lLE4Jqaek5k">video</a> where Nat Alison gave a talk at React Conf back in 2019. I didn’t know this, but it turns out that despite the fact that React has become the most popular front-end library, much of the documentation is still not available in other languages.</p><p>The problem is that there are developers all over the world. They may want to use React or has been using React for work but can’t look up issues or check out their documentations if they don’t speak English.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/710/1*47Y-zMS10EfW6TeCNfbvDw.jpeg" /></figure><h4>What’s Happened Since 2019</h4><p>Since then, a lot of efforts have been made to make the documentation available in different languages. But they faced a lot of issues with integrating translation into their web application.</p><p>Since Nat’s talk at the conference, the reality is that there is still a significant amount of work to be done. (<a href="https://translations.react.dev/">Source</a>)</p><h4>The Good News</h4><p>Recently they started using Github for the project and it seems to be working pretty well. I just tried it myself, and the process was relatively easy.</p><h3>Contributing to Open Source Localization Projects</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*bFJmOrS69VnT66TQCn91Uw.jpeg" /></figure><p>Wether open source or not, I love working on the localization projects because it promotes accessibility by breaking down language barriers.</p><p>Especially in the tech industry, learning how to program can empower so many people including those without traditional education, single-parents, people who had career breaks, and career switchers (like me), to name a few. Having resources available in their own languages means that more people have access, breaking down socio-economic barriers worldwide.</p><p>After watching the video, I had to start contributing to the React project. I just assumed their documentation was available in every language imaginable because, at the end of the day, React is a product of Meta, one of the largest corporations in the world. It is being translated for sure but definitely could use more help. As Nat says in the video, <strong>it is better done than perfect.</strong></p><p>So if you want to contribute to a great cause, go <a href="https://translations.react.dev/">here</a> and click on ‘contribute’ button for your preferred language.</p><p>Contributing to an open source project could also help you:<br>1. Build experience.<br>2. Learn new technologies.<br>3. Familiarize yourself with the workflow of software engineering.<br>4. Help others.<br>5. Keep your Github account active.</p><p>The <strong>React localization project</strong> doesn’t use a translation library. It simply uses <strong>markups</strong> and <strong>Git.</strong> Nothing is dynamically rendered, so it’s straightforward. You can keep your Github account active and certainly learn the Git workflow. The <strong>freeCodeCamp</strong> project uses <strong>Trello</strong> and <strong>Ghost</strong> for articles and <strong>Crowdin</strong> for carriculum. If you translate their articles, they create a profile page for you, allowing you to showcase your work on their page like <a href="https://www.freecodecamp.org/japanese/news/author/saki/">this</a>.</p><p>Let’s get them translated!</p><h4>…A Little Background</h4><p>Before I started coding, I was a translator for 10 years. When I started coding, I joined a localization project to add Japanese to the mobile application for a startup called <a href="https://www.thetuolife.com/">TUO</a>, in preparation for their launch in Japan this fall. I’ve also been contributing to the open source project at freeCodeCamp.org for their <a href="https://www.freecodecamp.org/japanese/news/author/saki/">localization project</a> since March this year.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e1b4640ffae3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unleash the Power of Google Maps in Your React Project: A Step-by-Step Guide]]></title>
            <link>https://medium.com/@sbasken/unleash-the-power-of-google-maps-in-your-react-project-a-step-by-step-guide-81ccf1a95409?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/81ccf1a95409</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[full-stack-developer]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[google-maps]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Thu, 01 Jun 2023 19:50:56 GMT</pubDate>
            <atom:updated>2023-06-16T15:19:57.787Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/644/1*B33GtdDN04VS9Rb3YZX0jQ.jpeg" /></figure><h3><strong>Why Google Maps?</strong></h3><p>Using Google Maps was part of my stretch goals for my capstone project. In fact, it wasn’t really necessary for the core functionalities of my application, which was an expense tracker for properties. However, as humans, we love visual effects. Even blog posts are easier to read when they include pictures, animations, and other elements. So, I knew that adding Google Maps would be a great enhancement to my project. I was also told that implementing Google Maps could be challenging, especially considering we only had three weeks to develop a full-stack web application. But I love challenges, so I decided to give it a try. In the end, it really helped with the forms by providing an Autocomplete feature for address input as well.</p><h3>2 Key Points</h3><p>(And I had to spend days figuring these out on my own)</p><ol><li>Avoid generating longitudes and latitudes every time the page renders. Instead, convert addresses to longitudes and latitudes when new data is created and save them along with other information in the database.<br>(You can see my struggles <a href="https://stackoverflow.com/questions/76195577/showing-markers-on-google-maps-react/76237907#76237907">here</a> when I did try to generate longitudes and latitudes every time the page is loaded. And yes, I answered my own question when I figured it out a couple days later)</li><li>If your map doesn’t get rendered for no apparent reasons, it probably needs to be placed inside a container with defined height and width, as shown below. (I really think this should be a built in feature of Google Maps…)</li></ol><pre>&lt;div style={{width: &#39;80vw&#39;, height: &#39;80vh&#39;, marginTop: &#39;5vh&#39;}}&gt;<br>  &lt;GoogleMap <br>    zoom={10} <br>    center={{lat: 47.6062, lng: -122.3321}} <br>    mapContainerStyle={{ width: &#39;80%&#39;, height: &#39;80%&#39; }}<br>  &gt;<br>      { markers }<br>  &lt;/GoogleMap&gt;<br>&lt;/div&gt;</pre><h3><strong>Where to Begin 🗺️</strong></h3><p>The very first thing to do is to get a <strong>Google API key</strong>. Google provides a great documentation for setting it up and is available <a href="https://developers.google.com/maps/documentation/javascript/get-api-key">here</a>. It even has a video demo so highly recommend checking it out.</p><h3><strong>No Google Cloud Account Yet?</strong></h3><p>If you don’t have a <strong>Google Cloud Platform</strong> account, you can create one <a href="https://cloud.google.com/">here</a>. I found this tutorial <a href="https://www.youtube.com/watch?v=RknlbwbRw_E">video</a> very helpful.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JnXoaXSw-Eu-b-K6zlAG2A.png" /><figcaption>Google Map Showing Property Locations</figcaption></figure><p>For the project, I added Google Maps to show property locations on the property page.</p><h3><strong>Google Maps &amp; React</strong></h3><p>Google provides amazing <strong>tutorial videos</strong> on YouTube and I highly recommend watching these videos before starting or at least coding along with them <a href="https://www.youtube.com/watch?v=9e-5QHpadi0&amp;t=1s">here</a>. It give you step-by-step guide from what to import, what variables can be used from them etc. It also talks about how to <strong>hide your API key</strong> and that was very helpful.</p><p>If you are building a full stack application like me instead of front end application, make sure you have your .env file in the front-end directory instead of the root directory.</p><p>Also, keep in mind that to restrict the key once you deploy your application, you need to pay small fees but otherwise by hiding your key in .env file, you get to enjoy Google Maps for free.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l8bskpi3809U-Rlssm7pyQ.png" /><figcaption>PropertyPage Component with Google Maps</figcaption></figure><p>As I mentioned earlier, I saved longitude and latitude for each address when each property is created and updated using getGeocode and getLatLng from the use-places-autocomplete module. Below is the code for the NewProperty component as an example.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aXlv-afwZNOAzVFVFMjo0g.png" /><figcaption>NewProperty Component</figcaption></figure><p>On submit, I am simply adding that information (longitude and latitude) to the data I obtained from the form using formik.</p><h3>Bonus Features</h3><p>Another thing that was really cool about Google Maps API was Autocomplete from @react-google-maps/api. With Autocomplete, you don’t even need to type the whole address anymore, and you can even search by names of landmarks like Eiffel Tower or Disney Land. You can see the demo video <a href="https://www.linkedin.com/feed/update/urn:li:activity:7066519026444734464/">here</a>!</p><p>I hope this helps with your project — let me know if you have any question!📍📍</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81ccf1a95409" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Full Stack App  Redux Toolkit  Deployment]]></title>
            <link>https://medium.com/@sbasken/full-stack-app-redux-toolkit-deployment-995b6a3baca8?source=rss-f9df6996e355------2</link>
            <guid isPermaLink="false">https://medium.com/p/995b6a3baca8</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[redux]]></category>
            <dc:creator><![CDATA[Sbasken]]></dc:creator>
            <pubDate>Tue, 09 May 2023 21:12:40 GMT</pubDate>
            <atom:updated>2023-05-22T20:57:43.183Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3ni8aHs0ZWOtU0_LklvWNA.png" /><figcaption>Redux Tool Kit</figcaption></figure><h3>State Management Using Redux Tool Kit</h3><p>For the capstone project, implementing state management such as useContext or Redux was a requirement so I decided to go with Redux.</p><p>I’ll cut to the chase.</p><p>I wouldn’t recommend using this for a simple state management such as keeping track of counts, votes, or likes unless you have hundreds of components in your app and different components located in completely different places in the component tree need to access it.</p><p>React’s useState hook is very efficient and so much simpler and easier. I like the idea of being able to access redux state from anywhere without passing it but in each component you would need to import the state, reducer to update the state, and dispatch to call the reducer and it seems like a lot for a simple state management.</p><p>However, for API fetches, it was pretty nice once one was set up. All I had to do was copy and paste, change the names for other tables. I had 6 relational tables for this project and it was definitely a time saver. I can only imagine that it gets easier and easier as you have significantly more tables or APIs to access.</p><p>That being said, I’m glad I decided to use it even though I know there are mix feelings about Redux and I’m not sure if I would use it again unless I have tons of tables or APIs. It took me a while to understand the set up and how this works. Here, I would like to point out a few things I wish I knew so those who are trying to create a full stack web application using react and redux toolkit, and deploy it like me have something to reference as I found it very hard to find resources online.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*QV4fbMC30Aea9J6kRLRnwA.png" /><figcaption>Redux State Management</figcaption></figure><p>I’m building a property management app designed to help property owners keep track of their expenses to make filing taxes a little less stressful and managing properties easier in general. The app is called<strong> Property Panda</strong> and the idea is that the owners can be as lazy as a cute cuddly panda while the app does the work 🐼</p><p>It is live <a href="https://property-panda-app.onrender.com/">here</a>! And Github repo is <a href="https://github.com/sbasken/phase5-project-property-management">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/548/1*d4g8VBcKXVPGPH1WUTxx7A.png" /></figure><p>The above is my file structure for the client side to show where the files for redux are. To use redux, I created two folders inside of src called <strong>app</strong> and <strong>features</strong>. Inside of <strong>app</strong>, I have <strong>services</strong> folder and the <strong>store</strong> file. I am using <strong>services </strong>folder to organize API requests and <strong>features</strong> folder for slices (simple state management.) Ultimately, everything in <strong>services</strong> and <strong>features</strong> will go into the <strong>store</strong> file because <strong>store</strong> becomes the single source of state for this app. As I mentioned earlier that I do not really recommend using redux for simple state management, I won’t go into details about the <strong>features</strong> folder.</p><h3><strong>baseUrl</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o4FTMU4sokuBeTOC6vmF5w.png" /></figure><p>One thing that had to be changed once the API requests were set up using the redux<strong> createApi</strong>and <strong>fetchBaseQuery</strong> from <strong>@reduxjs/toolkit/query/react </strong>was that <em>I had to change the baseUrl to the frontend server Url instead of backend server to fetch.</em></p><p>This was because I was using <strong>proxy</strong> for fetching like below in <strong>package.json</strong>:</p><pre>{<br>  &quot;name&quot;: &quot;phase5-project-property-management&quot;,<br>  &quot;version&quot;: &quot;0.1.0&quot;,<br>  &quot;private&quot;: true,<br>  &quot;proxy&quot;: &quot;http://localhost:5555&quot;,<br>  ...<br>}</pre><p>If you don’t have proxy set up, then you can just use the backend server url like regular react app for fetching. If you are having trouble fetching after setting up the services file, this is a good place to check.</p><p><strong>baseUrl — Deployment</strong></p><p>Another interesting thing was that once it was deployed, I had to change the <strong>baseUrl</strong> to ‘/’ like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RUibfg1HAJcix-XVGXVS9Q.png" /><figcaption>baseUrl changed to ‘/’ after deployment</figcaption></figure><p>For my previous project, I didn’t use Redux and had the server url in proxy and did not have to change it to anything else. However, for some reason, this was the only way I could send requests to server. Leave me a comment to let me know if you know why! I couldn’t find answer anywhere about this and this was the motivation behind writing this blog post because I had to spend sometime to figure this out on my own.</p><h3>tagTypes</h3><p>Another thing I had trouble while implementing <strong>Redux </strong>was updating DOM.<br>So my app structure was that when a user clicks on a property card, that would take them to the units page where thy can view units that belong to the property. Now, usually with useState, I would just fetch in property page, get the property data but since they are relational database, I can get the units information for each property from the property data so I would save it all in a state and pass units info for each property and the setter function to units page and if it gets updated, I’ll just do fetch to the endpoint for units and update the state with the setter.</p><p>At first I did the same with Redux. It was updating the database but the DOM wasn’t getting updated so I had to refresh to see the change.</p><p>As you can see below, there is an attribute called <strong>tagTypes</strong>. What this does is that it creates a tag that you can place on a query method. In this case, I placed a tag on <strong>getProperties </strong>method by adding <strong>providesTags: [‘Property’]</strong>. I also added <strong>invalidatesTags[‘Property] </strong>to <strong>addProperty</strong> method. By placing them, it tells it to run <strong>getProperties </strong>query method again if <strong>addProperty</strong> method is invoked.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ghmtzbCjkKMnsLlkM0TKBQ.png" /><figcaption>propertiesAPI using tagTypes, providesTags, and invalidatesTags</figcaption></figure><p>This is a really cool feature because this file is taking care of state <strong>properties </strong>and just by adding the tag, it automatically re-fetch, re-renders, and updates the DOM accordingly.</p><p>The problem was that because I was passing units that I got from properties API endpoints as props to units page, and was adding, updating, and deleting them via units API, that didn’t trigger the tag to act on properties, therefore, nothing was happening in the units page unless I refresh the page.</p><p>So here is what I did instead.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m9eZWI7qwjSXnOgSHDnHzQ.png" /></figure><p>Instead of passing the units object to Units component, I passed property id using routes and get the property id in question with <strong>useParams </strong>hook from <strong>react-router-dom </strong>and fetch units for a property from units api using its id. To do so, I added another Resource in my backend flask app called UnitsByProperty but that fixed the issue of (non) re-rendering.</p><h3>authAPI</h3><p>I also created a file called <strong>authAPI</strong> in services folder to handle <strong>login</strong>, <strong>logout</strong>, <strong>signup</strong>, and <strong>check</strong> <strong>session</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7dxVJBdhsziAVL1HJbQi1A.png" /></figure><p>It was pretty straight forward after I got a hang of the other API routes. For some reason, check session would not work and the original code without using redux was not that much anyway, I kept the original code for that but others worked fine.</p><p>I would just import the useLoginUserMutation, get the method and use it instead of fetching when a user submits a form. You can then save the data returned from the server and set it to the currentUser.</p><pre>import React from &#39;react&#39;<br>import RingLoader from &#39;react-spinners/RingLoader&#39;;<br>import * as yup from &quot;yup&quot;;<br>import { Grid, Form, Button, Icon } from &#39;semantic-ui-react&#39;<br>import { useFormik } from &quot;formik&quot;;<br>import { useNavigate, Link } from &#39;react-router-dom&#39;;<br>import { useLoginUserMutation } from &#39;../../app/services/authAPI&#39;;<br><br>const Login = ({ setCurrentUser }) =&gt; {<br>  const navigate = useNavigate();<br>  const [ loginUser, { isLoading } ] = useLoginUserMutation();<br><br>  const formSchema = yup.object({<br>      username: yup.string().required(&#39;Field required&#39;),<br>      password: yup.string().required(&#39;Field required&#39;),<br>  });<br><br>  const formik = useFormik({<br>    initialValues: {<br>      username: &quot;&quot;,<br>      password: &quot;&quot;<br>    },<br>    validationSchema: formSchema,<br>    onSubmit: async (values) =&gt; {<br>      if (formik.isValid) {<br>        try {<br>          const { data } = await loginUser(values)<br>          setCurrentUser(data)<br>          navigate(&#39;/&#39;)<br>        } catch (error) {<br>          alert(&#39;Oops, username and password don\&#39;t match&#39;);<br>        }<br>      }<br>    }<br>  });<br><br>  return (<br>    &lt;div&gt;<br>      &lt;RingLoader color={&#39;#F5A623&#39;} loading={isLoading}/&gt;<br>      &lt;div className=&#39;ui container hidden divider&#39;&gt;<br>        &lt;Grid &gt;<br>          &lt;Grid.Column &gt;<br>            &lt;Form onSubmit={formik.handleSubmit}&gt;<br>            &lt;h1&gt;Hi again! Please log in below&lt;/h1&gt;<br>            &lt;br/&gt;<br>              &lt;Form.Field &gt;<br>                &lt;label&gt;Username:&lt;/label&gt;<br>                &lt;Form.Input<br>                  name=&quot;username&quot;<br>                  type=&quot;text&quot;<br>                  placeholder=&quot;Username&quot;<br>                  value={formik.values.username}<br>                  onChange={formik.handleChange}<br>                /&gt;<br>                &lt;p style={{ color: &quot;orange&quot; }}&gt; {formik.errors.username}&lt;/p&gt;<br>              &lt;/Form.Field&gt;<br>              &lt;br/&gt;<br>              &lt;Form.Field&gt;<br>                &lt;label&gt;Password:&lt;/label&gt; <br>                &lt;Form.Input<br>                  name=&quot;password&quot;<br>                  type=&quot;password&quot;<br>                  placeholder=&quot;Password&quot;<br>                  value={formik.values.password} <br>                  onChange={formik.handleChange}<br>                /&gt;<br>                &lt;p style={{ color: &quot;orange&quot; }}&gt; {formik.errors.password}&lt;/p&gt;<br>                &lt;/Form.Field&gt;<br>                &lt;br/&gt;<br>                &lt;Button <br>                  color=&#39;teal&#39;<br>                  className=&#39;ui button&#39; <br>                  type=&#39;submit&#39;&gt;Log In&lt;/Button&gt;<br>                &lt;br/&gt;<br>            &lt;/Form&gt;<br>          &lt;/Grid.Column&gt;<br>        &lt;/Grid&gt;<br>          &lt;h4 style={{textAlign:&#39;center&#39;}}&gt;<br>            &lt;Icon color=&#39;teal&#39; name=&#39;arrow alternate circle right&#39;/&gt;<br>            No a panda yet? Sign up <br>            &lt;Link to=&quot;/signup&quot;&gt;  here  &lt;/Link&gt;<br>            &lt;Icon color=&#39;teal&#39; name=&#39;arrow alternate circle left&#39;/&gt;&lt;/h4&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  )<br>}<br><br>export default Login</pre><p>Nice thing about Redux is that you can de-structure things like <strong>isLoading, isSuccess, isError</strong>, and<strong> error </strong>when you call mutation (for post, patch, and delete) or query (for get) and it works really well with spinners from <strong>react-spinners</strong>. As you can see in the above code, you just pass isLoading to, in my case, &lt;RingLoader /&gt; and it shows itself when isLoading is true but if not, it’ll just hide itself. There are other styles as well <a href="https://www.davidhu.io/react-spinners/">here</a>.</p><p>I hope this helps with your project — Leave a comment if you have any other redux related question!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=995b6a3baca8" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>