<?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: anes</title>
    <description>The latest articles on DEV Community by anes (@aneshodza).</description>
    <link>https://dev.to/aneshodza</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%2F905106%2F9896a898-38f1-4d18-8f95-a0f1aec4fdba.png</url>
      <title>DEV Community: anes</title>
      <link>https://dev.to/aneshodza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aneshodza"/>
    <language>en</language>
    <item>
      <title>WCAG: Making the internet more accessible</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Mon, 20 Apr 2026 20:31:13 +0000</pubDate>
      <link>https://dev.to/aneshodza/wcag-making-the-internet-more-accessible-3484</link>
      <guid>https://dev.to/aneshodza/wcag-making-the-internet-more-accessible-3484</guid>
      <description>&lt;p&gt;We at &lt;a href="https://centrolabs.ch/" rel="noopener noreferrer"&gt;Centro Labs&lt;/a&gt; recently finished making &lt;a href="https://centrolabs.ch/localmate" rel="noopener noreferrer"&gt;LocalMate&lt;/a&gt; WCAG 2.2 Level AA Compliant.&lt;br&gt;
It's not something that shows up on a demo reel or has any flashy consequences, but it's one of the more meaningful things we have shipped. Here's how we did it and what we found out while doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What WCAG actually is
&lt;/h2&gt;

&lt;p&gt;The Web Content Accessibility Guidelines (or just WCAG) are international standards developed by the W3C Web Accessibility Initiative (WAI) to ensure digital contents are accessible to anyone, including people with disabilities.&lt;br&gt;
It applies to both web applications and mobile applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  POUR Principles
&lt;/h3&gt;

&lt;p&gt;It's centered around the four core &lt;em&gt;POUR&lt;/em&gt; principles:&lt;/p&gt;

&lt;h4&gt;
  
  
  Perceivable
&lt;/h4&gt;

&lt;p&gt;Information must be presentable to users in ways they can sense. This can be: Alt-Texts on images, aria labels, captions, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  Operable
&lt;/h4&gt;

&lt;p&gt;UI components and navigation must be operable. This means: being able to tab through the content of the website, having enough time to read the contents on it, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  Understandable
&lt;/h4&gt;

&lt;p&gt;Information and operation must be understandable, meaning: Readable text, predictable functionalities, etc.&lt;/p&gt;

&lt;h4&gt;
  
  
  Robust
&lt;/h4&gt;

&lt;p&gt;Content must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conformance Levels
&lt;/h3&gt;

&lt;p&gt;The standard is split up into three levels of compliance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A: Minimum level of accessibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AA&lt;/strong&gt;: Medium level of accessibility. This is often required for applications in the public sector, which is sadly not met by lots of applications.&lt;/li&gt;
&lt;li&gt;AAA: Maximum level of accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why it matters beyond compliance
&lt;/h2&gt;

&lt;p&gt;Usually when people pitch WCAG-Compliance they talk about government guidelines, legal requirements, etc. All of that is true, but its importance runs &lt;strong&gt;deeper than that:&lt;/strong&gt; Roughly 15%-20% of the population has some disability, affecting how they navigate and experience the web.&lt;br&gt;
A much larger group than that has &lt;em&gt;situational&lt;/em&gt; impairments: Navigating a website on a dark screen, using a service with a sprained wrist, using a service in a second or third language. &lt;br&gt;
Accessibility is &lt;strong&gt;not only for the permanently impaired&lt;/strong&gt;, but also for temporary constraints in how they use those digital services.&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://centrolabs.ch/localmate" rel="noopener noreferrer"&gt;LocalMate&lt;/a&gt; specifically the reasoning is clear: It's a service that makes information and services &lt;strong&gt;accessible to anyone.&lt;/strong&gt; Not complying with the WCAG AA guidelines is a &lt;strong&gt;contradiction to our mission.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What most websites get wrong
&lt;/h2&gt;

&lt;p&gt;Designers and developers often work on their applications in a controlled environment: On a desktop with bright screens, familiarity with the language and &lt;strong&gt;with a deep understanding on how the UX was designed&lt;/strong&gt;, I mean they were present when the application was written.&lt;br&gt;
Below are a few &lt;strong&gt;key requirements&lt;/strong&gt; that are often neglected.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Contrast ratios
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; Body text needs a contrast ratio of at least 4.5:1 against its background. For larger text (18pt+ or 14pt+ on bold text) this is eased to 3:1. This is &lt;strong&gt;success criterion 1.4.3.&lt;/strong&gt;&lt;br&gt;
Before we were compliant our AI disclaimer in the footer was a secondary light text on a grey background:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e61zfbxmsejpuqo5owh.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%2F3e61zfbxmsejpuqo5owh.png" alt="Footer with light grey AI disclaimer" width="800" height="74"&gt;&lt;/a&gt;&lt;br&gt;
This is a &lt;strong&gt;contrast ratio of 1.75:1&lt;/strong&gt;, making it &lt;strong&gt;not compliant&lt;/strong&gt;. We swapped this for darker text, achieving compliance.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 400% zoom without horizontal scroll
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;success criterion 1.4.10&lt;/strong&gt; says, that on a &lt;strong&gt;viewport of at least 1280px in width&lt;/strong&gt; the website must be usable at a &lt;strong&gt;400% zoom.&lt;/strong&gt;&lt;br&gt;
Most desktop-first designs don't comply: Sidebars, overflowing content, etc.&lt;br&gt;
We were also not compliant before, having the input overflow and making the application unusable:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lh59krwc50f5pyu8jai.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%2F2lh59krwc50f5pyu8jai.png" alt="LocalMate chat input going off to the side" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fixing this took a bit of &lt;strong&gt;UX-Engineering:&lt;/strong&gt; We turned off the minimum width on the input box and moved the "Open a new chat" button to the top of the page, disconnected from the input itself:&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%2Fs9ruafhlnvb37t6hulfa.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%2Fs9ruafhlnvb37t6hulfa.png" alt="LocalMate chat input fully contained in width" width="796" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The easiest way to tell &lt;strong&gt;if your website is compliant:&lt;/strong&gt; Try using it &lt;strong&gt;after zooming in to 400%.&lt;/strong&gt;&lt;br&gt;
This is what the cover image of the blog article is. The "ugly" input  conserves both width and height, by getting rid of most padding on very small screens.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Missing or lying ARIA labels
&lt;/h3&gt;

&lt;p&gt;ARIA stands for &lt;strong&gt;Accessible Rich Internet Applications.&lt;/strong&gt; They are the &lt;code&gt;aria-label&lt;/code&gt; tags that inputs and buttons often have.&lt;br&gt;
They add &lt;strong&gt;semantic annotations&lt;/strong&gt; for assistive technologies.&lt;/p&gt;

&lt;p&gt;Things that are &lt;strong&gt;frequently missed&lt;/strong&gt; are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Icon-only buttons&lt;/strong&gt; have no accessible names. They should all get an &lt;code&gt;aria-label&lt;/code&gt;, which describes the action.&lt;/li&gt;
&lt;li&gt;Inputs with &lt;strong&gt;placeholders as labels.&lt;/strong&gt; Those should also get an accompanying label.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Missing focus states and keyboard traps
&lt;/h3&gt;

