<?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>Forem: Adam Hawley</title>
    <description>The latest articles on Forem by Adam Hawley (@adamjhawley).</description>
    <link>https://forem.com/adamjhawley</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%2F278363%2Fa269f394-4c1a-4867-bd51-eb2c35b7d63b.jpg</url>
      <title>Forem: Adam Hawley</title>
      <link>https://forem.com/adamjhawley</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/adamjhawley"/>
    <language>en</language>
    <item>
      <title>Connecting to Firestore - Link-Sharing Site Part 3</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Tue, 26 Apr 2022 21:08:25 +0000</pubDate>
      <link>https://forem.com/adamjhawley/connecting-to-firestore-link-sharing-site-part-3-378f</link>
      <guid>https://forem.com/adamjhawley/connecting-to-firestore-link-sharing-site-part-3-378f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;New to this series? Start &lt;a href="https://adamjhawley.com/post/2022-02-16-creating-a-link-sharing-site-part-0/"&gt;here&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Thanks for taking the time to join me on my journey to create a new link-sharing site. In the &lt;a href="https://adamjhawley.com/post/2022-03-14-creating-a-link-sharing-site-part-2/"&gt;last post&lt;/a&gt; I talked about how I initialised Firebase. Today I get to talk about how I hooked the web app up to work with Firebase's offerings. In particular I will cover how I connected Firestore and gave users a way to submit and view links stored on it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Handling Authentication
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://adamjhawley.com/post/2022-03-14-creating-a-link-sharing-site-part-2/#creating-an-sign-up-page"&gt;previous post&lt;/a&gt;, I also described how I used the Firebase SDK function &lt;a href="https://firebase.google.com/docs/auth/web/password-auth#create_a_password-based_account"&gt;&lt;code&gt;createUserWithEmailAndPassword()&lt;/code&gt;&lt;/a&gt; to connect a sign-up form to Firebase Authentication.&lt;/p&gt;

&lt;p&gt;Even after signing up, I presumed that I would first have to create the account and then call a sign in function separately. However the Firebase SDK makes it easier than that! If an account is successfully created then the user is automatically signed in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Component Redirects
&lt;/h3&gt;

&lt;p&gt;So, a user has created an account and been signed in. At this point, most sites I know redirect the user back to their previous page or another specific page. To simplify things, I opted to redirect the user to the 'browse' page whenever&lt;br&gt;
they have signed in. This page is the page where users can 'browse' all of the recently added links, it also acts as the home page (see below).&lt;/p&gt;

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

