<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Firestore on Techformist</title>
    <link>https://techformist.com/tags/firestore/</link>
    <description>Recent content in Firestore on Techformist</description>
    <image>
      <url>https://techformist.com/logo.svg</url>
      <link>https://techformist.com/logo.svg</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 18 Nov 2020 06:30:00 +0000</lastBuildDate><atom:link href="https://techformist.com/tags/firestore/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Uploading Files in Vue Firestore App</title>
      <link>https://techformist.com/uploading-images-vue-firestore-storage/</link>
      <pubDate>Wed, 18 Nov 2020 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/uploading-images-vue-firestore-storage/</guid>
      <description>&lt;p&gt;Firestore is a super easy way to configure your backend. Firestore provides a range of services anywhere from a database, user authentication, to using machine learning for many use-cases.&lt;/p&gt;
&lt;p&gt;One of the many things you do in a typical app is to enable users to store files. While some find it easier to store files in database (huh?), the most popular option is to store files and reference them in the database record.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Firestore is a super easy way to configure your backend. Firestore provides a range of services anywhere from a database, user authentication, to using machine learning for many use-cases.</p>
<p>One of the many things you do in a typical app is to enable users to store files. While some find it easier to store files in database (huh?), the most popular option is to store files and reference them in the database record.</p>
<p>Firestore provides easy access to a service known as Firebase Storage to store files. Let&rsquo;s see how.</p>
<h2 id="create-vue-view">Create Vue View</h2>
<p>We get started with a simple Vue app (which is using Vuetify, but that does not matter)..</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">v-container</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">v-row</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">v-col</span> <span class="na">cols</span><span class="o">=</span><span class="s">&#34;12&#34;</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;mt-12 pt-md-6&#34;</span> <span class="na">align</span><span class="o">=</span><span class="s">&#34;center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;title font-weight-black&#34;</span><span class="p">&gt;</span>Image Handler<span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">v-col</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">v-col</span> <span class="na">cols</span><span class="o">=</span><span class="s">&#34;12&#34;</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;mt-12&#34;</span> <span class="na">align</span><span class="o">=</span><span class="s">&#34;center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">v-file-input</span>
</span></span><span class="line"><span class="cl">          <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;myFile&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">outlined</span>
</span></span><span class="line"><span class="cl">          <span class="na">:rules</span><span class="o">=</span><span class="s">&#34;[rules.maxsize]&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">accept</span><span class="o">=</span><span class="s">&#34;image/png, image/jpeg&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">placeholder</span><span class="o">=</span><span class="s">&#34;Click to upload file&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="err">@</span><span class="na">change</span><span class="o">=</span><span class="s">&#34;fileInput&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">:disabled</span><span class="o">=</span><span class="s">&#34;processing&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">template</span> <span class="na">v-slot:append-outer</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">v-progress-circular</span>
</span></span><span class="line"><span class="cl">              <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;processing&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="na">color</span><span class="o">=</span><span class="s">&#34;grey&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="na">indeterminate</span>
</span></span><span class="line"><span class="cl">              <span class="na">small</span>
</span></span><span class="line"><span class="cl">            <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">v-file-input</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">v-col</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">v-col</span> <span class="na">cols</span><span class="o">=</span><span class="s">&#34;12&#34;</span> <span class="na">align</span><span class="o">=</span><span class="s">&#34;center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">v-img</span> <span class="na">:src</span><span class="o">=</span><span class="s">&#34;fileUrl&#34;</span> <span class="na">contain</span> <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;fileUrl&#34;</span> <span class="na">max-height</span><span class="o">=</span><span class="s">&#34;500&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">v-img</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">v-col</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">v-row</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">v-container</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">mapState</span><span class="p">,</span> <span class="nx">mapMutations</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">FirebaseFunctions</span><span class="p">,</span> <span class="nx">FirebaseStorage</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;@/services/firebase.js&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">data</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">myFile</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">processing</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">fileUrl</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><h2 id="add-a-service-to-invoke-firebase">Add a Service to invoke Firebase</h2>
<p>Install Firebase in your vue app.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">npm i firebase
</span></span></code></pre></div><p>Add a service that can be consumed by any Vue components to upload files - <code>src/services/firebase.js</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">firebase</span> <span class="nx">from</span> <span class="s2">&#34;firebase/app&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s2">&#34;firebase/storage&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="c1">// get config from Firebase console
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">firebaseConfig</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">apiKey</span><span class="o">:</span> <span class="s2">&#34;the_api_key&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">authDomain</span><span class="o">:</span> <span class="s2">&#34;myapp.firebaseapp.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">databaseURL</span><span class="o">:</span> <span class="s2">&#34;https://myapp.firebaseio.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">projectId</span><span class="o">:</span> <span class="s2">&#34;myapp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">storageBucket</span><span class="o">:</span> <span class="s2">&#34;myapp.appspot.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">messagingSenderId</span><span class="o">:</span> <span class="s2">&#34;12345&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">appId</span><span class="o">:</span> <span class="s2">&#34;1:123512:web:1abcd23&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">measurementId</span><span class="o">:</span> <span class="s2">&#34;G-123COOL&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">firebase</span><span class="p">.</span><span class="nx">apps</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">firebase</span><span class="p">.</span><span class="nx">apps</span><span class="p">.</span><span class="nx">length</span>
</span></span><span class="line"><span class="cl">  <span class="o">?</span> <span class="nx">firebase</span><span class="p">.</span><span class="nx">initializeApp</span><span class="p">(</span><span class="nx">firebaseConfig</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">FirebaseStorage</span> <span class="o">=</span> <span class="nx">firebase</span><span class="p">.</span><span class="nx">storage</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="nx">firebase</span><span class="p">;</span>
</span></span></code></pre></div><p>We add the above code as a service instead of using them locally in components (or views) since we may need the same code in multiple places.</p>
<p>A few key points to note -</p>
<ul>
<li>Get configuration from your Firebase console. This forms the entirety of <code>firebaseConfig</code> object</li>
<li>We export <code>FirebaseStorage</code> (alongside <code>firebase</code>) and this a ready-to-use service to access the Firebase storage</li>
</ul>
<p>In the next section you will see how we use this service.</p>
<h2 id="add-method-to-upload-file">Add Method to Upload File</h2>
<p>Finally, add the methods to handle image uploads in the view.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">FirebaseStorage</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;@/services/firebase.js&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">data</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">myFile</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">processing</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">fileURL</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">methods</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">fileInput</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">if</span> <span class="p">(</span><span class="nx">file</span> <span class="o">&amp;&amp;</span> <span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">this</span><span class="p">.</span><span class="nx">processing</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="kr">const</span> <span class="nx">fr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FileReader</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">            <span class="nx">fr</span><span class="p">.</span><span class="nx">readAsDataURL</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">fr</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s2">&#34;load&#34;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="c1">// this is to load image on the UI
</span></span></span><span class="line"><span class="cl">              <span class="c1">// .. not related to file upload :)
</span></span></span><span class="line"><span class="cl">              <span class="k">this</span><span class="p">.</span><span class="nx">fileURL</span> <span class="o">=</span> <span class="nx">fr</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">});</span>
</span></span><span class="line"><span class="cl">            <span class="kr">const</span> <span class="nx">imgData</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">FormData</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgData</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="s2">&#34;image&#34;</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">myFile</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="kr">const</span> <span class="nx">filePath</span> <span class="o">=</span> <span class="sb">`mypath/</span><span class="si">${</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span><span class="si">}</span><span class="sb">-</span><span class="si">${</span><span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="sb">`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="kr">const</span> <span class="nx">metadata</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">contentType</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">myFile</span><span class="p">.</span><span class="nx">type</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="kr">await</span> <span class="nx">FirebaseStorage</span><span class="p">.</span><span class="nx">ref</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">              <span class="p">.</span><span class="nx">child</span><span class="p">(</span><span class="nx">filePath</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">myFile</span><span class="p">,</span> <span class="nx">metadata</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;filePath: &#34;</span><span class="p">,</span> <span class="nx">filePath</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">processing</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>We are doing a few simple things here -</p>
<ul>
<li>We read the file using <code>const fr = new FileReader();</code> and display the file on the UI. This is just a &ldquo;nice to have&rdquo; feature to provide feedback to user when she selects the file</li>
<li>The selected file gets appended to form data - <code>const imgData = new FormData()</code></li>
<li>Upload the file to the path <code>const filePath = ``mypath/${Date.now()}-${file.name}``;</code> on our Firebase storage using <code>FirebaseStorage.ref()</code></li>
</ul>
<p>That is it! You can now upload any file to Firestore (provided your security rules allow you to upload files).</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Using Vue with Firestore</title>
      <link>https://techformist.com/using-firestore-vue/</link>
      <pubDate>Wed, 26 Aug 2020 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/using-firestore-vue/</guid>
      <description>&lt;p&gt;Firestore can make up for a great backend application. You can get started quite easily, scale it up nicely, and in general, worry less about the &amp;ldquo;server&amp;rdquo; side of things. While it is quite easy to use Firestore as-is, using it in Vue opens up a whole new universe.&lt;/p&gt;
&lt;p&gt;But, first - let&amp;rsquo;s go through the grind of knowing why we would want to do this? And, of course, to please &lt;em&gt;everyone&lt;/em&gt; who just happens to be here reading the next exciting story on a lazy afternoon.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Firestore can make up for a great backend application. You can get started quite easily, scale it up nicely, and in general, worry less about the &ldquo;server&rdquo; side of things. While it is quite easy to use Firestore as-is, using it in Vue opens up a whole new universe.</p>
<p>But, first - let&rsquo;s go through the grind of knowing why we would want to do this? And, of course, to please <em>everyone</em> who just happens to be here reading the next exciting story on a lazy afternoon.</p>
<h2 id="firestore">Firestore?</h2>
<p><a href="https://firebase.google.com/products/firestore">Firestore</a> is a no SQL database by Google that is available on cloud. You can do exciting things like storing data and accessing data - all without maintaining a database of your own. If you are indeed truly delighted by this phenomenon -</p>
<ol>
<li>You have arrived to the great 2010&rsquo;s when everything&rsquo;s a web service - welcome! And oh, we crossed over to the new decade this year</li>
<li>What exactly are you doing here? I mean here on this Blog, on earth, and at this moment? It is time to contemplate life I guess</li>
</ol>
<p>That will be the last of the poor jokes, I promise. Onwards then.</p>
<p>Firestore is a God-send for -</p>
<ol>
<li>Small experiments and projects - you can get started for free, and have exactly zero ongoing server costs if you stay within limits</li>
<li>Large projects that require rapid scalability</li>
<li>Applications where you have enough problems and don&rsquo;t want to add a server ecosystem to the mix (e.g. mobile apps)</li>
</ol>
<p>Get started by visiting <a href="https://firebase.google.com/products/firestore">this link</a>, signing up and head over to the <a href="https://console.firebase.google.com/u/0/">console</a>.</p>
<p>Let&rsquo;s see some more of Firestore and Vue by creating a &ldquo;totally not twitter&rdquo; application. Users should be able to -</p>
<ul>
<li>Tweet</li>
<li>Retweet</li>
<li>That&rsquo;s pretty much it - this is not &ldquo;twitter&rdquo; after all</li>
</ul>
<p>This is how it looks -</p>
<p><img loading="lazy" src="/2020/fwtr-app-demo.gif" type="" alt="fwtr-app-demo"  /></p>
<p>If you are not disappointed yet (did you really think we will build Twitter in one blog post?), read on - things are going to be set on 🔥.</p>
<h2 id="getting-started">Getting Started</h2>
<p>Create a Vue project.</p>
<p>Install the Vue CLI if you have not done it before.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">npm i -g @vue/cli
</span></span></code></pre></div><p>Create the project.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">vue create fwtr
</span></span></code></pre></div><p>Answer a bunch of questions - we choose no to everything except Vue Router &amp; Vuex store. <code>vue-cli</code> installs and configures everything for you.</p>
<p>Next, install <code>vue-fire</code>, an awesome package that provides a Vue wrapper for firebase. We could use Firebase/Firestore as-is, but Vuefire just makes things a bit easy.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">npm i --save vuefire firebase
</span></span></code></pre></div><p>While at it, let&rsquo;s install a small toast library to show alerts and messages.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">npm i --save vue-toast-notification
</span></span></code></pre></div><p>Start your Vue project.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">npm run serve
</span></span></code></pre></div><p>Head over to the <a href="https://console.firebase.google.com/u/0/">Firestore console</a>. Create a new project by clicking the big, bold button, and follow the guided wizard.</p>
<ol>
<li>Name the project</li>
<li>Enable Google Analytics and select an Analytics account (optional)</li>
</ol>
<p>You will see the below project page once you are done with the setup.</p>
<p><img loading="lazy" src="/2020/firestore-new-project.jpg" type="" alt="firestore-new-project"  /></p>
<p>Click on <code>Web</code> icon to register your web app. We don&rsquo;t need Firestore hosting, but feel free to go wild. Provide any name and click <code>Register</code> to see the API details. Copy over the details.</p>
<p>Go to <code>Cloud Firestore</code> link in your Firebase console and click on &ldquo;Create Database&rdquo;. Choose &ldquo;Start in test mode&rdquo;, select a region near you and hit &ldquo;Enable&rdquo; to create a new database.</p>
<p>In the database page, click on &ldquo;Start collection&rdquo; &gt; enter &ldquo;tweets&rdquo; as the collection name, and save. You can optionally enter one or more records in the collection.</p>
<p><img loading="lazy" src="/2020/firestore-create-collection.jpg" type="" alt="firestore-create-collection"  /></p>
<p>You and your project are all fired up now.</p>
<h2 id="firestore-configuration">Firestore configuration</h2>
<p>In your project <code>main.js</code>, add two lines -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">firestorePlugin</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuefire&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Vue</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">firestorePlugin</span><span class="p">);</span>
</span></span></code></pre></div><p>We will also add the configuration required for the toast library.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">VueToast</span> <span class="nx">from</span> <span class="s2">&#34;vue-toast-notification&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s2">&#34;vue-toast-notification/dist/theme-default.css&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="c1">//  ...other code
</span></span></span><span class="line"><span class="cl"><span class="nx">Vue</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">VueToast</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">position</span><span class="o">:</span> <span class="s2">&#34;top-right&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>Now, create a new file called <code>db.js</code> in your project root folder.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">firebase</span> <span class="nx">from</span> <span class="s2">&#34;firebase/app&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="s2">&#34;firebase/firestore&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Get a Firestore instance
</span></span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="kr">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="nx">firebase</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">initializeApp</span><span class="p">({</span> <span class="nx">projectId</span><span class="o">:</span> <span class="s2">&#34;fwtr-fwtr&#34;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">firestore</span><span class="p">();</span>
</span></span></code></pre></div><p>Replace <code>fwtr-fwtr</code> with your own project name - you would have provided the project name in the Firebase console.</p>
<h2 id="home-page">Home Page</h2>
<p>Let&rsquo;s get back to our client app for a minute. First, let&rsquo;s include a stylesheet - because, we (most of us) don&rsquo;t live in caves no more.</p>
<p>Edit <code>/public/index.html</code>. Include the following statement to include an awesome library that automates your styling.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- Code --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://unpkg.com/chota@latest&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">&lt;!-- Code --&gt;</span>
</span></span></code></pre></div><p><code>Chota.css</code> is a minimal CSS framework that does not require you to &ldquo;class&rdquo; each and every element. It also provides a minimal grid and commonly used styled components.</p>
<p>Next, change the home page a bit to keep things interesting. Edit <code>src/views/Home.vue</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;app&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">nav</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;nav&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;nav-left&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;brand&#34;</span><span class="p">&gt;</span>Fwtr<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;nav-right&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">router-link</span> <span class="na">to</span><span class="o">=</span><span class="s">&#34;/&#34;</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;nav-link&#34;</span><span class="p">&gt;</span>Home<span class="p">&lt;/</span><span class="nt">router-link</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">router-link</span> <span class="na">to</span><span class="o">=</span><span class="s">&#34;/tweets&#34;</span> <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;user.uid&#34;</span><span class="p">&gt;</span>Tweets<span class="p">&lt;/</span><span class="nt">router-link</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">router-link</span> <span class="na">to</span><span class="o">=</span><span class="s">&#34;/signup&#34;</span> <span class="na">v-else</span><span class="p">&gt;</span>Signup<span class="p">&lt;/</span><span class="nt">router-link</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">router-link</span> <span class="na">to</span><span class="o">=</span><span class="s">&#34;/login&#34;</span><span class="p">&gt;</span>User<span class="p">&lt;/</span><span class="nt">router-link</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">router-link</span> <span class="na">to</span><span class="o">=</span><span class="s">&#34;/about&#34;</span><span class="p">&gt;</span>?<span class="p">&lt;/</span><span class="nt">router-link</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">nav</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">router-view</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">mapState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">computed</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="p">...</span><span class="nx">mapState</span><span class="p">([</span><span class="s2">&#34;user&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>We will also include some style classes but those have been ignored here for the sake of brevity - see <a href="https://github.com/techformist/fwtr/blob/master/src/App.vue">App.vue in the repo</a>.</p>
<p>Add code for router <code>/src/router/index.js</code> -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">Vue</span> <span class="nx">from</span> <span class="s2">&#34;vue&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">VueRouter</span> <span class="nx">from</span> <span class="s2">&#34;vue-router&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">Home</span> <span class="nx">from</span> <span class="s2">&#34;../views/Home.vue&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Vue</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">VueRouter</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">routes</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Home&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">component</span><span class="o">:</span> <span class="nx">Home</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;/about&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;About&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// route level code-splitting
</span></span></span><span class="line"><span class="cl">    <span class="c1">// this generates a separate chunk (about.[hash].js) for this route
</span></span></span><span class="line"><span class="cl">    <span class="c1">// which is lazy-loaded when the route is visited.
</span></span></span><span class="line"><span class="cl">    <span class="nx">component</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="kr">import</span><span class="p">(</span><span class="cm">/* webpackChunkName: &#34;about&#34; */</span> <span class="s2">&#34;../views/About.vue&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;/tweets&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Tweets&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">component</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="kr">import</span><span class="p">(</span><span class="s2">&#34;../views/Tweets.vue&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;/signup&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Signup&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">component</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="kr">import</span><span class="p">(</span><span class="s2">&#34;../views/Signup.vue&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">path</span><span class="o">:</span> <span class="s2">&#34;/login&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">name</span><span class="o">:</span> <span class="s2">&#34;Login&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">component</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="kr">import</span><span class="p">(</span><span class="s2">&#34;../views/Login.vue&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">router</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">VueRouter</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">mode</span><span class="o">:</span> <span class="s2">&#34;history&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">routes</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="nx">router</span><span class="p">;</span>
</span></span></code></pre></div><p>..and add some code to the store -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">Vue</span> <span class="nx">from</span> <span class="s2">&#34;vue&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="nx">Vuex</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">Vue</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">Vuex</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">export</span> <span class="k">default</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">state</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">user</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">mutations</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">setUser</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">state</span><span class="p">.</span><span class="nx">user</span> <span class="o">=</span> <span class="nx">val</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;updated state&#34;</span><span class="p">,</span> <span class="nx">state</span><span class="p">.</span><span class="nx">user</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">actions</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">  <span class="nx">modules</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></div><p>You should have something like this by now..</p>
<p><img loading="lazy" src="/2020/fwtr-home.jpg" type="" alt="fwtr-home"  /></p>
<h2 id="authentication">Authentication</h2>
<p>A good fwtr application cannot exist without users who can shout everyone down and argue on significant pointless stuff. Enable users and authentication with the click or two in Firebase and Vue.</p>
<p>In your Firebase home page, select <code>Authentication</code> on the left tab bar. Navigate to <code>Sign-in Method</code> and enable authentication method. I have selected <code>Email/Password</code> as the only sign-in provider.</p>
<p><img loading="lazy" src="/2020/firestore-auth.jpg" type="" alt="firestore-auth"  /></p>
<p>Back to your client app, let&rsquo;s build registration and login functionality in the <code>login</code> page.</p>
<p>Create a <code>Signup</code> page at <code>/src/views/Signup.vue</code> -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;justify: center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;row&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-3-md&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;card cardycard row is-center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">h2</span>
</span></span><span class="line"><span class="cl">            <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">style</span><span class="o">=</span><span class="s">&#34;font-weight:bold; padding-bottom:1em; padding-top:1em;&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            Sign up
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#34;login&#34;</span><span class="p">&gt;</span>Email<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;login&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;email&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#34;password&#34;</span><span class="p">&gt;</span>Password<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#34;userid&#34;</span><span class="p">&gt;</span>User Id<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;userid&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;userid&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;button primary&#34;</span> <span class="err">@</span><span class="na">click</span><span class="err">.</span><span class="na">stop</span><span class="o">=</span><span class="s">&#34;register&#34;</span><span class="p">&gt;</span>Sign up<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-3-md&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">db</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;../db&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="nx">firebase</span> <span class="nx">from</span> <span class="s2">&#34;firebase&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">mapState</span><span class="p">,</span> <span class="nx">mapMutations</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">data</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">email</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">password</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">userid</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">login</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">methods</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="p">...</span><span class="nx">mapMutations</span><span class="p">([</span><span class="s2">&#34;setUser&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">register</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kr">const</span> <span class="nx">provider</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">firebase</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">GoogleAuthProvider</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">          <span class="kr">const</span> <span class="nx">user</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">firebase</span>
</span></span><span class="line"><span class="cl">            <span class="p">.</span><span class="nx">auth</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">.</span><span class="nx">createUserWithEmailAndPassword</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">email</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">password</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="kr">await</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">updateProfile</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">displayName</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">userid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;user: &#34;</span><span class="p">,</span> <span class="nx">user</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">setUser</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">email</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">email</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">name</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">displayName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">uid</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">refreshToken</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">refreshToken</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">displayName</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">displayName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$toast</span><span class="p">.</span><span class="nx">success</span><span class="p">(</span><span class="s2">&#34;Signed up!&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$router</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s2">&#34;/tweets&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$toast</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>We collect user email, password and display name (no validation!), and passing it across to Firestore to create the user in our system.</p>
<p>You can start clicking around and see the users getting created provided you create blank <code>vue</code> files for all the other links outlined in <code>App.vue</code>.</p>
<p>Next create a new file called <code>/src/views/Login.vue</code> and add code to create a couple of fields -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;justify: center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;row&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-3-md&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;card cardycard row is-center&#34;</span> <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;!user.uid&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">h2</span>
</span></span><span class="line"><span class="cl">            <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">style</span><span class="o">=</span><span class="s">&#34;font-weight:bold; padding-bottom:1em; padding-top:1em;&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            Login
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">h2</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#34;login&#34;</span><span class="p">&gt;</span>Email<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;login&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;email&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">label</span> <span class="na">for</span><span class="o">=</span><span class="s">&#34;password&#34;</span><span class="p">&gt;</span>Password<span class="p">&lt;/</span><span class="nt">label</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">input</span> <span class="na">name</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;password&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;button primary&#34;</span> <span class="err">@</span><span class="na">click</span><span class="err">.</span><span class="na">stop</span><span class="o">=</span><span class="s">&#34;doLogin&#34;</span><span class="p">&gt;</span>Login<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;card cardycard row is-center&#34;</span> <span class="na">v-else</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>You are already logged in!<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;button primary&#34;</span> <span class="err">@</span><span class="na">click</span><span class="err">.</span><span class="na">stop</span><span class="o">=</span><span class="s">&#34;doLogout&#34;</span><span class="p">&gt;</span>Logout<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-3-md&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">db</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;../db&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="nx">firebase</span> <span class="nx">from</span> <span class="s2">&#34;firebase&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">mapMutations</span><span class="p">,</span> <span class="nx">mapState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">data</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">email</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">password</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">login</span><span class="o">:</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">computed</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="p">...</span><span class="nx">mapState</span><span class="p">([</span><span class="s2">&#34;user&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">methods</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="p">...</span><span class="nx">mapMutations</span><span class="p">([</span><span class="s2">&#34;setUser&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">doLogout</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">this</span><span class="p">.</span><span class="nx">setUser</span><span class="p">({});</span>
</span></span><span class="line"><span class="cl">        <span class="kr">await</span> <span class="nx">firebase</span><span class="p">.</span><span class="nx">auth</span><span class="p">().</span><span class="nx">signOut</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">doLogin</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kr">const</span> <span class="nx">provider</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">firebase</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">GoogleAuthProvider</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">          <span class="kr">const</span> <span class="p">{</span> <span class="nx">user</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">firebase</span>
</span></span><span class="line"><span class="cl">            <span class="p">.</span><span class="nx">auth</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="p">.</span><span class="nx">signInWithEmailAndPassword</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">email</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">password</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">setUser</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">            <span class="nx">email</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">email</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">name</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">displayName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">uid</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">refreshToken</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">refreshToken</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="nx">displayName</span><span class="o">:</span> <span class="nx">user</span><span class="p">.</span><span class="nx">displayName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$toast</span><span class="p">.</span><span class="nx">success</span><span class="p">(</span><span class="s2">&#34;Logged in!&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$router</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s2">&#34;/tweets&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$toast</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>You should be able to login with users created through the signup page.</p>
<p>Let&rsquo;s secure <code>tweets</code> on Firestore. Navigate to <code>Firebase Console</code> &gt; <code>Cloud Firestore</code>. Click on <code>Rules</code> tab on main page. We will replace the default rules to allow only authenticated users to interact with our app.</p>
<pre tabindex="0"><code>rules_version = &#39;2&#39;;
service cloud.firestore {
  match /databases/{database}/documents {

     match /tweets/{tweet} {
      allow create:
      	if request.auth != null &amp;&amp; request.auth.uid == request.resource.data.uid

    	allow update, delete:
      	if request.auth != null &amp;&amp; request.auth.uid == resource.data.uid
      allow read:
      	if true
    }
  }

}
</code></pre><p>All we have done here is to -</p>
<ul>
<li>enable authenticated users to read / create tweets</li>
<li>enable only owners to delete or update tweets</li>
</ul>
<p>With a couple of clicks on the Firebase console, and some copy/paste magic, we have created a secure app with full email/password authentication (incl. confirmation email and everything)!</p>
<h2 id="start-tweeting">Start Tweeting</h2>
<p>Create <code>/src/views/Tweet.vue</code> and include the below code -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;container&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">h1</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;font-weight:bold;&#34;</span><span class="p">&gt;</span>Tweets<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;row is-center&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-10 col-8-md&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">form</span>
</span></span><span class="line"><span class="cl">          <span class="na">class</span><span class="o">=</span><span class="s">&#34;row is-right&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="err">@</span><span class="na">submit</span><span class="err">.</span><span class="na">prevent</span><span class="o">=</span><span class="s">&#34;postTweet()&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;user.uid&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">input</span>
</span></span><span class="line"><span class="cl">            <span class="na">name</span><span class="o">=</span><span class="s">&#34;tweetin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">v-model</span><span class="o">=</span><span class="s">&#34;tweetin&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">placeholder</span><span class="o">=</span><span class="s">&#34;What&#39;s happening?&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-2&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span>
</span></span><span class="line"><span class="cl">              <span class="na">class</span><span class="o">=</span><span class="s">&#34;button primary outline&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="na">type</span><span class="o">=</span><span class="s">&#34;submit&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="err">@</span><span class="na">click</span><span class="err">.</span><span class="na">prevent</span><span class="o">=</span><span class="s">&#34;postTweet()&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">              Tweet
</span></span><span class="line"><span class="cl">            <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span>
</span></span><span class="line"><span class="cl">        <span class="na">class</span><span class="o">=</span><span class="s">&#34;card tweetcard col-10 col-8-md&#34;</span>
</span></span><span class="line"><span class="cl">        <span class="na">v-for</span><span class="o">=</span><span class="s">&#34;(tweet, index) in tweets&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;row&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-6 is-left&#34;</span><span class="p">&gt;</span>@{{ tweet.uname }}<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-6 is-right&#34;</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;color: grey; font-size: 80%&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            {{ tweet.createdAt ? new Date(tweet.createdAt).toUTCString() : &#34;&#34; }}
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12 is-left&#34;</span><span class="p">&gt;</span>{{ tweet.message }}<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;col-12 is-right&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span>
</span></span><span class="line"><span class="cl">              <span class="na">class</span><span class="o">=</span><span class="s">&#34;button icon clear&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="err">@</span><span class="na">click</span><span class="o">=</span><span class="s">&#34;deleteTweet(tweet.id)&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="na">v-if</span><span class="o">=</span><span class="s">&#34;tweet.uid == user.uid&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">              <span class="p">&lt;</span><span class="nt">img</span>
</span></span><span class="line"><span class="cl">                <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://icongr.am/feather/trash-2.svg?size=16&amp;amp;color=amber&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">alt</span><span class="o">=</span><span class="s">&#34;del&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;button icon clear&#34;</span> <span class="err">@</span><span class="na">click</span><span class="o">=</span><span class="s">&#34;postTweet(tweet.message)&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">              <span class="p">&lt;</span><span class="nt">img</span>
</span></span><span class="line"><span class="cl">                <span class="na">src</span><span class="o">=</span><span class="s">&#34;https://icongr.am/feather/refresh-ccw.svg?size=16&amp;amp;color=#e1e1e1&#34;</span>
</span></span><span class="line"><span class="cl">                <span class="na">alt</span><span class="o">=</span><span class="s">&#34;rt&#34;</span>
</span></span><span class="line"><span class="cl">              <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">template</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">db</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;../db&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">import</span> <span class="p">{</span> <span class="nx">mapState</span> <span class="p">}</span> <span class="nx">from</span> <span class="s2">&#34;vuex&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="kr">export</span> <span class="k">default</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">data</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">tweets</span><span class="o">:</span> <span class="p">[],</span>
</span></span><span class="line"><span class="cl">        <span class="nx">tweetin</span><span class="o">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">computed</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="p">...</span><span class="nx">mapState</span><span class="p">([</span><span class="s2">&#34;user&#34;</span><span class="p">]),</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">mounted</span><span class="p">()</span> <span class="p">{},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">methods</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">postTweet</span><span class="p">(</span><span class="nx">twt</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kr">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">collection</span><span class="p">(</span><span class="s2">&#34;tweets&#34;</span><span class="p">).</span><span class="nx">add</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">          <span class="nx">message</span><span class="o">:</span> <span class="sb">`</span><span class="si">${</span><span class="nx">twt</span> <span class="o">?</span> <span class="nx">twt</span> <span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">tweetin</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">uid</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">uid</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">uname</span><span class="o">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">displayName</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">createdAt</span><span class="o">:</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">twt</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">tweetin</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="kr">async</span> <span class="nx">deleteTweet</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kr">const</span> <span class="nx">rec</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">db</span><span class="p">.</span><span class="nx">collection</span><span class="p">(</span><span class="s2">&#34;tweets&#34;</span><span class="p">).</span><span class="nx">doc</span><span class="p">(</span><span class="nx">id</span><span class="p">).</span><span class="k">delete</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="k">this</span><span class="p">.</span><span class="nx">$toast</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="nx">firestore</span><span class="o">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">tweets</span><span class="o">:</span> <span class="nx">db</span><span class="p">.</span><span class="nx">collection</span><span class="p">(</span><span class="s2">&#34;tweets&#34;</span><span class="p">).</span><span class="nx">orderBy</span><span class="p">(</span><span class="s2">&#34;createdAt&#34;</span><span class="p">,</span> <span class="s2">&#34;desc&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>And.. that&rsquo;s it. You can celebrate and come back to do some testing whether your app indeed works.</p>
<p>Login with any user id, navigate to <code>Tweets</code>, and start tweeting. You can see others&rsquo; tweets and retweet them. You could also delete those <code>covfefe</code> tweets that seemed a good idea when you were in college.</p>
<h2 id="the-end">The End</h2>
<p>Hopefully you were entertained enough by this post? I always try to do my best with the jokes.. and of course, there was a bit of what Firestore could do.</p>
<p>The code for this project is available on <a href="https://github.com/techformist/fwtr">Github</a>.</p>
<p>Firestore is awesome, and Vue makes the entire developer experience delightful. Start weaving your magic with the combination and build great things.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
