<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Serah Nderi</title>
    <description>The latest articles on DEV Community by Serah Nderi (@mundianderi).</description>
    <link>https://dev.to/mundianderi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1069866%2Fa47a1ad1-55e8-4bbe-bd41-dc1175f7d852.jpeg</url>
      <title>DEV Community: Serah Nderi</title>
      <link>https://dev.to/mundianderi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mundianderi"/>
    <language>en</language>
    <item>
      <title>Making Debugging Easier: Stacktrace Support in Logpoints</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Mon, 04 Aug 2025 12:14:29 +0000</pubDate>
      <link>https://dev.to/mundianderi/making-debugging-easier-stacktrace-support-in-logpoints-5o8</link>
      <guid>https://dev.to/mundianderi/making-debugging-easier-stacktrace-support-in-logpoints-5o8</guid>
      <description>&lt;p&gt;After wrapping up my Outreachy Internship and my work with the SpiderMonkey team implementing the &lt;a href="https://spidermonkey.dev/blog/2025/03/05/iterator-range.html" rel="noopener noreferrer"&gt;Iterator.range&lt;/a&gt; among other features, I spent some time contributing to Firefox Developer Tools.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://images.unsplash.com/photo-1657885428171-0e164036a1f5?q=80&amp;amp;w=1724&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" rel="noopener noreferrer"&gt;Photo by Rubaitul Azad on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My task was to implement a checkbox that allows Developers to print a &lt;code&gt;stacktrace&lt;/code&gt; for a &lt;code&gt;logpoint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you’re unfamiliar with &lt;a href="https://firefox-source-docs.mozilla.org/devtools-user/debugger/set_a_logpoint/index.html" rel="noopener noreferrer"&gt;logpoints&lt;/a&gt;, here’s a quick refresher. In the Firefox Debugger, when you click on the gutter next to a line of code, an “Add log” option appears. Clicking it opens an input where you can enter a JavaScript expression. &lt;/p&gt;

&lt;h4&gt;
  
  
  Before
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hcqq1j6ao7zooee6fcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3hcqq1j6ao7zooee6fcc.png" alt="logpoints implementation before a show stacktrace option was added in Firefox" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time that line is executed, the expression is evaluated and its result is printed to the console — similar to using &lt;code&gt;console.log()&lt;/code&gt;, but without modifying your source code. While this is incredibly useful, it can be even more powerful when paired with a stacktrace. By printing the stacktrace along with the result, developers can better understand the context in which a line was executed — helping track down where and why a function was called.&lt;/p&gt;

&lt;p&gt;Adding a Stacktrace option would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;code&gt;Show stacktrace option checkbox&lt;/code&gt; to the logpoint when enabled.&lt;/li&gt;
&lt;li&gt;Show stacktrace information — similar to &lt;code&gt;console.trace()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Requires changes in both the DevTools Server (where the page actually lives) — to retrieve the &lt;code&gt;stacktrace&lt;/code&gt;, and the client component for UI updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  After
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24h2p7gp3j238tjs0loz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24h2p7gp3j238tjs0loz.png" alt="logpoints implementation after a show stacktrace option was added in Firefox" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Implementation
&lt;/h3&gt;