&lt;p&gt;If you &lt;strong&gt;can't see where the keyboard focus is&lt;/strong&gt;, you can't use the app with a keyboard, making it non-compliant with &lt;strong&gt;guideline 2.4.7.&lt;/strong&gt;&lt;br&gt;
The browser default is often removed by designers (using &lt;code&gt;outline: none&lt;/code&gt;, because it's &lt;em&gt;ugly&lt;/em&gt;).&lt;br&gt;
For compliance reasons &lt;strong&gt;we show an outline&lt;/strong&gt; and, if applicable, show the hover-labels:&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%2Fm3vx76q96mrga2j5kcym.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%2Fm3vx76q96mrga2j5kcym.png" alt="Send message button with focus styling" width="630" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Keyboard traps
&lt;/h4&gt;

&lt;p&gt;A keyboard trap is when a tab-cycle gets stuck in a loop, like tabbing in the footer and never getting out.&lt;br&gt;
This is a &lt;strong&gt;no-go&lt;/strong&gt;. For people that cannot use a mouse something like this means: &lt;strong&gt;Refreshing the page every time they get trapped.&lt;/strong&gt;&lt;br&gt;
This can be corrected by introducing a tabbing order on a website, even though most of the time, this should be handled by the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  The point
&lt;/h3&gt;

&lt;p&gt;I could go on for days about other things that are frequently non-compliant, but &lt;strong&gt;the core message is:&lt;/strong&gt; Don't just expect that your work is accessible, &lt;strong&gt;make sure it is.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools that helped us
&lt;/h2&gt;

&lt;p&gt;Doing this manually and finding all the weak spots is annoying and takes tons of time. Luckily, there are tools to help.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lighthouse reports
&lt;/h3&gt;

&lt;p&gt;Google has a website called &lt;a href="https://pagespeed.web.dev/analysis/https-winti-localmate-ch/654yz8ogmp?form_factor=mobile" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt;. While it also covers SEO and first contentful paint, it offers a &lt;strong&gt;section called Accessibility&lt;/strong&gt;, where some issues get caught.&lt;/p&gt;

&lt;h3&gt;
  
  
  axe DevTools
&lt;/h3&gt;

&lt;p&gt;axe DevTools is a browser plugin, that allows running a diagnostic on your localhost page, catching issues before they ever reach production.&lt;br&gt;
It &lt;strong&gt;doesn't catch all issues&lt;/strong&gt;, but quickly points out quick-wins and obvious problems, like missing contrast.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Agents
&lt;/h3&gt;

&lt;p&gt;Let's be honest: &lt;strong&gt;Most&lt;/strong&gt; of the heavy lifting can be done by AI Agents. They can quickly scan through the entire codebase, use playwright MCPs to figure out the tabbing order, etc.&lt;br&gt;
Running Claude Code in plan mode to find, explain and correct all mistakes gets you about &lt;strong&gt;90% of the way there.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable takeaway
&lt;/h2&gt;

&lt;p&gt;Most web apps aren't WCAG AA compliant because accessibility is &lt;strong&gt;hard to see and easy to defer.&lt;/strong&gt; There are &lt;strong&gt;no actionable bug reports&lt;/strong&gt; from the users that get left behind, because they got frustrated and left. There is almost &lt;strong&gt;no marketing upside&lt;/strong&gt;, because it hardly translates into a nice pitch deck and it &lt;strong&gt;slows down features.&lt;/strong&gt;&lt;br&gt;
The way I have come to think about it: WCAG is a proxy, for whether a team &lt;strong&gt;takes non-ideal users seriously.&lt;/strong&gt; They don't think about the person who forgot their glasses, uses the app on a phone while on the bus or someone whose first language isn't the one in the UI. If the response to any of those is: &lt;em&gt;"Well I don't know, it kind of works"&lt;/em&gt;, the product is &lt;strong&gt;shipping a product that divides.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Making LocalMate WCAG AA compliant &lt;strong&gt;took real engineering and UX time.&lt;/strong&gt; It also surfaced lots of small quality issues that improved the product for &lt;em&gt;everyone&lt;/em&gt;, not just users with disabilities.&lt;/p&gt;




&lt;p&gt;This article was originally published on the &lt;a href="https://centrolabs.ch/blog/making-localmate-wcag-aa-compliant" rel="noopener noreferrer"&gt;Centro Labs Blog&lt;/a&gt;, check it out there!&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>webdev</category>
      <category>a11y</category>
      <category>design</category>
    </item>
    <item>
      <title>Building LocalMate at Hack Winterthur</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Mon, 16 Mar 2026 11:08:50 +0000</pubDate>
      <link>https://dev.to/aneshodza/building-localmate-at-hack-winterthur-5ebm</link>
      <guid>https://dev.to/aneshodza/building-localmate-at-hack-winterthur-5ebm</guid>
      <description>&lt;p&gt;A few weeks back me and &lt;a class="mentioned-user" href="https://dev.to/meritonaliu"&gt;@meritonaliu&lt;/a&gt; walked into &lt;a href="https://hackwinterthur.ch/" rel="noopener noreferrer"&gt;Hack Winterthur 2026&lt;/a&gt; as two CS students from ZHAW.&lt;br&gt;
We walked out the winners, being able to provide actual results: &lt;a href="https://centrolabs.ch/#projects" rel="noopener noreferrer"&gt;Winterthurs LocalMate: A digital assistant that builds the bridge between information and the people that need it&lt;/a&gt;.&lt;br&gt;
In this blog I want to outline the story of how it happened, why it matters to us personally, and whats under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;The City of Winterthur proposed a straight forward problem: They want to strengthen the communication between their local government and the people they govern.&lt;/p&gt;

&lt;p&gt;A simple problem in theory, but in practice something that is hard to implement: People get lost in the infinite amount of documents, regulations and the complex German.&lt;/p&gt;

&lt;p&gt;This problem isn't abstract to us. We know what it's like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is personal
&lt;/h2&gt;

&lt;p&gt;We both grew up in Zürich as the children of migrants. We watched everyone around us struggle with letters they couldn't fully understand, systems that assume familiarity with the system and other barriers that make integrating into this society harder than it should be.&lt;/p&gt;

&lt;p&gt;We often built this bridge: Translating, explaining and navigating where we could. That experience shaped how we think about the accessibility of information.&lt;br&gt;
And seriously: It shouldn't require a native speaker, a law degree or a teenager at your diner table to figure out how things work.&lt;/p&gt;

&lt;p&gt;When we saw the challenge, we didn't need to brainstorm: Winterthur faces a challenge we faced our entire lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  48 Hours of Building
&lt;/h2&gt;

&lt;p&gt;Hack Winterthur wasn't just about hacking: We started with a simple prototype to start gathering insights as fast as we could.&lt;br&gt;
The schedule was intense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a prototype during a 2 hour train ride home from 11PM to 1AM.&lt;/li&gt;
&lt;li&gt;Deploying everything on a personal Proxmox server.&lt;/li&gt;
&lt;li&gt;Getting user feedback as quickly as possible by using every time between document indexing as an opportunity to walk around and let people try it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The atmosphere was electric. Entrepreneus from all sorts of fields (IT, Business, Fintech, etc.) all building under the same roof.&lt;br&gt;
The perfect opportunity for cross-pollination of ideas.&lt;/p&gt;

&lt;h2&gt;
  
  
  What LocalMate actually is
&lt;/h2&gt;

&lt;p&gt;LocalMate is a conversational AI assistant that answers questions about the City of Winterthur, accurately, simply and in any language.&lt;br&gt;
Additionally it's an agent that retrieves dynamic information on the fly: Ask him about the trash schedule and he goes retrieving on his own.&lt;/p&gt;

&lt;p&gt;You can try it right now: &lt;a href="https://winti.localmate.ch/" rel="noopener noreferrer"&gt;LocalMate MVP&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Under the hood, LocalMate is built on a &lt;strong&gt;RAG Pipeline&lt;/strong&gt; (Retrieval Augmented generation) with agentic workflows built in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Ingestion
&lt;/h3&gt;

&lt;p&gt;We scrape data from &lt;a href="https://stadt.winterthur.ch/" rel="noopener noreferrer"&gt;stadt.winterthur.ch&lt;/a&gt;, the official website of the City of Winterthur. This ensures that no information is wrong or hallucinated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vectorization
&lt;/h3&gt;

&lt;p&gt;Everything is vectorized in memory, enabling extremely fast semantic search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval
&lt;/h3&gt;

&lt;p&gt;Before every request the users question was enriched using a small model and translated into german to guarantee retrieval quality.&lt;br&gt;
For retrieval we used &lt;a href="https://sbert.net/" rel="noopener noreferrer"&gt;SBERT&lt;/a&gt;, a semantics aware transformer that allows for incredibly quick lookups that know what the user wants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multilingual by default
&lt;/h3&gt;

&lt;p&gt;The system can retrieve and respond in whatever language the user wants: Ask in Albanian, get an answer in Albanian.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes it different
&lt;/h2&gt;

&lt;p&gt;While most websites have an FAQ section or a simple chatbot, we offer something more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verified Sources only: Every answer traces back to a document or page the city provides. No hallucinations.&lt;/li&gt;
&lt;li&gt;Language-agnostic: It doesn't just translate, it understands the semantics and reformulates in the users language&lt;/li&gt;
&lt;li&gt;Plain language: Administrative jargon gets simplified without losing accuracy.&lt;/li&gt;
&lt;li&gt;Agentic: Beyong simple Q&amp;amp;A, LocalMate can autonomously fetch dynamic data like schedules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Winning Hack Winterthur was the starting line, not the finish.&lt;/p&gt;

&lt;h3&gt;
  
  
  WinLab
&lt;/h3&gt;

&lt;p&gt;We have submitted LocalMate to the &lt;a href="https://kooperation.winterthur.ch/processes/co-kreation/f/470/proposals/2214" rel="noopener noreferrer"&gt;WinLab co-creating platform&lt;/a&gt;, seeking collaboration with the city to pilot the tool on a larger scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Launch Control Incubator
&lt;/h3&gt;

&lt;p&gt;We're participating in the &lt;a href="//launchcontrol.ch/programme/bring-your-idea-to-life/"&gt;Home of Innoviation's incubator program&lt;/a&gt; to develop our understanding for business and creating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Winterthur
&lt;/h3&gt;

&lt;p&gt;The architecture is instance-agnostic. Any municipality, canton, public- or private-sector organization that has tons of public or private knowledge could get their own LocalMate instance.&lt;br&gt;
We're actively looking for early adpoters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The best hackathon projects solve a problem the builders actually have. For us, LocalMate is something we wished existed growing up.&lt;br&gt;
We're building it so the next family doesn't have to figure it out alone&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Me (Anes Hodza) and Meriton Aliu are students at ZHAW.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;We publish our side projects under the name &lt;a href="https://centrolabs.ch/" rel="noopener noreferrer"&gt;Centro Labs&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally featured on the &lt;a href="https://www.zhaw.ch/de/ueber-uns/aktuell/news/detailansicht-news/event-news/zugang-fuer-alle-ist-uns-ein-persoenliches-anliegen" rel="noopener noreferrer"&gt;ZHAW News Blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>watercooler</category>
      <category>machinelearning</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Ruby function design and other stuff I like ranting about</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Tue, 04 Jun 2024 22:09:31 +0000</pubDate>
      <link>https://dev.to/aneshodza/ruby-function-design-and-other-stuff-i-like-ranting-about-32oe</link>
      <guid>https://dev.to/aneshodza/ruby-function-design-and-other-stuff-i-like-ranting-about-32oe</guid>
      <description>&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;If the posts title looks weird: it is. This is a small rant about code-functionality that makes little to no sense (in my eyes).&lt;br&gt;
This whole article can be summed up like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdug879xycl8931yoc6s4.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%2Fdug879xycl8931yoc6s4.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;I was talking to a coworker about getting the numerical value of a character, like you can in Java, because a &lt;code&gt;char&lt;/code&gt; stores the number behind that character.&lt;br&gt;
As an example of that behavior is this function, that counts the occurrence of every character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="nf"&gt;countCharacters&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toCharArray&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;]++;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My &lt;em&gt;naive&lt;/em&gt; suggestion was that you could just run &lt;code&gt;number.to_i&lt;/code&gt; to convert it to its (what I think is) ASCII number.&lt;br&gt;
The problem with that are cases like converting &lt;code&gt;"49".to_i&lt;/code&gt;, where ruby, as a non-typed language, has to convert that to the number the string represents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;017&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the one hand there is the &lt;code&gt;"12".to_i&lt;/code&gt;, which translates to &lt;code&gt;12&lt;/code&gt;. Fair enough, that makes sense. The other case, where the &lt;code&gt;String&lt;/code&gt; doesn't represent a number, it just translates to &lt;code&gt;0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;012&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;013&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"fdsgsdf"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That leads to some weird (but expected) behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;003&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;006&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now look &lt;em&gt;closely&lt;/em&gt; at that first codeblock. You might realize that there are two operations used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;017&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The weird part is the &lt;code&gt;"12".sum&lt;/code&gt; - as ruby loves translating strings to the numbers they represent, you would expect that to translate to something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;# Because 1 + 2 = 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you get something completely different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"12"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now why does this happen you might as?&lt;br&gt;
Because of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;027&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;02&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;49&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because it takes their &lt;strong&gt;ASCII&lt;/strong&gt; representation, the same as java does!&lt;/p&gt;