&lt;p&gt;Initially, &lt;code&gt;createAccount()&lt;/code&gt; looked 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;createAccount(email, password) {
  const auth = getAuth();
  createUserWithEmailAndPassword(auth, email, password)
  .then((userCredential) =&amp;gt; {
      const user = userCredential.user;
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, I called &lt;code&gt;createAccount()&lt;/code&gt; and then immediately redirected the user to a new page. &lt;strong&gt;Without waiting for the response to &lt;code&gt;createUserWithEmailAndPassword()&lt;/code&gt;.&lt;/strong&gt; I quickly realised this was an issue, whether the account creation was successful or not was not important. If a user clicked the 'submit' button in the sign-up form, they were getting redirected, authenticated or not.&lt;/p&gt;

&lt;p&gt;However, if an account is not created due to an error such as an invalid email or password being used, then the user interface should give the user an opportunity to amend their form entries. To get around this, I wrapped my &lt;code&gt;createAccount()&lt;/code&gt; logic in a &lt;code&gt;Promise&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;createAccount(email, password) {
  return new Promise ((resolve, reject) =&amp;gt; {
    const auth = getAuth()
    createUserWithEmailAndPassword(auth, email, password)
    .then((userCredential) =&amp;gt; {
        this.user = userCredential.user;
        resolve()
    })
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a relative-newcomer to JavaScript, I am still trying to get to grips with everything related to &lt;code&gt;async&lt;/code&gt;, &lt;code&gt;await&lt;/code&gt;, &lt;code&gt;Promise&lt;/code&gt; etc. So for fellow newcomers, I recently published &lt;a href="https://adamjhawley.com/post/2022-04-12-basics-of-javascript-promises/"&gt;a guide on getting started with JavaScript Promises&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signing In
&lt;/h3&gt;

&lt;p&gt;Users could create accounts, hurrah! But they couldn't yet sign in without making a new account every time. Doesn't sound too user friendly to me...&lt;/p&gt;

&lt;p&gt;Keeping it as simple as possible, I put together a sign in page which looked exactly the same as the sign up page. The only difference being what went on when the user hit 'submit'. My &lt;code&gt;signIn()&lt;/code&gt; method is almost identical to &lt;code&gt;createAccount()&lt;/code&gt;. The difference being that &lt;code&gt;signIn()&lt;/code&gt; uses&lt;br&gt;
&lt;a href="https://firebase.google.com/docs/auth/web/password-auth#sign_in_a_user_with_an_email_address_and_password"&gt;&lt;code&gt;signInWithEmailAndPassword()&lt;/code&gt;&lt;/a&gt; rather than the aforementioned &lt;code&gt;createUserWithEmailAndPassword()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8TUz1_8U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojk7u0u1drbr3736z2tl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8TUz1_8U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojk7u0u1drbr3736z2tl.png" alt="Sign-in page" width="880" height="413"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Working Sign-in Page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now it's time to celebrate! Working authentication hooked up to Firestore. Users can now create accounts on the site and sign-in later.&lt;/p&gt;


&lt;h2&gt;
  
  
  Firestore
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Adding Links
&lt;/h3&gt;

&lt;p&gt;Onto the content of the site. We have already seen how users will view links on the browse page in the web component redirects section and in &lt;a href="https://adamjhawley.com/post/2022-03-04-creating-a-link-sharing-site-part-1/#a-page-for-producing"&gt;part 1 of the series&lt;/a&gt;, I showed how I created a page for submitting links but mentioned that the submit button did nothing at all. Time for that to change!&lt;/p&gt;

&lt;p&gt;I started by creating an event handler &lt;code&gt;submitLink&lt;/code&gt; to handle when the submit button in the form is pressed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get _form () {
  return this.renderRoot.querySelector('#submit-form')
}

async submitLink (e) {
  let userTitle = this._form.querySelector('#title-input').value
  let userLink = this._form.querySelector('#link-input').value
  const db = getFirestore(this.app);
  let col = collection(db, 'links')
  await addDoc(col, {
    link: userLink,
    title: userTitle
  })

  const event = new CustomEvent('submitted-link')
  this.dispatchEvent(event)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also amended the submit button in the template to use the new &lt;code&gt;submitLink&lt;/code&gt; handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;sl-button @click=${this.submitLink}&amp;gt;Submit&amp;lt;/sl-button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Firebase side of things, I start by using&lt;br&gt;
&lt;a href="https://firebase.google.com/docs/firestore/quickstart#initialize"&gt;getFirestore()&lt;/a&gt;. I pass &lt;code&gt;this.app&lt;/code&gt; to &lt;code&gt;getFirestore()&lt;/code&gt; where &lt;code&gt;this.app&lt;/code&gt; is a property passed to the web component equal to the output of &lt;a href="https://firebase.google.com/docs/firestore/quickstart#initialize"&gt;&lt;code&gt;initializeApp()&lt;/code&gt;&lt;/a&gt;. The aim of this first line is to initialise a variable with access to the database.&lt;/p&gt;

&lt;p&gt;Then I define &lt;code&gt;col&lt;/code&gt;, a variable with access to the specific collection within the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let col = collection(db, 'links')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to add the document containing the link to the collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await addDoc(col, {
  link: userLink,
  title: userTitle
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this operation is successful then we have added the link to the database! Following this, I use the same strategy as described earlier to redirect the user to a new page by dispatching a custom event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading Links
&lt;/h3&gt;

&lt;p&gt;Luckily reading from Firestore is very similar to writing to it. Here are the lines I use to get all of the available links from the links collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const db = getFirestore(this.app)
let col = collection(db, 'links')
const querySnapshot = await getDocs(col)
querySnapshot.forEach((doc) =&amp;gt; {
  this.linkBoxes.push(doc.data())
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two lines are exactly the same as writing and follow exactly what I described in the previous part. Things change a little in the third line.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://firebase.google.com/docs/reference/js/v8/firebase.firestore.QuerySnapshot"&gt;&lt;code&gt;querySnapshot&lt;/code&gt;&lt;/a&gt; contains the results of a query. By using &lt;code&gt;getDocs()&lt;/code&gt; on the whole collection &lt;code&gt;col&lt;/code&gt;, I am asking to return all of the documents in the collection into the variable &lt;code&gt;querySnapshot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the query is resolved, I loop through each document and add them to the list of links shown on the browse page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: to access the contents of each document you have to iterate through each and call its &lt;code&gt;.data()&lt;/code&gt; method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's all there is to it! Link submission works and now the home page is populated using links properly submitted by the user(s).&lt;/p&gt;




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

&lt;p&gt;In this update I have discussed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How I used JavaScript promises to perform redirects&lt;/li&gt;
&lt;li&gt;How the sign-in page came to existence&lt;/li&gt;
&lt;li&gt;How users gained the ability to submit links&lt;/li&gt;
&lt;li&gt;How the home page dynamically loads links from Firestore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I sincerely hope you have enjoyed this update. If you would like to hear when I publish more updates, follow me here on &lt;a href="https://dev.to/adamjhawley"&gt;Dev.to&lt;/a&gt; or follow me on &lt;a href="https://twitter.com/_adamjhawley"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Get Started with JavaScript Promises (in Under 2 Minutes)</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Tue, 12 Apr 2022 19:48:48 +0000</pubDate>
      <link>https://forem.com/adamjhawley/get-started-with-javascript-promises-in-under-2-minutes-58ge</link>
      <guid>https://forem.com/adamjhawley/get-started-with-javascript-promises-in-under-2-minutes-58ge</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Welcome to an extremely brief introduction to JavaScript Promises. After getting to grips with Promises myself I thought I would share the essentials that I needed to put them into practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Basics of JS Promises
&lt;/h2&gt;

&lt;p&gt;Promises can be defined with the following recipe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function function1 () {
  return new Promise ((resolve, reject) =&amp;gt; {
    try {
      doSomeStuff()
      resolve()
    } catch (err) {
      reject(err) 
    }
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;resolve()&lt;/code&gt; should be called if the operation associated with the Promise has been successful. &lt;code&gt;reject()&lt;/code&gt; should be called if the Promise could not be &lt;strong&gt;resolved&lt;/strong&gt;, maybe there was some sort of problem when trying to perform the associated operation.&lt;/p&gt;

&lt;p&gt;The caller function then has the option to asynchronously wait for the Promise to resolve using &lt;code&gt;await&lt;/code&gt; or the &lt;code&gt;then()&lt;/code&gt; method of Promises. To use &lt;code&gt;await&lt;/code&gt;, declare the entire function as asynchronous using the &lt;code&gt;async&lt;/code&gt; keyword. Here are examples of both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function callerFunc1() {
  // Use 'await'
  await function1()
}

function callerFunc2() {
  // Use '.then()'
  function1().then(() =&amp;gt; {
    doSomethingAfterwards() 
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two extra things about &lt;code&gt;Promise.then()&lt;/code&gt;. Firstly, we can chain &lt;code&gt;.then()&lt;/code&gt; statements together to make something that operates like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function callerFunc3() {
  function1.then(() =&amp;gt; {
    console.log('First thing finished')
  }).then(() =&amp;gt; {
    console.log('Second thing finished')
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secondly, &lt;code&gt;then()&lt;/code&gt; can actually take two arguments: one in case the Promise &lt;strong&gt;resolves&lt;/strong&gt; and another to handle the case when the Promise &lt;strong&gt;rejects&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function callerFunc4() {
  function1.then(() =&amp;gt; {
    console.log('Everything went to plan!')
  }, () =&amp;gt; {
    console.log('The Promise rejected :(')
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to see these examples in action, check out &lt;a href="https://stackblitz.com/edit/js-mkctvv?devToolsHeight=33&amp;amp;file=index.js"&gt;this StackBlitz&lt;/a&gt; &lt;/p&gt;




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

&lt;p&gt;Hopefully you found this helpful, to get updates as soon as I release helpful guides such as this follow me on &lt;a href="https://twitter.com/_adamjhawley"&gt;Twitter&lt;/a&gt; or &lt;a href="https://dev.to/adamjhawley"&gt;Dev&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Initialising a Firebase App</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Sun, 20 Mar 2022 21:50:37 +0000</pubDate>
      <link>https://forem.com/adamjhawley/initialising-a-firebase-app-7e3</link>
      <guid>https://forem.com/adamjhawley/initialising-a-firebase-app-7e3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Welcome to the latest update in the "Creating a Link-Sharing Website" series where I try to build a StackExchange and HackerNews crossover. Before this update, I had a couple of working UI elements and (hopefully) a cool idea. See my &lt;a href="https://adamjhawley.com/post/2022-03-04-creating-a-link-sharing-site-part-1/"&gt;last post&lt;/a&gt; to see exactly how I got started building out the first core UI elements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to jump straight to reading how I got started with Firebase, click here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I concluded the last post by discussing how my top priority was to consider database solutions. This is because, at that point, a user could interact with the UI and &lt;em&gt;'submit'&lt;/em&gt; links to the website but with no real effect. The UI would simply gobble up the form entries and do nothing with them. Content generation that doesn't involve generating content? Sounds pretty redundant to me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deciding on a Storage Solution
&lt;/h2&gt;

&lt;p&gt;So I needed a way to store the links users would be uploading to the website. Naturally, I started to consider a number of database solutions I have used in the past.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.mongodb.com/"&gt;MongoDB&lt;/a&gt;: a document-based NoSQL database that I have extensive prior experience with.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt;: actually a whole suite of services provided by Google. It includes, but is not limited to, two different database offerings, an authentication service and hosting.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.elastic.co/elasticsearch/"&gt;ElasticSearch&lt;/a&gt;: in the past, I have worked with ElasticSearch as a database for storing text data. Because of this, I know that it has extremely powerful search and query capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When evaluating the different choices I had to think about what I was going to be storing. URLs and the title's of the pages. Text. The basis of the site is for people to share website links. If I want people to be able to share and view&lt;br&gt;
them, I have to store them somewhere. Specifically, my plan is to store simple objects in the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  url: "https://adamjhawley.com/post/2022-02-07-using-git-rebase-to-perfect-commits/",
  title: "Using 'git rebase' to Perfect Commits"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though MongoDB would definitely be up to the job if I had opted to select it, I ultimately disregarded it. It was going to do exactly what it said on the tin; no more, no less. It would serve as a document-based database with developer-friendly APIs. So this would have definitely been my choice if another wasn't so tempting...&lt;/p&gt;

&lt;p&gt;Despite the fact that I had experience using ElasticSearch to quickly navigate mountains of text data, I had an important realisation. I was not going to be doing any complicated queries. So what's the point? I had to stop myself from&lt;br&gt;
dodging &lt;a href="https://en.wikipedia.org/wiki/Occam%27s_razor"&gt;Occam's razor&lt;/a&gt; and consider something else.&lt;/p&gt;

&lt;p&gt;It is important to me to keep the website true to itself. I know from experience that I, like many other developers, am easily distracted by the thought of adding cool new features, insights and analytics to websites long before they are necessary.&lt;/p&gt;

&lt;p&gt;Now onto Firebase. As I mentioned earlier, Firebase is rather a whole suite of services provided by Google. Apart from a storage solution, Firebase offers &lt;a href="https://firebase.google.com/products/hosting"&gt;hosting&lt;/a&gt;, &lt;a href="https://firebase.google.com/products/auth"&gt;authentication&lt;/a&gt; and several other services.&lt;/p&gt;

&lt;p&gt;Initially it might appear as if I am going against what I just said with regards to keeping things as simple as possible. However, there is a key difference between the extra features of Elasticsearch and the other services offered by Firebase.&lt;/p&gt;

&lt;p&gt;Solutions for hosting and authentication are things I would need to even get the base functionality of the site off the ground. For example, without a way to host the site, there is no way for users to reach it. Of course, I could handle&lt;br&gt;
this myself but that would involve taking on a considerably large amount of work. Remember, at this point, &lt;a href="https://adamjhawley.com/post/2022-03-04-creating-a-link-sharing-site-part-1/"&gt;I am focusing on an MVP&lt;/a&gt;. Furthermore, I am considering making the website open source as a template for other developers to use. By using Firebase it means that it would be much easier for someone else to pick up the project. All they need is a Google account!&lt;/p&gt;


&lt;h2&gt;
  
  
  Firebase
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Initialising a Firebase Project
&lt;/h3&gt;

&lt;p&gt;So how did I actually get started? The first thing I did was turn to the Firebase &lt;a href="https://firebase.google.com/docs/web/setup"&gt;web documentation on getting started&lt;/a&gt;. From there I followed the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Created a Firebase project using the &lt;a href="https://console.firebase.google.com/u/0/"&gt;Firebase
console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Installed the &lt;a href="https://firebase.google.com/docs/cli/#install-cli-mac-linux"&gt;Firebase CLI
tools&lt;/a&gt;:
&lt;code&gt;npm install -g firebase-tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Logged in using Firebase CLI: &lt;code&gt;firebase login&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Initialised the project as a Firebase app: &lt;code&gt;firebase init&lt;/code&gt; with the following configuration:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ivbIMAM3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uby2a7cfobyepzovdm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ivbIMAM3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uby2a7cfobyepzovdm6.png" alt=" raw `firebase init` endraw  dialogue." width="880" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: during the &lt;code&gt;firebase init&lt;/code&gt; dialogue you might get an error similar to the following. Don't panic. For some reason, Google requires that users create the Firestore instance in the UI before it can be accessed with CLI tools. Simply follow the URL in the error and create a Firebase instance in your browser.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: It looks like you haven't used Cloud Firestore in this project before. Go
to https://console.firebase.google.com/project/&amp;lt;PROJECT-ID&amp;gt;/firestore to
create your Cloud Firestore database.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, Firebase CLI automatically generates a handful of config files which it will use for deploying to Firebase, configuring storage etc.&lt;/p&gt;

&lt;p&gt;In order to submit links to Firestore (the Firebase storage service I have opted for), it requires a working authentication system. By default, Firestore does not allow for unrestricted access to the database. Besides, I plan to limit users to only be able to post links if they are signed in to an account. So authentication is a necessary step. So I decided it was best to start with it rather than working around it and then having to come back and rework in future.&lt;/p&gt;




&lt;h3&gt;
  
  
  Problems with FirebaseUI
&lt;/h3&gt;

&lt;p&gt;During the process of setting up the application to use Firebase authentication, I found &lt;em&gt;helpful&lt;/em&gt; &lt;a href="https://firebase.google.com/docs/auth/web/firebaseui"&gt;documentation&lt;/a&gt; on how to use a pre-built UI for authentication which apparently allows for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Multiple authentication providers (email/password, Google, Github etc.)&lt;/li&gt;
&lt;li&gt;Account linking&lt;/li&gt;
&lt;li&gt;Customisation&lt;/li&gt;
&lt;li&gt;One-tap sign-up and automatic sign-in&lt;/li&gt;
&lt;li&gt;Localised UI&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;This all sounded great. I tried to integrate this into the application but ran into an issue trying to import the package.&lt;/p&gt;

&lt;p&gt;In the project, I use ES module imports. That is, imports in the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import x from 'npm-module/app';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For some reason, this doesn't seem to be supported by the FirebaseUI. &lt;a href="https://github.com/firebase/firebaseui-web/issues/674"&gt;This GitHub issue&lt;/a&gt; has been open since 2020 with no clear progress seemingly made.&lt;/p&gt;

&lt;p&gt;After reading through the issue thread I decided to abandon using the FirebaseUI and build my own authentication UI.&lt;/p&gt;




&lt;h3&gt;
  
  
  Creating an Sign-Up Page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GEdynYMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ovfauszoweayse2374y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GEdynYMG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ovfauszoweayse2374y.png" alt="Link-Sharer sign-up page." width="880" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using shoelace.style's helpful &lt;a href="https://shoelace.style/components/input"&gt;&lt;code&gt;&amp;lt;sl-input&amp;gt;&lt;/code&gt; elements&lt;/a&gt; with built-in input validation for emails, I put together a sign-up page with a component with the following render functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
get _form () {
  return this.renderRoot.querySelector('#signupform')
}

handleSubmit (event) {
  let email = this._form.querySelector('#email').value
  let password = this._form.querySelector('#password').value
  this.createAccount(email, password)
  this.signIn(email, password)
}

render() {
  return html`
      &amp;lt;div id="signupform"&amp;gt;
          &amp;lt;sl-input id="email" label="Email" type="email" placeholder="Enter email here" clearable&amp;gt;&amp;lt;/sl-input&amp;gt;
          &amp;lt;sl-input id="password" label="Password" type="password" toggle-password placeholder="Enter password here"&amp;gt;&amp;lt;/sl-input&amp;gt;
          &amp;lt;br&amp;gt;
          &amp;lt;sl-button @click=${this.handleSubmit}&amp;gt;Submit&amp;lt;/sl-button&amp;gt;
      &amp;lt;/div&amp;gt;
  `;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;createAccount()&lt;/code&gt; and &lt;code&gt;signIn()&lt;/code&gt; use the &lt;a href="https://firebase.google.com/docs/auth/web/password-auth"&gt;Firebase authentication SDK&lt;/a&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;createAccount(email, password) {
  const auth = getAuth();
  createUserWithEmailAndPassword(auth, email, password)
  .then((userCredential) =&amp;gt; {
      const user = userCredential.user;
  })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of interesting things here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I linked &lt;code&gt;handleSubmit()&lt;/code&gt; to the click event of the &lt;code&gt;&amp;lt;sl-button&amp;gt;&lt;/code&gt; element
using &lt;code&gt;@click=${this.handleSubmit}&lt;/code&gt;. For more information, see the lit documentation on &lt;a href="https://lit.dev/docs/components/events/#adding-event-listeners-in-the-element-template"&gt;&lt;em&gt;adding event listeners in the element template&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_form&lt;/code&gt; acts as a way to make the child &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element accessible throughout the component and to parent components. This technique is also documented in the lit documentation. See &lt;a href="https://lit.dev/docs/components/shadow-dom/#accessing-nodes-in-the-shadow-dom"&gt;&lt;em&gt;accessing nodes in the shadow DOM&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;At the end of this update I have a working way for users to sign up! I had hoped to have a working storage solution by this point but I am happy with the progress I have made. I think the time I have invested into setting up Firebase will pay dividends in future when it comes to integrating with other services.&lt;/p&gt;

&lt;p&gt;Only time will tell! Make sure you follow me to find out! Or catch up on my personal site where these blogs are posted first: &lt;a href="//adamjhawley.com"&gt;adamjhawley.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>lit</category>
    </item>
    <item>
      <title>Creating a Link-Sharing Site Part 1</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Fri, 04 Mar 2022 22:41:36 +0000</pubDate>
      <link>https://forem.com/adamjhawley/creating-a-link-sharing-site-part-1-2llp</link>
      <guid>https://forem.com/adamjhawley/creating-a-link-sharing-site-part-1-2llp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Welcome to the first update on my journey to creating a link-sharing site. If you are interested in what I am doing and why I am doing it check out the &lt;a href="https://adamjhawley.com/post/2022-02-16-creating-a-link-sharing-site-part-0/"&gt;introduction to the series&lt;/a&gt;. And if you want to get notified when I post new updates, follow me on &lt;a href="https://twitter.com/_adamjhawley"&gt;Twitter&lt;/a&gt; or sign up to &lt;a href="https://adamjhawley.com/post/2022-03-04-creating-a-link-sharing-site-part-1/#mailing-list"&gt;my mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have prioritised getting something functional. This means that I haven't exactly created anything &lt;em&gt;beautiful&lt;/em&gt; yet. But I'm sure that will be very obvious.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the Basics
&lt;/h2&gt;

&lt;p&gt;I broke down my requirements based on the pages and functionality I needed to create to get an MVP (&lt;a href="https://en.wikipedia.org/wiki/Minimum_viable_product"&gt;minimum viable product&lt;/a&gt;) up and running.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Page for Consuming
&lt;/h3&gt;

&lt;p&gt;Link-sharing websites are, simply put, a platform for facilitating content consumption. That is, the &lt;em&gt;'content creation'&lt;/em&gt; side of this website is limited to a user providing a link and a title. At least for the time being... Furthermore, I expect the majority of users to spend much more time &lt;strong&gt;consuming&lt;/strong&gt; content rather than &lt;strong&gt;producing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Therefore, I need a way for users to find content to consume! This page will probably act as the home page for the site.&lt;/p&gt;

&lt;p&gt;My current intention is for this page to simply contain a list of cards where each one contains just the title of the link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y_2U2YJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoudq5yxm0k4xvlxy55s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y_2U2YJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoudq5yxm0k4xvlxy55s.png" alt="Screenshot of my ‘browsing’ page" width="880" height="377"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  A Page for Producing
&lt;/h3&gt;

&lt;p&gt;Then again, what's the point in a page for consuming content if there is no content to be consumed! Sounds like I can't get away with not building a page for submitting links to the site.&lt;/p&gt;

&lt;p&gt;So, as I said, I went ahead and made it as minimal as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SZdpRczx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3n4ntdr6d34vu2sawa4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SZdpRczx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3n4ntdr6d34vu2sawa4j.png" alt="Screenshot of my 'submit' page" width="880" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it's worth noting that for the time being, that 'Submit' button sends the link nowhere. My plan is to hook this up to a database which will contain all of the links on the site.&lt;/p&gt;




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

&lt;p&gt;That's all I have for this update. My main priority in upcoming updates will be hooking up the site to use a persistent database to store the links. It has been great fun getting started with this project and I am very excited to see where it can go!&lt;/p&gt;

&lt;p&gt;I know that I am new to the concept of 'sharing your work' but I know consistency is key so stay tuned for another post coming soon!&lt;/p&gt;

&lt;p&gt;If you enjoyed this post then please consider following me on &lt;a href="https://dev.to/adamjhawley"&gt;dev.to&lt;/a&gt; or on &lt;a href="https://twitter.com/_adamjhawley"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Using 'git rebase' to Perfect Commits</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Mon, 21 Feb 2022 16:00:17 +0000</pubDate>
      <link>https://forem.com/adamjhawley/using-git-rebase-to-perfect-commits-19d9</link>
      <guid>https://forem.com/adamjhawley/using-git-rebase-to-perfect-commits-19d9</guid>
      <description>&lt;p&gt;I have long tried to get into the good habit of committing as I develop. However, I often fell into the same scenario. On commit №4, I would realise that I should have worked something differently in commit №2.&lt;/p&gt;

&lt;p&gt;Naively, my old approach was a combination of adding extra re-work commits and different forms of &lt;code&gt;git reset&lt;/code&gt;. &lt;code&gt;git rebase&lt;/code&gt; to the rescue!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;git rebase -i&lt;/code&gt; command was everything I believed had to be part of git but didn't know of. The &lt;code&gt;-i&lt;/code&gt; flag is the 'interactive' mode of &lt;code&gt;git rebase&lt;/code&gt;. Which allows you to choose which commits you want to rebase.&lt;/p&gt;

&lt;p&gt;Let's have a look at an example to illustrate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fm0EfBfn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lenlv6gwqb1sfz568vas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fm0EfBfn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lenlv6gwqb1sfz568vas.png" alt=" raw `git log` endraw  output before correcting my mistake" width="880" height="953"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;At this point I made a mistake a couple of commits ago and have even made further changes to some of the bad code I have written as part of future commits.&lt;/p&gt;

&lt;p&gt;To go back in time, I use &lt;code&gt;git rebase -i &amp;lt;COMMIT_ID&amp;gt;&lt;/code&gt;. Where &lt;code&gt;&amp;lt;COMMIT_ID&amp;gt;&lt;/code&gt; is the commit id of a commit BEFORE my mistake.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fU72OeiX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8vjl2we6hoc5804jbi0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fU72OeiX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8vjl2we6hoc5804jbi0.png" alt=" raw `git rebase -i` endraw " width="880" height="738"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;As shown in the helpful comments, there are many commands I can use for each commit and each one is explained. The commands I use most-frequently are 'edit' and 'reword' ('reword' is for the times when you have a typo in your commit message).&lt;/p&gt;

&lt;p&gt;Here we can change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;e&lt;/code&gt; or &lt;code&gt;edit&lt;/code&gt; next to our bad commit before saving and closing the file.&lt;/p&gt;

&lt;p&gt;Then I can go in and change my mistake. Once the changes are made, I can &lt;code&gt;git commit --amend&lt;/code&gt; to fix the commit itself.&lt;/p&gt;

&lt;p&gt;Once my initial mistakes have been corrected and git knows about the fixes I can use &lt;code&gt;git rebase --continue&lt;/code&gt;. git will now try to apply my old commits (№3 &amp;amp; №4) on top of my fixes.&lt;/p&gt;

&lt;p&gt;If there are any conflicts git will let you know. These happen in this case if your fix for the broken code replaced some of the code that you changed in later, good commits.&lt;/p&gt;

&lt;p&gt;You should solve the conflicts so that the code is as you would want it at that commit. Importantly, you should stop before using &lt;code&gt;git commit --amend here&lt;/code&gt;. git stopped to let you shape the commit in the way you want it and did not apply it yet. This means that to save this rework in the same commit, you should just go straight to &lt;code&gt;git rebase --continue&lt;/code&gt; where git will ask you to confirm/edit the commit message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r3fSmw1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efcuwom2kvfxy9f4i9km.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r3fSmw1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efcuwom2kvfxy9f4i9km.png" alt=" raw `git log` endraw  output as if nothing was ever any different…" width="880" height="1010"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And there we have it! A clean git history with useful commits. Learning &lt;code&gt;git rebase&lt;/code&gt; has truly given me a greater confidence using git and helped increase both my productivity and the quality of my work. I hope this you have managed to learn something too and thanks for reading this far!&lt;/p&gt;

&lt;p&gt;To keep in the loop consider following me or signing up to my mailing list on the &lt;a href="https://adamjhawley.com/post/2022-02-07-using-git-rebase-to-perfect-commits/"&gt;original post on my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>vcs</category>
    </item>
    <item>
      <title>Creating a Link-Sharing Site Part 0</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Sat, 19 Feb 2022 21:24:35 +0000</pubDate>
      <link>https://forem.com/adamjhawley/creating-a-link-sharing-site-part-0-2f2j</link>
      <guid>https://forem.com/adamjhawley/creating-a-link-sharing-site-part-0-2f2j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Welcome to a new series of blog posts. In this series I will be sharing my progress on a new project. What's the new project? I want to create a link-sharing site similar to &lt;a href="https://news.ycombinator.com/"&gt;HackerNews&lt;/a&gt; but with the flexibility of &lt;a href="https://stackexchange.com/"&gt;StackExchange&lt;/a&gt;.&lt;br&gt;
Read on for more details.&lt;/p&gt;


&lt;h2&gt;
  
  
  Motivation - Why am I doing this?
&lt;/h2&gt;

&lt;p&gt;As an avid reader of &lt;a href="https://news.ycombinator.com/"&gt;HackerNews&lt;/a&gt; one day I started to wonder if this kind of site exists in other domains. I knew that aggregators were popular in areas like finding new music but these tend to be more complex.&lt;/p&gt;

&lt;p&gt;The thing I love about HackerNews is the organic growth of different links. When a link is shared on the site it is not surrounded by some long description or backstory. Just the title of the page. This means that the quality of the link is evaluated by readers based on the content rather than how well the poster is able to dress up the page with a misleading or exaggerating description.&lt;/p&gt;

&lt;p&gt;As a developer, I also spend a lot of time on another site, &lt;a href="https://stackoverflow.com/"&gt;StackOverflow&lt;/a&gt; or more generally, &lt;a href="https://stackexchange.com/"&gt;StackExchange&lt;/a&gt;. One interesting thing I find about StackExchange is the way that it has taken a concept which works in separate domains and implemented it across them separately. For example, as well as StackOverflow for programming, there is also &lt;a href="//english.stackexchange.com"&gt;english.stackexchange.com&lt;/a&gt; and &lt;a href="//mathematics.stackexchange.com"&gt;mathematics.stackexchange.com&lt;/a&gt; for English and maths respectively. See a full list here: &lt;a href="https://stackexchange.com/sites"&gt;https://stackexchange.com/sites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Considering these two sites I spend an awful lot of time on, I thought I would try to create a network of link sharing sites across different domains.&lt;/p&gt;


&lt;h2&gt;
  
  
  Showing My Work
&lt;/h2&gt;

&lt;p&gt;Recently, I finished reading &lt;a href="https://www.goodreads.com/book/show/18290401-show-your-work"&gt;'Show Your Work!' by Austin Kleon&lt;/a&gt; (and I highly recommend it)! To complement this, I recently listened to &lt;a href="https://www.indiehackers.com/podcast/006-josh-pigford-of-baremetrics"&gt;a great Indie Hackers podcast with Josh Pigford&lt;/a&gt;. Both of these inspired me to get into the habit of sharing my work. My blog itself is still in its infancy and I am trying to build up a habit of  posting more regularly both as a good incentive to publicise work I produce and to track my learning with time.&lt;/p&gt;

&lt;p&gt;Because of this I plan to blog my progress on this project and will be open to any feedback. If you want to keep updated with my progress, I strongly recommend signing up to my mailing list on my blog &lt;a href="https://adamjhawley.com/post/2022-02-16-creating-a-link-sharing-site-part-0/#mailing-list"&gt;here&lt;/a&gt;. &lt;/p&gt;


&lt;h2&gt;
  
  
  Technology - How am I going to build this thing?
&lt;/h2&gt;

&lt;p&gt;I have recently been picking up some experience using &lt;a href="https://lit.dev/"&gt;lit&lt;/a&gt; and have found that it provides a very quick and easy way to get going with web components. This is about all the thinking I wanted to do at this point. Too often I get bogged down planning and deciding on frameworks, languages etc. This time I wouldn't let that happen. For better or for worse...&lt;/p&gt;

&lt;p&gt;One thing I had heard of but not had the chance to use was the &lt;a href="https://github.com/lit/lit-element-starter-js"&gt;Lit element JavaScript project template&lt;/a&gt;. So this is going to act as the baseline for the project.&lt;/p&gt;

&lt;p&gt;Here's the first element I created which is incredibly basic. &lt;code&gt;LinkBox&lt;/code&gt; refers to a box or card containing the link someone has shared.&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;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&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;lit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * A small box containing a link and a title.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;LinkBox&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;properties&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="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/**
       * The title of the link.
       * @type {string}
       */&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;type&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="cm"&gt;/**
       * The link itself.
       * @type {string}
       */&lt;/span&gt;
      &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;type&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="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&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;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;a href=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;sl-button&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/sl-button&amp;gt;&amp;lt;/a&amp;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;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ls-link-box&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LinkBox&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Keep in Touch
&lt;/h2&gt;

&lt;p&gt;For now, this is where I am. I aim to post roughly once a week with updates on my progress. I hope you enjoyed reading and wish me luck! As mentioned earlier, if you want to get updates straight to your inbox, consider following me or checking out the original article and joining my mailing list on my blog &lt;a href="https://adamjhawley.com/post/2022-02-16-creating-a-link-sharing-site-part-0/#mailing-list"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Part-of-Speech Tagging Simplified</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Sat, 17 Oct 2020 08:53:07 +0000</pubDate>
      <link>https://forem.com/adamjhawley/part-of-speech-tagging-simplified-2c12</link>
      <guid>https://forem.com/adamjhawley/part-of-speech-tagging-simplified-2c12</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;How are POS Tags Assigned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Part-of-Speech tagging is a very useful foundation of NLP and deeper NLP concepts.  The action involves analysing text and returning the tokens of the text with the appropriate Part-of-Speech (POS) tags.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  POS Tags
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Read this blog post on &lt;a href="//adamjhawley.github.io"&gt;my website&lt;/a&gt; for a better experience (dev.to please implement markdown tables)!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;ADJ: &lt;a href="https://universaldependencies.org/u/pos/ADJ.html" rel="noopener noreferrer"&gt;adjective&lt;/a&gt; -&amp;gt; super &lt;strong&gt;cat&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ADP: &lt;a href="https://universaldependencies.org/u/pos/ADP.html" rel="noopener noreferrer"&gt;apposition&lt;/a&gt; -&amp;gt; my &lt;strong&gt;friend Liam&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ADV: &lt;a href="https://universaldependencies.org/u/pos/ADV.html" rel="noopener noreferrer"&gt;adverb&lt;/a&gt; -&amp;gt; The boy ran &lt;strong&gt;quickly&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;AUX: &lt;a href="https://universaldependencies.org/u/pos/AUX_.html" rel="noopener noreferrer"&gt;auxiliary&lt;/a&gt; -&amp;gt; He &lt;strong&gt;will&lt;/strong&gt; make&lt;/li&gt;
&lt;li&gt;CCONJ: &lt;a href="https://universaldependencies.org/u/pos/CCONJ.html" rel="noopener noreferrer"&gt;coordinating conjunction&lt;/a&gt; -&amp;gt; this &lt;strong&gt;and&lt;/strong&gt; that&lt;/li&gt;
&lt;li&gt;DET: &lt;a href="https://universaldependencies.org/u/pos/DET.html" rel="noopener noreferrer"&gt;determiner&lt;/a&gt; -&amp;gt; &lt;strong&gt;the&lt;/strong&gt; squirrel&lt;/li&gt;
&lt;li&gt;INTJ: &lt;a href="https://universaldependencies.org/u/pos/INTJ.html" rel="noopener noreferrer"&gt;interjection&lt;/a&gt; -&amp;gt; &lt;strong&gt;Oi!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;NOUN: &lt;a href="https://universaldependencies.org/u/pos/NOUN.html" rel="noopener noreferrer"&gt;noun&lt;/a&gt; -&amp;gt; the &lt;strong&gt;dog&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;NUM: &lt;a href="https://universaldependencies.org/u/pos/NUM.html" rel="noopener noreferrer"&gt;numeral&lt;/a&gt; -&amp;gt; &lt;strong&gt;one&lt;/strong&gt; fork&lt;/li&gt;
&lt;li&gt;PART: &lt;a href="https://universaldependencies.org/u/pos/PART.html" rel="noopener noreferrer"&gt;particle&lt;/a&gt; -&amp;gt; &lt;strong&gt;not&lt;/strong&gt; Sam &lt;strong&gt;’s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;PRON: &lt;a href="https://universaldependencies.org/u/pos/PRON.html" rel="noopener noreferrer"&gt;pronoun&lt;/a&gt; -&amp;gt; &lt;strong&gt;he&lt;/strong&gt; shouts&lt;/li&gt;
&lt;li&gt;PROPN: &lt;a href="https://universaldependencies.org/u/pos/PROPN.html" rel="noopener noreferrer"&gt;proper noun&lt;/a&gt; -&amp;gt; &lt;strong&gt;Helsinki&lt;/strong&gt; is beautiful&lt;/li&gt;
&lt;li&gt;PUNCT: &lt;a href="https://universaldependencies.org/u/pos/PUNCT.html" rel="noopener noreferrer"&gt;punctuation&lt;/a&gt; -&amp;gt; Hello &lt;strong&gt;,&lt;/strong&gt; there &lt;strong&gt;!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;SCONJ: &lt;a href="https://universaldependencies.org/u/pos/SCONJ.html" rel="noopener noreferrer"&gt;subordinating conjunction&lt;/a&gt; -&amp;gt; I do this &lt;strong&gt;while&lt;/strong&gt; they do that&lt;/li&gt;
&lt;li&gt;SYM: &lt;a href="https://universaldependencies.org/u/pos/SYM.html" rel="noopener noreferrer"&gt;symbol&lt;/a&gt; -&amp;gt; 5 &lt;strong&gt;+&lt;/strong&gt; 10&lt;/li&gt;
&lt;li&gt;VERB: &lt;a href="https://universaldependencies.org/u/pos/VERB.html" rel="noopener noreferrer"&gt;verb&lt;/a&gt; -&amp;gt; They &lt;strong&gt;think&lt;/strong&gt; that&lt;/li&gt;
&lt;li&gt;X: &lt;a href="https://universaldependencies.org/u/pos/X.html" rel="noopener noreferrer"&gt;other&lt;/a&gt; -&amp;gt; this &lt;strong&gt;asd;lfkjasd;flkj&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Source: &lt;a href="https://universaldependencies.org/u/pos/" rel="noopener noreferrer"&gt;Universal POS tags&lt;/a&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Above is a list of the standardised POS tags. You will probably recognise many of them from English class.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;

&lt;p&gt;Courtesy of Spacy’s visualiser (as always!), below I have included an example where the phrase “This is my house while I live here” has been analysed and POS tags have been assigned. You can see that the tags line up with what would be expected from the list above.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd80u19xe0bp8bb9zy6co.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd80u19xe0bp8bb9zy6co.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How Are POS Tags Assigned?
&lt;/h1&gt;

&lt;p&gt;There are many different ways that POS Tags are assigned. These methods include dynamic programming algorithms (such as the popular &lt;a href="https://en.wikipedia.org/wiki/Viterbi_algorithm" rel="noopener noreferrer"&gt;Viterbi algorithm&lt;/a&gt;). It is common to see hidden Markov models implemented in POS-tagging algorithms. As with many modern NLP elements, machine learning is now very popular for POS-tagging. In this case, computers analyse corpora of text which has been appropriately tagged already and try to learn how to tag tokens itself.&lt;/p&gt;

</description>
      <category>nlp</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Named Entity Recognition (NER) Simplified</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Sat, 12 Sep 2020 21:44:43 +0000</pubDate>
      <link>https://forem.com/adamjhawley/named-entity-recognition-ner-simplified-2dhj</link>
      <guid>https://forem.com/adamjhawley/named-entity-recognition-ner-simplified-2dhj</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Defining Named Entity Recognition&lt;/li&gt;
&lt;li&gt;What makes NER Difficult&lt;/li&gt;
&lt;li&gt;Current Approaches&lt;/li&gt;
&lt;li&gt;Experimenting With NER&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;This blog post is post number two in a series aimed at making Natural Language Processing topics more accessible by abstracting these topics away from mathematics and implementation details.&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Defining Named Entity Recognition
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Named Entity Recognition (NER) is the detection and labelling of named entities (organisations, people, locations etc.)  within a text.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is an example of what an NER analysis returns on a given sentence (using &lt;a href="https://spacy.io/usage/linguistic-features#named-entities-101"&gt;spaCy's NER and visualiser&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5WT-I7A6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ng6axdwrvefjixrkxuhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5WT-I7A6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ng6axdwrvefjixrkxuhx.png" alt="Alt Text" width="880" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tags (labels such as &lt;em&gt;organisation&lt;/em&gt;) can vary between different systems and implementations but they will usually include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ORG&lt;/strong&gt;anisation&lt;/li&gt;
&lt;li&gt;(&lt;strong&gt;GPE&lt;/strong&gt;) Geo-Political Entities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PERSON&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Other categories you may encounter include &lt;em&gt;location&lt;/em&gt;, &lt;em&gt;money&lt;/em&gt; and &lt;em&gt;time&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What Makes NER Difficult?
&lt;/h1&gt;

&lt;p&gt;At first glance, the task can seem very easy. However, after considering a few examples it can equally quickly become clear how the task could be troublesome for a machine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“First Lady Makes an Appearance at John Smith’s”  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Are we discussing the first lady to ever exist or are we talking about the president’s wife here? Is John Smith's a pub, a person's house or something completely different? And, more importantly, how can a computer know?&lt;/p&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Approaches to NER
&lt;/h1&gt;

&lt;p&gt;There are several different approaches that people use to meet their NER requirements. Generally, these can be broken down into techniques using statistics (including machine learning) and techniques based on grammar. Obviously most implementations take a combination of both of these approaches. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More grammar-based techniques involve a higher labour cost but see much more accurate results.&lt;/li&gt;
&lt;li&gt;Statistical approaches produce slightly less accurate results but can analyse sample sets much quicker. A common bottleneck for statistical approaches is the amount of annotated data (these are sentences like in the picture above which are labelled correctly so that the computer can learn how to label too).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Experimenting with NER
&lt;/h1&gt;

&lt;p&gt;Now that you hopefully have a baseline understanding of what NER is, I could not end this post without suggesting using the NLP package spaCy's NER feature and visualiser (which I even used when making this post)!&lt;/p&gt;

&lt;p&gt;You can find an interactive code playground &lt;a href="https://spacy.io/usage/linguistic-features#named-entities-101"&gt;here&lt;/a&gt; where you can change anything from the NLP pipeline or just the sentence to analyse.&lt;/p&gt;

</description>
      <category>nlp</category>
      <category>computerscience</category>
      <category>linguistics</category>
    </item>
    <item>
      <title>Word Vectors Simplified</title>
      <dc:creator>Adam Hawley</dc:creator>
      <pubDate>Fri, 04 Sep 2020 20:42:06 +0000</pubDate>
      <link>https://forem.com/adamjhawley/word-vectors-simplified-3j49</link>
      <guid>https://forem.com/adamjhawley/word-vectors-simplified-3j49</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Note:&lt;br&gt;
This blog post is based on assignment 1 from the Stanford CS 224N NLP And Deep Learning Course which is available &lt;a href="http://web.stanford.edu/class/cs224n/index.html#schedule" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I highly recommend this course for people beginning NLP as it is freely available, has great content and is great fun to follow!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Word Meaning From Context&lt;/li&gt;
&lt;li&gt;Co-occurrence Matrices&lt;/li&gt;
&lt;li&gt;Synonyms from Vector Similarity&lt;/li&gt;
&lt;li&gt;Using Vector Maths to Find Semantic Relations&lt;/li&gt;
&lt;li&gt;Flattening Matrices for Graphical Representation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Below I hope to outline the concept of word vectors and to show how useful they can be. With the aim of keeping this concise, I will not be discussing implementation details. However these can be found in the course linked at the beginning of this post.&lt;/p&gt;

&lt;p&gt;Word vectors (or word embeddings) are vector representations of the meaning of a given word.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding Word Meaning From Surrounding Words
&lt;/h2&gt;

&lt;p&gt;Word vectors commonly rely on the fact that words which are commonly found next or close to other words are usually linguistically related (either syntactically or semantically).&lt;/p&gt;

&lt;p&gt;For example, it is natural to think that you would find the word "trombone" in contexts with a musical theme so you could predict other words which might be in the text such as "instrument" or "song". You would probably also say that it is unlikely that you would find the word "kebab" around the word "trombone" because of their very different meanings.&lt;/p&gt;

&lt;p&gt;In real NLP practices, many of the words surrounding a word are used to create a mathematical definition of the word. This number of words is commonly referred to as the &lt;strong&gt;window&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example of an active window when our centre word is "snowflakes" and with a window size of 1:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxqw2fopu7mz8ctrg5k98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxqw2fopu7mz8ctrg5k98.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Co-Occurrence Matrices
&lt;/h2&gt;

&lt;p&gt;An easy way to represent how frequently words are in the context of other words is to use a &lt;strong&gt;co-occurrence matrix&lt;/strong&gt;. The simple way to think of a co-occurrence matrix is that it is a table where the values are counters of how many times two words &lt;strong&gt;co-occur&lt;/strong&gt;!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"the snowflakes fall from above"&lt;/li&gt;
&lt;li&gt;"some raindrops fall from above"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Given the sentences above with a window size 1, we would get the following co-occurrence matrix:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdnhlvwgz84gi3yg93irn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdnhlvwgz84gi3yg93irn.png" alt="Co-occurrence Matrix"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Synonyms from Vector Similarity
&lt;/h2&gt;

&lt;p&gt;Once you have the vector representations of each word calculated, you effectively have vector &lt;em&gt;definitions&lt;/em&gt; for each word. It turns out that you can use vector calculations to interact with these representations. For example, many people learn how to find angles between vectors using &lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity" rel="noopener noreferrer"&gt;cosine similarity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;similarity=cos(θ)=A⋅B∥A∥∥B∥
similarity = cos(\theta) = \frac{\mathbf{A \cdot B}}{\Vert A \Vert \Vert B \Vert}
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord mathnormal"&gt;imi&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;y&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;cos&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;θ&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;∥&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord"&gt;∥∥&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mord"&gt;∥&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathbf"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathbf"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The more similar the two vectors, the more closely related the two words are likely to be in meaning.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Vector Maths to Find Semantic Relations
&lt;/h2&gt;

&lt;p&gt;An interesting find which is discussed in the course practical this is based on, revolves around the difference in vectors and using vector representations to explore relations between words as well as meanings.&lt;/p&gt;

&lt;p&gt;One of the examples uses the the roles of King and Queen and &lt;a href="https://radimrehurek.com/gensim/models/word2vec.html#gensim.models.word2vec.Word2Vec.most_similar" rel="noopener noreferrer"&gt;gensim's most_similar()&lt;/a&gt; to investigate. They show that the difference between man and king should be the same vector difference between queen and woman.&lt;br&gt;
Hence: &lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;woman+king−man=queen
woman + king - man = queen
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;man&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;kin&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;man&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ee&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flattening Matrices for Graphical Representation
&lt;/h2&gt;

&lt;p&gt;Once we have a co-occurrence matrix we can see that the dimensions are too large to display on a standard 2D or 3D graph (and would but much much larger in a practical situation with a corpus consisting of more than 7 words)!&lt;/p&gt;

&lt;p&gt;In order to represent our matrix on a graph we will have to shrink the matrix so that we have appropriate x and y coordinates.&lt;/p&gt;

&lt;p&gt;A popular way to do this is to use &lt;strong&gt;SVD (singular value decomposition)&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;Since this post is about keeping it simple I won't go into how SVD works but &lt;a href="https://ocw.mit.edu/courses/mathematics/18-06sc-linear-algebra-fall-2011/positive-definite-matrices-and-applications/singular-value-decomposition/MIT18_06SCF11_Ses3.5sum.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt; is a useful resource from MIT on understanding SVD if you want to delve deeper. The key thing for us is that SVD will help us through &lt;em&gt;dimensionality reduction&lt;/em&gt; (going from an n x n matrix to a 2 x n matrix).&lt;/p&gt;

</description>
      <category>nlp</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