&lt;p&gt;At first, the implementation seemed straightforward — famous last words. The key tasks were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Locate the files to modify.&lt;/li&gt;
&lt;li&gt;Add a checkbox UI element labeled “Show stacktrace”.&lt;/li&gt;
&lt;li&gt;Update component state to track the checkbox state (&lt;code&gt;checked&lt;/code&gt; or &lt;code&gt;unchecked&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Connect that state to the logic that retrieves and displays the &lt;code&gt;stacktrace&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The end-to-end flow looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;showStacktrace&lt;/code&gt; boolean starts from the Conditional Panel UI (the checkbox),&lt;/li&gt;
&lt;li&gt;Passes through the client-side logic,&lt;/li&gt;
&lt;li&gt;Gets sent to the server (with the &lt;code&gt;setBreakpoint&lt;/code&gt; command)&lt;/li&gt;
&lt;li&gt;Is received on the server,&lt;/li&gt;
&lt;li&gt;And is finally used to conditionally trigger &lt;code&gt;logEvent&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges Faced
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Manipulating React State
&lt;/h3&gt;

&lt;p&gt;The Firefox Debugger is built using &lt;code&gt;React&lt;/code&gt;, and in this case, the &lt;code&gt;ConditionalPanel.js&lt;/code&gt; component is implemented as a class component. It utilises the hyperscript functions (&lt;code&gt;div, input, label,&lt;/code&gt; etc.) imported from React DOM factories instead of JSX. This presented a learning curve compared to the functional components and hooks I’m more familiar with. &lt;/p&gt;

&lt;p&gt;Instead of using &lt;code&gt;useState&lt;/code&gt;, I had to work with class instance properties and understand the component lifecycle methods. This not only introduced complexity in managing state but also made the debugging process more nuanced, especially when ensuring state flowed correctly from the UI to the server logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Controlled and Uncontrolled elements
&lt;/h3&gt;

&lt;p&gt;Speaking of state, I experienced a lot of React UI desync problems. The Show Stacktrace UI was being rendered based on outdated props or state due to lifecycle render quirks. While the state was changing correctly, the changes weren’t reflected in the DOM until a later re-render.&lt;/p&gt;

&lt;p&gt;As a result, I spent quite some time reading GitHub issues on the same topic. While they enhanced my understanding on the topic, most of them were not browser-focused and relied heavily on React hooks, which didn’t apply directly to my case.&lt;/p&gt;

&lt;p&gt;However, this &lt;a href="https://github.com/facebook/react/issues/13477" rel="noopener noreferrer"&gt;particular GitHub issue&lt;/a&gt; turned out to be incredibly useful.&lt;/p&gt;

&lt;p&gt;The key was using defaultChecked instead of checked, which makes the checkbox uncontrolled. In our case, we realized we didn’t need to store &lt;code&gt;_showStacktrace&lt;/code&gt; on the component instance. Instead, we could use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defaultChecked: this.props.breakpoint?.options?.showStacktrace

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

&lt;/div&gt;



&lt;p&gt;This allowed us to simplify the component by avoiding internal state and relying on form submission (&lt;code&gt;FormData.get&lt;/code&gt;) to read the final value when needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input({
  type: "checkbox",
  id: "showStacktrace",
  name: "showStacktrace",
  defaultChecked: this.props.breakpoint?.options?.showStacktrace,
}),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The checkbox behavior now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;code&gt;defaultChecked instead&lt;/code&gt; of &lt;code&gt;checked&lt;/code&gt;, so the initial state is set once when the component first renders.&lt;/li&gt;
&lt;li&gt;There’s no &lt;code&gt;onChange&lt;/code&gt; handler to update any component state.&lt;/li&gt;
&lt;li&gt;The value is read from the form data only when the form is submitted via &lt;code&gt;handleFormSubmit&lt;/code&gt;.
After the initial render, the parent component has no way to programmatically change the checkbox state.
When the form is submitted, the code retrieves the checkbox value like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const formData = new FormData(this.panelNode);
const showStacktrace = formData.get("showStacktrace") === "on";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This boolean value is then passed to the &lt;code&gt;saveAndClose&lt;/code&gt; function, which forwards it to &lt;code&gt;setBreakpoint&lt;/code&gt;, fully replacing the use of &lt;code&gt;this._showStacktrace&lt;/code&gt; and aligning better with the form-based approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Checkbox Disappearance onClick in Firefox
&lt;/h3&gt;

&lt;p&gt;Previously, the conditional panel (where you edit logpoints) would close when the logpoint input lost focus (&lt;code&gt;onBlur event&lt;/code&gt;). However, we’re now introducing new UI elements, like checkboxes and buttons, so the panel should remain open during interaction.&lt;/p&gt;

&lt;p&gt;Clicking on the new checkbox triggered the &lt;code&gt;onBlur event&lt;/code&gt; from the input field, which caused the panel to disappear.&lt;/p&gt;

&lt;p&gt;To fix this, my mentor Nicolas suggested using a Firefox-specific event property: &lt;code&gt;e?.explicitOriginalTarget&lt;/code&gt;. I added a check to the &lt;code&gt;onBlur handler&lt;/code&gt; to verify whether the &lt;code&gt;explicitOriginalTarget&lt;/code&gt; is still within the conditional panel. This prevents the panel from closing when users interact with its internal elements, like the checkbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; onBlur = e =&amp;gt; {
   let explicitOriginalTarget = e?.explicitOriginalTarget;
   // The explicit original target can be a text node, in such case retrieve its parent
   // element so we can use `closest` on it.
   if (explicitOriginalTarget &amp;amp;&amp;amp; !Element.isInstance(explicitOriginalTarget)) {
     explicitOriginalTarget = explicitOriginalTarget.parentElement;
   }

   if (
     // if there is no event
     // or if the focus is the conditional panel
     // do not close the conditional panel
     !e ||
     (explicitOriginalTarget &amp;amp;&amp;amp;
       explicitOriginalTarget.closest(
         ".conditional-breakpoint-panel-container"
       ))
   ) {
     return;
   }

   this.props.closeConditionalPanel();
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing the Implementation: Mochitests
&lt;/h3&gt;

&lt;p&gt;After completing the implementation, I needed to verify that everything worked as expected, and make sure that we do get the stacktrace. For Firefox, this means writing Mochitests, Mozilla’s testing framework that allows us to simulate user interactions and verify expected behaviors.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Internship to Contribution
&lt;/h3&gt;

&lt;p&gt;Contributing to Firefox DevTools has felt like a natural next step after my internship, building on the foundations I laid while working on Iterator.range with the SpiderMonkey team. The experience working on Iterator.range provided a solid foundation, but DevTools presented its own unique challenges and opportunities for growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact for Developers
&lt;/h3&gt;

&lt;p&gt;This small enhancement to logpoints makes a significant difference for developers debugging complex applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context Awareness: Stacktraces provide immediate context about how execution reached a particular point&lt;/li&gt;
&lt;li&gt;Debugging Efficiency: Developers can now get the information they need without switching between tools&lt;/li&gt;
&lt;li&gt;Optional Verbosity: The checkbox allows developers to control information density based on their current needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contributing to Firefox
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For anyone interested in contributing to Firefox DevTools, my experience suggests:&lt;/li&gt;
&lt;li&gt;Start Small: Focus on well-defined features or bug fixes to understand the codebase.&lt;/li&gt;
&lt;li&gt;Ask Questions: The Firefox development community is supportive and responsive.&lt;/li&gt;
&lt;li&gt;Test Thoroughly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Helpful links to get started:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;DevTools contribution opportunities - There's a lot of &lt;a href="https://codetribute.mozilla.org/projects/devtools" rel="noopener noreferrer"&gt;good first issues for developers&lt;/a&gt; who are new to Firefox.&lt;/li&gt;
&lt;li&gt;Join the &lt;a href="https://chat.mozilla.org/#/room/#devtools:mozilla.org" rel="noopener noreferrer"&gt;DevTools chat on Matrix&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m grateful for the guidance provided by my mentor Nicolas throughout this process. His feedback and support was instrumental in bringing this feature to completion.&lt;/p&gt;

&lt;p&gt;You may also like:&lt;br&gt;
&lt;a href="https://spidermonkey.dev/blog/2025/03/05/iterator-range.html" rel="noopener noreferrer"&gt;Implementing Iterator.range in SpiderMonkey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4"&gt;Decoding Open Source: Vocabulary I’ve Learned on My Outreachy Journey&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>browser</category>
    </item>
    <item>
      <title>Exploring Career Opportunities in Open Source &amp; Data Science</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Mon, 17 Feb 2025 08:21:11 +0000</pubDate>
      <link>https://dev.to/mundianderi/exploring-career-opportunities-in-open-source-data-science-2ko1</link>
      <guid>https://dev.to/mundianderi/exploring-career-opportunities-in-open-source-data-science-2ko1</guid>
      <description>&lt;h2&gt;
  
  
  Career Reflections: What's Next After Outreachy?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyxogb5ymtlu9y0xr2vd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyxogb5ymtlu9y0xr2vd.jpg" alt="Photo by Christina @ wocintechchat.com on Unsplash" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In September 2022, I joined ALX to learn programming and work on my programming knowledge. As a Manual Quality Assurance Engineer, my goal was to learn enough programming to automate repetitive tasks, such as regression testing, and eventually transition into an Automated QA Engineer role. Over time, my interests expanded to software development, leading me to seek further learning opportunities&lt;/p&gt;

&lt;p&gt;Previously, I had always wanted to study Data Analysis and Data Science, and sought out to Datacamp to learn python and data analysis. As an Economics and Statistics graduate, this was a full circle moment for me - using data and leveraging my undergraduate degree. However, I quickly discovered that I was lacking in simple skills such as Git and that I could benefit from structured learning, deadlines, and learning the basics which led me to ALX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining My Career Goals
&lt;/h2&gt;

&lt;p&gt;My career journey has evolved into something far greater than I initially envisioned. Transitioning from Quality Assurance to Software Development, I have actively contributed to Open Source projects, participated in Outreachy, and contributed to organizations like Ushahidi, Humanitarian OpenStreetMap Team (HOTOSM), and Mozilla.&lt;/p&gt;

&lt;p&gt;As a Mozilla Outreachy intern, I had the opportunity to work on TC39 proposals in SpiderMonkey - the JavaScript engine powering the Firefox browser.&lt;/p&gt;

&lt;p&gt;I implemented the &lt;code&gt;Error.isError&lt;/code&gt; and &lt;code&gt;Range&lt;/code&gt; proposals, collaborating with incredible mentors and gaining exposure to a development ecosystem far different from my previous experience in eCommerce. Through this work, I have not only deepened my understanding of JavaScript internals but also actively contributed to shaping the future of the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Skills &amp;amp; Tools
&lt;/h2&gt;

&lt;p&gt;My role at Mozilla required strong knowledge of JavaScript and Git, and while C++ was preferred, I was fortunate to already possess the skills necessary to contribute effectively to a production-level codebase.&lt;/p&gt;

&lt;p&gt;Skills &amp;amp; Expertise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript:&lt;/strong&gt; Deep understanding of JS fundamentals and advanced concepts. Experience with working on TC39 proposals in SpiderMonkey and contributing to open-source projects.
-** Tailwind CSS:** Expertise in building responsive, scalable UIs using utility-first CSS frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React.js:&lt;/strong&gt; Proficient in building dynamic, single-page applications, with a focus on component-based architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test262 Tests:&lt;/strong&gt; I wrote and contributed to Test262 tests for SpiderMonkey, the JavaScript engine behind Firefox, to validate the correct implementation of proposals like &lt;code&gt;Error.isError&lt;/code&gt; and &lt;code&gt;Iterator.range&lt;/code&gt;. Test262 is a test suite designed to ensure that JavaScript engines correctly implement ECMAScript standards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software Testing:&lt;/strong&gt; Skilled in White, Gray, and Black Box Testing and API testing with Postman.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Languages &amp;amp; Communication:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;English:&lt;/strong&gt; Native proficiency, with excellent verbal and written communication skills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kiswahili:&lt;/strong&gt; Native proficiency, enabling effective communication in both formal and informal settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;German:&lt;/strong&gt; Intermediate proficiency (B1 level), certified by the Goethe Institute Nairobi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting a Datacamp Scholarship
&lt;/h2&gt;

&lt;p&gt;I was awarded a one-year DataCamp scholarship to further develop my data skills. Over the next year, I plan to focus on enhancing my SQL, database management, Python, and data analysis capabilities.&lt;/p&gt;

&lt;p&gt;This opportunity feels like a full-circle moment, as my programming journey began with DataCamp. This time, I'm equipped with the programming skills needed to truly understand and make the most of the coursework.&lt;/p&gt;




&lt;h2&gt;
  
  
  Opportunities that I'm Looking forward to
&lt;/h2&gt;

&lt;p&gt;I'm eager to contribute to frontend development projects, especially those with a strong connection to data and data analysis. I'm particularly interested in roles that allow me to grow my skills while making meaningful contributions.&lt;/p&gt;

&lt;p&gt;Roles of Interest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full-time or part-time Frontend Development positions&lt;/li&gt;
&lt;li&gt;Paid internships that allow me to contribute while gaining valuable experience&lt;/li&gt;
&lt;li&gt;Open-source opportunities where I can collaborate and make meaningful contributions.&lt;/li&gt;
&lt;li&gt;Open source opportunities in the data analysis and data science space.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Availability
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I will be available for new opportunities starting March 2025, after my Mozilla internship concludes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flexibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I am open to remote or hybrid software development roles.&lt;/li&gt;
&lt;li&gt;I am willing to relocate for positions, particularly within the DACH region.&lt;/li&gt;
&lt;li&gt;Additionally, I am available for contract or consultant roles.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you're working on any projects or know of opportunities that align with my interests, or believe they could, I'd love to hear from you! Feel free to connect with me on &lt;a href="https://www.linkedin.com/in/serah-nderi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://x.com/nderisarah" rel="noopener noreferrer"&gt;X (formerly Twitter)&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  You may also like:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/navigating-tc39-proposals-from-error-handling-to-iteratorrange-306a"&gt;Navigating TC39 Proposals: From Error Handling to Iterator.range&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/mundianderi/mid-internship-progress-report-achievements-and-goals-ahead-4jif"&gt;Mid-Internship Progress Report: Achievements and Goals Ahead&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Mid-Internship Progress Report: Achievements and Goals Ahead</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Fri, 07 Feb 2025 12:12:10 +0000</pubDate>
      <link>https://dev.to/mundianderi/mid-internship-progress-report-achievements-and-goals-ahead-4jif</link>
      <guid>https://dev.to/mundianderi/mid-internship-progress-report-achievements-and-goals-ahead-4jif</guid>
      <description>&lt;h2&gt;
  
  
  What's Done, What's Changed, and What's Next
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjs6xsd4ulx13gajb8do.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjs6xsd4ulx13gajb8do.jpg" alt="Photo by Lauren Mancke on Unsplash" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/mundianderi/navigating-tc39-proposals-from-error-handling-to-iteratorrange-306a"&gt;last post&lt;/a&gt; I went in depth on my work at Mozilla, specifically my implementation of TC39 proposals and my current work on the &lt;a href="https://github.com/tc39/proposal-iterator.range/issues/74" rel="noopener noreferrer"&gt;Range Proposal&lt;/a&gt;. What was remaining was setting up &lt;code&gt;BigInt&lt;/code&gt;support and setting a proper Prototype for the iterator returned by &lt;code&gt;Iterator.range&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My implementation followed the specification, ie - create a separate prototype that inherits from the iterator, along with the necessary implementations for &lt;code&gt;toString&lt;/code&gt; and &lt;code&gt;next&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Initially, I had an &lt;code&gt;IteratorRangeGenerator*&lt;/code&gt; function (ie, step 18 of the Range proposal), that when called doesn't execute immediately, but returns a generator object which follows the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol" rel="noopener noreferrer"&gt;iterator protocol&lt;/a&gt;. Inside the generator function you have &lt;code&gt;yield&lt;/code&gt; statements which represents where the function suspends its execution and provides value back to the caller.&lt;/p&gt;

&lt;p&gt;The generator will pause at each &lt;code&gt;yield&lt;/code&gt;, and will not continue until the next method is called on the generator object that is created.&lt;br&gt;
The &lt;code&gt;NumericRangeIteratorPrototype&lt;/code&gt; is the object that holds the iterator prototype for the Numeric range iterator.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;next()&lt;/code&gt; method is added to the &lt;code&gt;NumericRangeIteratorPrototype&lt;/code&gt;, when you call the &lt;code&gt;next()&lt;/code&gt; method on an object created from &lt;code&gt;NumericRangeIteratorPrototype&lt;/code&gt;, it doesn't directly return a value, but it makes the generator yield the next value in the series, effectively resuming the suspended generator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first time you invoke &lt;code&gt;next()&lt;/code&gt; on the generator object created via &lt;code&gt;IteratorRangeGenerator&lt;/code&gt;, the generator will run up to the first &lt;code&gt;yield&lt;/code&gt; statement and return the first value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you invoke &lt;code&gt;next()&lt;/code&gt; again, the &lt;code&gt;NumericRangeIteratorNext()&lt;/code&gt; will be called. This method uses &lt;code&gt;GeneratorResume(this)&lt;/code&gt;, which means the generator will pick up right where it left off, continuing to iterate the next yield statement or until iteration ends.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Generator Alternative
&lt;/h3&gt;

&lt;p&gt;After discussions with my mentors, I transitioned from a generator-based implementation to a more efficient slot-based approach. This change involved defining slots to store the state necessary for computing the next value. The reasons included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency:&lt;/strong&gt; Directly managing iteration state is faster than relying on generator functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Implementation:&lt;/strong&gt; A slot-based approach eliminates the need for generator-specific handling, making the code more maintainable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Alignment with Other Iterators:&lt;/strong&gt; Existing built-in iterators such as &lt;code&gt;StringIteratorPrototype&lt;/code&gt; and &lt;code&gt;ArrayIteratorPrototype&lt;/code&gt; do not use generators in their implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Final Implementation
&lt;/h3&gt;

&lt;p&gt;The final approach stores state in reserved slots rather than relying on generator suspension. This change better fits SpiderMonkey's Iterator architecture and aligns with other built-in iterators such as &lt;code&gt;StringIteratorPrototype&lt;/code&gt; and &lt;code&gt;ArrayIteratorPrototype&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By moving away from generators, the implementation now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operates purely on numbers without additional complexity.&lt;/li&gt;
&lt;li&gt;Avoids cleanup operations, simplifying state management.&lt;/li&gt;
&lt;li&gt;Uses a dedicated prototype, ensuring consistency with other iterators.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Adding BigInt Support
&lt;/h3&gt;

&lt;p&gt;Implementing &lt;code&gt;BigInt&lt;/code&gt; support was straightforward from a specification perspective, but I encountered two blockers:&lt;br&gt;
&lt;strong&gt;1. Handling Infinity Checks Correctly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The specification ensures that start is either a &lt;code&gt;Number&lt;/code&gt; or a &lt;code&gt;BigInt&lt;/code&gt; in steps 3.a and 4.a. However, step 5 states:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;If start is +∞ or -∞, throw a RangeError.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Despite following this, my implementation still threw an error stating that start must be finite. After investigating, I found that the issue stemmed from using a self-hosted &lt;code&gt;isFinite&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The specification requires &lt;code&gt;isFinite&lt;/code&gt; to throw a &lt;code&gt;TypeError&lt;/code&gt; for BigInt, but the self-hosted &lt;code&gt;Number_isFinite&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt; instead. This turned out to be more of an implementation issue than a specification issue.&lt;/p&gt;

&lt;p&gt;See Github discussion &lt;a href="https://github.com/tc39/proposal-iterator.range/issues/74" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Fix: Explicitly check that start is a number before calling isFinite:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Step 5: If start is +∞ or -∞, throw a RangeError.
if (typeof start === 'number' &amp;amp;&amp;amp; !Number_isFinite(start)) {
  ThrowRangeError(JSMSG_ITERATOR_RANGE_START_INFINITY);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After making this adjustment, the implementation correctly handled infinite values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Floating Point Precision Errors&lt;/strong&gt;&lt;br&gt;
When testing floating-point sequences, I encountered an issue where some decimal values were not represented exactly due to JavaScript's floating-point precision limitations. This caused incorrect test results.&lt;/p&gt;

&lt;p&gt;There's a &lt;a href="https://github.com/tc39/proposal-iterator.range/issues/64#issuecomment-1477257423" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt; discussing this in depth. I implemented an approximatelyEqual function to compare values within a small margin of error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix: Using approximatelyEqual in tests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const resultFloat2 = Array.from(Iterator.range(0, 1, 0.2));
approximatelyEqual(resultFloat2, [0, 0.2, 0.4, 0.6, 0.8]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function ensures that minor precision errors do not cause test failures, improving floating-point range calculations.&lt;/p&gt;




&lt;p&gt;This project has been an incredible learning experience, allowing me to deep-dive into SpiderMonkey's internals and improve my understanding of TC39 proposals. I'm excited to continue refining this work and collaborating with the team to ensure an optimal implementation for Iterator.range.&lt;/p&gt;

&lt;p&gt;Stay tuned for further updates!&lt;/p&gt;

&lt;h3&gt;
  
  
  You may also like:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/navigating-tc39-proposals-from-error-handling-to-iteratorrange-306a"&gt;Navigating TC39 Proposals: From Error Handling to Iterator.range&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4"&gt;Decoding Open Source: Vocabulary I've Learned on My Outreachy Journey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/want-a-remote-internship-working-on-free-software-47mm"&gt;Want a Remote Internship Working on Free Software?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tc39</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Navigating TC39 Proposals: From Error Handling to Iterator.range</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Wed, 08 Jan 2025 18:06:27 +0000</pubDate>
      <link>https://dev.to/mundianderi/navigating-tc39-proposals-from-error-handling-to-iteratorrange-306a</link>
      <guid>https://dev.to/mundianderi/navigating-tc39-proposals-from-error-handling-to-iteratorrange-306a</guid>
      <description>&lt;h3&gt;
  
  
  A Intern's Journey Through SpiderMonkey and JavaScript Engine Enhancements
&lt;/h3&gt;

&lt;p&gt;The first time I saw the &lt;code&gt;Iterator.range&lt;/code&gt; proposal and the algorithms inside I wasn't sure that I'd be able to hack it. As an Outreachy contributor, I and other contributors would contribute for a month, and then one intern would get chosen to work on the proposal/specification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfes1541vssqr725bdif.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfes1541vssqr725bdif.jpg" alt="A woman in front of a workspace - Photo by ThisisEngineering on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preamble
&lt;/h2&gt;

&lt;p&gt;A couple of days into the contribution period, I was assigned tasks designated to Outreachy contributors, but most importantly, I was assigned the &lt;a href="https://tc39.es/proposal-is-error/#sec-fundamental-objects" rel="noopener noreferrer"&gt;ErrorIsError TC39 proposal&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The first step to implementing a TC39 proposal in SpiderMonkey (Mozilla JavaScript Engine) is to add a preference for it.&lt;br&gt;
 &lt;br&gt;
This allows for the feature to be enabled or disabled at runtime, which is important, because we don't want to enable a feature by default until we've tested it enough to be confident that it won't cause problems for our users. In this case, we create a preference and set the value to false.&lt;/p&gt;

&lt;p&gt;As you can see, when implemented with JavaScript, &lt;a href="https://tc39.es/proposal-is-error/#sec-fundamental-objects" rel="noopener noreferrer"&gt;the proposal&lt;/a&gt; is quite straightforward and was the initial implementation. However, code review came back and it was better to implement the proposal as a native C++ function which was a learning process for me, both in terms of the reason and working with C++.&lt;/p&gt;

&lt;p&gt;During the process, we encountered some interesting challenges involving cross-compartment wrappers (CCWs) and intrinsic type checks in JavaScript engines. &lt;/p&gt;




&lt;h2&gt;
  
  
  The Issue with Cross-Compartment Wrappers and ErrorObject Checks
&lt;/h2&gt;

&lt;p&gt;When handling Error objects , the &lt;code&gt;IsErrorObject&lt;/code&gt; function determines if a given value is an instance of the &lt;code&gt;ErrorObject&lt;/code&gt; type. However, a critical edge case arises when the argument is a cross-compartment wrapper (CCW) for an &lt;code&gt;ErrorObject&lt;/code&gt; from another compartment. The &lt;code&gt;IsErrorObject&lt;/code&gt; check does not account for CCWs directly, as they obscure the underlying object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Context:&lt;/strong&gt; In the &lt;a href="https://searchfox.org/mozilla-central/rev/754074e05178e017ef6c3d8e30428ffa8f1b794d/js/src/vm/SelfHosting.cpp#266-269,273" rel="noopener noreferrer"&gt;code handling intrinsic type checks&lt;/a&gt;, the &lt;code&gt;intrinsic_IsInstanceOfBuiltin&lt;/code&gt; function is used to check if an object is of a specific type. While it works when applied to the &lt;code&gt;this&lt;/code&gt; value; assuming it's already unwrapped; it doesn't handle arguments that might still be wrapped by CCWs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Proposed Solution: A Dedicated Native Function
&lt;/h2&gt;

&lt;p&gt;To address this issue, the solution involves:&lt;br&gt;
&lt;strong&gt;1. Adding a new native function:&lt;/strong&gt; A dedicated native function is created to handle CCWs transparently by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unwrapping CCWs.&lt;/li&gt;
&lt;li&gt;Testing if the unwrapped object is of type &lt;code&gt;ErrorObject&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Verifying the object type in one cohesive operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Removing Self-Hosted Complexity:&lt;/strong&gt;&lt;br&gt;
By implementing this new function as JSNative, we can streamline the process, performing all operations within a single native function without relying on self-hosted helpers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Handles Non-Object Cases:&lt;/strong&gt; The new function integrates checks for whether the value is even an object before proceeding to unwrap it.&lt;br&gt;
&lt;strong&gt;Simplifies Specification Alignment:&lt;/strong&gt; Since CCWs are an implementation detail and not part of the TC39 JavaScript specification, these changes ensure behavior aligns with the spec while avoiding discrepancies.&lt;/p&gt;




&lt;p&gt;The above consisted of 45 lines of code, excluding two test files: one for JIT (Just-In-Time) compiled tests and another for Test262 tests/files. However, through those 45 lines of code, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn where predefined error messages are within the Mozilla codebase and how to use them. This proved handy when I needed to define error messages for Iterator.range.&lt;/li&gt;
&lt;li&gt;Understand &lt;a href="https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4"&gt;nightly and nightly builds&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Code consistency: Tailor my code to meet TC39 specifications and avoid shorthand for newly added code as per Mozilla standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm Currently Working On: Iterator.range
&lt;/h2&gt;

&lt;p&gt;After diving into the complexities of cross-compartment wrappers and enhancing &lt;code&gt;ErrorObject&lt;/code&gt; handling during my Outreachy contribution period, I turned my attention to something equally exciting: the &lt;a href="https://tc39.es/proposal-iterator.range/#sec-control-abstraction-objects" rel="noopener noreferrer"&gt;Iterator.range proposal&lt;/a&gt; for my Mozilla Outreachy Internship.&lt;/p&gt;

&lt;p&gt;For those unfamiliar, Iterator.range is an addition to the TC39 proposals for JavaScript, aimed at making iterators more versatile. This method introduces an efficient way to generate ranges of values, which can be particularly useful in everyday programming, such as iterating over a sequence of numbers or creating step-based loops.&lt;br&gt;
The concept itself might seem simple; generate a series of values from a start point to an end point, but implementing it in SpiderMonkey is proving to be an excellent challenge. &lt;/p&gt;

&lt;p&gt;Unlike the previous ErrorObject work, which involved handling abstract operations and native C++ functions, Iterator.range requires a deep dive into how JavaScript iterators work internally and how SpiderMonkey integrates these features at the engine level.&lt;/p&gt;

&lt;p&gt;When I started working on Iterator.range, the initial implementation - similar to what I had done for ErrorIsError proposal had been done, ie; adding a preference for the proposal and making the builtin accessible in the JavaScript shell.&lt;/p&gt;

&lt;p&gt;The Iterator.range simply returned false, a stub indicating that the actual implementation of Iterator.range was under development or not fully implemented, which is where I came in.&lt;/p&gt;

&lt;p&gt;As a start, I created a &lt;code&gt;CreateNumericRangeIterator&lt;/code&gt; function that delegates to the &lt;code&gt;Iterator.range&lt;/code&gt; function. Following that, I implemented the &lt;a href="https://tc39.es/proposal-iterator.range/#sec-iterator.range" rel="noopener noreferrer"&gt;first three steps&lt;/a&gt; within the Iterator.range function.&lt;br&gt;
Next, I initialised variables and parameters for the &lt;code&gt;NUMBER-RANGE&lt;/code&gt; data type in the &lt;code&gt;CreateNumericRangeIteratorfunction&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I focused on implementing sequences that increase by one, such as Iterator.range(0, 10). I also updated the &lt;code&gt;CreateNumericRangeIterator&lt;/code&gt; function to invoke &lt;code&gt;IteratorRangeGenerator&lt;/code&gt; (which handles step 18 of the Range Proposal specification) with the appropriate arguments, aligning with Step 19 of the specification, and added tests to verify its functionality.&lt;br&gt;
This week, I am exploring how to properly set the prototype for generators returned by &lt;code&gt;Iterator.range&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;My work for the next couple of weeks/months includes, but is not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set proper prototype for generator returned by Iterator.range.&lt;/li&gt;
&lt;li&gt;Support BigInt in Iterator.range.&lt;/li&gt;
&lt;li&gt;Support other sequences, as I have only covered sequences that increase by one for now.&lt;/li&gt;
&lt;li&gt;Add adequate tests for the above.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  You may also like:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4"&gt;Decoding Open Source: Vocabulary I've Learned on My Outreachy Journey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mundianderi/want-a-remote-internship-working-on-free-software-47mm"&gt;Want a Remote Internship Working on Free Software?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>shell</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Decoding Open Source: Vocabulary I've Learned on My Outreachy Journey</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Thu, 19 Dec 2024 12:46:40 +0000</pubDate>
      <link>https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4</link>
      <guid>https://dev.to/mundianderi/decoding-open-source-vocabulary-ive-learned-on-my-outreachy-journey-34o4</guid>
      <description>&lt;h2&gt;
  
  
  Speaking the Language of Open Source: Week 2 Reflections
&lt;/h2&gt;

&lt;p&gt;When I first joined Outreachy as a Mozilla contributor, I quickly realized that diving into the world of open source meant immersing myself in a whole new language. Phrases, tools, and acronyms that had been unfamiliar to me just months ago became integral to my daily work. &lt;/p&gt;

&lt;p&gt;This week, I'm reflecting on some of the most impactful vocabulary terms I've encountered along the way and what they've taught me about Mozilla and open source development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqq5l62pe388k4xs8nno1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqq5l62pe388k4xs8nno1.png" alt="Women looking at code. Photo by ThisisEngineering on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mercurial and Git Cinnabar
&lt;/h2&gt;

&lt;p&gt;I had heard of Mercurial before as an alternative to Git, but I had never used it. To make the transition smoother for contributors familiar with Git, Mozilla provided Git Cinnabar, a bridge tool that lets developers work with Mercurial repositories using Git commands. This small setup process opened the door to working seamlessly with Mozilla's upstream branches without abandoning my Git knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phabricator
&lt;/h2&gt;

&lt;p&gt;Phabricator was a revelation. Unlike GitHub, its interface and tools feel tailored to fostering deeper collaboration and feedback on code. Its inline commenting system, in particular, stood out for how naturally it integrates into review workflows. It's more than a code host - it's a communication hub for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bugzilla
&lt;/h2&gt;

&lt;p&gt;Bugzilla is where all of Mozilla's issues are filed and tracked. While I'd heard of Bugzilla from users needing to report problems with Firefox, using it as a developer felt different. It became my roadmap and task manager, where bugs transitioned from abstract concepts to actionable work items.&lt;/p&gt;

&lt;h2&gt;
  
  
  Landed/Landing an Issue
&lt;/h2&gt;

&lt;p&gt;I learned that Mozilla developers say an issue has 'landed' when it's been approved to be merged into the codebase. There's no more back-and-forth on reviews, and it marks a tangible accomplishment. For an intern, there's an incredible sense of achievement when your code has 'landed'.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searchfox
&lt;/h2&gt;

&lt;p&gt;Searchfox has been an invaluable tool during my Outreachy internship. When tasked with implementing features similar to existing ones or reusing predefined error messages or functions, my mentor often provides Searchfox links that take me directly to the relevant lines of code.&lt;/p&gt;

&lt;p&gt;This powerful tool streamlines the process of navigating Mozilla's expansive codebase by delivering precise and relevant search results. It has been great in helping me efficiently explore and understand complex sections of the codebase, making development tasks far more manageable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nightly and Nightly Builds
&lt;/h2&gt;

&lt;p&gt;The term "Nightly" refers to Mozilla's development channel, where experimental features and early-stage implementations are tested. During my contributor period, I became familiar with the concept of "Nightly Builds," which are essential for testing work in progress, particularly for features still under active development. &lt;/p&gt;

&lt;p&gt;My first interaction with this was working on a TC39 JavaScript proposal. I had to ensure the feature I was contributing was enclosed within a nightly build, using the #ifdef NIGHTLY_BUILD directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#ifdef NIGHTLY_BUILD
/*
* Code between the nightly
*/
#endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Free and Open Source Software (FOSS)
&lt;/h2&gt;

&lt;p&gt;Before starting my Open Source journey, I wasn't aware of the FOSS acronym.&lt;br&gt;
Understanding FOSS goes beyond software; it's about embracing a philosophy. Open source isn't just about freely available code - it's about collaboration, shared learning, and the belief that innovation thrives in openness.&lt;/p&gt;




&lt;p&gt;This journey as an Outreachy intern at Mozilla is a whirlwind of learning and growth. Each new tool, term, and concept has not only expanded my technical vocabulary but also deepened my understanding of what open source truly represents.&lt;/p&gt;

&lt;p&gt;Every "landed" issue and each successfully implemented feature serves as a reminder that learning is iterative - progress builds one commit, one review, and one build at a time. For me, open source is no longer just a concept; it's a space where I continue to challenge myself, contribute, and grow.&lt;/p&gt;

&lt;p&gt;For anyone considering stepping into the world of FOSS, know this: you won't just learn tools or frameworks - you'll learn how to be part of something bigger.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>programming</category>
      <category>outreachy</category>
    </item>
    <item>
      <title>Want a Remote Internship Working on Free Software?</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Tue, 10 Dec 2024 07:30:41 +0000</pubDate>
      <link>https://dev.to/mundianderi/want-a-remote-internship-working-on-free-software-47mm</link>
      <guid>https://dev.to/mundianderi/want-a-remote-internship-working-on-free-software-47mm</guid>
      <description>&lt;h2&gt;
  
  
  Read my blog post on how I got an @outreachy internship with Mozilla Firefox
&lt;/h2&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3sowrwiey4ubrou1kb7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3sowrwiey4ubrou1kb7.jpg" alt="Woman coding: Photo by ThisisEngineering on Unsplash&amp;lt;br&amp;gt;
" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first time I applied to Outreachy was this year, for the May internship around, although I didn't make it past the contributor round, I was priviledged to work on great projects on accessibility and localization. &lt;/p&gt;

&lt;p&gt;In particular, I worked on interpreting a Deutsch Transifex glossary from English to German. This was fun because I recently learned German in 2023 and 2024 and I'm currently at the B1 level, so it was exciting to use the language at a professional level.&lt;/p&gt;

&lt;p&gt;The second time I applied to Outreachy was this year July/August thereabout, for the October Contributor period and subsequently for the December through March 2025 Internship round. I got chosen for the Contributor stage and later on got accepted for the internship  as a Mozilla Firefox Intern working on their JavaScript engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwogh0hvv6c8029qcze6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwogh0hvv6c8029qcze6f.png" alt="Outreachy acceptance email: image source: courtesy of the author." width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contributor Stage
&lt;/h2&gt;

&lt;p&gt;The contributor stage is a month long open source contribution period, where you choose two projects from different firms to work with and contribute to. &lt;/p&gt;

&lt;p&gt;The projects usually have a list of required, preferred, nice to have skills that one must have in order to successfully contribute to the projects and stand a chance to be accepted as an intern. Projects range from Accessibility, Localisation, Frontend, Backend, Shell, Devops, Marketing, Design, Data and Geospatial Analysis. &lt;br&gt;
You don't necessarily have to know how to code to be an Outreachy Intern as the projects and firms are diverse and vary from each internship round. &lt;/p&gt;

&lt;p&gt;The projects that I chose require development and engineering knowledge and I was lucky to be chosen by my first choice which was Mozilla Firefox. Mozilla was my first choice because the issues were broken down into good first issues issues  which made it easy to find files, functions etc in the codebase and start contributing which was pretty neat.&lt;/p&gt;

&lt;p&gt;Also Mozilla is a notable firm to contribute to. The mentors Daniel and Arai, were very helpful and were quick in giving feedback. They were also very accessible and reachable through out the contribution stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributor Stage Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Are your issues merged?&lt;/strong&gt;:
Aim to have at least four issues merged into the codebase. Outreachy organizers look at your contributions during the final application, so document your progress carefully. If you are working on non-development tasks, ask your mentor what this looks like for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask Detailed Questions&lt;/strong&gt;:
When stuck, ask detailed questions, e.g., "I encountered this bug while doing XYZ. Here's what I tried and what didn't work. How can I proceed?" This demonstrates initiative and problem-solving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Efficient&lt;/strong&gt;:
The contributor stage can be competitive. Prioritize tasks, engage with mentors, and ensure you are consistently making progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apart from working on a couple of bugs during my contributor stage, I worked on the &lt;a href="https://tc39.es/proposal-is-error/#sec-iserror" rel="noopener noreferrer"&gt;ErrorIsError TC39&lt;/a&gt; proposal which was a full feature complete with tests. It tested me for a moment but it also helped me understand the codebase and find things, pre-defined error messages etc. I also got to work with C++ on a production level codebase which was fun.&lt;/p&gt;




&lt;p&gt;During the contributor period, I kept a diary on my &lt;a href="https://serahnderi.substack.com/publish/home" rel="noopener noreferrer"&gt;substack open source newsletter&lt;/a&gt; of the experience, highs, lows, blockers and how I resolved them. You can access it &lt;a href="https://serahnderi.substack.com/publish/home" rel="noopener noreferrer"&gt;here&lt;/a&gt; to see what mind space I was in at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1 Status Report
&lt;/h2&gt;

&lt;p&gt;I just started my Internship as of 9th December 2024. Apart from these blog posts, I will continue writing my weekly diary reports on my Substack should anyone fancy reading that or following along my journey. I anticipate to post a lot after the holidays or from January 2025.&lt;/p&gt;

&lt;p&gt;I spoke with my mentors last week and have a few issues assigned to me from last week Thursday thereabout that I have already started on. We'll have more detailed reports and blog posts as the weeks go by.&lt;/p&gt;




&lt;p&gt;Until the next report, bye.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>internship</category>
      <category>javascript</category>
      <category>outreachy</category>
    </item>
    <item>
      <title>How to Connect a Private Windows EC2 Instance to VPC Resources via S3 Gateway Endpoint</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Sun, 07 Jul 2024 21:01:07 +0000</pubDate>
      <link>https://dev.to/mundianderi/connecting-a-private-windows-ec2-instance-to-vpc-resources-via-s3-gateway-endpoint-6oh</link>
      <guid>https://dev.to/mundianderi/connecting-a-private-windows-ec2-instance-to-vpc-resources-via-s3-gateway-endpoint-6oh</guid>
      <description>&lt;p&gt;I recently had to connect a private Windows EC2 instance to VPC resources through an S3 Gateway endpoint and run into a couple of issues which has prompted me to write this article.&lt;/p&gt;

&lt;p&gt;Many of the online resources that I found focused on Linux servers and provisioning resources from the terminal or as a service. I, however, was doing it via the AWS console and not provisioning the resources through Infrastructure as a service. &lt;/p&gt;

&lt;p&gt;Here are a couple of problems I faced and how I resolved them as well as a step by step guide on how to provision a similar cloud system. If you're a Mac user, download Microsoft Remote Desktop from the App Store. If you're a Windows user, search for remote connection on the Windows start tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing your implementation
&lt;/h2&gt;

&lt;p&gt;To test that your implementation works as it should be - a user outside the VPC should not be able to download or upload images to the S3 bucket while a user within the VPC should be able to access the items in the S3 bucket.&lt;/p&gt;

&lt;p&gt;This being the case and considering that we're doing all these in a private subnet without internet connection, how do we :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download python from the internet?&lt;/li&gt;
&lt;li&gt;Install the aws cli?&lt;/li&gt;
&lt;li&gt;Interact with AWS resources from the terminal?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I spent quite a while trying to understand how to manoeuvre this problem.&lt;/p&gt;

&lt;p&gt;A public VPC is public by virtue of it being accessible to the internet.&lt;/p&gt;

&lt;p&gt;A private VPC is private by virtue of it being unaccessible to the internet. This is where we're going to place the private EC2 instance.&lt;/p&gt;

&lt;p&gt;Now that you have downloaded Microsoft Remote Desktop, lets start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create 2 Windows EC2 instances, one public, one private
&lt;/h2&gt;

&lt;p&gt;We're going to use the public EC2 instance as a jump box/ Bastion host, and then connect to the private EC2 instance from the Bastion Host. Both EC2 instances should have a Windows Amazon Machine Image (AMI).&lt;/p&gt;

&lt;p&gt;Within Network settings, we're going to specify the subnets. The public EC2 instance should be in the public subnet, while the private  EC2 instance should be in the private subnet.&lt;/p&gt;

&lt;p&gt;To ensure that our connections are right, check the route tables. The public subnet should have a local and an internet gateway attached, while the private subnet should only have the local route attached.&lt;/p&gt;

&lt;p&gt;Ideally, your VPC's route table should be resemble this - which means you'll have to create a separate route table for the private subnet.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Create the S3 bucket and the VPC S3 gateway endpoint
&lt;/h2&gt;

&lt;p&gt;To create an S3 bucket, navigate to S3 and create one, making sure to block all public S3 access.&lt;/p&gt;

&lt;p&gt;To create a VPC S3 gateway endpoint, under VPC navigate to endpoints, search for gateway and create the endpoint. Make sure to attach it to the VPC you created earlier.&lt;/p&gt;

&lt;p&gt;Your options while creating could look like this:&lt;/p&gt;

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

&lt;p&gt;For our bucket to now use the S3 endpoint, we need to update the S3 bucket policy. AWS offers a resource to generate S3 bucket policies based on your needs. Mine looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::bucketname",
                "arn:aws:s3:::bucketname/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpc": "vpc-id"
                }
            }
        }
    ]
}

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