&lt;h3&gt;
  
  
  Okay, so shouldn't this work for accessing arrays?
&lt;/h3&gt;

&lt;p&gt;This (obviously) doesn't work out of the box, as you need to convert the string to a number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mo"&gt;004&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="ss"&gt;:in&lt;/span&gt; &lt;span class="sb"&gt;`[]=': no implicit conversion of String into Integer (TypeError)

summand["1"] = 'test'
        ^^^^^^^^^^^^^
    from (irb):4:in `&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'
irb(main):005&amp;gt; summand["a"] = '&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="s1"&gt;'
(irb):5:in `[]='&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;conversion&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;summand&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;
        &lt;span class="o"&gt;^^^^^^^^^^^^^&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;irb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="ss"&gt;:in&lt;/span&gt; &lt;span class="sb"&gt;`&amp;lt;main&amp;gt;'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What about scientific notation?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;"What about scientific notation?"&lt;/em&gt; you might ask. That's also what I was wondering:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):022&amp;gt; 2e10
=&amp;gt; 20000000000.0
irb(main):024&amp;gt; "2e10".to_i
=&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ?!
&lt;/h4&gt;

&lt;p&gt;Yes, you are seeing this right: It converts the &lt;code&gt;"2e10"&lt;/code&gt; to a &lt;code&gt;2&lt;/code&gt;, as it's all the numbers until the first non-number. This behavior is seen in longer strings too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):036&amp;gt; "21f10".to_i
=&amp;gt; 21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here it cuts the &lt;code&gt;to_i&lt;/code&gt; operation after reaching the &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Actually converting scientific notation to a number
&lt;/h4&gt;

&lt;p&gt;Now, how can we make this work? This is how:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):037&amp;gt; "2e10".to_f.to_i
=&amp;gt; 20000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this only works, as numbers of scientific notation have the class &lt;code&gt;Float&lt;/code&gt; per default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):038&amp;gt; 2e10.class
=&amp;gt; Float
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a dynamically-typed language it still seems to be unable to do a lot of casting for you!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where is this leading?
&lt;/h2&gt;

&lt;p&gt;Nowhere. Everything I mentioned before is really obscure and won't be important 99% of the time. This article is just for those 1% of cases.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Publishing your first npm library</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Wed, 24 Apr 2024 23:49:22 +0000</pubDate>
      <link>https://dev.to/aneshodza/publishing-your-first-npm-library-51k2</link>
      <guid>https://dev.to/aneshodza/publishing-your-first-npm-library-51k2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently published my &lt;a href="https://www.npmjs.com/package/pushdown-automaton" rel="noopener noreferrer"&gt;first npm library called &lt;code&gt;pushdown-automaton&lt;/code&gt;&lt;/a&gt; which allows users to create &lt;a href="https://en.wikipedia.org/wiki/Pushdown_automaton" rel="noopener noreferrer"&gt;Pushdown Automata&lt;/a&gt;. And while it is a very niche use-case I am still proud of my achievement.&lt;br&gt;
This article's purpose is highlighting anything important I ran into to help everyone reading this.&lt;/p&gt;
&lt;h2&gt;
  
  
  Librarification of your code
&lt;/h2&gt;

&lt;p&gt;Personally, I started off with something 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;/
  PushdownAutomaton.js
  Stack.js
  State.js
  TerminationMessage.js
  TransitionFunction.js
  package.json
  .gitignore
  .tool-versions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And while this is fine to hand in for a school project, there is still a lot missing to turn it into a library.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using typescript (optional)
&lt;/h2&gt;

&lt;p&gt;First, the project should be converted to TypeScript. That makes using the library as an end-user much easier, as there are type-errors in case someone uses it wrong:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1omnmi06zdqbue5esmhp.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%2F1omnmi06zdqbue5esmhp.png" alt="Screenshot of a type error when using the library wrong" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Coverting your files
&lt;/h3&gt;

&lt;p&gt;Firstly you should change all &lt;code&gt;*.js&lt;/code&gt; files to &lt;code&gt;*.ts&lt;/code&gt;.&lt;br&gt;
Then you need to add types everywhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;automaton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;automaton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PushdownAutomaton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;oneState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;oneState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;otherState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;otherState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;q1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While I did it manually, you can probably just feed all your files into ChatGPT and make it do the manual labor. Just use at your own discretion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing folder structure
&lt;/h3&gt;

&lt;p&gt;To make everything more readable and easier to understand you might want to move the source &lt;code&gt;*.ts&lt;/code&gt; files into their own folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
  src/
    PushdownAutomaton.ts
    Stack.ts
    State.ts
    TerminationMessage.ts
    TransitionFunction.ts
  package.json
  .gitignore
  .tool-versions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later we will set up an &lt;code&gt;out/&lt;/code&gt; folder that holds our end-user code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the ts compiler
&lt;/h3&gt;

&lt;p&gt;As we still want to make the library usable for non-ts users we have to add the &lt;code&gt;tscompiler&lt;/code&gt; that turns our code into JavaScript.&lt;br&gt;
As we only need it when developing and not when sending our package to the user, make sure to only install it in development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we define a few commands in our &lt;code&gt;package.json&lt;/code&gt; that make compilation easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc --outDir out/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to just run &lt;code&gt;npm run ...&lt;/code&gt; and have it compile directly into the correct directory. Now running any of those commands doesn't work as of now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ npm run build

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pushdown-automaton@1.1.3 build
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tsc &lt;span class="nt"&gt;--outDir&lt;/span&gt; out/

Version 5.4.5
tsc: The TypeScript Compiler - Version 5.4.5

COMMON COMMANDS
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TypeScript config
&lt;/h4&gt;

&lt;p&gt;This happens, as we don't yet have a typescript config set up.&lt;br&gt;
Luckily, we can generate one by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;

Created a new tsconfig.json with:
                                                                                                                 TS
  target: es2016
  module: commonjs
  strict: &lt;span class="nb"&gt;true
  &lt;/span&gt;esModuleInterop: &lt;span class="nb"&gt;true
  &lt;/span&gt;skipLibCheck: &lt;span class="nb"&gt;true
  &lt;/span&gt;forceConsistentCasingInFileNames: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the generated &lt;code&gt;tsconfig.json&lt;/code&gt; might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And while this works, it's not quite what we want. After changing it around a bit, this one looked pretty good for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Basic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ESNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dom"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declaration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sourceMap"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Strict&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Type-Checking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Resolution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Advanced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"examples"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.ts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important settings are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;target: This is the JS Version our files will be transpiled to&lt;/li&gt;
&lt;li&gt;module: This defines the module system our code will use. &lt;code&gt;ESNext&lt;/code&gt; allows for keywords like &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;export&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;lib: This defines what will be included in our compilation environment&lt;/li&gt;
&lt;li&gt;declaration: This option tells the compiler to create declaration files (explained better under the chapter &lt;code&gt;*.d.ts&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;sourceMap: This option tells the compiler to create sourcemap files (explained better under the chapter &lt;code&gt;*.js.map&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;outDir: Where our files are sent to (if nothing is specified in the command)&lt;/li&gt;
&lt;li&gt;include: What glob pattern to use when searching for files to be compiled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we can re-run our commands sucessfully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜ npm run build

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; pushdown-automaton@1.1.3 build
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tsc &lt;span class="nt"&gt;--outDir&lt;/span&gt; out/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of the &lt;code&gt;out/&lt;/code&gt; folder you should now see a bunch of files, having following endings:&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;*.js&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;These are JavaScript files. They contain the actual code.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;code&gt;.d.ts&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;These are Type declarations: These files tell any TypeScript compilers about types, etc. giving them the ability to catch type errors before runtime.&lt;br&gt;
The content looks like a Java &lt;code&gt;interface&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PushdownAutomaton&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TerminationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TerminationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;setStartSate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;code&gt;.js.map&lt;/code&gt;
&lt;/h5&gt;

&lt;p&gt;These files are used by the browser to allow users to see the original files instead of the compiled ones. Reading them doesn't make much sense, as they are just garbage.&lt;/p&gt;

&lt;h4&gt;
  
  
  ESNext issues when using TypeScript
&lt;/h4&gt;

&lt;p&gt;If you already tried using your library you might have realized that nothing works. That is for one simple reason: TypeScript imports don't get &lt;code&gt;.js&lt;/code&gt; added after filenames with &lt;code&gt;tsc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This import in ts:&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./PushdownAutomaton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Gets turned into this in js:&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./PushdownAutomaton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// While this is needed:&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./PushdownAutomaton.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix that, I used some random npm package I found, called &lt;code&gt;fix-esm-import-path&lt;/code&gt;.&lt;br&gt;
Automating the process of using this needs us to add more &lt;code&gt;scripts&lt;/code&gt; in our &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run build:compile &amp;amp;&amp;amp; npm run build:fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build:fix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fix-esm-import-path out/*.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build:compile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reflecting the changes in our &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;We made many structural changes to our project, we need to change the &lt;code&gt;package.json&lt;/code&gt; by adding an indicator for the type of project we have and where our files are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"out/**/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding JSDocs
&lt;/h3&gt;

&lt;p&gt;JavaScript supports something called "JSDocs". They are those helpful messages you sometimes see when using a function:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qmhvetydu3j1bbyliyc.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%2F4qmhvetydu3j1bbyliyc.png" alt="Image of a jsdoc help message" width="680" height="187"&gt;&lt;/a&gt;&lt;br&gt;
Adding these docs to every method and class will increase the usability by a lot, so I would suggest you do that.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the "entry point"
&lt;/h2&gt;

&lt;p&gt;When someone uses our package now, that person would expect to import our libraries code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TransitionFunction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pushdown-automaton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But as of now that isn't possible. They would have to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import PushdownAutomaton from &lt;span class="s1"&gt;'pushdown-automaton/out/PushdownAutomaton'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enable this first type of imports we will create something called an entry point. That file is located under &lt;code&gt;src/index.ts&lt;/code&gt; and looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PushdownAutomaton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./PushdownAutomaton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Stack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./State&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TransitionFunction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./TransitionFunction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All this does is just bundle up everything the user needs. Configuring it like this increases ease of use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting that in our &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now we need to define the entry point in our &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"out/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"out/index.d.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All this does is tell the end-user where to find the "entry point" and its types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean code and testing (optional)
&lt;/h2&gt;

&lt;p&gt;Most libraries make use of things like linters and tests to guarantee maintainability and expand-ability. &lt;br&gt;
While this is not needed, I always advocate for it. It makes the development experience for you and any potential future maintainers much better.&lt;/p&gt;
&lt;h3&gt;
  
  
  Clean code check
&lt;/h3&gt;

&lt;p&gt;First, we want to set up &lt;code&gt;eslint&lt;/code&gt;, which is a JavaScript library that allows us to check for certain clean-code standards and if we are following them.&lt;/p&gt;
&lt;h4&gt;
  
  
  Installing packages
&lt;/h4&gt;

&lt;p&gt;We will start by installing a few packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; eslint @eslint/js typescript-eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configuring eslint
&lt;/h4&gt;

&lt;p&gt;Next, we will create a file called &lt;code&gt;eslint.config.mjs&lt;/code&gt;. It will be pretty empty, only having following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ts-check&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;eslint&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@eslint/js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;tseslint&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typescript-eslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;tseslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;eslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tseslint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just takes what clean-code rules are popular at the moment and enforces them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Next, we will set up &lt;code&gt;jest&lt;/code&gt; in combination with &lt;code&gt;istanbul&lt;/code&gt; to check coverage.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installing
&lt;/h4&gt;

&lt;p&gt;With following command you can install &lt;code&gt;jest&lt;/code&gt;, which also contains &lt;code&gt;istanbul&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jest ts-jest @types/jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configuring
&lt;/h4&gt;

&lt;p&gt;To configure &lt;code&gt;jest&lt;/code&gt; you can add following content to your &lt;code&gt;jest.config.mjs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// jest.config.mjs&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;testEnvironment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;roots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;rootDir&amp;gt;/tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;testRegex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(/__tests__/.*|(&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.|/)(test|spec))&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.tsx?$&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;moduleFileExtensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;collectCoverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;coverageDirectory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;coverage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;coverageReporters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lcov&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;coverageThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;statements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can run our tests and see the coverage listed of every mentioned file:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friur0po6sdz1cdqsb6rs.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%2Friur0po6sdz1cdqsb6rs.png" alt="Image of 100% coverage" width="695" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The config a few interesting options, which you can look up yourself. Important are following options:&lt;/p&gt;
&lt;h5&gt;
  
  
  roots
&lt;/h5&gt;

&lt;p&gt;This defines where the tests are. In this case they are under &lt;code&gt;/tests/&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;
  
  
  testRegex
&lt;/h5&gt;

&lt;p&gt;This defines the syntax filenames of tests have to follow. This regex enforces the format &lt;code&gt;something.test.ts&lt;/code&gt; but also allows similar names like &lt;code&gt;something.spec.tsx&lt;/code&gt;.&lt;/p&gt;
&lt;h5&gt;
  
  
  coverageTheshold
&lt;/h5&gt;

&lt;p&gt;This defines what percentage of lines have to be touched by our tests. In this case all options are set to 100%, which enforces complete test coverage.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding scripts
&lt;/h3&gt;

&lt;p&gt;After adding and configuring both a linter and tests, we need to have a standard way of running them.&lt;br&gt;
That can be achieved by adding following options to our &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint 'src/**/*.ts'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fix-lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint 'src/**/*.ts' --fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automated testing and git hooks (optional)
&lt;/h2&gt;

&lt;p&gt;To make enforcing of code-quality easier we will add git-hooks and GitHub actions to run our linter and tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  git hooks
&lt;/h3&gt;

&lt;p&gt;To help us with adding git hooks, we will use husky:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luckily &lt;code&gt;husky&lt;/code&gt; has tools to help us with setting up the hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A pre-commit script under &lt;code&gt;.husky&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adds &lt;code&gt;prepare&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we can add our linter under &lt;code&gt;.husky/pre-commit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/_/husky.sh"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running pre-commit hooks..."&lt;/span&gt;


&lt;span class="c"&gt;# Run ESLint&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Linting..."&lt;/span&gt;
npm run lint
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ESLint found issues. Aborting commit."&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pre-commit checks passed."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it runs the linter before every commit and forbids us from finishing the commit if there are any complaints by &lt;code&gt;eslint&lt;/code&gt;. That might look like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnehcinod1yock4epcq1c.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%2Fnehcinod1yock4epcq1c.png" alt="Image of a commit with hooks" width="463" height="169"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up GitHub actions
&lt;/h3&gt;

&lt;p&gt;Now we want to set up GitHub actions so it runs our tests and lints on every push.&lt;br&gt;
For that, we will create &lt;code&gt;.github/workflows/tests.yml&lt;/code&gt;. In there we define the workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tests on push&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;16.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;18.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;windows-latest&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;macos-latest&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;
        &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache node modules&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.npm&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}&lt;/span&gt;
        &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;${{ runner.os }}-node-&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint Code&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs our tests on ubuntu, windows and macos on versions 16 and 18 of &lt;code&gt;node&lt;/code&gt;.&lt;br&gt;
Feel free to change the matrix!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbtrlt01rfc1h37ln72nx.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%2Fbtrlt01rfc1h37ln72nx.png" alt="Image of successful checks" width="573" height="280"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Publishing a package
&lt;/h2&gt;

&lt;p&gt;Finally, we can publish our package. For that we need to create an account under &lt;a href="https://www.npmjs.com" rel="noopener noreferrer"&gt;npmjs.com&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Final settings
&lt;/h3&gt;

&lt;p&gt;Some final things we will want to configure before uploading are in our &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git+ssh://git@github.com/user/repo"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"some"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"keywords"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"you, of course :)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT I hope"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bugs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/user/repo/issues"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"homepage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/user/repo#readme"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we will want to create a file called &lt;code&gt;CHANGELOG.md&lt;/code&gt; and reference it in our &lt;code&gt;README&lt;/code&gt;. The file looks as follows for now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Changelog&lt;/span&gt;

All notable changes to this project will be documented in this file.

The format is based on &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Keep a Changelog&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://keepachangelog.com/en/1.1.0/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;,
and this project adheres to &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Semantic Versioning&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://semver.org/spec/v2.0.0.html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.

&lt;span class="gu"&gt;## [1.0.0] - yyyy-mm-dd&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Initial release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out &lt;a href="https://keepachangelog.com/en/1.1.0/" rel="noopener noreferrer"&gt;how to keep a changelog&lt;/a&gt; and &lt;a href="https://semver.org/spec/v2.0.0.html" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; to always keep your library understandable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual publish
&lt;/h3&gt;

&lt;p&gt;To publish the package manually, we can do that in our console.&lt;br&gt;
First we log in by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm adduser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will open the browser window and ask us to log in.&lt;br&gt;
After doing that you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build&lt;span class="p"&gt;;&lt;/span&gt; npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automating that work
&lt;/h3&gt;

&lt;p&gt;If you want to automate this work we can configure a GitHub action to automatically publish on npm when pushing a new tag.&lt;/p&gt;

&lt;h4&gt;
  
  
  YAML config to publish
&lt;/h4&gt;

&lt;p&gt;With following file under &lt;code&gt;.github/workflows/publish.yml&lt;/code&gt; a new release gets triggered on every new tag.&lt;br&gt;
Special about this file is also, that it makes sure our &lt;code&gt;package.json&lt;/code&gt; has the same version for our package as the pushed tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish to npm registry&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check-tag-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check if tag matches version in package.json&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;TAG_NAME=${GITHUB_REF#refs/tags/}&lt;/span&gt;
          &lt;span class="s"&gt;PACKAGE_VERSION=$(jq -r '.version' package.json)&lt;/span&gt;
          &lt;span class="s"&gt;if [ "$TAG_NAME" != "$PACKAGE_VERSION" ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "::error::Tag version ($TAG_NAME) does not match version in package.json ($PACKAGE_VERSION)"&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;

  &lt;span class="na"&gt;check-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18.x'&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache node modules&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.npm&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-node-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint Code&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;

  &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;check-tag-version&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;check-code&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18.x'&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache node modules&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.npm&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-node-&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build the project&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish to npm&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm publish&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;NODE_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Generating an access token
&lt;/h4&gt;

&lt;p&gt;After adding this, you will need to add an npm auth token to your GitHub Actions environment variables.&lt;br&gt;
Get that key under "Access Tokens" after clicking on your profile picture. Generate a "Classic Token".&lt;br&gt;
On that page, add a name and choose "Automation" to allow managing the package in our CI&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftws6i8ecny2q8r4z2cqz.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%2Ftws6i8ecny2q8r4z2cqz.png" alt="Image of access token generation" width="602" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding that token
&lt;/h4&gt;

&lt;p&gt;To now add that token to GitHub Actions secrets.&lt;br&gt;
You can find that setting under (Project) Settings &amp;gt; Secrets and variables &amp;gt; Actions.&lt;br&gt;
Then click on "New repository secret" and add &lt;code&gt;NPM_TOKEN&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw97q7lyasuqntxexga9.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%2Fcw97q7lyasuqntxexga9.png" alt="Image of an added env key" width="624" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing our automated publish
&lt;/h4&gt;

&lt;p&gt;If we did everything correctly a new tag should trigger the "publish" action, which automatically publishes:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwaottr9nrmlchft6jzfc.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%2Fwaottr9nrmlchft6jzfc.png" alt="Image of the automatic publish" width="633" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Now you can finally check out your own npm package on the official website. Good job!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpnybdbc0ebjfyvqovup.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%2Fkpnybdbc0ebjfyvqovup.png" alt="Image of a list with npm packages" width="677" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>npm</category>
      <category>node</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Accessing local services with SSRF attacks</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Mon, 11 Mar 2024 16:06:45 +0000</pubDate>
      <link>https://dev.to/aneshodza/accessing-local-services-with-ssrf-attacks-2cjb</link>
      <guid>https://dev.to/aneshodza/accessing-local-services-with-ssrf-attacks-2cjb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So you thought about a great new business idea for your company: Making an URL-Preview service, that stores the URL for a user and then displays it along with an icon inside a list.&lt;br&gt;
That service should then run locally and get forwarded into the internet by a service like &lt;code&gt;ngrok&lt;/code&gt;.&lt;br&gt;
So you start coding and come up with a service that looks as follows: A node.js backend (using express.js) that exposes a few API endpoints so the user can interact with the storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/public`&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/urls&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userUrls&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/add-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;URL is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;userUrls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;URL added successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;URL is required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch the URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And some simple HTML and JavaScript to display everything, and allow the user to add new URLs:&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%2F8k7kwtgzr235b6ica36d.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%2F8k7kwtgzr235b6ica36d.png" alt="Screenshot of the website, displaying a form" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The company architecture
&lt;/h2&gt;