&lt;/div&gt;



&lt;p&gt;Essentially, we're denying any S3 interaction with resources that are outside the VPC. Replace bucket name and VPC id with the actual bucket name and VPC Id. &lt;/p&gt;

&lt;p&gt;Your routes should look like these:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Connect the private EC2 instance to the internet via a Nat Gateway
&lt;/h2&gt;

&lt;p&gt;I did a lot of research to avoid using the Nat gateway to get internet access on the private instance but I had to anyway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/awscloudclubs/vpc-nat-gateway-tutorial-4ibp"&gt;Here's how to create a NAT Gateway.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, be advised that you can't connect to the private subnet with a Nat gateway and a VPC S3 gateway endpoint at the same time. The S3 endpoint gets dropped, and the Nat gateway remains.&lt;/p&gt;

&lt;p&gt;To access the Internet on the private subnet, attach the Nat Gateway on the private subnet and then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect to the public EC2 instance via RDP by passing in the the it's public IP address and the password. You can generate the password by clicking on connect on the EC2, and parsing the  key/value pair you created while creating the EC2 instance.&lt;/li&gt;
&lt;li&gt;Now that you're inside/within the public instance, repeat step 1. Pass the private IP address and the password generated when you click on connect on the private EC2 instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you're connected to the private EC2 instance, configure AWS by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening Microsoft Edge within the private EC2 instance and downloading the latest version of Python for Windows.&lt;/li&gt;
&lt;li&gt;Run the python installer.&lt;/li&gt;
&lt;li&gt;Download a random image from the internet.&lt;/li&gt;
&lt;li&gt;Open the Windows command line and run the following command. You should see python installed, indicating successful installation
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install the AWS CLI using pip
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install awscli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt; Verify AWS CLI installation by running this command. You should see the installed version of the awscli.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now run the following command to configure AWS
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;p&gt;To configure AWS, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your AWS access key ID which you can find under 'My security credentials'&lt;/li&gt;
&lt;li&gt;Your AWS secret key.&lt;/li&gt;
&lt;li&gt;Specify the region. You can find the region by hovering on the region next to your name on the top right corner of your screen.&lt;/li&gt;
&lt;li&gt;Default output format - json format.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  To NAT Gateway or to S3 gateway
&lt;/h2&gt;

&lt;p&gt;This depends on your needs. If you want to continue accessing the internet on the private instance, you can continue using the NAT Gateway but be ware of AWS charges before committing.&lt;/p&gt;

&lt;p&gt;If you choose to use S3 gateway, drop the NAT Gateway, reattach the S3 gateway endpoint and use endpoint only after you have configured AWS for the private EC2.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you choose the S3 gateway endpoint
&lt;/h2&gt;

&lt;p&gt;And you want to test the connection, follow these instructions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload an image to the S3 bucket from the private EC2 instance by running the following command on the Windows command line. This should be successful.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; aws s3 cp &amp;lt;image&amp;gt; &amp;lt;bucket name&amp;gt;/

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On your Mac terminal/ Windows command line outside the VPC, try downloading the image using the following command. Replace with actual names. This should result in a Fatal/ forbidden error.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws s3 cp s3://&amp;lt;bucket name&amp;gt;/&amp;lt;image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a fun and tough project to work on and using Windows made it a bit more complex. Figuring out how to work the remote connection which can raise its own errors can be tedious, but hopefully this gives you a roadmap if you want to interact with Windows EC2 instances.&lt;/p&gt;

&lt;p&gt;Another solution would be to provision this through infrastructure as code.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>aws</category>
      <category>cloudpractitioner</category>
    </item>
    <item>
      <title>Comparing Svelte and Vue.js: A Battle of Frontend Technologies</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Tue, 02 Jul 2024 09:26:21 +0000</pubDate>
      <link>https://dev.to/mundianderi/comparing-svelte-and-vuejs-a-battle-of-frontend-technologies-1co2</link>
      <guid>https://dev.to/mundianderi/comparing-svelte-and-vuejs-a-battle-of-frontend-technologies-1co2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k22l8t99bbggwy5qkjw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k22l8t99bbggwy5qkjw.jpg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The field of frontend development is dynamic and offers a wide selection of frameworks and libraries. Notable participants are Vue.js and Svelte. Both provide strong tools for creating contemporary web apps, but they differ in their capabilities and methods. We will explore the key distinctions between Svelte and Vue.js in this post and look at what makes each platform unique. I'll also talk about my hopes for the HNG Internship and my excitement about utilising ReactJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Svelte: What is it?