&lt;p&gt;Unbeknownst to you, the company has a few other (security critical) services running:&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%2Fhdgrdgndfywpqfr5yb0n.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%2Fhdgrdgndfywpqfr5yb0n.png" alt="Image of the company architecture showing various internal services" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both other express.js services aren't meant to be connected to the public internet, but rather to an internal network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abusing the vulnerability
&lt;/h2&gt;

&lt;p&gt;Because we don't sanitize the URLs given by the user, we can easily abuse security flaws in the code, which we will be doing in this chapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the architecture
&lt;/h3&gt;

&lt;p&gt;For testing purposes, I have created &lt;a href="https://github.com/aneshodza/ssrf-demo" rel="noopener noreferrer"&gt;this repository&lt;/a&gt;, which contains whole server architecture. The &lt;a href="https://github.com/aneshodza/ssrf-demo/blob/main/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt; contains how to run the project and forward the port trough ngrok.&lt;br&gt;
If you did everything correctly, you should be able to go on your ngrok URL and see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Welcome to your URL storage tool!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding the security flaw
&lt;/h3&gt;

&lt;p&gt;One potential security flaw is that the URL storage app runs on the same network as all the other architecture and also allows us to pass in &lt;code&gt;localhost&lt;/code&gt; URLs, without sanitizing them.&lt;br&gt;
To verify that, we first have to see how exactly this storage tool works. For that we add some random domain and submit it. After that we refresh the page:&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%2Fjn5g54ay9szqqa4vdmy0.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%2Fjn5g54ay9szqqa4vdmy0.png" alt="Image of the first added URL" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we should check the network tab, to see how much we actually get:&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%2Fxxwsvcf4rmilikb4pdoa.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%2Fxxwsvcf4rmilikb4pdoa.png" alt="Image of the given URL returning the website" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see following things: The server does the request for us, and we get the whole response back.&lt;/p&gt;
&lt;h3&gt;
  
  
  Trying to exploit it