&lt;/h2&gt;

&lt;p&gt;Rich Harris founded Svelte, a relatively young contender in the frontend framework market. Svelte transfers most of the work to compile time, in contrast to conventional frameworks that operate by executing in the browser. &lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Elements of Svelte
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No Virtual DOM:&lt;/strong&gt; Svelte updates the DOM directly with compiled JavaScript, doing away with the requirement for a virtual DOM. Performance is enhanced and rendering is accelerated as a result.&lt;br&gt;
&lt;strong&gt;Reactive Declarations:&lt;/strong&gt; Reactive declarations are a feature of Svelte that let developers construct reactive variables with less boilerplate.&lt;br&gt;
&lt;strong&gt;Scoped Styles:&lt;/strong&gt; Svelte components have pre-installed scoped styles, which guarantee that the component contains the styles.&lt;br&gt;
&lt;strong&gt;Simplicity:&lt;/strong&gt; Svelte is a great option for both novice and seasoned developers because of its simple and easy to learn syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits and Drawbacks of Svelte
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No virtual DOM means high performance.&lt;/li&gt;
&lt;li&gt;Reduced bundle sizes.&lt;/li&gt;
&lt;li&gt;The syntax is clear and easy to read.&lt;/li&gt;
&lt;li&gt;Easy reactive programming.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Smaller ecosystem in comparison to older models.&lt;/li&gt;
&lt;li&gt;Fewer tools and libraries from third parties.&lt;/li&gt;
&lt;li&gt;For those accustomed to conventional frameworks, a learning curve.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Vue.js: What is it?
&lt;/h2&gt;

&lt;p&gt;Evan You developed the progressive JavaScript framework Vue.js, which is used to construct user interfaces. Because of its incremental adoption architecture, it may be applied to a single component or a whole application. The greatest elements of React and Angular are combined in Vue.js, giving developers a feature-rich and adaptable environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principal Attributes of Vue.js
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Virtual DOM:&lt;/strong&gt; To enhance rendering and boost speed, Vue.js makes use of a virtual DOM.&lt;br&gt;
&lt;strong&gt;Component-Based Architecture:&lt;/strong&gt; Vue promotes maintainability and reusability by using a component-based architecture.&lt;br&gt;
&lt;strong&gt;Two-Way Data Binding:&lt;/strong&gt; This feature of Vue makes it easier to synchronise data between the view and the model.&lt;br&gt;
&lt;strong&gt;Vue CLI:&lt;/strong&gt; Strong project management and scaffolding features are available through Vue's command-line interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits and Drawbacks of Vue.js
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Adaptable and multipurpose, fit for a variety of uses.&lt;/li&gt;
&lt;li&gt;Huge, vibrant community with a diverse ecosystem.&lt;/li&gt;
&lt;li&gt;thorough documentation and educational materials.&lt;/li&gt;
&lt;li&gt;Integration with current projects and other libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Its feature-rich design may make it difficult for novices to use.&lt;/li&gt;
&lt;li&gt;Greater bundle sizes than that of Svelte.&lt;/li&gt;
&lt;li&gt;Larger applications might not have performance comparable to Svelte.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My anticipations and enthusiasm around ReactJS in HNG
&lt;/h2&gt;

&lt;p&gt;ReactJS is a great option for creating dynamic user interfaces because of its virtual DOM and component-based architecture. I'm excited to learn more about ReactJS as a software engineer intern and use its powers to make effective and interesting web applications.&lt;/p&gt;

&lt;p&gt;The extensive React ecosystem offers a full platform for creating intricate applications, with features like Redux for state management and React Router for navigation. I'm excited to work with mentors and other interns, pick up best practices, and contribute to actual projects.&lt;/p&gt;