&lt;/h3&gt;

&lt;p&gt;Our instinct should be to check what other domains we can get, starting from the more used ports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:80 &amp;lt;- http
localhost:3306 &amp;lt;- mysql
localhost:3000 &amp;lt;- rails/node
localhost:300x &amp;lt;- additional rails/node apps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding both &lt;code&gt;localhost:3000&lt;/code&gt; and &lt;code&gt;localhost:3001&lt;/code&gt; we can see, that those have things running:&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%2Fh0142p93lgzudm19gzjy.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%2Fh0142p93lgzudm19gzjy.png" alt="Image of a running internal service" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What we are now essentially doing is creating this red bridge, to access more than we should:&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%2Fzm650l1t29fbtbv6cv0q.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%2Fzm650l1t29fbtbv6cv0q.png" alt="Image visualising how our request went from one service to the next" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside the HTML we can see that this page calls a route called:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v1/customer-data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try to request that one we get what we came for:&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%2F846kx2k5hn3xi4wn02f7.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%2F846kx2k5hn3xi4wn02f7.png" alt="Image of customer data" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Causing more damage
&lt;/h3&gt;

&lt;p&gt;Let's get back to port 3000 now, where we saw that something is running:&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%2Fherhbjwd1vdany2ycarb.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%2Fherhbjwd1vdany2ycarb.png" alt="Image of a web-service on localhost:3000" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following what we know from the first request we made, maybe we can deduce that this service also follows the aforementioned pattern of API URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v1/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we just try known endpoints there, until we arrive at this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/api/v1/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding that URL and refreshing, nets us this in the network tab:&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%2Fy0d9gripldk55jmzl90v.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%2Fy0d9gripldk55jmzl90v.png" alt="Image of the api documentation" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which is everything we need. We can see that this is some sort of database proxy, used internally to more easily query the database.&lt;br&gt;
As we now may have complete SQL-Access we can try to see what tables the database has, by sending it &lt;code&gt;show%20tables&lt;/code&gt; as the parameter:&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%2Fufcptfaeq2dtbz5zal6r.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%2Fufcptfaeq2dtbz5zal6r.png" alt="Image showing us sending any sort of SQL queries" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we wanted to get crazy, we could try to query a user and all the pills he is prescribed using this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;customer_pills&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;pills&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pill_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting this query to a URL that we can pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000/api/v1/db-proxy?query=SELECT%20c.firstname,%20c.lastname,%20p.name,%20p.description,%20p.price%20FROM%20customers%20c%20JOIN%20customer_pills%20cp%20ON%20c.id%20=%20cp.customer_id%20JOIN%20pills%20p%20ON%20cp.pill_id%20=%20p.id%20WHERE%20c.id%20=%20(SELECT%20MIN(id)%20FROM%20customers);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding this URL and refreshing we can see:&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%2Fc7bdtls48fzwfkr41lmv.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%2Fc7bdtls48fzwfkr41lmv.png" alt="Image of a user and all his pills" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, as they would say in the movies: WE'RE IN!&lt;/p&gt;

&lt;h2&gt;
  
  
  The consequences of this breach
&lt;/h2&gt;

&lt;p&gt;Getting root access to a database is bad enough. It gets even worse when that database contains sensitive medical information.&lt;br&gt;
There are lots of ways to abuse this security flaw. One of them being a "double-extortion", which we could do as follows:&lt;br&gt;
First, we dump everything from this database that we can dump. And by that I mean query every table we can see and then store everything we got locally.&lt;br&gt;
Then, we can use our privileges to delete the customer data, and hope that they don't have a backup.&lt;br&gt;
Finally we inform the victim that we want money for two separate things: Returning the deleted data AND not leaking this confidential customer data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Preventing the exploit
&lt;/h2&gt;

&lt;p&gt;One simple way to prevent this security flaw is by sanitizing the given URLs, by for example returning a 400 every time &lt;code&gt;localhost&lt;/code&gt; is mentioned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/v1/add-url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt; This isn't enough, as URLs that replace the &lt;code&gt;localhost&lt;/code&gt; with &lt;code&gt;127.0.0.1&lt;/code&gt; are valid and still locally. Please sanitize further in this case!&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%2Fa76p67hw32ct26d4trtz.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%2Fa76p67hw32ct26d4trtz.png" alt="Image showing that 127.0.0.1 can also be used to get local things" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A safer fix
&lt;/h3&gt;

&lt;p&gt;A safer way to fix this, is to have the URL app running on a different network and separate it by a firewall&lt;/p&gt;

&lt;h2&gt;
  
  
  The OWASP definition
&lt;/h2&gt;

&lt;p&gt;Luckily &lt;a href="https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_%28SSRF%29/" rel="noopener noreferrer"&gt;OWASP has a good article&lt;/a&gt; about this exploit, how often it happens and how well it is covered.&lt;br&gt;
Please read that one for further information.&lt;/p&gt;

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

&lt;p&gt;While exploiting vulnerabilities is highly illegal it is still important to understand how they work.&lt;br&gt;
This example showed a very real thread of exposing anything on a local network, especially if (unsanitized) user input is run.&lt;br&gt;
Code Responsibly!&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Randomizing pages titles (and having good SEO)</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Tue, 20 Feb 2024 18:47:37 +0000</pubDate>
      <link>https://dev.to/aneshodza/randomizing-pages-titles-and-having-good-seo-jp</link>
      <guid>https://dev.to/aneshodza/randomizing-pages-titles-and-having-good-seo-jp</guid>
      <description>&lt;p&gt;I recently implemented a new feature on my &lt;a href="//aneshodza.ch"&gt;portfolio website&lt;/a&gt; where the website randomizes its title every time its refreshed.&lt;br&gt;
An example of that:&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%2Fqbfw48cmfrrgmgnx3ay8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbfw48cmfrrgmgnx3ay8.gif" alt="Gif of the changing page titles" width="600" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article is about how I implemented this (with code examples in NextJS) and how I fixed my SEO.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why would you need to fix your SEO?
&lt;/h3&gt;

&lt;p&gt;The issue with the changing page titles is simple: Every time the google crawler goes onto your website he sees a different title that gets indexed, changing it in the search results.&lt;br&gt;
That can mess with your SEO, as something like "[Your Name]'s personal website" is much better for finding the website than "Ran on my machine".&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing the titles
&lt;/h2&gt;

&lt;p&gt;This tutorial on how to implement it will be in NextJS, but you can follow along in every language, as it shouldn't change depending on the language.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting the title for the Google crawler
&lt;/h3&gt;