&lt;p&gt;The HNG Internship presents a special chance for me to develop my abilities, work on fascinating projects, and acquire priceless experience in the tech sector. Visit HNG Internship to find out more about the programme and find out how you can join this incredible group of individuals.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;Both Svelte and Vue.js are strong front-end technologies, with different applications and advantages. Svelte's compile-time methodology and ease of use make it a strong option for applications that require high performance, whereas Vue.js's adaptability and vibrant community suit a diverse array of applications. I'm eager to learn more about ReactJS and advance as a developer as I start my experience with it during my HNG internship.&lt;/p&gt;

&lt;p&gt;For additional details regarding the HNG Internship Programme and how to get involved, visit &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG Internship&lt;/a&gt; and &lt;a href="https://hng.tech/hire" rel="noopener noreferrer"&gt;HNG Hire&lt;/a&gt;. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Host a Static Website on Amazon S3</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Sun, 21 Apr 2024 11:26:00 +0000</pubDate>
      <link>https://dev.to/mundianderi/how-to-host-a-static-website-on-amazon-s3-m9f</link>
      <guid>https://dev.to/mundianderi/how-to-host-a-static-website-on-amazon-s3-m9f</guid>
      <description>&lt;p&gt;Amazon S3 is an object storage service provided by Amazon Web Services (AWS). It is designed to store and retrieve any amount of data from anywhere on the web, making it ideal for a wide range of use cases, from simple storage for backup and archiving to serving static website content and hosting entire applications.&lt;/p&gt;

&lt;p&gt;If you’re studying for AWS projects and looking for easy and beginner friendly projects, this is one of them.&lt;/p&gt;

&lt;p&gt;To start:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create an AWS account. You will get one year Free to test and use various functions — some are free but some have pay as you go pricing so be careful and do your research.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A static HTML site. If you need inspiration or Figma Designs you can explore Frontend Mentor for the designs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VScode and Github to code and store your code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a Bucket
&lt;/h2&gt;

&lt;p&gt;Navigate to Amazon S3 and create a bucket. Every object in AWS S3 is stored in a bucket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create objects by uploading your static HTML and related files and folders
&lt;/h2&gt;

&lt;p&gt;You can upload them as files or you can upload them as folders. Use the same file structure as you had in your local machine. I have an additional src file as I’m using Tailwind CSS.&lt;/p&gt;

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

&lt;p&gt;This is my view after uploading all the files, similar to what I had in my project locally.&lt;/p&gt;

&lt;p&gt;Clicking on the associated Object URL on the index.html object view will return an error, because you need to some changes to your bucket configuration.&lt;/p&gt;

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

&lt;p&gt;To change this, we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enable static hosting. To do that, navigate to properties on your particular bucket view and scroll down to Static Website Hosting. Click on enable and specify the website home or default page, in this case index.html. Save changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the website publicly accesible. To do that, click on permissions and uncheck the block public access box. Save changes and confirm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Within permissions, navigate to Object ownership and make public using ACL.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;To find your object URL, click in the index.html object. You should be able to see the Object URL.&lt;br&gt;
Here’s a look on my static site on AWS S3.&lt;/p&gt;

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

&lt;p&gt;This is a fairly easy and beginner friendly AWS project especially if you want to study for your AWS Certified Cloud Practioner certificate. You can also add it to your cloud engineer portfolio.&lt;/p&gt;

&lt;p&gt;If you liked this article, support me on &lt;a href="https://www.patreon.com/mundianderi" rel="noopener noreferrer"&gt;Patreon&lt;/a&gt;. &lt;em&gt;This article first appeared on &lt;a href="https://medium.com/blog-write-heal/how-to-host-a-static-website-on-amazon-s3-9cea5a9ad9e6" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>aws</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Seamless Database Integration: How to Use pgAdmin with ElephantSQL</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Fri, 21 Jul 2023 06:52:13 +0000</pubDate>
      <link>https://dev.to/mundianderi/seamless-database-integration-how-to-use-pgadmin-with-elephantsql-11cl</link>
      <guid>https://dev.to/mundianderi/seamless-database-integration-how-to-use-pgadmin-with-elephantsql-11cl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5dc2qqydc3qqmtleb32.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5dc2qqydc3qqmtleb32.jpg" alt="Photo by Sincerely Media on Unsplash" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Say for instance you’re working in a small team of newbie developers and you need to store and fetch data to a database. You can create the database locally but that would mean only one person can store and fetch data. Other team members cannot access the data.&lt;/p&gt;

&lt;p&gt;This scenario is what led me to a PGAdmin and ElephantSQL connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ElephantSQL?
&lt;/h2&gt;

&lt;p&gt;Elephant SQL is a PostgreSQL database administrator that installs and sets up database management in the cloud. I used their free Shared Instance Tiny Turtle plan that offers shared high performance server, 20 MB data, and 5 concurrent connections.&lt;/p&gt;

&lt;p&gt;I’m not sure how many team members are allowed in the free plan, but me and my team member used it for a previous project.&lt;/p&gt;

&lt;p&gt;To use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account &lt;a href="https://www.elephantsql.com" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Click on &lt;em&gt;Create New Instance&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Name your instance and tag it.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Choose a Data center closest to you. For me, that’s Ireland.&lt;/li&gt;
&lt;li&gt;Confirm new instance and create the instance. For the purposes of this article, I’ve named mine Medium.&lt;/li&gt;
&lt;li&gt;Click on browser. This opens a SQL Browser view where you can run SQL queries. Start by creating a Database and database tables.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Click on the newly created instance. It opens up a Details view. We’re going to use these details to connect to PGAdmin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is PGAdmin?
&lt;/h2&gt;

&lt;p&gt;PGAdmin is a management tool for postgreSQL and derivative relational databases.&lt;/p&gt;

&lt;p&gt;While PGAdmin is used to perform administrative tasks, query development, and manage databases on local systems, ElephantSQL is used for cloud-based PostgreSQL database hosting.&lt;/p&gt;

&lt;p&gt;Therefore, if you’re developing in a team, you can create the database on ElephantSQL, and then each team member can establish a connection to the database for easier collaboration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you connect ElephantSQL and PGAdmin?
&lt;/h2&gt;

&lt;p&gt;To connect the databases, go to the details view of ElephantSQL.&lt;/p&gt;

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

&lt;p&gt;Copy the URL and use it in your code to establish a connection. I used flask and sqlalchemy so my code will look like this:&lt;/p&gt;

&lt;p&gt;`import os&lt;br&gt;
from flask import Flask&lt;br&gt;
from flask_sqlalchemy import SQLAlchemy&lt;/p&gt;

&lt;p&gt;app = Flask(&lt;strong&gt;name&lt;/strong&gt;)&lt;br&gt;
app.config['SECRET_KEY'] = "key"&lt;br&gt;
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://retxeucg:&lt;a href="mailto:SUceqLZZySPh56oIBKKc3_c_5ImgGwWf@trumpet.db.elephantsql.com"&gt;SUceqLZZySPh56oIBKKc3_c_5ImgGwWf@trumpet.db.elephantsql.com&lt;/a&gt;/retxeucg'&lt;br&gt;
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False&lt;/p&gt;

&lt;p&gt;db = SQLAlchemy(app)`&lt;/p&gt;

&lt;p&gt;If it throws an error, change the URL. Notice that my url starts with ‘postgres’, make it ‘postgresql://…’&lt;/p&gt;

&lt;p&gt;After making this change in your code, head over to pgadmin for desktop or MacBook. I’ve had it installed for more than a year so I don’t remember much about the setup. If you haven’t set up pgadmin, do that then come back.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch pgAdmin: Open pgAdmin after installation.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a new Server: In the pgAdmin interface, you will see a “Browser” section on the left sidebar. Right-click on “Servers” and select “Create” &amp;gt; “Server…”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;General Tab: Enter a name for the server in the “Name” field (e.g., MyElephantSQL). Switch to the “Connection” tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connection Tab:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the “Host name/address” field, enter the database URL provided by ElephantSQL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the “Port” field, enter the port number provided by ElephantSQL (usually 5432).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the “Maintenance database” field, enter the default database name (usually the same as your username).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the “Username” field, enter the username provided by ElephantSQL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the “Password” field, enter the password associated with your ElephantSQL account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the connection: Click on the “Save” button to save the connection settings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect to the database: In the left sidebar, under “Servers,” you should now see the server you just added. Expand it, and you will see the databases available on your ElephantSQL instance. You can now interact with your PostgreSQL database using pgAdmin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From my URL,; postgres://retxeucg:&lt;a href="mailto:SUceqLZZySPh56oIBKKc3_c_5ImgGwWf@trumpet.db.elephantsql.com"&gt;SUceqLZZySPh56oIBKKc3_c_5ImgGwWf@trumpet.db.elephantsql.com&lt;/a&gt;/retxeucg, my connection details that’d need to add on pgadmin are:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Host name/address: trumpet.db.elephantsql.com&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port: Default PostgreSQL port is usually 5432.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintenance database: retxeucg&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Username: retxeucg&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Password: SUceqLZZySPh56oIBKKc3_c_5ImgGwWf&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is because the URL takes the format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;postgres://username:password@hostname/databasename&lt;br&gt;
A successful connection should look like this:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz63tgft7eh83v98ba4xk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz63tgft7eh83v98ba4xk.png" alt="Elephantsql" width="800" height="352"&gt;&lt;/a&gt;&lt;br&gt;
The elephant sign depicts a successful connection. The cancel sign depicts an unsuccessful connection.&lt;br&gt;
This should give you a head start in creating and using a postgreSQL database.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post first appeared on &lt;a href="https://medium.com/blog-write-heal/seamless-database-integration-how-to-use-pgadmin-with-elephantsql-627d25679500" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;br&gt;
_&lt;br&gt;
_I'm an ALX Full Stack Engineering student and a QA Engineer. Find me on &lt;a href="https://www.linkedin.com/in/serah-nderi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/nderisarah" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://github.com/MundiaNderi" rel="noopener noreferrer"&gt;Github&lt;/a&gt; and &lt;a href="https://medium.com/@sarahngima77" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>postgressql</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Behind the Scenes: Exploring the Technical Challenges and Solutions in Building Shielded</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Tue, 11 Jul 2023 09:30:26 +0000</pubDate>
      <link>https://dev.to/mundianderi/behind-the-scenes-exploring-the-technical-challenges-and-solutions-in-building-shielded-edd</link>
      <guid>https://dev.to/mundianderi/behind-the-scenes-exploring-the-technical-challenges-and-solutions-in-building-shielded-edd</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86wxd04p1bykzqvu52gk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86wxd04p1bykzqvu52gk.png" alt="Shielded" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;We built Shielded to help girls in FGM practising societies. Our aim is to protect the innocence of girls and women by redefining what purity means in FGM practicing societies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team members