&lt;p&gt;First you want to go on your &lt;code&gt;_document.jsx&lt;/code&gt;, or inside of any layout page that you have, like &lt;code&gt;application.html.erb&lt;/code&gt; if you're implementing this in Rails. There you want to set the boring title, or the one that should get indexed. In addition to that you want to set the meta description and your favicon:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// NextJS code example
&amp;lt;Head&amp;gt;
  &amp;lt;meta
    name="description"
    content="I need to make the computer overlord happy, so: Anes Hodza made this! This is Anes Hodzas' digital property!"
  /&amp;gt;
  &amp;lt;link rel="icon" href="/favicon.ico" /&amp;gt;
  &amp;lt;title&amp;gt;Anes Hodzas' personal website&amp;lt;/title&amp;gt;
&amp;lt;/Head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating the custom titles
&lt;/h3&gt;

&lt;p&gt;Then you want to go to your &lt;code&gt;index&lt;/code&gt; page (the one that gets shown on &lt;code&gt;/&lt;/code&gt;).&lt;br&gt;
There you want to create a &lt;code&gt;const&lt;/code&gt; array with all your titles as strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const titles = [
  'Ran on my machine',
  'Web developer? I think?',
  'Engineer is an overstatement',
  'I\'m testing this in prod',
  'Does anyone read these?',
  'I\'m not a robot',
  'http://localhost:3000',
  'I don\'t use arch, btw'
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of something like Rails, where the backend logic is somewhat separated from the html code, you would probably put this in the controller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending the user your custom titles
&lt;/h3&gt;

&lt;p&gt;It's very important that the changing page titles are handled in the backend, as otherwise Google starts indexing your webpage weirdly.&lt;br&gt;
In the case of NextJS you would want to create a &lt;code&gt;getServerSideProps&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function getServerSideProps(context) {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in there we want to pick the title randomly and return it as a &lt;code&gt;prop&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function getServerSideProps(context) {
  const index = Math.floor(Math.random() * titles.length);
  let title = titles[index];

  return {
    props: {
      index,
      title
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you start refreshing your page you should see that the title changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing Google SEO again, because it's better to be safe than sorry
&lt;/h3&gt;

&lt;p&gt;The Google crawler for some reason sometimes still indexes a random title, so we will also have to change that in the server-side function. What we do first is define a function that checks if the &lt;code&gt;useragent&lt;/code&gt; is any google crawler. That we can do as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const isGooglebot = (userAgent) =&amp;gt; {
  return /(googlebot|google-inspectiontool\/1\.0)/i.test(userAgent);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why not just match any occurrence of Google you might ask. It's just a precaution in case Chrome decides to adapt the word Google into its user agent string.&lt;/p&gt;

&lt;p&gt;And now you also have to call the function and return your wanted title in case its the crawler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function getServerSideProps(context) {
  const index = Math.floor(Math.random() * titles.length);
  let title = titles[index];

  let userAgent = context.req.headers['user-agent'] || '';

  if (isGooglebot(userAgent)) {
    title = "Anes Hodzas' personal website"
  }

  return {
    props: {
      index,
      title
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after waiting for Google to index your website again, you should be good to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Won't this get marked as cloaking?
&lt;/h2&gt;

&lt;p&gt;I had this feature on for two weeks by now and there wasn't any indication of it being marked as cloaking:&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%2Fhnth33i1a85htq2j0jqu.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%2Fhnth33i1a85htq2j0jqu.png" alt="Picture of my website being show in the google search results" width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case anything happens, I'll keep you updated!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>design</category>
    </item>
    <item>
      <title>Getting out of tutorial hell</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Tue, 29 Aug 2023 22:53:50 +0000</pubDate>
      <link>https://dev.to/aneshodza/getting-out-of-tutorial-hell-cbi</link>
      <guid>https://dev.to/aneshodza/getting-out-of-tutorial-hell-cbi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We have all been there; You are watching the next hours long tutorial on language X or on framework Y, but for some odd reason you feel like you don't know anything in the end.&lt;br&gt;
That's what I call "tutorial hell" and with this article I hope I can teach you how I was able to leave tutorial hell and productively learn new languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why don't tutorials work?
&lt;/h2&gt;

&lt;p&gt;The reasons can be vastly different from person to person, as everyone has their own style/pace of learning. Nonetheless here are some reasons I found that cause tutorials to be ineffective:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pace
&lt;/h3&gt;

&lt;p&gt;Due to the tutorials needing to be made for a broad audience the pace will be off for most people: It either starts at the wrong skill-level or is overall just too fast/slow.&lt;br&gt;
That can be very frustrating, as having to skip around the video all the time costs a lot of time and feels like you did nothing in the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lack of interactivity
&lt;/h3&gt;

&lt;p&gt;The biggest problem for me personally was, how little you have to think on your own when following the videos.&lt;br&gt;
You simply just type whatever the person in the video is typing while their voice attempts to explain what exactly is happening, in vain.&lt;br&gt;
The lack of solving the coding problems yourself causes you to not learn how you would approach a new problem. That in turn renders you unable to make products on your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Over-simplification
&lt;/h3&gt;

&lt;p&gt;Something I always tried to fight with my articles like &lt;a href="https://dev.to/aneshodza/frameworks-hurt-junior-devs-and-why-math-is-important-1nbi"&gt;Frameworks hurt junior devs (and why math is important)&lt;/a&gt; is the neglect for properly understanding a topic.&lt;br&gt;
Being able to create 100 different Web-Apps in Rails using Devise (the authentication gem) doesn't mean that you actually understand what is happening and what you're doing.&lt;br&gt;
This shallow knowledge might be fine for a while, but it won't be long until you hit a, for you, unfixable problem because you actually have no idea what you are making. You only know how you are making it. &lt;/p&gt;

&lt;h2&gt;
  
  
  The "Question Framework" as your savior
&lt;/h2&gt;

&lt;p&gt;In a YouTube video about exactly this topic I heard the YouTuber use the name "Question Framework" to something I have been doing for a while now. I liked the name a lot, so I decided to adopt it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the "Question Framework" and how does it work?
&lt;/h3&gt;

&lt;p&gt;The Question Framework attempts to teach you, the user, something in a more interactive way by letting you figure out and solve problems on your own by asking the right questions.&lt;br&gt;
There are a few easy steps which you strictly have to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set an end goal&lt;/li&gt;
&lt;li&gt;Ask yourself "What do I need to do next?"&lt;/li&gt;
&lt;li&gt;Google how to do that specific task&lt;/li&gt;
&lt;li&gt;Repeat step 2
And it's as easy as that! An example is how I taught myself rust:&lt;/li&gt;
&lt;li&gt;Build a command line tool that reminds you about peoples birthdays&lt;/li&gt;
&lt;li&gt;I asked myself "How do I create a new rust app?"&lt;/li&gt;
&lt;li&gt;I googled it and found out I can simply run the command &lt;code&gt;rust new appname&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I asked myself "How do I read a text file and save it to a variable?"&lt;/li&gt;
&lt;li&gt;I googled and found out that &lt;code&gt;read_to_string(&amp;amp;dir).expect("Unable to read file");&lt;/code&gt; does the job&lt;/li&gt;
&lt;li&gt;Next I asked myself "How do I parse the file to users?"&lt;/li&gt;
&lt;li&gt;I googled...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Well, you get the idea. By following this principle you will probably need a lot longer to create your first product, but creating the 2nd one will be much easier, as you already had to face problems and think about solutions on your own.&lt;br&gt;
For anyone interested, the rust project is &lt;a href="https://github.com/aneshodza/birthday-reminder" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Next time you want to learn a new skill, try to challenge yourself with the Question Framework. This approach to learning new languages enables you to get a much deeper and more useful understanding of concepts and languages.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>An opinionated article about vim</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Fri, 30 Jun 2023 09:10:29 +0000</pubDate>
      <link>https://dev.to/aneshodza/an-opinionated-article-about-vim-4cdg</link>
      <guid>https://dev.to/aneshodza/an-opinionated-article-about-vim-4cdg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I have now been using vim and neovim for almost a year. In that time I built a lot of experience with the IDE, which I wanted to share with people thinking about making the switch.&lt;br&gt;
This article will mostly just go over why I &lt;strong&gt;like&lt;/strong&gt; vim, but I'll also be talking about some disadvantages.&lt;br&gt;
When showing code to use as an example of editing, I'll be taking code from my own Redmine plugin: &lt;a href="https://github.com/aneshodza/gnosis" rel="noopener noreferrer"&gt;gnosis&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Super fast code navigation
&lt;/h2&gt;

&lt;p&gt;The most obvious and most talked about point is how fast you can navigate code with vim. There are a lot of keybindings used for jumping around code. One example would be following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;protect_from_forgery&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[github_webhook_catcher semaphore_webhook_catcher]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if I want to remove the &lt;code&gt;github_webhook_catcher&lt;/code&gt; from the &lt;code&gt;protect_from_forgery&lt;/code&gt; statement, I would go following steps (assuming my cursor is somewhere completely random): &lt;code&gt;:4 WWW db&lt;/code&gt; does the job. Here is a video of how that might look:&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%2Fzb0uwrbxmc1c6em3v1bv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb0uwrbxmc1c6em3v1bv.gif" alt="Video of text being deleted, vim style" width="600" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot more keybindings and tricks that improve your speed. If you have trouble memorizing them all, &lt;a href="https://www.reddit.com/r/vim/comments/32r85c/this_is_my_favorite_vim_cheat_sheet_does_anyone/" rel="noopener noreferrer"&gt;this cheat sheet was A-tier&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extreme configuration
&lt;/h2&gt;

&lt;p&gt;A personal favorite is how much you can personalize vim. Everything is customizable, from your background color to very specific keybindings. One example of that would be &lt;a href="https://github.com/aneshodza/.dotfiles/blob/main/.vimrc" rel="noopener noreferrer"&gt;my own &lt;code&gt;.vimrc&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
As someone who gets irritated as soon as something tiny is wrong with their code editor, the ability to customize everything was a very big bonus.&lt;br&gt;
Currently I am using &lt;a href="https://github.com/NvChad/NvChad" rel="noopener noreferrer"&gt;nvchad&lt;/a&gt; with my &lt;a href="https://github.com/aneshodza/nvchad_config" rel="noopener noreferrer"&gt;own nvchad config&lt;/a&gt;, which makes for a beautiful code editor:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxplkrn53mv37ubx83sii.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%2Fxplkrn53mv37ubx83sii.png" alt="Screenshot of my nvchad dashboard" width="800" height="429"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43uv2ks56amymugrqqxf.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%2F43uv2ks56amymugrqqxf.png" alt="Screenshot of nvchad with open code" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Very good plugin system
&lt;/h2&gt;

&lt;p&gt;(Neo)vim supports plugins, which make your code editor much better. You need a faster way to comment stuff? Sure, here is &lt;a href="https://github.com/terrortylor/nvim-comment" rel="noopener noreferrer"&gt;nvim-comment&lt;/a&gt;. Now you need a better tool to surround text by certain characters? Alright, we also have &lt;a href="https://github.com/kylechui/nvim-surround" rel="noopener noreferrer"&gt;nvim-surround&lt;/a&gt;. And this goes on for almost everything you ever needed.&lt;br&gt;
And in the rare case that you &lt;strong&gt;can't&lt;/strong&gt; find a plugin for what you need: Write it yourself! It's very easy to write plugins, as vim and neovim both have a lot of functions that help with writing those.&lt;/p&gt;

&lt;h2&gt;
  
  
  The steep learning curve
&lt;/h2&gt;

&lt;p&gt;The biggest problem to vim is its steep learning curve. If you're someone who is already in a commercial setting and need to produce at a certain speed, learning vim will be pretty hard. As someone who is still in education I had the option of killing my coding speed for a few months, just so I could learn vim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alright, I'm convinced. Should I use vim or neovim?
&lt;/h2&gt;

&lt;p&gt;That choice everybody should make for himself, but I use &lt;strong&gt;neovim&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the difference between vim and neovim?
&lt;/h3&gt;

&lt;p&gt;The major difference is that neovim uses lua for its plugins, which vim is still on vimscript.&lt;br&gt;
Most people prefer lua, as it's more intuitive to write and has loads of uses outside of writing neovim plugins, making lua a much more useful language than vimscript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which one has better plugins?
&lt;/h3&gt;

&lt;p&gt;From personal experience, neovim has much better plugins, while not more.&lt;br&gt;
The fact that they're written in lua makes them more performant than vimscript, which already is a big benefit. On top of that: The fact that learning lua is much more useful than vimscript means that more people are willing to spend time learning it, making neovim plugins feel much more refined.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example comparison: fzf-vim vs. telescope
&lt;/h4&gt;

&lt;p&gt;As someone that has been using fzf for most of the time, changing to telescope opened up so much more options. Telescope has integrated git diffs, commit histories, language server settings, and much more.&lt;br&gt;
This is an example of how the commit history check looks like&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7nlbu5glqzf3q6hqreh.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%2Ft7nlbu5glqzf3q6hqreh.png" alt="Commit history of telescope" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I think learning vim is something everyone that is still in education should do, independent of if you actually stick with it or not.&lt;br&gt;
The great amount of configuration and useful keybindings makes using vim a great experience.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>productivity</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Memory in Rust</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Wed, 14 Jun 2023 16:01:46 +0000</pubDate>
      <link>https://dev.to/aneshodza/memory-in-rust-5g7e</link>
      <guid>https://dev.to/aneshodza/memory-in-rust-5g7e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently started getting more and more into Rust, as I wanted to adopt a fast programming language into my tech-stack. Coming from Java and Ruby I had various mountains to climb, one of them being Rust and its relation with memory. This article aims to explain it in an way that is easy to grasp for beginners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory allocation
&lt;/h2&gt;

&lt;p&gt;To understand ownership and borrowing we first need to understand how the memory is allocated. Rust allocates memory based on if the data size is fixed or dynamic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static Allocation
&lt;/h3&gt;

&lt;p&gt;On data types like &lt;code&gt;i32&lt;/code&gt; that have a fixed memory size, rust opts for static allocation on the stack.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fki7o9syg49r0laumof.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%2F7fki7o9syg49r0laumof.png" alt="Memory allocation on the stack for an i32" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Dynamic allocation
&lt;/h3&gt;

&lt;p&gt;Dynamic memory allocation happens on the heap. In this case, the needed memory to store a value can change over time, like with the &lt;code&gt;String&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"abcd"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"efgh"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case (assuming the &lt;code&gt;String&lt;/code&gt; is &lt;code&gt;UTF-8&lt;/code&gt; encoded) the variable first needs 4 bytes and then 8 bytes:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sqmwfdszixsssrbncd8.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%2F2sqmwfdszixsssrbncd8.png" alt="Memory where 4 more bytes were added" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Memory management
&lt;/h2&gt;

&lt;p&gt;Rust manages the memory at compile time, which means it doesn't have a garbage collector to find dead memory. That allows the code to run faster, but can also be the cause for memory leaks. To circumvent leaking memory and causing the code to slow down or crash after a while, the compiler enforces a strict set of rules. Those can primarily be split up into: &lt;strong&gt;ownership&lt;/strong&gt; and &lt;strong&gt;borrowing&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ownership
&lt;/h3&gt;

&lt;p&gt;Every value in Rust has a variable that owns it. So for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would make &lt;code&gt;x&lt;/code&gt; the owner of our &lt;code&gt;5&lt;/code&gt;. When &lt;code&gt;x&lt;/code&gt; goes out of scope the value will be dropped, as there isn't any owner left. That would look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This prints: "5"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Here the memory is dropped&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This gives a compiler error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when we check what the compiler says we see exactly what we predicted:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqknc41rrraerbistgj3m.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%2Fqknc41rrraerbistgj3m.png" alt="Screenshot of compiler error" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now when we assign &lt;code&gt;x&lt;/code&gt; to another variable, like &lt;code&gt;y&lt;/code&gt; normally we change the owner. That means, that after we do &lt;code&gt;let y = x&lt;/code&gt; accessing the variable &lt;code&gt;x&lt;/code&gt; will render an error. Following code example is used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Initialize x as "5"&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This prints: "5"&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This moves the value "5" from x to y&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This throws an error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the second &lt;code&gt;println!&lt;/code&gt; statement will error, as we try to borrow (explanation in next chapter) &lt;code&gt;x&lt;/code&gt;, after it has been moved to &lt;code&gt;y&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x7ageht1gk2x8kkoebg.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%2F0x7ageht1gk2x8kkoebg.png" alt="Borrowing moved value" width="800" height="198"&gt;&lt;/a&gt;&lt;br&gt;
It's quite visible what happened: &lt;code&gt;x&lt;/code&gt; does not hold the value anymore.&lt;br&gt;
If you're wondering why rust doesn't allow two variables to reference the same value, consider this scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- Here the value goes out of scope&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On line four the value references by &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; goes out of scope, which makes rust call the &lt;code&gt;drop&lt;/code&gt; function (in the case of dynamically allocated values) to free the memory. Now because both variables go out of scope it runs &lt;code&gt;drop(x)&lt;/code&gt; and &lt;code&gt;drop(y)&lt;/code&gt;, which causes a "double free condition", which means that both try to free the same memory. This won't happen with languages that have a garbage collector, because the collector properly clears.&lt;/p&gt;

&lt;h4&gt;
  
  
  The copy trait
&lt;/h4&gt;

&lt;p&gt;While that's the default behavior, certain types like integers, floats, etc. implement the &lt;code&gt;Copy&lt;/code&gt; trait, which changes how the move operation behaves.&lt;br&gt;
Let's take the move code again, but with &lt;code&gt;i32&lt;/code&gt; as its data type instead of &lt;code&gt;String&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Initialize x as an i32&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This prints: 5&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This copies the value instead of moving it&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Now this works fine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  When can we copy and when not?
&lt;/h4&gt;

&lt;p&gt;If we think back on how memory is allocated, it should be pretty obvious: If a variable is statically allocated the &lt;code&gt;Copy&lt;/code&gt; trait is included.&lt;br&gt;
The issue with having the &lt;code&gt;String&lt;/code&gt; type implement &lt;code&gt;Copy&lt;/code&gt; is, that &lt;code&gt;Copy&lt;/code&gt; creates a bit for bit copy. A simple example of why that is an issue would be as follows: As the &lt;code&gt;String&lt;/code&gt; is stored on the Heap, it needs to have a &lt;code&gt;Drop&lt;/code&gt; function, which clears the heap memory. The &lt;code&gt;Drop&lt;/code&gt; works, by taking the &lt;code&gt;pointer&lt;/code&gt;, that every String has to a memory address and clearing the memory there. The issue with using &lt;code&gt;Copy&lt;/code&gt; is, that it's a bit by bit copy, which would mean that the &lt;code&gt;pointer&lt;/code&gt; is the same in both &lt;code&gt;String&lt;/code&gt;s. When the scope ends, &lt;code&gt;Drop&lt;/code&gt; is called on both Strings, which would cause a "double-free", which causes the program to error.&lt;br&gt;
As a replacement for &lt;code&gt;Copy&lt;/code&gt;, those data types tend to implement &lt;code&gt;Clone&lt;/code&gt;, which, depending on the data type, can have very complex logic to properly copy the values and give it a new &lt;/p&gt;
&lt;h3&gt;
  
  
  Borrowing
&lt;/h3&gt;

&lt;p&gt;The issue with rusts ownership system is, that with a few function calls we can quickly have a lot of variables. That can look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;calculate_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A better approach would be to using "borrowing". A borrow is signalized with the &lt;code&gt;&amp;amp;&lt;/code&gt; symbol. That gives the variable temporary access to the variable.&lt;br&gt;
A simple example would be this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", world"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are able to push to &lt;code&gt;x&lt;/code&gt; by accessing both &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. The difference to just doing &lt;code&gt;let y = x&lt;/code&gt; is, that the type of &lt;code&gt;y&lt;/code&gt; is different now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;print_type_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="err"&gt;\\&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;string&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;print_type_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="err"&gt;\\&lt;/span&gt; &lt;span class="nn"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;string&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;print_type_of&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;any&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;type_name&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also improve our function from before by using borrowing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The length of '{}' is {}."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;calculate_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Already looks much cleaner, doesn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  De-referencing
&lt;/h3&gt;

&lt;p&gt;Let's say we want to create a function that takes in a &lt;code&gt;i32 x&lt;/code&gt; and mutates that value. The first thing that comes to mind would be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;double_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the value doubled is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;double_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this will throw an exception, as &lt;code&gt;x&lt;/code&gt; (inside the function scope) is only a reference to the value, instead of the value itself:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs22kvpdveokojcvstkr2.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%2Fs22kvpdveokojcvstkr2.png" alt="Screenshot of a compiler error saying " width="800" height="150"&gt;&lt;/a&gt;&lt;br&gt;
It is only the reference, because the parameter &lt;code&gt;x&lt;/code&gt; has been borrowed by using &lt;code&gt;&amp;amp;&lt;/code&gt; when passing it. Now if we want to access and manipulate the value we "de-reference" it by using a &lt;code&gt;*&lt;/code&gt;. Here is the same function, but corrected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// double_number(&amp;amp;mut x);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"the value doubled is {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;double_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// x *= 2; // This would mutate the pointer position x&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This will mutate the value at the pointer position x&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example that is easier to understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are making &lt;code&gt;y&lt;/code&gt; a mutable borrow of &lt;code&gt;x&lt;/code&gt;, i.e. a reference to &lt;code&gt;x&lt;/code&gt;. To then be able to manipulate the value &lt;code&gt;x&lt;/code&gt; trough &lt;code&gt;y&lt;/code&gt;, we "de-reference" it.&lt;br&gt;
We can visualize it like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsxy2xkthpigb0fc2jsj.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%2Fwsxy2xkthpigb0fc2jsj.png" alt="Visualization of dereferencing" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Rust trades off efficiency for simplicity, which can make it hard for developers to understand how memory is managed. I hope you were able to learn something from this article.&lt;br&gt;
Thanks to &lt;a href="https://www.youtube.com/watch?v=DJdUjjOmyx8" rel="noopener noreferrer"&gt;Low Level Learning&lt;/a&gt; for a very comprehensible explanation of almost every topic talked about in this article.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Is learning LaTeX worth it?</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Wed, 07 Jun 2023 18:38:27 +0000</pubDate>
      <link>https://dev.to/aneshodza/is-learning-latex-worth-it-11c6</link>
      <guid>https://dev.to/aneshodza/is-learning-latex-worth-it-11c6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;So I just finished my final project to get the "Swiss Certificate of Competence" in software development. That project consists of two major parts: Writing software and documenting it.&lt;br&gt;
The software part was a Redmine plugin, which you can find &lt;a href="https://github.com/aneshodza/gnosis" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The more important part, the documentation, you can find &lt;a href="https://github.com/aneshodza/ipa-documentation" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After small deliberation I decided to write it in LaTeX, based on a template. This articles goal is to share my experience with LaTeX.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is LaTeX?
&lt;/h2&gt;

&lt;p&gt;LaTeX is another way to write documents, like MS Word or Google Docs. But instead of the "What you see is what you get" approach taken by those editors, it takes a completely different one: You "code" the text. That leads to very fast (and mouse-less) writing, which has highly specialized results. For example, my documentation for the finals, had a chapter about the tools I was using. The source code for it looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\newpage&lt;/span&gt;
&lt;span class="k"&gt;\section&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Entwicklungsumgebung&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\subsection&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Versionierung&lt;span class="p"&gt;}&lt;/span&gt;
Für die Versionierung wird Git verwendet. Dabei wird GitHub als Remote-Repository verwendet. Das Repository mit
dem Source-Code kann unter &lt;span class="k"&gt;\url&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;https://github.com/aneshodza/gnosis&lt;span class="p"&gt;}&lt;/span&gt; gefunden werden. Für eine genauere Beschreibung
der Versionierung siehe Kapitel &lt;span class="k"&gt;\ref&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;sec:versioning&lt;span class="p"&gt;}&lt;/span&gt;.
&lt;span class="k"&gt;\subsection&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;IDE&lt;span class="p"&gt;}&lt;/span&gt;
Als IDE wird vim mit verschiedenen Plugins verwendet. Bestimmte Sachen wurden in der &lt;span class="k"&gt;\bgmintinline&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;bash&lt;span class="p"&gt;}{&lt;/span&gt;.vimrc&lt;span class="p"&gt;}&lt;/span&gt; Datei
konfiguriert, damit die Arbeit möglichst effizient ist. &lt;span class="k"&gt;\newline&lt;/span&gt;
Diese Konfigurationen sind unter &lt;span class="k"&gt;\newline&lt;/span&gt;
&lt;span class="k"&gt;\url&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;https://github.com/aneshodza/.dotfiles/blob/ad87ee9ecc5588a59d66e211797792099569ca95/.vimrc&lt;span class="p"&gt;}&lt;/span&gt; zu finden.
&lt;span class="k"&gt;\subsection&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;CI/CD&lt;span class="p"&gt;}&lt;/span&gt;
Für die CI/CD Pipeline wird SemaphoreCI verwendet. Das ist passend, da auch die PA sehr eng mit SemaphoreCI verbunden
ist.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which turned into this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z726ugt1nw5qsh2xx9u.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%2F1z726ugt1nw5qsh2xx9u.png" alt="Screenshot of rendered LaTeX" width="781" height="584"&gt;&lt;/a&gt;&lt;br&gt;
You can see: automatic page enumeration, showing the current date, numerated titles, professional font and a lot more.&lt;br&gt;
To be fair, that was achieved by using a template, but that's how LaTeX is supposed to be operated: You pick a nice template and write your documentation based on that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantages of LaTeX
&lt;/h2&gt;

&lt;p&gt;LaTeX has a wide variety of advantages to software developers, especially which are in education.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uniform and professional designs
&lt;/h3&gt;

&lt;p&gt;Every documentation written in LaTeX can look the same, have the same formatting and the same feel, as long as the same template is always used.&lt;br&gt;
Something that helped me a lot in my finals: There were a lot of points given by simply conforming to formatting rules (like having a header with the title, page enumeration, the current date in the footer) etc. All things that were done for me, simply by using a template.&lt;/p&gt;

&lt;h3&gt;
  
  
  Git versioning
&lt;/h3&gt;

&lt;p&gt;Having a safe versioning of your documentation may not be a bad idea. While you can also do the same with docx files, versioning LaTeX files is seamless due to the text being written and stored as actual text. Diffs just show that a binary file has been changed, but you can't really retrace your steps:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fneqmmjr4x5n7vmpb98xs.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%2Fneqmmjr4x5n7vmpb98xs.png" alt="Diff of a docx file" width="800" height="229"&gt;&lt;/a&gt;&lt;br&gt;
While in LaTeX, that looks a lot better:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdoxb4ypr7kow3hy30k8.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%2Fvdoxb4ypr7kow3hy30k8.png" alt="Diff of a LaTeX file" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Work speed
&lt;/h3&gt;

&lt;p&gt;The speed at which you can write documentation is a lot faster in LaTeX that most WYSIWYG editors. You can write it completely on the keyboard and even use your fancy code editors (like the most supreme: vim). Language servers make things like cross referencing very easy and other things like a table of contents or a bibliography are generated (and in the case of the bibliography even alphabetically sorted).&lt;br&gt;
After getting a grip on LaTeX you will feel the speed at which you write documentation going up.&lt;/p&gt;

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

&lt;p&gt;My personal experience with LaTeX is overall very positive and I would definitely suggest every student to learn it. My finals look very professional and conform to every formatting standard expected from it.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>productivity</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Looking for ruby open source contributions? Find them here.</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Fri, 19 May 2023 12:40:44 +0000</pubDate>
      <link>https://dev.to/aneshodza/looking-for-ruby-open-source-contributions-find-them-here-3od2</link>
      <guid>https://dev.to/aneshodza/looking-for-ruby-open-source-contributions-find-them-here-3od2</guid>
      <description>&lt;p&gt;I just wanted to start a small prompt, where open source projects that need contributions in ruby find contributors skilled in ruby.&lt;br&gt;
Happy hacking :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating multiple accounts with one E-Mail address</title>
      <dc:creator>anes</dc:creator>
      <pubDate>Wed, 12 Apr 2023 15:03:19 +0000</pubDate>
      <link>https://dev.to/aneshodza/creating-multiple-accounts-with-one-e-mail-address-3p0k</link>
      <guid>https://dev.to/aneshodza/creating-multiple-accounts-with-one-e-mail-address-3p0k</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When I was coding my first twitter bot, I ran into a major issue: I needed to register a new account for the bot, which required me to provide a unique email address.&lt;br&gt;
There was one big issue with that: I had the intention of making multiple bots, just to test the capabilities of the twitter API.&lt;br&gt;
I quickly realized that creating a new email for everyone of those would be really cumbersome and unmanageable after a while.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making use of "Address Aliasing"
&lt;/h2&gt;

&lt;p&gt;I quickly found out about a neat little trick called "address aliasing". What it does is, allow you to add a "tag" to your email address, without actually changing it.&lt;br&gt;
For Gmail and many other services you simply add a plus sign (+) right before the at (@) and add some text between the plus and at.&lt;br&gt;
That could look as follows:&lt;br&gt;
&lt;a href="mailto:some.example@gmail.com"&gt;some.example@gmail.com&lt;/a&gt; --&amp;gt; &lt;a href="mailto:some.example+devto@gmail.com"&gt;some.example+devto@gmail.com&lt;/a&gt;&lt;br&gt;
And that's also what I did for my bot account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important things to keep in mind
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If you are using a different provider than Gmail, there may be a different syntax for doing this.&lt;/li&gt;
&lt;li&gt;It won't work for all services, as some built tag checks into their uniqueness check. For me it has worked everywhere I used it.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>watercooler</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