&lt;/h2&gt;

&lt;p&gt;Serah Nderi - Backend and DevOps&lt;br&gt;
Hasina Said - Wireframes, Frontend and Devops&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;p&gt;Research: 3 weeks&lt;br&gt;
Development: 3 weeks&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In 2014, the national prevalence of FGM was 21%. This decline can be attributed to multifaceted approaches by GoK and NGO's.Yet, despite the steady decline nationally, the prevalence of FGM remains relatively high in some communities.&lt;/p&gt;

&lt;p&gt;FGM is not only a harmful practice but also a violation of human rights.&lt;/p&gt;

&lt;p&gt;The practice poses serious risks to the health and wellbeing of girls and women and is widely recognised as a human rights violation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Since there is little to no access to internet in FGM practising societies, our USSD Shielded seeks to provide information, access to safe houses credit, airtime, ambulance and emergency services to women in these societies.&lt;/p&gt;

&lt;p&gt;Our solution is unique as it consolidates these solutions at a low cost affordable manner. Currently, these solutions are offered in the country independent of each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Personal Focus
&lt;/h2&gt;

&lt;p&gt;Our project helps girls achieve the highest education level possible and escape FGM and early marriages by connecting them with safehouses and social workers through a USSD. It is also designed to work with other shareholders such as Village Chiefs to increase literacy rates in FGM practising areas.&lt;/p&gt;

&lt;p&gt;The team members are Hasina and myself and we wanted to focus on a USSD and a website solution. Those who find us via website still have access to the USSD information and an option to donate to the cause. Hasina worked on the FE while I integrated with the Africa's Talking USSD, Airtime, and SMS API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Shielded?
&lt;/h2&gt;

&lt;p&gt;Although I don't have a personal story around FGM and early marriage, I wanted to use Africa's Talking API and what better way than to champion for girls in Marginalised communities.&lt;/p&gt;

&lt;p&gt;Educated girls play a vital role in driving social and economic development. When girls receive an education, they contribute to the workforce, drive innovation, and foster economic growth. &lt;/p&gt;

&lt;p&gt;Educated women are more likely to become agents of change within their communities, promoting sustainable development and social progress.&lt;br&gt;
Education plays a big role in breaking poverty and abuse cycles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accomplishments
&lt;/h2&gt;

&lt;p&gt;For the Frontent we used HTML5, CSS3 and a bit of Vanilla JS around the navigation elements and toggle menu. We did not use any frameworks because we're yet to solidify our understanding of JavaScript which is the focus the next couple of months.&lt;/p&gt;

&lt;p&gt;For the Backend, we used Python, Flask web application and Postgresql database with Elephant SQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features 
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0v537ezjdvsz5dhis5mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0v537ezjdvsz5dhis5mu.png" alt="Shielded data flow" width="800" height="373"&gt;&lt;/a&gt;&lt;br&gt;
USSD - Serves as an entry point for the users. They dial the USSD and are presented with 3 options.&lt;/p&gt;

&lt;p&gt;Donate - For anyone who would like to donate to the course, the donate page integrates with the Safaricom daraja API.&lt;/p&gt;

&lt;p&gt;Airtime - Integrates with Africa's Talking API and sends the user airtime should they request the third option which is request airtime.&lt;/p&gt;

&lt;p&gt;SMS - For every USSD option, the user gets a message alert for the details they requested or the action they just took.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Challenges
&lt;/h2&gt;

&lt;p&gt;The most difficult challenge we faced is that the USSD wouldn't run and when it did I got a 504 time out error or a duplicate airtime send from the airtime file.&lt;/p&gt;

&lt;p&gt;Unbeknownst to me, while the USSD requires no api key, the sms api only consumes live keys and not sandbox keys. Changing my api key to a live key as opposed to a sandbox key solved the sms problem. We had also altered the USSD code a bit so refactoring it to run as a flask app solved our problems and now the app runs via the terminal.&lt;/p&gt;

&lt;p&gt;The USSD requires a callback URL which I did not know how to go about but after attending one of their sessions I learnt about ngrok. It was possible to fix errors as they all appeared under their sessions Tab courtesy of the callback URL/ngrok.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I've Learned
&lt;/h2&gt;

&lt;p&gt;Reading the documentation may not always be adequate. if something is not included in the documentation, join their slack or discord channels and see if there's discussions and how you can get help.&lt;/p&gt;

&lt;p&gt;When working on a project, all the concepts you've been reading and working will be a deciding factor on how you choose to go about the project.&lt;/p&gt;

&lt;p&gt;I also learned I work best by setting a minimum hours to code, in this case a minimum of 3 hours a day, research not included seemed to be my streak. Moving forward I want to finish some html, css projects and learning about Safaricom daraja API before I can specialise with Frontend or Backend.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm an ALX Full Stack Engineering student and a QA Engineer. Find me on &lt;a href="https://www.linkedin.com/in/serah-nderi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/nderisarah" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://medium.com/@sarahngima77" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MundiaNderi/Shielded" rel="noopener noreferrer"&gt;Shielded on Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://lucent-monstera-799cff.netlify.app" rel="noopener noreferrer"&gt;Shielded on Netflify&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/serah-nderi/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>css</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>How to Create a Callback URL using Ngrok</title>
      <dc:creator>Serah Nderi</dc:creator>
      <pubDate>Sat, 08 Jul 2023 19:24:04 +0000</pubDate>
      <link>https://dev.to/mundianderi/how-to-create-a-callback-url-using-ngrok-338e</link>
      <guid>https://dev.to/mundianderi/how-to-create-a-callback-url-using-ngrok-338e</guid>
      <description>&lt;p&gt;A while back I came across the need to create a callback URL while consuming Africa’s Talking USSD API. This was my first time coming across it and I didn’t know how to go about it.&lt;br&gt;
I thought that I’d need to host the project first so I ignored it for a while.&lt;/p&gt;

&lt;p&gt;Until I attended one of their sessions and they mentioned ngrok.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Ngrok Account
&lt;/h2&gt;

&lt;p&gt;You’ll be led to this page after signup or login.&lt;/p&gt;

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

&lt;p&gt;If you’re a windows user, follow the instructions. For macOS users you don’t need to follow the instructions because the download isn't a zip file as per their documentation but a Unix Executable file.&lt;/p&gt;

&lt;p&gt;Just download and fire it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fire up Ngrok
&lt;/h2&gt;

&lt;p&gt;After opening the downloaded unix file, open a new window on the terminaL, cd to the directory where you downloaded ngrok and run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./ngrok http &amp;lt;specify the port you want to use&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I used port 3000 so my command was:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./ngrok http 3000&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It opens an ngrok session where you can copy your URL. Below is my expired URL.&lt;/p&gt;

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

&lt;p&gt;My call back URL is: &lt;a href="https://1f9b-105-163-0-134.eu.ngrok.io" rel="noopener noreferrer"&gt;https://1f9b-105-163-0-134.eu.ngrok.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re using Africa’s Talking API, create a channel and update the callback URL, save and start debugging. The details tab will let you know where your code is failing, though their error messages are pretty generic.&lt;/p&gt;

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

&lt;p&gt;The disadvantage of using the free version of ngrok is that the URL expires after 2 hours thus you have to keep changing and updating it. Additionally, being on a free version means you have to keep that terminal open, else you lose the connection to ngrok.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://medium.com/blog-write-heal/how-to-create-a-callback-url-using-ngrok-9efd3061eba" rel="noopener noreferrer"&gt;This article first appeared on Medium&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
