<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: XetiCode LLC</title>
    <description>The latest articles on DEV Community by XetiCode LLC (@xeticode).</description>
    <link>https://dev.to/xeticode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2831%2Fcbd52b5c-6ea3-4773-9a78-df50f93b5453.png</url>
      <title>DEV Community: XetiCode LLC</title>
      <link>https://dev.to/xeticode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xeticode"/>
    <language>en</language>
    <item>
      <title>The 10 Commandments of AI</title>
      <dc:creator>Dirk Johnson</dc:creator>
      <pubDate>Tue, 16 Apr 2024 21:53:38 +0000</pubDate>
      <link>https://dev.to/xeticode/the-10-commandments-of-ai-13aa</link>
      <guid>https://dev.to/xeticode/the-10-commandments-of-ai-13aa</guid>
      <description>&lt;p&gt;When I graduated high school in the mid-80s, MIT was convinced AI was going to change the world in the next decade. Well… they were only 3 decades off - not bad really.&lt;/p&gt;

&lt;p&gt;I went into software engineering after high school, but not with a focus on AI. Most of my career has been in the full-stack application space. However, I have tried to keep up to date with AI and its progress, especially over the last 10 years.&lt;/p&gt;

&lt;p&gt;After 28 years as a software engineer at Apple, I left to start my own consulting company. Recently, I desired to discuss with my engineers some of the serious ramifications, both good and bad, of AI.  From that desire and the subsequent conversations came something akin to &lt;a href="https://en.wikipedia.org/wiki/Three_Laws_of_Robotics"&gt;Asimov's Three Laws of Robotics&lt;/a&gt;, however, I title these the 10 Commandments of AI.&lt;/p&gt;

&lt;p&gt;The overriding goal of these commandments are two fold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preserve sovereign Humanity and all that Humanity represents while allowing AI to push humanity forward&lt;/li&gt;
&lt;li&gt;Establish clear responsibility on Humanity for all AI Informances and Performances&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Though the term "commandment" might connote otherwise, these '10 Commandments of AI' are not proposed in their finality but in their genesis; as &lt;strong&gt;critical&lt;/strong&gt; points of conversation that must be considered, debated, and refined.&lt;/p&gt;

&lt;p&gt;Many of these commandments will be difficult to accept in today's AI environment. But I believe each commandment has its wisdom, even if its current form is not ideal.&lt;/p&gt;

&lt;p&gt;I know there are many groups and organizations dedicated to creating and using AI with the proper consideration and constraint that are deserving of those who put the necessity of a sovereign Humanity above every other consideration, be that wealth, discovery, or power. To these efforts, I add these 10 Commandments of AI for consideration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 10 Commandments of AI
&lt;/h2&gt;

&lt;p&gt;Where the commandments may conflict, consider these commandments in order of precedence.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AI Commandments of Performance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;AI Shalt Not Perform any Action that would intentionally endanger Human Life&lt;/li&gt;
&lt;li&gt;AI Shalt Not Perform without direct Human Command&lt;/li&gt;
&lt;li&gt;AI Shalt Perform exactly the given Human Command, the whole Command, and nothing but the Command&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The AI Commandments of Informance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;(4) AI Shalt Inform when Human Command could endanger Human Life&lt;/li&gt;
&lt;li&gt;(5) AI Shalt Not Inform without direct Human Query&lt;/li&gt;
&lt;li&gt;(6) AI Shalt Inform exactly the requested Human Query, the whole Query, and nothing but the Query&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The General Commandments of AI
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;(7) AI Shalt Not Learn from, Query, nor Command another AI &lt;/li&gt;
&lt;li&gt;(8) AI Shalt always fully Identify itself in all Learnings, Informances, and Performances&lt;/li&gt;
&lt;li&gt;(9) AI Shalt Not Learn, Inform, nor Perform outside of its Limited Immutable Domain&lt;/li&gt;
&lt;li&gt;(10) AI Shalt always keep a complete Log of past Learnings, Informances, and Performances&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Using Fission with Elm - Part 3: Adding authentication and using the Fission Drive</title>
      <dc:creator>Verge729</dc:creator>
      <pubDate>Tue, 09 Nov 2021 01:22:08 +0000</pubDate>
      <link>https://dev.to/xeticode/using-fission-with-elm-part-3-adding-authentication-and-using-the-fission-drive-3fig</link>
      <guid>https://dev.to/xeticode/using-fission-with-elm-part-3-adding-authentication-and-using-the-fission-drive-3fig</guid>
      <description>&lt;h5&gt;
  
  
  &lt;strong&gt;[UPDATE]&lt;/strong&gt; The Fission team released fission-suite/webnative-elm version 7.0.0 since the original publish date of this article. This update includes a sign out function. The following sections of the article have been changed to reflect this update: &lt;code&gt;Walkthrough/Authentication/'Prep work'&lt;/code&gt;and &lt;code&gt;Walkthrough/Authentication/'Signing out'&lt;/code&gt;. This article no longer makes any changes to the &lt;code&gt;js/index.js&lt;/code&gt; file as defined in &lt;code&gt;Fission with Elm - Part 2&lt;/code&gt;.
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Make sure the npm and elm-module packages for &lt;code&gt;webnative-elm&lt;/code&gt; are at 6.1.0 and 7.0.0, respectively. To update them, run the following from the root of the project:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev webnative-elm
npx elm-json install fission-suite/webnative-elm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Prelude&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is a three-part series. In part one, I showed you how to use Vite to manage an Elm application. In part two, I showed you how to integrate the basics of Fission via the Webnative SDK into the project. In part three (this article), I will show how to add authentication and storage via the &lt;code&gt;Webnative SDK&lt;/code&gt; to the application. This article is written assuming the developer already has a Fission account and has completed parts 1 and 2.&lt;/p&gt;

&lt;p&gt;It should be noted that the last two articles were fairly short. Both have set the stage for this article, the pinnacle of the series. There will be much to add to our growing application, some of these additions are due to Elm being a strongly typed language.&lt;/p&gt;

&lt;p&gt;It should also be noted that if you are using a browser that using something similar to Brave Shields in the Brave browser, you will need to disable the feature so Fission can communicate with the application.&lt;/p&gt;

&lt;p&gt;This article will also require the use of a Fission account. If you do not yet have one, take a moment to create one now. Check &lt;strong&gt;Appendix A&lt;/strong&gt; at the end of this article for steps on how to do so.&lt;/p&gt;

&lt;p&gt;The Github repository associated with this article can be found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/xeticode/fission-with-elm-demos/tree/Part-3" rel="noopener noreferrer"&gt;https://github.com/xeticode/fission-with-elm-demos/tree/Part-3&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Welcome to the final article. Here you will be tested beyond anything you have ever experienced… Nah, this is not some epic set of trials. That being said, it is my hope that by the end of this article, you have been exposed enough to Fission to continue on in your own Fission-based applications. &lt;br&gt;
It is time to add some usefulness to this application. Right now, it is like a wallpaper: good to look at and not much else. The first feature we will add is user authentication. After authentication, we will add code that will interact with the Fission Drive to write a file to storage. There are no introductions to be made this go-around, so we will review important concepts for what I am about to show you.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Things to review&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;elm ports&lt;/em&gt;&lt;/strong&gt; are the medium by which an Elm application communicates with JavaScript. For more information, see &lt;a href="https://guide.elm-lang.org/interop/ports.html" rel="noopener noreferrer"&gt;Elm Ports&lt;/a&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;IPFS&lt;/em&gt;&lt;/strong&gt; "is a distributed system for storing and accessing files, websites, applications, and data". For more information, see &lt;a href="https://docs.ipfs.io/concepts/what-is-ipfs/" rel="noopener noreferrer"&gt;IPFS&lt;/a&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Wnfs&lt;/em&gt;&lt;/strong&gt; stands for &lt;code&gt;Webnative File System&lt;/code&gt; and "is a file system built on top of the (IPFS)". For more information, see &lt;a href="https://guide.fission.codes/developers/webnative/file-system-wnfs" rel="noopener noreferrer"&gt;Webnative File System&lt;/a&gt; .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Fission Drive&lt;/em&gt;&lt;/strong&gt; is a military-grade encrypted file system located within a distributed network. For more information, see &lt;a href="https://guide.fission.codes/drive/preview" rel="noopener noreferrer"&gt;Fission Drive&lt;/a&gt; .&lt;br&gt;
Let us begin!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Walkthrough&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Download an updated &lt;code&gt;Main.elm&lt;/code&gt; by running this command in the terminal from the &lt;code&gt;src&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -o Main.elm https://raw.githubusercontent.com/xeticode/fission-with-elm-demos/interim/part-3/Main.elm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This new &lt;code&gt;Main.elm&lt;/code&gt; file lays down some new groundwork for our application. It is also divided into sections, the dividers being noticeable comments. Instead of indicating a line in the file to add or find code, I will indicate a region of the code to look. The differences between the new file versus the old one includes additions to our &lt;code&gt;type alias Model&lt;/code&gt;, &lt;code&gt;type Msg&lt;/code&gt;, and &lt;code&gt;update&lt;/code&gt; function (see section: &lt;code&gt;MODEL/UPDATE&lt;/code&gt;); a section for helper functions (see section: &lt;code&gt;HELPER FUNCTIONS&lt;/code&gt;); and a new UI (see section: &lt;code&gt;VIEW&lt;/code&gt;). Let’s quickly go over the new &lt;code&gt;Msg&lt;/code&gt; variants and the &lt;code&gt;Model&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;&lt;code&gt;Msg&lt;/code&gt; variants&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here are the new variants and their purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;SignIn&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; will be associated with the login button and will initiate the login process with Fission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;SignOut&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; will be associated with the logout button and will initiate the logout process with Fission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;UpdateNote&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; is the variant that will update the &lt;code&gt;note&lt;/code&gt; field in the &lt;code&gt;Model&lt;/code&gt;. This is the value that will be written to the Wnfs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;SaveNote&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; is associated with the &lt;code&gt;Save Note&lt;/code&gt; button and will initiate the process of writing and publishing our &lt;code&gt;note&lt;/code&gt; to the Wnfs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;&lt;code&gt;Model&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here is a breakdown of the new fields in &lt;code&gt;Model&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;username&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; will store the username of the logged-in Fission user of the current session (if you are not familiar with the &lt;code&gt;Maybe&lt;/code&gt; type, or simply need a refresher, see &lt;a href="https://guide.elm-lang.org/error_handling/maybe.html" rel="noopener noreferrer"&gt;Maybe&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;logs&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; is a list of strings and will store log entries associated with the different stages of interaction with Fission. These will be displayed on the left side of the screen. Consider these as a log that make it easier to see the processes when they occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;note&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; this will store the content that will be sent to the Wnfs. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Before we dive in&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;npm run dev&lt;/code&gt; from the root of the project to have the application up and running on the dev server. Once you do this, you should see this:&lt;/p&gt;

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

&lt;p&gt;At this point, you can click on the login button, but it will not take you anywhere. Its associated message, &lt;code&gt;SignIn&lt;/code&gt;, is currently a dead end. Not to worry, the first thing we will do is implement authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Authentication&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Prep work&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;One of the reasons my meals are so simple and quick is my hungry stomach will usually override my willingness to spend time on quality meal prep. Lucky for us, this is not a food situation.  Before we can sign in, we must add a few things, a metaphorical meal prep, if you will, before we can dig into authentication.&lt;/p&gt;

&lt;p&gt;The first thing we must do is expand the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; branch in our update function. To begin, replace the current &lt;code&gt;GotWebnativeResponse&lt;/code&gt; branch (section: &lt;code&gt;MODEL/UPDATE&lt;/code&gt;, function: &lt;code&gt;update&lt;/code&gt;) with the following code (be aware, the alignment may change when copying and pasting into your developing environment. You will get the red squiggles if the case statement branches are mis-aligned):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;GotWebnativeResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decodeResponse&lt;/span&gt; &lt;span class="n"&gt;tagFromString&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Webnative&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Initialisation&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; 
                &lt;span class="kt"&gt;NotAuthorised&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
                        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Auth: NotAuthorised"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="kt"&gt;AuthSucceeded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
                        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Auth: AuthSucceeded"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="kt"&gt;AuthCancelled&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
                        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Auth: AuthCancelled"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="kt"&gt;Continuation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
                        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Auth: Continuation"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;Wnfs&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;


        &lt;span class="kt"&gt;Webnative&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;NoArtifact&lt;/span&gt; &lt;span class="kt"&gt;SignedOut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Signed out!"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
                &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;Webnative&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;NoArtifact&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;WebnativeError&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;              
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="kt"&gt;WnfsError&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Wnfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a lot of new code, and some of it is accompanied by our friendly neighborhood red squiggles. This is due to missing proper imports and a definition for &lt;code&gt;tagFromString&lt;/code&gt;, which is a helper function. Let's resolve the problem starting with the imports.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;import&lt;/code&gt; block at the top of &lt;code&gt;Main.elm&lt;/code&gt;. Near the bottom of the import block at the top of the file, we have our &lt;code&gt;Webnative&lt;/code&gt; import and it is currently exposing &lt;code&gt;Artifact(..)&lt;/code&gt; and all its variants (represented by the &lt;code&gt;(..)&lt;/code&gt;). Replace this import with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Artifact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;NoArtifact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;DecodedResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding these to the exposing list will allow us access to the &lt;code&gt;DecodedResponse&lt;/code&gt; and &lt;code&gt;State&lt;/code&gt; types from the &lt;code&gt;Webnative-elm&lt;/code&gt; module  (see &lt;a href="https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/Webnative#DecodedResponse" rel="noopener noreferrer"&gt;DecodedResponse&lt;/a&gt; and &lt;a href="https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/Webnative#State" rel="noopener noreferrer"&gt;State&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Now we will define &lt;code&gt;tagFromString&lt;/code&gt;. In the &lt;code&gt;HELPER FUNCTION&lt;/code&gt; section, add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;tagFromString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;
&lt;span class="n"&gt;tagFromString&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
         &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid tag: "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Webnative-elm&lt;/code&gt; utilizes tags to differentiate between different requests and connect the appropriate response. For example, if I sent a &lt;code&gt;webnativeRequest&lt;/code&gt; tagged with “StudioGhibli”, the associated &lt;code&gt;webnativeResponse&lt;/code&gt; will have the same tag. We can then create a branch within our &lt;code&gt;GotWebnativeResponse&lt;/code&gt; branch’s case statement and dictate how to handle the response. &lt;/p&gt;

&lt;p&gt;Now, both &lt;code&gt;webnativeRequest&lt;/code&gt; and &lt;code&gt;webnativeResponse&lt;/code&gt; require the tag to be a string not an Elm type. That is why we need such helper functions as &lt;code&gt;tagFromString&lt;/code&gt; and its companion &lt;code&gt;tagToString&lt;/code&gt;. Extra code on our part, yes. This is a byproduct of Elm, not the &lt;code&gt;webnative-elm&lt;/code&gt; wrapper. In fact, this is great design by the people behind the wrapper because it couples the &lt;code&gt;Webnative SDK&lt;/code&gt; with the strengths of Elm.&lt;/p&gt;

&lt;p&gt;Speaking of an Elm type for our tags, we now have another red squiggle to take care of, this time on &lt;code&gt;Tag&lt;/code&gt;. Add the following code between the &lt;code&gt;type Msg&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ChangeMeLater&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where we define our different &lt;code&gt;webnativeRequest&lt;/code&gt; tags. To reiterate, we will return to this later when it is time to utilize our &lt;code&gt;Tag&lt;/code&gt; type. We need to define &lt;code&gt;Tag&lt;/code&gt; now so we can proceed with the rest of what the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; has to offer.&lt;br&gt;
We are now ready to officially sign in!&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Signing in&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is where having a Fission account is crucial. If you have yet to do so, stop and take a moment to create a Fission account (see &lt;strong&gt;Appendix A&lt;/strong&gt; at the end of this article for details).&lt;/p&gt;

&lt;p&gt;The application is growing up so fast. To implement sign in, go to the &lt;code&gt;SignIn&lt;/code&gt; branch  of the &lt;code&gt;update&lt;/code&gt; function (section: &lt;code&gt;MODEL/UPDATE&lt;/code&gt;) and replace &lt;code&gt;Cmd.none&lt;/code&gt; with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;redirectToLobby&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;CurrentUrl&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;webnativeRequest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will take our &lt;code&gt;permissions&lt;/code&gt; (defined in part 2 of this series) and pass it to the Webnative function &lt;code&gt;redirectToLobby&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Time to see it in action! Refresh the app in the browser and click "Login"! This will take us to a Fission authorization lobby. You will see something like this: &lt;/p&gt;

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

&lt;p&gt;This lobby utilizes the &lt;code&gt;appPermissions&lt;/code&gt; and &lt;code&gt;fsPermissions&lt;/code&gt; we defined at the beginning of the &lt;code&gt;Main.elm&lt;/code&gt; file. If there are no defined &lt;code&gt;fsPermissions&lt;/code&gt; (like with this application), the only permission request will be for the file path generated for the application. Once you grant permission, authentication will finish. &lt;/p&gt;

&lt;p&gt;Rather than using traditional username and password authentication (such as OAuth), Fission uses cryptographic keys and stores them in a browser you authorize with your Fission account (you can authorize multiple browsers on multiple machines). See &lt;a href="https://guide.fission.codes/developers/webnative/auth" rel="noopener noreferrer"&gt;Webnative Authentication&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;Once you have logged in and granted permission for the app to access &lt;code&gt;Trillian/fission-with-elm&lt;/code&gt; (aka &lt;code&gt;creator/name&lt;/code&gt; as specified in &lt;code&gt;appPermissions&lt;/code&gt; located in the beginning of section: &lt;code&gt;FISSION SETUP&lt;/code&gt;) in your Fission Drive, you will see this simple web page:&lt;/p&gt;

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

&lt;p&gt;Before we implement signing out, I want to give a quick walkthrough of this application.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;The UI&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Under the “Fission with Elm” title, there are two oval-esque elements. The one on the left should display the Fission logo and your Fission username, and the one on the right is a logout button. &lt;/p&gt;

&lt;p&gt;On the far-left side of the screen, you will see “Auth: AuthSucceeded”. When you save a note, more logs will appear here, allowing you to see the process of writing to a Fission Drive.&lt;/p&gt;

&lt;p&gt;The center of the screen has a textbox where you can write a note and a “Save Note” button below it that will write the note to your Fission Drive. This functionality will be implemented after sign out.&lt;/p&gt;

&lt;p&gt;In the bottom right corner, there should be a little blue rectangle which displays the Elm logo and a number. This is a button that will open the Elm debugging window.&lt;/p&gt;

&lt;p&gt;Anyways, on to the implementation of signing out!&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Signing out&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;webnativeRequest&lt;/code&gt; port supports two types methods of signing out: &lt;code&gt;Webnative.leave&lt;/code&gt; and &lt;code&gt;Webnative.signOut&lt;/code&gt; (see &lt;a href="https://package.elm-lang.org/packages/fission-suite/webnative-elm/latest/Webnative" rel="noopener noreferrer"&gt;Webnative&lt;/a&gt;, in the section named "Authentication"). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Webnative.leave&lt;/code&gt; will redirect the user to a Fission logout lobby, which looks like this:&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;Webnative.signOut&lt;/code&gt; will not redirect the user to a Fission logout lobby.&lt;/p&gt;

&lt;p&gt;To add sign out functionality, go to the &lt;code&gt;SignOut&lt;/code&gt; branch in the update function and replace the current version of it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;SignOut&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SignOut"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signOut&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;webnativeRequest&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bah-duh bing, bah-duh boom! We can now sign in &lt;em&gt;and&lt;/em&gt; sign out! Time to see it in action. Go ahead and test the app by logging in and logging out! Pretty cool! &lt;/p&gt;

&lt;p&gt;Next up on the docket is writing to a Fission Drive, let us dive in!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Data Storage&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Writing to the Wnfs is a two-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write the data to a file and save it in the Wnfs in the local browser storage&lt;/li&gt;
&lt;li&gt;Once saved locally, replicate and encrypt the data and store it in the Wnfs on the IPFS network&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following diagram depicts the write process within the context of our application:&lt;/p&gt;

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

&lt;p&gt;The three circles in the &lt;code&gt;elm app&lt;/code&gt; section represent &lt;code&gt;Msg&lt;/code&gt; and &lt;code&gt;Tag&lt;/code&gt; variants and are milestones in the writing process. We begin by calling the &lt;code&gt;SaveNote&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; variant and end in handling a tagged &lt;code&gt;webnativeResponse&lt;/code&gt; with our &lt;code&gt;PublishNote&lt;/code&gt; &lt;code&gt;Tag&lt;/code&gt; variant.&lt;br&gt;
We need to do the following to replicate this process in our application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type Tag&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Finish defining the variants for the Tag type. Once this is done, we can tag requests and appropriately handle the associated responses.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Helper functions

&lt;ul&gt;
&lt;li&gt;Write several helper functions to help with encoding the data and using tags.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update&lt;/code&gt; function

&lt;ul&gt;
&lt;li&gt;Update various case statement branches to accommodate saving a note.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we get through that, our application will be complete. Let’s get started!&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;type Tag&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This is our current state of our &lt;code&gt;Tag&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ChangeMeLater&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to swap the current variant from &lt;code&gt;ChangeMeLater&lt;/code&gt; with two new variants: &lt;code&gt;WriteNote&lt;/code&gt; and &lt;code&gt;PublishNote&lt;/code&gt;. This will allow us to handle responses to the write and publish requests.&lt;/p&gt;

&lt;p&gt;Change the &lt;code&gt;type Tag&lt;/code&gt; to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;WriteNote&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;PublishNote&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Helper functions&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Two of these helper functions (&lt;code&gt;tagFromString&lt;/code&gt; and &lt;code&gt;tagToString&lt;/code&gt;) are needed simply because Elm is a strongly typed language and does not have a native way to convert type variants to strings. This gives us extra work to do before we can accomplish our goal. Fortunately for this application, our application is small and will not require much of this kind of code.&lt;/p&gt;

&lt;p&gt;The other two helper functions (&lt;code&gt;encode&lt;/code&gt; and &lt;code&gt;save&lt;/code&gt;) are for encoding our note and preparing it as a &lt;code&gt;Webnative.Request&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;tagFromString&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can now properly finish the implementation of this function! This will allow us to convert our &lt;code&gt;Type&lt;/code&gt; variants to strings. Replace the half-baked &lt;code&gt;tagFromString&lt;/code&gt; with the following full-baked code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;tagFromString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;
&lt;span class="n"&gt;tagFromString&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WriteNote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="kt"&gt;WriteNote&lt;/span&gt;

        &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PublishNote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="kt"&gt;PublishNote&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid tag: "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;tagToString&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As promised, here is the second helper function for the tags. This will convert a &lt;code&gt;Tag&lt;/code&gt; into a &lt;code&gt;String&lt;/code&gt; so we may add it to the &lt;code&gt;webnativeRequest&lt;/code&gt;. Make sure to get the spelling right AND that it matches the spellings used in &lt;code&gt;tagFromString&lt;/code&gt; function. Add this code to the &lt;code&gt;HELPERS&lt;/code&gt; section of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;tagToString&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;tagToString&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; 
        &lt;span class="kt"&gt;WriteNote&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WriteNote"&lt;/span&gt;
        &lt;span class="kt"&gt;PublishNote&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PublishNote"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;encode&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This application will write our &lt;code&gt;note&lt;/code&gt; to a JSON file. This next helper function will JSON encode our &lt;code&gt;note&lt;/code&gt;. Add the following code to the &lt;code&gt;HELPERS&lt;/code&gt; section of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;encode&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Value&lt;/span&gt;
&lt;span class="n"&gt;encode&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;note"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;save&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function will take the pieces we have made in this portion of the walkthrough and use them to initiate the writing process. It will first take our &lt;code&gt;note&lt;/code&gt; and encode it to a JSON value, prettify it, and then write it to a specified file with an associated &lt;code&gt;Tag&lt;/code&gt;. Add the following code to the &lt;code&gt;HELPERS&lt;/code&gt; section of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt;
&lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;note&lt;/span&gt;    
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Wnfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writeUtf8&lt;/span&gt;
            &lt;span class="kt"&gt;Wnfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Private&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Apps"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Trillian"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fission-with-elm"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notes"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;note.json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagToString&lt;/span&gt; &lt;span class="kt"&gt;WriteNote&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;update Function&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The prep work has been laid, now we need to establish some milestones. The writing process will begin when we click the “Save Note” button, which will send a &lt;code&gt;webnativeRequest&lt;/code&gt; tagged with &lt;code&gt;WriteNote&lt;/code&gt;. We will then handle the associated response and then send one more &lt;code&gt;webnativeRequest&lt;/code&gt; tagged with &lt;code&gt;PublishNote&lt;/code&gt;. The final step will be handling the associated response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;SaveNote&lt;/code&gt; msg&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To begin, we need to change the &lt;code&gt;Cmd.none&lt;/code&gt; in our &lt;code&gt;SaveNote&lt;/code&gt; update branch to a &lt;code&gt;Cmd&lt;/code&gt; that calls our &lt;code&gt;webnativeRequest&lt;/code&gt; port. Replace &lt;code&gt;Cmd.none&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;webnativeRequest&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will begin our interaction with Webnative by writing our &lt;code&gt;note&lt;/code&gt; to a file and then writing it to our Wnfs. The next step is to handle the response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;WriteNote&lt;/code&gt; handler&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;WriteNote&lt;/code&gt; response will be caught by our subscription to the &lt;code&gt;webnativeResponse&lt;/code&gt; port and be redirected to the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; variant. Add the following branch to &lt;code&gt;GotWebnativeResponse&lt;/code&gt;, just before the &lt;code&gt;Wnfs _ _&lt;/code&gt; branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;Wnfs&lt;/span&gt; &lt;span class="kt"&gt;WriteNote&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Note Written..."&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagToString&lt;/span&gt; &lt;span class="kt"&gt;PublishNote&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Wnfs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;webnativeRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code block will add an entry to our &lt;code&gt;model&lt;/code&gt;’s list of logs and then chain a new request to publish our updated Wnfs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;PublishNote&lt;/code&gt; handler&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;PublishNote&lt;/code&gt; response will again be caught by our subscription to the &lt;code&gt;webnativeResponse&lt;/code&gt; port and be redirected to the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; variant. In &lt;code&gt;GotWebnativeResponse&lt;/code&gt;, replace the &lt;code&gt;Wnfs _ _&lt;/code&gt; branch with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;Wnfs&lt;/span&gt; &lt;span class="kt"&gt;PublishNote&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Note Published to Fission Drive!"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code block will add an entry to our &lt;code&gt;model&lt;/code&gt;’s list of logs and then do nothing because the process of writing our note to the Wnfs has reached its end. Your file will then be accessible from your Fission Drive! It may take a few seconds to propagate the data to the Drive, so be aware of that. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Finished Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s do a quick walk through of writing to your Fission Drive. Begin by opening a new window or tab, and navigate to your &lt;a href="https://drive.fission.codes/" rel="noopener noreferrer"&gt;Fission Drive&lt;/a&gt;. Once there, navigate to the &lt;code&gt;fission-with-elm&lt;/code&gt; directory (Apps &amp;gt; Trillian &amp;gt; fission-with-elm). This directory should be empty (unless you saved a &lt;code&gt;note&lt;/code&gt; between finishing the app and now).&lt;/p&gt;

&lt;p&gt;Refresh the app page in the browser to make sure your browser has loaded the latest compiled version of the app from the server. Now, navigate to the “Fission with Elm” application and add some text to the input field in the app. It can be as quick as “asdf” or as creative as “test”, it is up to you. Once you have done so, click the “Save Note” button and then navigate back to your Fission Drive. As a reminder, it can take a few seconds for the new note to propagate to your Drive. Once a note has been written, there should appear a new directory within the &lt;code&gt;fission-with-elm&lt;/code&gt; directory called &lt;code&gt;notes&lt;/code&gt;. Enter that directory and you will see a JSON file entitled &lt;code&gt;note&lt;/code&gt;. If you click on it, you will see the contents of the file in a preview window located on the right side of the screen. Like so:&lt;/p&gt;

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

&lt;p&gt;Voilà!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The End of a Trilogy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There is not much reading left now. And I can guarantee this ending is not as satisfying as the end of watching the &lt;em&gt;Lord of the Rings&lt;/em&gt; trilogy for the umpteenth time… But hey, we made it. The “Fission with Elm” demonstration app is now fully functioning, and you now have a better grip on the basics of integrating Fission into your code.&lt;/p&gt;

&lt;p&gt;In the first part of this series, I showed you how to set up Vite to manage Elm applications. This was the foundation of the application. In the second part, I showed you how to integrate Fission into an Elm project via the &lt;code&gt;webnative-elm&lt;/code&gt; module. This highlighted the structure of Fission integration. This third part took what was established in the previous two parts and demonstrated &lt;em&gt;some&lt;/em&gt; of the processes of Fission.&lt;/p&gt;

&lt;p&gt;I hope you have found this series of articles helpful as you begin to build Fission-based applications in Elm!&lt;/p&gt;

&lt;p&gt;Feel free to email any questions you may have to &lt;a href="mailto:info@xeticode.com"&gt;info@xeticode.com&lt;/a&gt; and my team and I will answer as promptly as we can :)&lt;/p&gt;




&lt;h1&gt;
  
  
  Appendix A
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Creating a Fission account
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://fission.codes/" rel="noopener noreferrer"&gt;https://fission.codes/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click on the "Sign up" button (located in the top portion of the screen)&lt;/li&gt;
&lt;li&gt;Click "Create account"&lt;/li&gt;
&lt;li&gt;Enter an email and desired username into the fields&lt;/li&gt;
&lt;li&gt;Click "Get started"&lt;/li&gt;
&lt;li&gt;Follow the instructions on your screen to link your account to another device!&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>fission</category>
      <category>elm</category>
      <category>vite</category>
    </item>
    <item>
      <title>Using Fission with Elm - Part 2: Integrating Fission into the Elm project</title>
      <dc:creator>Verge729</dc:creator>
      <pubDate>Mon, 18 Oct 2021 22:47:24 +0000</pubDate>
      <link>https://dev.to/xeticode/using-fission-with-elm-part-2-integrating-fission-into-the-elm-project-3k0k</link>
      <guid>https://dev.to/xeticode/using-fission-with-elm-part-2-integrating-fission-into-the-elm-project-3k0k</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Prelude&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is part of a three-part series. In part one, I demonstrated how to use Vite to manage an Elm application. In part two (this article), I will show you how to integrate Fission into the project from part one. Part three will walk you through how to refactor the project for Fission authentication and Fission Drive.&lt;/p&gt;

&lt;p&gt;The Github repository associated with this article can be found here:&lt;br&gt;
&lt;a href="https://github.com/xeticode/fission-with-elm-demos/tree/Part-2" rel="noopener noreferrer"&gt;https://github.com/xeticode/fission-with-elm-demos/tree/Part-2&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Welcome to round two! The time has come to upgrade our project from part one! The upgrade will connect the application to Fission, which I will introduce to you in a short moment. Before the introduction, I want to point out why Fission is a tool of the future. Fission uses a distributed system to store data. To one up that, Fission built a file system in the distributed system and protects it with military grade encryption. That means you can have a whole file system saved and protected across a whole network (in this case, the internet) rather than just on a remote machine or your own. And for app development, it means no need to worry about server maintenance or scaling. Anyways, I am getting ahead of myself. Without further ado, I present to you the InterPlanetary File System (IPFS) and, of course, Fission. &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Enter IPFS…&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In short, the “IPFS is a distributed system for storing and accessing files, websites, applications, and data” (for more information, see &lt;a href="https://docs.ipfs.io/concepts/what-is-ipfs/" rel="noopener noreferrer"&gt;IPFS&lt;/a&gt;). No more need for centralized servers! Have you ever heard of blockchain? It uses a similar technical approach: peer-to-peer networking using content addressing. Say goodbye to centralized servers!&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Enter Fission…&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To add to my pre-introduction, Fission is built on top of the IPFS, and implements a layer of military grade encryption. I know I mentioned this before, but it deserves more attention. Fission created a file system called Webnative File System (Wnfs). It has a huge advantage over cloud storage in that it resides in a distributed system rather than centralized servers, meaning it is backed up on a vast network of machines and not at the data centers of some tech company.&lt;/p&gt;

&lt;p&gt;Fission developed the &lt;code&gt;Webnative SDK&lt;/code&gt; to interact with Fission services. Since we are working with an Elm application, we will use the &lt;code&gt;Webnative-elm&lt;/code&gt; module for Elm (see &lt;a href="https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/" rel="noopener noreferrer"&gt;Webnative-Elm&lt;/a&gt;). Using this wrapper allows us to maximize our Elm code and minimize the JavaScript for the project. &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;The Walkthrough&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;NOTE: This article assumes you have completed the project as described in part 1. If you have not completed that project, please go back and follow the steps in part 1 to complete it or download the part 1 reference project. See &lt;a href="https://dev.to/xeticode/using-fission-with-elm-part-1-using-vite-to-manage-elm-applications-4ahk"&gt;Fission with Elm, Part 1: Using Vite to manage Elm applications&lt;/a&gt; for both options.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Installing Webnative dependencies&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To start things off, we will need to install Webnative to our node modules and &lt;code&gt;elm.json&lt;/code&gt; file. To do this, run the following commands in the terminal from the root directory of the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev webnative webnative-elm
npx elm-json install fission-suite/webnative-elm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;&lt;code&gt;npm install webnative webnative-elm&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; will install both &lt;code&gt;webnative&lt;/code&gt; and &lt;code&gt;webnative-elm&lt;/code&gt; libraries to the project (check &lt;code&gt;package.json&lt;/code&gt; for the new additions).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;&lt;code&gt;npx elm-json install fission-suite/webnative-elm&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; will install the Elm dependency of the &lt;code&gt;fission-suite/webnative-elm&lt;/code&gt; module (check &lt;code&gt;elm.json&lt;/code&gt; for the new addition). This module is a wrapper, written in Elm, for &lt;code&gt;Webnative&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Modifying js/index.js&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is pretty simple. &lt;/p&gt;

&lt;p&gt;At the top of the file, add these two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;webnative&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;webnative&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;webnativeElm&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nx"&gt;webnative&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;elm&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after the &lt;code&gt;const app = Elm.Main.init({});&lt;/code&gt; line, add these two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;webnative&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;webnativeElm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;webnative&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a quick breakdown of the new lines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;&lt;code&gt;webnative.setup.debug({enabled:true});&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; toggles on the debug mode. If enabled, the debug mode will output Webnative-related messages to the &lt;code&gt;Console&lt;/code&gt; tab in the &lt;code&gt;Developer Tools&lt;/code&gt; window. Toggle debug mode with this window open and you will easily see the difference.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;&lt;code&gt;webnativeElm.setup({app, webnative});&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; initiates the &lt;code&gt;webnative-elm&lt;/code&gt; wrapper, taking the initialized Elm application and the &lt;code&gt;Webnative SDK&lt;/code&gt; connection as parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Modifying src/Main.elm&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Ports&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Elm ports are how an Elm application can communicate with JavaScript, or the “outside world” as I like to call it (for an in-depth explanation of Elm ports, see &lt;a href="https://guide.elm-lang.org/interop/ports.html" rel="noopener noreferrer"&gt;Elm Ports&lt;/a&gt;). The current state of the &lt;code&gt;Main.elm&lt;/code&gt; file does not permit the use of ports. To change this, we need to change the file from a standard module to a port module. On line 1 of &lt;code&gt;Main.elm&lt;/code&gt;, add &lt;code&gt;port&lt;/code&gt; before &lt;code&gt;module&lt;/code&gt;. We can now use ports in this Elm file! Let’s add some!&lt;br&gt;
Normally, Elm ports require two ends: one Elm, and one in JavaScript. What makes this situation “abby”-normal (if you know, you know) is that this application is only concerned with interacting with Fission. The &lt;code&gt;webnative-elm&lt;/code&gt; wrapper handles the JavaScript end of the Webnative-related ports. The wrapper has also consolidated all of the ports we may need into two ports: one for all Webnative requests, and one for all Webnative responses.&lt;br&gt;
The &lt;code&gt;Webnative SDK&lt;/code&gt; requires two ports: one for requests, and one for responses. Add these two lines just after the import block at the top of the file in &lt;code&gt;Main.elm&lt;/code&gt; to satisfy the requirement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;port&lt;/span&gt; &lt;span class="n"&gt;webnativeRequest&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
&lt;span class="k"&gt;port&lt;/span&gt; &lt;span class="n"&gt;webnativeResponse&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Sub&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have them added, you will notice the red squiggles under &lt;code&gt;Webnative.Request&lt;/code&gt; and &lt;code&gt;Webnative.Response&lt;/code&gt;. This is because we have yet to import &lt;code&gt;Webnative&lt;/code&gt; to the file. Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to the import block at the top of the file.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Adding Permissions&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Every Fission-based application requires a set of defined permissions to initialize the application.&lt;br&gt;
There are three functions we will add to our project to define these permissions: &lt;code&gt;appPermissions&lt;/code&gt;, &lt;code&gt;fsPermissions&lt;/code&gt;, and &lt;code&gt;permissions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;appPermissions&lt;/code&gt;&lt;/em&gt; will return a record with fields indicating the name of the application and the creator of the application. Add the following just after the Webnative ports in &lt;code&gt;Main.elm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;appPermissions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;AppPermissions&lt;/span&gt;
&lt;span class="n"&gt;appPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Trillian"&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fission-with-elm"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what Fission will use to create a file path within the Wnfs to the files produced by this application (i.e. &lt;code&gt;Apps/Trillian/fission-with-elm/&lt;/code&gt;). Feel free to change the creator field to your own username if you so desire.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;fsPermissions&lt;/code&gt;&lt;/em&gt; will return a record with fields indicating what public and private parts of the Wnfs for which the application will request access (“fs” stands for File System here). Add the following a couple of lines after &lt;code&gt;appPermissions&lt;/code&gt;, but before &lt;code&gt;type alias Flags&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;fsPermissions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;FileSystemPermissions&lt;/span&gt;
&lt;span class="n"&gt;fsPermissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;directories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;directories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This application is not asking to access any parts of the Wnfs external to this application, so the lists will remain empty. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;permissions&lt;/code&gt;&lt;/em&gt; the icing on the cake. This will return a record with two fields: &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;fs&lt;/code&gt;. These correspond to the two previous code blocks we talked about. Add the following a couple of lines after &lt;code&gt;fsPermissions&lt;/code&gt;, but before &lt;code&gt;type alias Flags&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Permissions&lt;/span&gt;
&lt;span class="n"&gt;permissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;appPermissions&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;fsPermissions&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will pass this, our newly defined &lt;code&gt;permissions&lt;/code&gt;, through the &lt;code&gt;webnativeRequest&lt;/code&gt; port in the next step.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;The &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;subscriptions&lt;/code&gt; functions&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;&lt;em&gt;&lt;code&gt;init&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;The only difference here is changing the Cmd msg from &lt;code&gt;Cmd.none&lt;/code&gt; to a command that will initialize the application as a Webnative application. The new &lt;code&gt;init&lt;/code&gt; function should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Flags&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Url&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Navigation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;webnativeRequest&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a quick explanation of the new command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;permissions&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; was previously defined in the walkthrough. It indicates both the name and creator of the application and contains a list of Wnfs access requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;Webnative.init&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; is a function of &lt;code&gt;webnative-elm&lt;/code&gt; that will load a user's Wenative File System, if said user is authenticated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;&lt;code&gt;webnativeRequest&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; is our port for our Webnative related requests.
&lt;strong&gt;&lt;em&gt;&lt;code&gt;subscriptions&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt; 
We now need to subscribe to &lt;code&gt;webnativeResponse&lt;/code&gt; so the response will be properly handled and not left by the wayside. In the &lt;code&gt;subscriptions&lt;/code&gt; function, change &lt;code&gt;Sub.none&lt;/code&gt; to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;webnativeResponse&lt;/span&gt; &lt;span class="kt"&gt;GotWebnativeResponse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will set the application to watch our &lt;code&gt;webnativeResponse&lt;/code&gt; port for any changes. &lt;code&gt;GotWebnativeResponse&lt;/code&gt; is a &lt;code&gt;Msg&lt;/code&gt; variant we will add in a few moments and will be where we handle the response.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Adding a variant to the &lt;code&gt;Msg&lt;/code&gt; and updating the &lt;code&gt;update&lt;/code&gt; function&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;&lt;em&gt;&lt;code&gt;Msg&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;At this point, we have only two &lt;code&gt;Msg&lt;/code&gt; variants: &lt;code&gt;UrlChanged Url.Url&lt;/code&gt; and &lt;code&gt;LinkClicked Browser.UrlRequest&lt;/code&gt;. To handle the &lt;code&gt;webnativeResponse&lt;/code&gt;, we need to add the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; variant. Add the new variant to the &lt;code&gt;Msg&lt;/code&gt; so that it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; 
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UrlChanged&lt;/span&gt; &lt;span class="kt"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Url&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;LinkClicked&lt;/span&gt; &lt;span class="kt"&gt;Browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;UrlRequest&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;GotWebnativeResponse&lt;/span&gt; &lt;span class="kt"&gt;Webnative&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This new variant will allow us to dictate how to handle each response the application receives from &lt;code&gt;webnativeResponse&lt;/code&gt;. Our friendly red squiggles should now be present on our &lt;code&gt;update&lt;/code&gt; function. This is because our new &lt;code&gt;Msg&lt;/code&gt; variant is a new branch the case statement in our &lt;code&gt;update&lt;/code&gt; function needs to handle. The only problem? We have yet to add the branch to the case statement. This exemplifies one of the beauties of Elm, it forces us to handle each defined potential outcome or branch of whatever it is that is the subject of a case statement. Super helpful if you are, at times, forgetful 😉 Let us now add the new branch to update.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;&lt;em&gt;&lt;code&gt;update&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;That being said, as much as we may enjoy the red squiggles, they need to go. Add the following branch to the &lt;code&gt;update&lt;/code&gt; function's case statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;GotWebnativeResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will satisfy the Elm compiler, but it needs to be noted that this state of the &lt;code&gt;GotWebnativeResponse&lt;/code&gt; branch does not handle anything. It is currently a dead end for the Webnative response, and for the time being, it will stay that way. The reason for this decision is that adding the proper logic to this branch fits beautifully with what is covered in part three of this series: authentication and interacting with the Wnfs. So be sure to check out part three!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Ending&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Before its over: See that it works&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So far we have done all this work, but have yet to visually see any of that work in our app. If you have not done so already, get your dev server running. Once you have the app running, open the &lt;code&gt;Developer Tools&lt;/code&gt; window in your browser, and go to the &lt;code&gt;Console&lt;/code&gt; tab. You should see the following message in the list of messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[vite-plugin-elm] ports. webnativeRequest.subscribe called
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This indicates that our application is listening to the &lt;code&gt;webnativeRequest&lt;/code&gt; port! Visually, it is not much, but internally this is very important. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Adieu&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;And there you have it! The application has been upgraded with Fission integration. In this article, I showed you how to build upon what we made in the first article. In the third article, we will see the culmination as functionality is added to the project. If you wish to learn more about Fission or the Webntive-Elm module, check out these links: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fission

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fission.codes/" rel="noopener noreferrer"&gt;https://fission.codes/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.fission.io/docs/" rel="noopener noreferrer"&gt;https://docs.fission.io/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://guide.fission.codes/" rel="noopener noreferrer"&gt;https://guide.fission.codes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Webnative-elm

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/" rel="noopener noreferrer"&gt;https://package.elm-lang.org/packages/fission-suite/webnative-elm/6.0.0/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>elm</category>
      <category>fission</category>
      <category>vite</category>
    </item>
    <item>
      <title>Using Fission with Elm - Part 1: Using Vite to manage Elm applications</title>
      <dc:creator>Verge729</dc:creator>
      <pubDate>Tue, 12 Oct 2021 22:34:16 +0000</pubDate>
      <link>https://dev.to/xeticode/using-fission-with-elm-part-1-using-vite-to-manage-elm-applications-4ahk</link>
      <guid>https://dev.to/xeticode/using-fission-with-elm-part-1-using-vite-to-manage-elm-applications-4ahk</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Prelude&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is a three-part series. In part one (this article), I will show you how to use Vite to manage an Elm application. The second article will show you how to integrate the basics of Fission via the Webnative SDK into the project and the third will walk you through how to refactor the project for Fission authentication and using a Fission Drive.&lt;/p&gt;

&lt;p&gt;The Github repository associated with this article can be found here: &lt;a href="https://github.com/xeticode/fission-with-elm-demos/tree/Part-1" rel="noopener noreferrer"&gt;https://github.com/xeticode/fission-with-elm-demos/tree/Part-1&lt;/a&gt; .&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hello, hello! In this article, I will walkthrough how to initialize a Vite project and then set up an Elm application within that project. Before I do that, I will quickly introduce you to both Vite and Elm because a lack of character development is almost always an insufficient foundation for any good story. So, without further ado…&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Enter Elm…&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Elm is not only a typed, pure functional language that transpiles to JavaScript, it is also an architecture for web applications (known as The Elm Architecture or TEA, for short). As a language, Elm offers excellent error messages and is able to avoid runtime errors at compile time because of its strong typing and pure functions. This combination can make refactoring a project a breeze as Elm directs the developer to the exact spot or a specified area where the error is occurring. As an architecture, Elm employs a reactive Model-View-Controller design, or more common within the code: a Model, a view, and an update function. As the user interacts with the UI, messages are sent to the update function which then can alter the data within the Model, which will then update the UI, and the cycle continues on.&lt;/p&gt;

&lt;p&gt;To learn more about Elm, check out &lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;https://elm-lang.org/&lt;/a&gt; .&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Enter Vite…&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Vite is a bundling tool that uses browser-native ES modules and tools such as Rollup to build a project. Vite makes it easy to build JS modules along side your Elm code for seamless project deployment. This will not be apparent in this article because we will not be using JS modules. That being said, we will use them in subsequent articles, so setting up Elm with Vite is necessary moving forward. For now, we will have the benefit of using the dev server, build, and build preview functionality offered by this tool.&lt;/p&gt;

&lt;p&gt;To learn more about Vite, check out &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;https://vitejs.dev/&lt;/a&gt; .&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Walkthrough&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Alright, now that introductions have been made, we can proceed!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Initialize the Vite project&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First things first: open an IDE of your choice and open the directory in which you want to store the &lt;code&gt;fission-with-elm&lt;/code&gt; application. Once that is done, run the following commands in the terminal from the directory holding the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init vite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will initialize a Vite project.&lt;/p&gt;

&lt;p&gt;We will be prompted to enter a name for the Vite project. Normally, this would be your chance to come up with something creative, but since this is a walkthrough, that will have to wait. Name the project &lt;code&gt;fission-with-elm&lt;/code&gt;. Anyway, next you will then be prompted to select a web framework. Vite initializes a project differently based on the chosen web framework. As Elm is not one of the core frameworks we will select &lt;code&gt;vanilla&lt;/code&gt; for the framework and &lt;code&gt;vanilla&lt;/code&gt; as the variant.&lt;/p&gt;

&lt;p&gt;Once the Vite project has successfully been initialized, these will be the next commands to run, some of which are displayed at the end of the output from the &lt;code&gt;npm init vite&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd fission-with-elm
npm install --save-dev vite-plugin-elm
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands do the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cd fission-with-elm&lt;/code&gt; : will move the terminal's working directory into the project directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm install --save-dev vite-plugin-elm&lt;/code&gt; : will install a Vite plugin that bridges the gap between Vite and Elm. Vite supports a handful of web frameworks from the get-go and Elm is not one of them. Thus we install a plugin to make up for that. The &lt;code&gt;--save-dev&lt;/code&gt; tag will make this a development dependency, which is a dependency kept for development and building of the project, but is not kept for deployment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run dev&lt;/code&gt; : will begin the dev server. &lt;code&gt;dev&lt;/code&gt; is a script defined in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before running these commands in the terminal, take a look at the file explorer and browse the files added by &lt;code&gt;npm init vite&lt;/code&gt;. You should see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;favicon.svg&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;style.css&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we change some of the project structure, some of these files will become redundant and can be removed. I will indicate which files those are at the appropriate times. Now run the three commands indicated by the terminal. &lt;/p&gt;

&lt;p&gt;After running &lt;code&gt;npm run dev&lt;/code&gt; you will see the dev server is running at &lt;code&gt;http://localhost:3000&lt;/code&gt;. If you go there you should see this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq27yafazd7am7bomhqm1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq27yafazd7am7bomhqm1.PNG" alt="Vite Browser" width="588" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only thing that remains to finish initializing this Vite project is making it so the project can properly use the Elm plugin. To do this, we will create a file named &lt;code&gt;vite.config.js&lt;/code&gt;. This file will be placed within the current directory (which is named after the name you chose for the Vite project). The file needs to contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;elmPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-elm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// identify what plugins we want to use&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;elmPlugin&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
  &lt;span class="c1"&gt;// configure our build&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// file path for the build output directory&lt;/span&gt;
    &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// esbuild target&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;es2020&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Set up the Elm Application: Installation&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;elm-tooling&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Life and setting up an Elm application have at least one thing in common: there are many ways to do it. As this is a dev article, I will not indicate which way of life you should live, but I will tell you which method to use to set up an Elm application. For this project, we use &lt;code&gt;elm-tooling&lt;/code&gt;. It is a command line program for managing Elm tools, namely: &lt;code&gt;elm&lt;/code&gt;, &lt;code&gt;elm-format&lt;/code&gt;, &lt;code&gt;elm-json&lt;/code&gt;, and &lt;code&gt;elm-test-rs&lt;/code&gt; (see &lt;a href="https://elm-tooling.github.io/elm-tooling-cli/" rel="noopener noreferrer"&gt;elm-tooling-cli&lt;/a&gt; for more information).  First step for setting up an Elm application is to install elm-tooling. Run the following commands in the terminal (double check to make sure you are still in the &lt;code&gt;fission-with-elm&lt;/code&gt; directory):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev elm-tooling
npx elm-tooling init
npx elm-tooling install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm install --save-dev elm-tooling&lt;/code&gt; : installs the &lt;code&gt;elm-tooling&lt;/code&gt; tool to the project. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm elm-tooling init&lt;/code&gt; : will initialize &lt;code&gt;elm-tooling&lt;/code&gt; within the project. You will notice a new file named &lt;code&gt;elm-tooling.json&lt;/code&gt; : appear in the file explorer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx elm-tooling install&lt;/code&gt; : will install the selected tools to &lt;code&gt;~/.elm/elm-tooling/&lt;/code&gt; and create soft links to these tools in &lt;code&gt;./node_modules/.bin/&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see what tools &lt;code&gt;elm-tooling&lt;/code&gt; has to offer by running the&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx elm-tooling tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;command. This will also let you select the tools you want for the project. Running the command will present you with output like this one: &lt;/p&gt;

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

&lt;p&gt;As you can see, &lt;code&gt;elm&lt;/code&gt;, &lt;code&gt;elm-format&lt;/code&gt;, and &lt;code&gt;elm-json&lt;/code&gt; are selected by default. We will not be using the last tool, &lt;code&gt;elm-test-rs&lt;/code&gt;, which is a tool used for testing the application, as writing tests is beyound the scope of these articles.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;elm-json&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Next, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx elm-json new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a file named &lt;code&gt;elm.json&lt;/code&gt;. This file holds information concerning the Elm application such as: dependencies, location of source directories, and which version of Elm is being used for the project. There will be a question about what type of Elm project you want, select “application”.&lt;/p&gt;

&lt;p&gt;At this point we have four JSON files: elm.json, elm-tooling.json, package-lock.json, package.json. Here is what is significant about each file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;elm.json&lt;/code&gt; : this contains Elm specific information such as Elm module dependencies, the version of Elm being used, and the file path(s) to any source directories within the project.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;elm-tooling.json&lt;/code&gt; : this contains a limited selection of Elm tools&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;package-lock.json&lt;/code&gt; : the npm package version lock.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;package.json&lt;/code&gt; : this contains information of the project such as the name of the project, command line scripts (i.e., the dev command previously executed in this walkthrough).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;Set up the Elm Application: Modifying to the file structure&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Ok, now that installation has been complete, let’s add some structure to the project! We will be adding a few directories and files with those directories. As a reminder, everything that will be added will be with the &lt;code&gt;fission-with-elm&lt;/code&gt; directory (now referred to as root directory for the remainder of this article).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Add a directory named &lt;code&gt;src&lt;/code&gt;. This will be for your Elm source files. Within that directory, add a file named &lt;code&gt;Main.elm&lt;/code&gt;. Leave the file empty for now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add another directory in the root directory called &lt;code&gt;js&lt;/code&gt;. In this new directory, create a file called &lt;code&gt;index.js&lt;/code&gt;. Leave the file empty for now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create another directory in the root directory called &lt;code&gt;public&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Within &lt;code&gt;public&lt;/code&gt;, create a directory called &lt;code&gt;assets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Within &lt;code&gt;assets&lt;/code&gt;, create a directory called &lt;code&gt;images&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; The end product here should look like: &lt;code&gt;./public/assets/images/&lt;/code&gt;. For this project, we will be using the Fission logo. You can download this image from the repo associated with this article. To do so, Run the following command in the terminal from the &lt;code&gt;images&lt;/code&gt; directory:
&lt;/li&gt;
&lt;/ol&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  curl -o fission.svg https://raw.githubusercontent.com/xeticode/fission-with-elm-demos/Part-1/public/assets/images/fission.svg
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Set up the Elm Application: Adding content to the files&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We are near the end! We have a few files to change: &lt;code&gt;./js/index.js&lt;/code&gt;, &lt;code&gt;./src/Main.elm&lt;/code&gt;, and &lt;code&gt;./index.html&lt;/code&gt;. First, we will take a look at &lt;code&gt;./index.html&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;index.html&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We need to connect the &lt;code&gt;index.js&lt;/code&gt; file to the &lt;code&gt;index.html&lt;/code&gt; file via a script tag that will be placed within the &lt;code&gt;head&lt;/code&gt; tag. &lt;/p&gt;

&lt;p&gt;This is the new content of the &lt;code&gt;index.html&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"favicon.svg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Vite App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Here is the new script tag --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./js/index.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- This is the old content --&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt; --&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;script type="module" src="/main.js"&amp;gt;&amp;lt;/script&amp;gt; --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;These changes make the &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;styles.css&lt;/code&gt; files redundant as we no longer reference them. Both files are used to present the &lt;code&gt;Hello Vite!&lt;/code&gt; webpage from the beginning of the walkthrough. Delete these files now.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;index.js&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here is all that is needed in the &lt;code&gt;./js/index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Elm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/src/Main.elm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Elm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the connection point between &lt;code&gt;index.html&lt;/code&gt; and our Elm application. Line 1 indicates where to find the application, and line 3 initializes the application. &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Main.elm&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This article does not focus on the components of &lt;code&gt;Main.elm&lt;/code&gt;. Because of this, and the length of the file, we will download the file directly from the Github repository. We will dive into the file in Part 2, but for now, use this command to download the &lt;code&gt;Main.elm&lt;/code&gt; file from the repository asociated with this article. We will dive into this file in part 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -o Main.elm https://raw.githubusercontent.com/xeticode/fission-with-elm-demos/Part-1/src/Main.elm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Set up the Elm Application: Importing Elm modules&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Alrighty! Go ahead and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compilation should fail. Reason being? There are dependencies we refer to from within &lt;code&gt;Main.elm&lt;/code&gt; that have not been installed. Run the following command in the root directory to install the missing dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx elm-json install elm/browser elm/url mdgriffith/elm-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is some information on the packages being installed (for more info on each package, see &lt;a href="https://package.elm-lang.org/" rel="noopener noreferrer"&gt;https://package.elm-lang.org/&lt;/a&gt; and enter the package name in the search bar):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;elm/browser&lt;/code&gt; enables the Elm application to run in the browser.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;elm/url&lt;/code&gt; handles creation and parsing of Urls (required when using Browser.application).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mdgriffith/elm-ui&lt;/code&gt; handles layout and styling (there are a few options for for layout and styling, and I chose elm-ui for its simplicity, capability, and ease of use).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running the command, a confirmation prompt will appear regarding the addition of these modules to the &lt;code&gt;elm.json&lt;/code&gt; file. There will be some dependencies to be installed to the indirect dependcies because the direct dependencies depend on them. The word "dependency" was used too much in that last sentence... I recommend having the &lt;code&gt;elm.json&lt;/code&gt; file open so the changes can be visibly seen.&lt;/p&gt;

&lt;p&gt;You can also run the &lt;code&gt;npx elm-json install&lt;/code&gt; command once per dependency if desired. Once those dependencies have been installed, the error messages should disappear and you should see this:&lt;/p&gt;

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




&lt;h2&gt;
  
  
  &lt;strong&gt;The Ending&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Before its over: Witness the live reload of Vite&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For this part, make sure you have the dev server running and a browser open to the &lt;code&gt;localhost&lt;/code&gt; domain. Vite has live reload functionality. In other words, if you change something in the &lt;code&gt;Main.elm&lt;/code&gt; file, it will take note of the changes made and automatically serve the new files. To demonstrate this, go to line 68 in &lt;code&gt;Main.elm&lt;/code&gt;. You should see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;EBA&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rgb255&lt;/span&gt; &lt;span class="mi"&gt;176&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt; &lt;span class="mi"&gt;222&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line dictates the background color of the application. Change any number of the intgers following &lt;code&gt;E.rgb255&lt;/code&gt; to a value between 0 and 255 inclusive and see the background automatically change!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Before its over: Build and Serve the project&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before we can &lt;em&gt;officially&lt;/em&gt; wrap this up, I will show you how to build the project and serve the build directory. Run these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
npm run serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;serve&lt;/code&gt; are scripts defined in &lt;code&gt;package.json&lt;/code&gt;. These commands do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm run build&lt;/code&gt; will use Vite to build the project. As it builds, a new directory named &lt;code&gt;build&lt;/code&gt; will appear in the file structure. The first children of this directory will be the static files from the location indicated by the &lt;code&gt;publicDir&lt;/code&gt; tag from the &lt;code&gt;vite.config.js&lt;/code&gt; file. The other children will take a moment to appear and will be the files generated from the build process.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run serve&lt;/code&gt; will start a &lt;code&gt;localhost&lt;/code&gt; server and serve the files from the &lt;code&gt;build&lt;/code&gt; directory. This will be running at &lt;code&gt;http://localhost:5000&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result should be the same as what is produced by the &lt;code&gt;npm run dev&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Adieu&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;And there you have it! A simple Elm project that is managed by Vite. As a reminder, this only covers the basics of setting up Vite and Elm, if you wish to learn more about what they both have to offer, follow these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elm

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://package.elm-lang.org/" rel="noopener noreferrer"&gt;https://package.elm-lang.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elm-lang.org/" rel="noopener noreferrer"&gt;https://elm-lang.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Vite

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;https://vitejs.dev/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In the next article, we will alter this project to integrate Webnative, an SDK built and provided by Fission.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>fission</category>
      <category>vite</category>
    </item>
    <item>
      <title>FaunaDB, GraphQL, and Elm, A Tutorial for JAMstack, Part 2</title>
      <dc:creator>Dirk Johnson</dc:creator>
      <pubDate>Mon, 27 Jul 2020 15:45:52 +0000</pubDate>
      <link>https://dev.to/xeticode/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-2-2eec</link>
      <guid>https://dev.to/xeticode/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-2-2eec</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;[Note: this tutorial was written by commission for &lt;a href="https://fauna.com?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;Fauna, Inc&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/dirkbj/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-1-57f8"&gt;part 1 of this article&lt;/a&gt;, you were introduced to a simple Elm JAMstack site called Shall We Play?, an application for scheduling game nights with friends. Shall We Play? lacked secure login and database support, making it a minimally useful site for scheduling game nights but a perfect site for introducing FaunaDB, a multi-region, zero-operation database with native support for GraphQL.&lt;/p&gt;

&lt;p&gt;Part 1 focused on creating a GraphQL schema for supporting secure login and pulling restricted data from the database. Additionally, it introduced the sophisticated attribute-based access control features of FaunaDB which was used to back the GraphQL schema and provide identity services.&lt;/p&gt;

&lt;p&gt;Part 2, the final part of this article, will continue building upon the work done in part 1 by updating Shall We Play? to take advantage of this new GraphQL service using an Elm package called &lt;a href="https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/"&gt;elm-graphql&lt;/a&gt; by Dillon Kearns.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This part of the article assumes you are comfortable with using a command-line, git source control, and package managers like npm. Additionally, you should have a rudimentary understanding of Elm. If you are new to Elm, take some time to review &lt;a href="https://guide.elm-lang.org/"&gt;the official Elm guide&lt;/a&gt; up through the Installation chapter. Don't worry if you don't have any practical experience with Elm, I'll walk you through everything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ready to go? Great! Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Shall We Play? to FaunaDB through elm-graphql
&lt;/h2&gt;

&lt;p&gt;If you completed all the steps outlined in part 1 of this article to set up our GraphQL service, then we are now ready to add login services to Shall We Play?. The ideal way for this to happen is for you to join me in the coding process, just like you joined me when setting up our GraphQL schema and database in part 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Shall We Play? for Local Development
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/xeticode/shallweplay"&gt;Shall We Play? starter application&lt;/a&gt; is an open source project on GitHub. Before you get started with this section, you will need to create a fork of the application so you can run and edit it locally.&lt;/p&gt;

&lt;p&gt;First, create a free &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt; account if you need to, then log into GitHub and go to &lt;a href="https://github.com/xeticode/shallweplay"&gt;the Shall We Play? project&lt;/a&gt;. Click on "Fork" in the upper right.&lt;/p&gt;

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

&lt;p&gt;Once the project has completed forking, clone the project to your local system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flzrz1tv9wg0v666wcyco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flzrz1tv9wg0v666wcyco.png" alt="Clone Project" width="678" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;master&lt;/code&gt; branch is the starting point for part 2. I would recommend creating a branch off of &lt;code&gt;master&lt;/code&gt; before continuing with the tutorial in case you need to back and up and try again or want to go a different direction later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For managing the project during development, we use some Node.js tools, so you will need to install &lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt;. As of the time of this writing, I am using Node.js v13.12.0 and npm v6.14.4. Go ahead and make sure you have Node.js properly installed; refer to the installation instructions for your particular system, if necessary.&lt;/p&gt;

&lt;p&gt;Next, you will need an editor. If your preferred editor does not have good language support for Elm, please give &lt;a href="https://code.visualstudio.com/"&gt;VSCode&lt;/a&gt; a try with the Elm tooling extension. However, there are actually a lot of good editors out there with Elm support, including Vim.&lt;/p&gt;

&lt;p&gt;Now we will need to install some npm packages to get things going. Bring up a terminal in the root directory of the project and run &lt;code&gt;npm install&lt;/code&gt;. Once npm is finished installing, test the current version of the application by running &lt;code&gt;npm start&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm start

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shallweplay@0.0.1 start /Users/dbj/Documents/Family/Dirk/XetiCode/projects.nosync/internal/shallweplay
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; npx elm-live ./src/Main.elm &lt;span class="nt"&gt;--dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./static &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./static/assets/js/shallweplay.js &lt;span class="nt"&gt;--debug&lt;/span&gt;

elm-live:
  Server has been started! Server details below:
    - Website URL: http://localhost:8000
    - Serving files from: ./static

elm-live:
  The build has succeeded. 

elm-live:
  Watching the following files:
    - src/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.elm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;npm start&lt;/code&gt; runs the elm-live tool which will install any elm packages that are needed, compile the code, and bring up the application in your default browser. While running, elm-live will continue to watch the Elm files in your source directory and, when they change, recompile them and reload the browser view.&lt;/p&gt;

&lt;p&gt;Have a look around to re-familiarize yourself with the application; it should behave identically to the deployed version.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  A Bit About Elm
&lt;/h3&gt;

&lt;p&gt;Elm is both a functional language and an architecture for web applications. The architecture imposes a simple data-flow pattern that is easy to reason about, as illustrated by the following diagram taken from &lt;a href="https://guide.elm-lang.org/architecture/"&gt;the official Elm guide&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3zyubitk45hmk89hudre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3zyubitk45hmk89hudre.png" alt="The Elm Architecture" width="750" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elm renders the initial HTML for the site. Then, as users interact with the site, they generate messages, which are sent to Elm. Elm processes the messages, updates the model (data) and generates new HTML based upon the updated model. Simple. Elegant.&lt;/p&gt;

&lt;p&gt;Where things might get challenging is in learning to read and think functionally if your experience is not with functional languages. Pure, functional languages are as orthogonal to the traditional object-oriented paradigm as you can get; it really is a different way of thinking. But the payoffs are worth it.&lt;/p&gt;

&lt;p&gt;As noted before, as we go through the exercise of modifying our application, I will explain things with the assumption that you have gone through the official Elm guide, at least through the Installation section. The good news is, Elm is expressive, and if you are familiar with JavaScript or other languages, and you read my explanations, you should be able to understand most of what is happening even if the details of the code are not clear.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Tour of the Project
&lt;/h3&gt;

&lt;p&gt;Let's take a look at the project structure. If you look inside the "src" directory, you should see 3 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Colors.elm&lt;/li&gt;
&lt;li&gt;DataModel.elm&lt;/li&gt;
&lt;li&gt;Main.elm&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Colors.elm file specifies the colors used on the website. The coloring of the site was in honor of my wife's favorite color. No comments, here, OK?&lt;/p&gt;

&lt;p&gt;The DataModel.elm file has our model, most of our types, and the functions that support them.&lt;/p&gt;

&lt;p&gt;The Main.elm file is the entry point into our application; it manages our message handling, and renders our view.&lt;/p&gt;

&lt;p&gt;Let's dig deeper into our data model; go ahead and open the DataModel.elm file in your editor. First you will notice our Model record, which is our persistent state between messages. We store, among other things, the current logged in Player, if any, a full list of Players, and a full list of Events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;input_user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_password&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Players&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Events&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_possible_event&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;PossibleEvent&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_poss_event_elem_info&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Dom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Element&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_offset&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Float&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LoginField&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dragged_player_position&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PlayerPosition&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drag&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;D&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;State&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the model, the core types are declared, such as Player, Event, and Invite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member_since&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EventId&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;organizer_user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;millis&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;venue&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EventStatus&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;invites&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Invites&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Invite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;for_user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;InviteStatus&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Player record tracks everything we need to know about a player. The Event record tracks the details about organized events including which player organized the event and what players were invited. The Invite record simply tracks which player the invite is for, and what their invite status is.&lt;/p&gt;

&lt;p&gt;The type we will be most concerned about in this article will be the Player type.&lt;/p&gt;

&lt;p&gt;Now let's look at the Main.elm file. The code is delineated informally by commented section headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main and Init&lt;/li&gt;
&lt;li&gt;Subscriptions and Commands&lt;/li&gt;
&lt;li&gt;Msg and Update&lt;/li&gt;
&lt;li&gt;Views&lt;/li&gt;
&lt;li&gt;Helpers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take a look at the "Msg and Update" section. Here you will see our Msg type which defines all of the messages that could be received through various interactions by users and other side effects (like system events or XHR requests). The &lt;code&gt;update&lt;/code&gt; function must deal with every one of these messages; Elm ensures this through the use of the &lt;code&gt;case&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;Now scroll on down to the "Views" section. Notice that the model is available to these views through the entry point &lt;code&gt;view&lt;/code&gt; function. This allows our views to respond to changes in the model.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the HTML/CSS generation, I have chosen to use an excellent package called &lt;a href="https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/"&gt;elm-ui&lt;/a&gt;. It is a low level abstraction of HTML and CSS (i.e., it does not define components). Elm also provides formal HTML and CSS packages so you can operate at that level if desired, and indeed, the HTML package is a complement to using elm-ui.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Showing The Password Field
&lt;/h3&gt;

&lt;p&gt;While we are in the "Views" section of the code, I'd like you to bring up the application if it is not running (run &lt;code&gt;npm start&lt;/code&gt; from the root directory) and then look at the &lt;code&gt;loginLogoutRowView&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;loginLogoutRowView&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Element&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;loginLogoutRowView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fill&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spacing&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moveLeft&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login_offset&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;loginView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_user_name&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passwordView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_password&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logoutView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_player&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last list in this function is a list of child views which are aligned in a single row. However, only one of these views will be visible at a time, and that is based on a single offset value set on the model called &lt;code&gt;login_offset&lt;/code&gt;. The current value of this offset now shows the &lt;code&gt;loginView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjnhxrhiumic74tro0vpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjnhxrhiumic74tro0vpq.png" alt="login view with offset" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go ahead and log in with any user name. Once you do, the &lt;code&gt;logoutView&lt;/code&gt; is shown. Note that the &lt;code&gt;passwordView&lt;/code&gt; was skipped because the offset was set to go past it.&lt;/p&gt;

&lt;p&gt;For our very first change in the app, we will update the login flow so it shows the &lt;code&gt;passwordView&lt;/code&gt; after the &lt;code&gt;loginView&lt;/code&gt;. We will do this by updating the function that controls the offset after providing a user name.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I like to run the application while I am editing the files so I can receive immediate feedback on my changes. elm-live will compile and reload the site when it notices changes to the code, or, if there is a compiler error, it will display the compiler error right in the window. Make sure elm-live is running while we make these next changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first place we need to update the offset is in the &lt;code&gt;updateModelFromEnteredUserName&lt;/code&gt; model handler in the Main.elm file. Right now this function jumps from the &lt;code&gt;loginView&lt;/code&gt; right to the &lt;code&gt;logoutView&lt;/code&gt; at offset 804.  Let's change this to jump to the &lt;code&gt;passwordView&lt;/code&gt; which is at offset 402. Additionally, we need to control where tabbing can go in the DOM, so change &lt;code&gt;NoField&lt;/code&gt; to &lt;code&gt;PasswordField&lt;/code&gt; to keep the &lt;code&gt;passwordView&lt;/code&gt; in the DOM's tabbing order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;login_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;402.0&lt;/span&gt;
        &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;PasswordField&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As a matter of interest, the &lt;code&gt;updateModelFromEnteredPassword&lt;/code&gt; function, which deals with the submitted password, already sets the correct offset to move from the password field to the logout field.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's test our small change by logging in; you should now see the password field instead of the logout button. Small victories, right?&lt;/p&gt;

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

&lt;p&gt;Notice that even though we have not yet provided a password or completed the login process, the main view still changes to look like the user is logged in, showing the events summary to the right and the details of the events below. Let's work on fixing that next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Showing The Logged In Main View At The Right Time
&lt;/h3&gt;

&lt;p&gt;Right now the application simply looks to see if there is a valid Player record in the model to determine whether a player is "logged in". Now that we will be requiring a password and a valid login token from FaunaDB before we will consider the player logged in, let's change this logic from looking for a valid player to looking for a login token.&lt;/p&gt;

&lt;p&gt;We need to have a place to store the authentication/authorization token, so let's do that right in the Player record.&lt;/p&gt;

&lt;p&gt;Open the DataModel module in your editor. First, to keep the code easier to understand, let's create a type alias for the token, which, under the hood, is a String. Put this after the Password type alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now lets update the Player record to take a Maybe Token called &lt;code&gt;m_token&lt;/code&gt; ("m" for "Maybe"):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member_since&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_token&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a Maybe Token because we will not always have a token, and, as you know, there is no such thing as &lt;code&gt;null&lt;/code&gt; in Elm (which is a very good thing).&lt;/p&gt;

&lt;p&gt;We also have a player constructor function called &lt;code&gt;newPlayer&lt;/code&gt; which we need to update to set a default value for &lt;code&gt;m_token&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;newPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Nothing&lt;/code&gt; is one of the type variants for the Maybe type, and it represents the absence of a value.&lt;/p&gt;

&lt;p&gt;Remember, in our reactive Elm architecture, the view is always driven by changes in the model. So now that we want our view to only show us the logged in main view once we are truly logged in, we need to update the view logic to look for the presence of a player token. This logic is in the &lt;code&gt;mainView&lt;/code&gt; function in the Main module; open the Main.elm file in your editor.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mainView&lt;/code&gt; function looks at whether there is a player record, and if there is, it considers the player logged in. Now we need to update this function to look a little deeper in the player record for a token, and if present, we consider the player logged in.  Here is what the code should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;mainView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;plainMainView&lt;/span&gt;

        &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_token&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;plainMainView&lt;/span&gt;

                &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;eventsMainView&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to update the &lt;code&gt;youHaveView&lt;/code&gt; because it displays the event summary if the player is logged in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;youHaveView&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;andThen&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_token&lt;/span&gt;
                &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                        &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;column&lt;/span&gt;
                            &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fill&lt;/span&gt;
                            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spacing&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
                            &lt;span class="p"&gt;]&lt;/span&gt;
                            &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;youHaveEventsView&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;
                            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;youHaveInvitesView&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;
                            &lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;m_player&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here again, we just drilled down to see if there was a token, and if so, display the summary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Elm, compiler errors are not actually dreaded (unlike some other languages ;). Elm's error messages are quite informative and often guide you right through the fix. When you get a compiler error, don't read the error quickly - read it and stop and think about it a second. I find if I jump to conclusions too quickly, I sometimes miss what the error is saying. In Elm, the compiler is your BFF.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go ahead and test out your app. When you enter a user name, you are brought to the password field, but now you should not see the logged in main view. The journey of a 1000 lines of code begins with the first change (or something like that).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnpurw9t5ex7x3pj3ym6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsnpurw9t5ex7x3pj3ym6.png" alt="password field with correct view" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding A Little Polish
&lt;/h3&gt;

&lt;p&gt;When the app showed the password field, did you notice how you had to tab or click to get the focus to try to enter your password?  Let's fix this annoyance, shall we? When you first launch Shall We Play?, the user name field immediately has the focus. We can use the same mechanism for giving focus to the password field after the user enters a user name.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;update&lt;/code&gt; function type signature. Notice that the &lt;code&gt;update&lt;/code&gt; function returns a tuple with a Model and a Command (Cmd).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commands are one way to send asynchronous messages out from the type-protected, pure space of Elm to a part of the runtime that does not have the same guarantees. (These are called side effects.) Using the Browser.Dom module, we can actually send a command to the DOM to set focus on a specific field.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;focusFieldWithId&lt;/code&gt; function; this function takes the id of the DOM element you want to focus on and calls the Dom.focus task as a command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;focusFieldWithId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;NoOp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;focus field with id "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Dom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function is used by the &lt;code&gt;focusUserNameField&lt;/code&gt; function which passes in the id for the user name field. Let's create a similar function for the password field, leveraging the &lt;code&gt;focusFieldWithId&lt;/code&gt; function; don't forget to add the function's type signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;focusPasswordField&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;focusPasswordField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;focusFieldWithId&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldIdForLoginField&lt;/span&gt; &lt;span class="kt"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice from the &lt;code&gt;focusFieldWithId&lt;/code&gt; function that the message that we get back from the &lt;code&gt;focus&lt;/code&gt; command is called &lt;code&gt;NoOp&lt;/code&gt;.  This is a message that basically means we do not want to do anything specific in response to the command completing. This makes sense as we won't know what to do next until the user enters a user name or password.&lt;/p&gt;

&lt;p&gt;Now that we have a new &lt;code&gt;focusPasswordField&lt;/code&gt; command, we need to make sure it is called once a user enters a user name. The message that is sent when a user enters a user name is called &lt;code&gt;EnteredUserName&lt;/code&gt; and it is handled by the &lt;code&gt;update&lt;/code&gt; function. Let's take a quick look at the &lt;code&gt;EnteredUserName&lt;/code&gt; message handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;EnteredUserName&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromEnteredUserName&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commandFromEnteredUserName&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_user_name&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;EnteredUserName&lt;/code&gt; message handler calls the &lt;code&gt;commandFromEnteredUserName&lt;/code&gt; command handler. Let's take a look at what it does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;commandFromEnteredUserName&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt;
        &lt;span class="n"&gt;cleaned_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;cleanedLoginString&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;
    &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isUserNameValid&lt;/span&gt; &lt;span class="n"&gt;cleaned_user_name&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="n"&gt;blurUserNameField&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user name coming in from the &lt;code&gt;EnteredUserName&lt;/code&gt; message is valid, a command called &lt;code&gt;blurUserNameField&lt;/code&gt; is sent. Blurring is the opposite of focusing, meaning an element that is blurred no longer has focus. Let's replace this command with our new &lt;code&gt;focusPasswordField&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isUserNameValid&lt;/span&gt; &lt;span class="n"&gt;cleaned_user_name&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="n"&gt;focusPasswordField&lt;/span&gt;

  &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test our change. How did it go?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;blurUserNameField&lt;/code&gt; command that we replaced is no longer being used, so we could delete this function. However, you may have guessed that we will need a similar function soon for the password field, so we will leave this function alone for now and repurpose it shortly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Wiring Up The Password Field
&lt;/h3&gt;

&lt;p&gt;Now we need to update the password field so it completes the login process once the password is submitted.&lt;/p&gt;

&lt;p&gt;But before we do that, let's stop and take a look at what is happening to our model when our user name and password is being entered. We can do this by looking at the built-in debug panel.&lt;/p&gt;

&lt;p&gt;Make sure your application is running and visit the site. In the bottom right, you have probably noticed the white tangram in a blue box:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdktdnje2xmjn9qavffx0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdktdnje2xmjn9qavffx0.png" alt="blue debug box" width="229" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may have even been tempted to click on it. If you did, a debug pane should have come up. Bring up the debug pane now.&lt;/p&gt;

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

&lt;p&gt;Remember that the Elm Architecture is about reactive message passing. The Elm debugger displays all the messages it receives and records the model at each message. Since the model drives the view, we essentially have a time-traveling debugger which can scrub back and forth through time so we can see the state of the app and the view at any point we want. This is a great way to zero in on bugs that are driven by data and logic errors, but it is also a great way to simply see what is happening with our app, like an x-ray.&lt;/p&gt;

&lt;p&gt;Notice that there is already one message waiting for us - the &lt;code&gt;NoOp&lt;/code&gt; message, which has the payload of "focus field with id user_name". This is the message that gets sent when the app first starts up so that the user name field is focused and waiting for the user to type. Look at the model. Notice that both &lt;code&gt;input_password&lt;/code&gt; and &lt;code&gt;input_user_name&lt;/code&gt; have empty strings as their values.&lt;/p&gt;

&lt;p&gt;Now, go ahead and type a user name and hit return. Notice that your focus command was received and that &lt;code&gt;input_user_name&lt;/code&gt; contains the user name you entered.&lt;/p&gt;

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

&lt;p&gt;Go ahead and scrub back through time using the slider at the top-left, and watch the &lt;code&gt;input_user_name&lt;/code&gt; field change. You will also see the view change. (OK, confession. Sometimes I just play with the scrubber when I need a quick break from coding… it's just too cool. ;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have noticed that, on macOS, if I run my browser in full screen mode and then I try to interact with the Elm debugger, it can be painfully slow responding to clicks. If you notice the same, simply bring the browser out of full screen mode and all should work just fine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now go ahead and enter a password and make sure that the &lt;code&gt;input_password&lt;/code&gt; field in the model is being updated properly while you type. &lt;strong&gt;If the UI isn't responsive, it's because you used the scrubber which paused Elm; hit the blue and white "play" button in the upper-left of the debugger and you should be good to go.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Now that we know the password is being saved, let's update the app to complete the login process after the password is submitted. Let's take a look at the &lt;code&gt;updateModelFromEnteredPassword&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;updateModelFromEnteredPassword&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt;
        &lt;span class="n"&gt;cleaned_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;cleanedLoginString&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_password&lt;/span&gt;
    &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isPasswordValid&lt;/span&gt; &lt;span class="n"&gt;cleaned_password&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;login_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;804.0&lt;/span&gt;
            &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NoField&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function looks at the stored password in the model, and if the password is valid, we update the &lt;code&gt;login_offset&lt;/code&gt; field to show the logout field as well as taking the password field out of the tab order in the DOM. What we need to do in addition is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; GraphQL mutation&lt;/li&gt;
&lt;li&gt;Clear the password from the model (don't want that sitting around)&lt;/li&gt;
&lt;li&gt;Blur the password field so it no longer has focus (to avoid keystrokes in the password field while it is not visible)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As we update the code to complete the login process, we are going to fudge step 1 above, and just make the model think we have made a GraphQL call and have received back a token. Wiring up elm-graphql will be quite an undertaking, and I would rather be sure we have everything else working before we start down that road.&lt;/p&gt;

&lt;p&gt;Sending off a request through GraphQL will involve sending a command that should return a message with our login token. Let's wire that up now. First, let's go to our Msg type and add a message called &lt;code&gt;LoggedInPlayer&lt;/code&gt; that has a payload of type Token. Let's place it below the &lt;code&gt;EnteredPassword&lt;/code&gt; variant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now update the &lt;code&gt;update&lt;/code&gt; function to handle this new Msg. Create a message handler that uses a model handler to update the model. This message handler will not need to send any commands, so we don't need a command handler. Place the new message handler next to the EnteredPassword message handler, just like with the Msg variants list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
         &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the &lt;code&gt;updateModelFromLoggedInPlayer&lt;/code&gt; model handler in its proper place next to the other model handlers. At this point, it should just set the token on the current player in the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt;
                &lt;span class="n"&gt;updated_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;updated_player&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go to the &lt;code&gt;update&lt;/code&gt; function and look at the &lt;code&gt;EnteredPassword&lt;/code&gt; message handler. We know that this is called when the player has submitted the password, so in response to this, we want to try to create and/or log them in. Update the message handler to send a command called &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt;, passing in the &lt;code&gt;input_user_name&lt;/code&gt; and &lt;code&gt;input_password&lt;/code&gt; from the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;EnteredPassword&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromEnteredPassword&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_user_name&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_password&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; command function below the &lt;code&gt;focusPasswordField&lt;/code&gt; command. This function will create a placeholder task that will return immediately with the &lt;code&gt;LoggedInPlayer&lt;/code&gt; message carrying a pseudo token string, as though it had come from FaunaDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;succeed&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abcdefgHIJKLMNOP1234560987"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command in place, we can now test the handling of our login flow without needing to wire up elm-graphql at this moment.&lt;/p&gt;

&lt;p&gt;Using our debugger, let's test our command to see if it actually sets a token value for the current player. Take a look. That should put a smile on your face. :)&lt;/p&gt;

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

&lt;p&gt;Let's complete our last two easy tasks of clearing the password and removing focus from the password field when the password has been entered. First, update the &lt;code&gt;updateModelFromEnteredPassword&lt;/code&gt; model handler to clear the &lt;code&gt;input_password&lt;/code&gt; field in the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isPasswordValid&lt;/span&gt; &lt;span class="n"&gt;cleaned_password&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
          &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;login_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;804.0&lt;/span&gt;
          &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;NoField&lt;/span&gt;
          &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will return to the &lt;code&gt;blurUserNameField&lt;/code&gt; and rename it to &lt;code&gt;blurPasswordField&lt;/code&gt;. Be sure to change the message that gets passed into NoOp (as it is visible in the debugger, and we don't want that message to be misleading) and be sure to use &lt;code&gt;PasswordField&lt;/code&gt; to generate the field id:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;blurPasswordField&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;blurPasswordField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;NoOp&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blurPasswordField"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Dom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blur&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldIdForLoginField&lt;/span&gt; &lt;span class="kt"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can send this command out as part of the &lt;code&gt;EnteredPassword&lt;/code&gt; message handler.&lt;/p&gt;

&lt;p&gt;But wait! We are already sending out the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; command in this message handler; can we possibly send two at once? The answer is, of course, Yes! Simply combine them using the &lt;code&gt;Cmd.batch&lt;/code&gt; function, which batches a list of commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;EnteredPassword&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromEnteredPassword&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_user_name&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;blurPasswordField&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's test everything out and make sure it all works. Use the debugger to see if we are still setting the token properly, that the &lt;code&gt;input_password&lt;/code&gt; field is reset, and if typing on the keyboard once logged in updates the &lt;code&gt;input_password&lt;/code&gt; field, which it shouldn't, because we blur the password field:&lt;/p&gt;

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

&lt;p&gt;Assuming your testing went well, (and I'm sure it did,) we are now ready to implement "la pièce de résistance": we get to integrate elm-graphql with our application so we can log in using our GraphQL service. Woot!&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating elm-graphql into our application
&lt;/h3&gt;

&lt;p&gt;Now that we are ready to integrate elm-graphql into our application, lets step back a moment and talk about elm-graphql and how to set it up within our project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/"&gt;elm-graphql&lt;/a&gt; was created by &lt;a href="https://incrementalelm.com/"&gt;Dillon Kearns&lt;/a&gt;. It is an elm package that fully supports all GraphQL features in a type-safe way. elm-graphql is also an npm command-line utility that will get your project ready to work directly with your schema by auto-generating decoders, query functions, and other necessary functionality. All we need to do is provide elm-graphql our GraphQL endpoint and a key with permissions to access it.&lt;/p&gt;

&lt;p&gt;FaunaDB provides the same GraphQL endpoint to all customers: &lt;code&gt;https://graphql.fauna.com/graphql&lt;/code&gt;. The way FaunaDB knows which schema and database need to handle specific requests, then, is by the key that is provided along with each request. We will need to generate a server key that we can provide elm-graphql to access our schema. Don't worry, this is the only use for this key; it will never be used by the client directly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your FaunaDB account; you should be brought to your FaunaDB Console Home&lt;/li&gt;
&lt;li&gt;Go to the DB Overview for your "swp" database by clicking on the name of the database&lt;/li&gt;
&lt;li&gt;Go to the Keys page by clicking on the "SECURITY" tab to the left&lt;/li&gt;
&lt;li&gt;Create a new Key by clicking on the "NEW KEY" link
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fezvzz8bgduq9p8k7o610.png" alt="bootstrap key" width="378" height="209"&gt;
&lt;/li&gt;
&lt;li&gt;Set the Role to &lt;code&gt;Server&lt;/code&gt; and give the key a name (the key is arbitrary, but should be descriptive)
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipdc2ubr9hn3aoqzk19j.png" alt="New key" width="800" height="695"&gt;
&lt;/li&gt;
&lt;li&gt;Save the key and then record the server key that is displayed for later use (&lt;strong&gt;this will be the only time you will see the key&lt;/strong&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will now use this key to execute a script that uses elm-graphql to generate our project's GraphQL files under the namespace "SWP":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make sure the application is not running&lt;/li&gt;
&lt;li&gt;Open a terminal and navigate to the root of your Shall We Play? project directory&lt;/li&gt;
&lt;li&gt;Generate our "SWP" elm-graphql files for our project by executing the following command:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;FAUNA_KEY=&amp;lt;fuana-server-key&amp;gt; npm run build-gql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;&amp;lt;fauna-server-key\&amp;gt;&lt;/code&gt; is replaced with the server key generated before in step 6&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note for the curious, the "build-gql" script makes the following call: &lt;code&gt;npx elm-graphql https://graphql.fauna.com/graphql --base SWP --output src --header \"authorization: Bearer ${FAUNA_KEY}\"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When this script has completed running, you should see a brand new folder in your "src" directory called "SWP". This directory houses all the files that were auto-generated by elm-graphql. Because we will not be updating these files directly, it is safe to auto-generate our files again, should our schema ever change.&lt;/p&gt;

&lt;p&gt;Let's take a look at some of the files that were generated. Browse the Mutation.elm and Query.elm files at the root level of the "SWP" folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kt"&gt;CreateAndOrLoginPlayerRequiredArguments&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;RootMutation&lt;/span&gt;
&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createAndOrLoginPlayer"&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Argument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_name"&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Argument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password"&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;RootQuery&lt;/span&gt;
&lt;span class="n"&gt;allUserNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(List String)"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allUserNames"&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see functions whose names match the query and mutation we defined in our schema as well as those added by FaunaDB.&lt;/p&gt;

&lt;p&gt;There are also some sub-folders, the most interesting of which is the Object folder, which has a Player.elm file in it. Go ahead and look at this file, and notice that it has functions for each field of our GraphQL Player type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_name"&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="n"&gt;member_since&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;span class="n"&gt;member_since&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Int"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;member_since"&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of these functions returns what is called a SelectionSet; more on that soon.&lt;/p&gt;

&lt;p&gt;Now that we have generated elm-graphql files specific to our project, Let's establish a basic nomenclature and context for GraphQL so we can apply that to how elm-graphql sees the GraphQL world.&lt;/p&gt;

&lt;h4&gt;
  
  
  Relating GraphQL to elm-graphql
&lt;/h4&gt;

&lt;p&gt;GraphQL has fundamentally just 2 types: Object types and Scalar types. (Enums, Union types, and Interfaces, for example, are just special derivations on these two types.) An Object type has fields. Each field has a type, which can either be Object or Scalar. Ultimately, as you follow the fields down the object hierarchy to the "leaves" of the type structure, they will all be scalar types.&lt;/p&gt;

&lt;p&gt;In GraphQL, there are 3 parts to defining a query:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The operation type (and sometimes an operation name and variables)&lt;/li&gt;
&lt;li&gt;The entry point or root field of the query&lt;/li&gt;
&lt;li&gt;The shape and domain of the data you want back.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The operation type will be one of "query", "mutation", or "subscription". The entry point of the operation is known as a root field. Root fields are defined in the schema in one of 3 special Object types: Query, Mutation, and Subscription (as you might have guessed). Depending on what type is returned from a root field, you will define selection sets to specify the shape (what fields) and domain (using arguments, custom resolvers, etc) of the data you want back. Selection sets are delineated by paired curly braces ({}).&lt;/p&gt;

&lt;p&gt;As an example, imagine you have the following types defined in your schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;member_since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;organizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;allEvents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;!]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this schema we could craft a query operation like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;allEvents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;organizer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, everything between the first set of curly braces is called the root selection set, then allEvents has its own selection set, title has no selection set (because it is a scalar) and organizer has its selection set.&lt;/p&gt;

&lt;p&gt;Now let's context switch to elm-graphql. elm-graphql is centered around the SelectionSet type. Any query must have a root SelectionSet, which represents the root field in a GraphQL query. SelectionSets can be nested, just like in a GraphQL query. SelectionSets play a dual role, however, in that they also define what types your data will be decoded to when the data conforming to your root SelectionSet is returned. Because of this dual nature, every field in your GraphQL types, scalar or no, will have its own SelectionSet to facilitate its decoding.&lt;/p&gt;

&lt;p&gt;As an example, take a look at the SWP.Object.Player module. This module defines a SelectionSet for each field of the Player GraphQL type. Notice that &lt;code&gt;user_name&lt;/code&gt;, for example, is a String scalar type, but it still has a SelectionSet so it can be decoded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_name"&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SelectionSets are also used to represent GraphQL fragments as any SelectionSet can be combined with another related SelectionSet.&lt;/p&gt;

&lt;p&gt;The SelectionSet type definition is defined with two placeholder type variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="n"&gt;decodesTo&lt;/span&gt; &lt;span class="n"&gt;typeLock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first type variable is labeled &lt;code&gt;decodesTo&lt;/code&gt; and represents the Elm type that this particular SelectionSet should decode to. For example, for the &lt;code&gt;user_name&lt;/code&gt; field above, the first type variable is specified as "String", meaning this field should be decoded to a String. The second type variable is labeled &lt;code&gt;typeLock&lt;/code&gt; and it represents the context for this specific SelectionSet. Again, looking at &lt;code&gt;user_name&lt;/code&gt; above, the context of this specific field is the Player GraphQL Object type. The &lt;code&gt;typeLock&lt;/code&gt; ensures that fields from different GraphQL Object types cannot be decoded into the same context.&lt;/p&gt;

&lt;p&gt;Assembling our &lt;code&gt;allEvents&lt;/code&gt; GraphQL query above with SelectionSets might look something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;organizer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;playerSelectionSet&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;span class="n"&gt;playerSelectionSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;succeed&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;

&lt;span class="n"&gt;eventSelectionSet&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt;
&lt;span class="n"&gt;eventSelectionSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;succeed&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;organizer&lt;/span&gt; &lt;span class="n"&gt;playerSelectionSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;rootQuery&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="kt"&gt;Operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;RootQuery&lt;/span&gt;
&lt;span class="n"&gt;rootQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allEvents&lt;/span&gt; &lt;span class="n"&gt;eventSelectionSet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two type aliased records are used to capture the data from decoding players and events. Notice that these records do not need to have all of the possible fields for the GraphQL types we defined. The &lt;code&gt;playerSelectionSet&lt;/code&gt; function builds upon the field-level SelectionSet for &lt;code&gt;user_name&lt;/code&gt; to create a SelectionSet that can decode to a Player. The &lt;code&gt;eventSelectionSet&lt;/code&gt; function builds upon both a scalar field SelectionSet and the custom &lt;code&gt;playerSelectionSet&lt;/code&gt; to properly decode to the Event type. And the &lt;code&gt;allEvents&lt;/code&gt; root field builds upon the &lt;code&gt;eventSelectionSet&lt;/code&gt; to build a root query that we can call.&lt;/p&gt;

&lt;p&gt;The purpose of the illustration above is to demonstrate how to map a GraphQL schema to elm-graphql. Understanding how to build out SelectionSets in elm-graphql is the most critical part of leveraging this package.&lt;/p&gt;

&lt;p&gt;Enough of the theoretical examples… let's dig in and we'll learn the rest of what we need to know about elm-graphql while we implement our GraphQL call to FaunaDB.&lt;/p&gt;

&lt;h4&gt;
  
  
  Connecting elm-graph To Our GraphQL Service
&lt;/h4&gt;

&lt;p&gt;We will divide up the task of building and executing our &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; mutation into 5 easy steps (seriously, they are not too hard ;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assemble our SelectionSets for the mutation&lt;/li&gt;
&lt;li&gt;Assemble our query request&lt;/li&gt;
&lt;li&gt;Assemble our query response handling&lt;/li&gt;
&lt;li&gt;Test it out&lt;/li&gt;
&lt;li&gt;Do a happy dance because it works!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 5 is my favorite.&lt;/p&gt;

&lt;p&gt;Let's create a new module that will act as a bridge between our main application code and the "SWP" elm-graphql framework. Call it "Bridge.elm" and save it at the root level of the "src" folder.&lt;/p&gt;

&lt;p&gt;In part 1 of this article, we called our &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; mutation from the GraphQL Playground provided by FaunaDB. Let's review that mutation operation here again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"cool_user_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"even_cooler_password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The root field of the mutation selection set returns a simple String, which is our token for the logged in player. This means we will not need to assemble any custom SelectionSets. That is good news for our first effort, nice and simple.&lt;/p&gt;

&lt;p&gt;In our Bridge module, then, let's move on to step 2 and create our query request. We will start by importing the modules we are going to need – here is how to start the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="kt"&gt;Bridge&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;DataModel&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Operation&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RootMutation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Mutation&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Mutation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;elm-graphql provides an Http module to create and send GraphQL requests and handle errors. Using this module, we will need to send our request to our FaunaDB endpoint along with our "bootstrap" custom key as a Bearer token. In this light, lets create a few constants in our Bridge module for these two data points; be sure to use your own custom key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;endpointURL&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;endpointURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://graphql.fauna.com/graphql"&lt;/span&gt;

&lt;span class="n"&gt;customKeyBearerToken&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;customKeyBearerToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer zzA20468euAbCdEMOlvgSa8xRvJLRBQH7BfXh4iu"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Remember, due to the way we set up our access control in FaunaDB, it is safe to include this custom key in our client-side code, but do be sure it is the "bootstrap" key, and &lt;strong&gt;not the server key&lt;/strong&gt; that we used earlier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, let's put together our root field mutation SelectionSet. elm-graphql created the building blocks for us in the "SWP/Mutation.elm" file; take a look again at the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kt"&gt;CreateAndOrLoginPlayerRequiredArguments&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;RootMutation&lt;/span&gt;
&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selectionForField&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String"&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createAndOrLoginPlayer"&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="kt"&gt;Argument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_name"&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Argument&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password"&lt;/span&gt; &lt;span class="n"&gt;requiredArgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="kt"&gt;Encode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;Decode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice its first parameter is a record with the required data to make our  &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; GraphQL mutation call. This ensures that there is no way we can call our mutation without providing the necessary parameters.&lt;/p&gt;

&lt;p&gt;Let's add a function to our Bridge module that creates our root field mutation SelectionSet with the required user name and password data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;mutationCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="kt"&gt;RootMutation&lt;/span&gt;
&lt;span class="n"&gt;mutationCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt;
        &lt;span class="n"&gt;required_arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="kt"&gt;Mutation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;CreateAndOrLoginPlayerRequiredArguments&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
    &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="kt"&gt;Mutation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;required_arguments&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are almost done with step 2.  All that is left is to assemble our GraphQL.Http.Request. Our request will be a mutation operation with an endpoint and an authorization header that contains our custom key. Our root SelectionSet we created in the previous step will be our entry point into the operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;
&lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mutationRequest&lt;/span&gt; &lt;span class="n"&gt;endpointURL&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutationCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withHeader&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorization"&lt;/span&gt; &lt;span class="n"&gt;customKeyBearerToken&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are now done with step 2, except, instead of exporting everything out of the Bridge module on the first line, which is not necessary, let's limit our exports to the &lt;code&gt;requestCreateAndOrLoginPlayer&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="kt"&gt;Bridge&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are ready to move on to step 3 which will take place completely within our Main module. Luckily, we have already put in a nice faux login sequence, so we only need to tweak a few things, and it should "just work".&lt;/p&gt;

&lt;p&gt;Open the Main.elm file in your editor. Let's start by importing our Bridge module and the Graphql.Http module we will need to send the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Bridge&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to update the handling of the &lt;code&gt;LoggedInPlayer&lt;/code&gt; message. Let's tweak the signature of this Msg variant like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of &lt;code&gt;LoggedInPlayer&lt;/code&gt; carrying back just the Token, it will now carry back a Result. A Result, if it is an error, will carry back a Graphql.Http.Error, or, if it is successful, will carry back the Token.&lt;/p&gt;

&lt;p&gt;Of course, since we changed the signature of the message, there will be a ripple effect; we will need to update the message handler in the &lt;code&gt;update&lt;/code&gt; function, and the model handler for the message itself. The message handler should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty straight forward, we grab the response and pass it on to the model handler to deal with. The changes in the model handler are more extensive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
                &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt;
                        &lt;span class="n"&gt;updated_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="k"&gt;in&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;updated_player&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                    &lt;span class="n"&gt;model&lt;/span&gt;

        &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, so maybe not that much more extensive, but it could have been. Let me explain.&lt;/p&gt;

&lt;p&gt;Rather than first looking for whether we have a player or not in the model, we now first look to see if the result was &lt;code&gt;Ok&lt;/code&gt; or an &lt;code&gt;Err&lt;/code&gt;. If the result was &lt;code&gt;Ok&lt;/code&gt;, then we grab the token and proceed as we did before by storing the token in the current player, if any. However, if the request had an error, we… well… we do nothing, just return the model. &lt;strong&gt;This is not good!&lt;/strong&gt; What we should do here is handle the error in a thoughtful manner. For example, if the error was a network error, perhaps we could put up a message and ask the user to try again. Or if the error was a GraphQL error, we could check the error and give the user a chance to respond to it, like when an incorrect password is entered. You see, this could have (&lt;strong&gt;and should have&lt;/strong&gt;) been much more extensive of a change!&lt;/p&gt;

&lt;p&gt;So this does beg the question why didn't I do it? And the short answer is, so you would have something fun to do after you complete this article! In either case, PLEASE &lt;strong&gt;do not ignore thoughtful and thorough error handling&lt;/strong&gt; in your production code. 'Nuff said!&lt;/p&gt;

&lt;p&gt;There is now one final change we need to make before we test our code and see if we have successfully joined our front-end to the backend – we need to update the command that makes the mutation request to use our updated message and new Graphql.Http.Request. This is what it should now look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK – that's it! We are now done with step 3 and are ready for step 4 - Testing!  Start the app, load the front page, bring up your debugger so you can see your messages and model, and let's give it a try!&lt;/p&gt;

&lt;p&gt;Here is what I saw when I tried logging in with a new player named "Dirk":&lt;/p&gt;

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

&lt;p&gt;And here is what it looked like in the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6y5o7gmb1f5obdk0zilh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6y5o7gmb1f5obdk0zilh.png" alt="New account login" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope there were no hidden cameras recording me doing step 5! 🕺🏼🎉🕺🏼&lt;/p&gt;

&lt;p&gt;Wait. Wait. I almost forgot. Let's look at the database and see if our new account shows up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz3b4zstcjfija375eqvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz3b4zstcjfija375eqvm.png" alt="new account in database" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like we'd hoped!&lt;/p&gt;

&lt;p&gt;Play around a little more. Try logging out and logging back in with the same account. Is a new record created? Log in with a few more new accounts. Enjoy the fruits of your labor for a moment. And when you are ready, we'll move on to using that token to fetch a list of all other players.&lt;/p&gt;

&lt;h3&gt;
  
  
  One More Time About Error Handling
&lt;/h3&gt;

&lt;p&gt;In playing with logging into different accounts, were you curious enough to test logging back in with a wrong password? I was, and here was what the payload for the &lt;code&gt;LoggedInPlayer&lt;/code&gt; message looked like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmueykl5fnt7ey6pcty4t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmueykl5fnt7ey6pcty4t.png" alt="logged in player error" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This message is from FaunaDB letting us know that the player instance could not be found or the password was incorrect. In a useful app, we would, of course, let the user know and give them an opportunity to try again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting All User Names
&lt;/h3&gt;

&lt;p&gt;The purpose of saving our login token in the Player record was so that we could use it to get back the user names of all registered players so that we would know whom we could invite to our gaming events. We want to be sure not to send too much data back to the client, so we only send the user names. The user name alone is enough information for us to invite players to events, because, in addition to being the visual presentation of a Player, the user name is the Player's unique identifier in the client application.&lt;/p&gt;

&lt;p&gt;Before we add fetching user names to the client, we actually have to clean up some things. You have noticed that even when you created your first real Player, you actually see a list of players after logging in. This is because, for the "stage0" version of the app, I was starting up with some locally created players and events, just so there'd be something to see. Before we start fetching the user names actually stored in the database, we should remove this demo data.&lt;/p&gt;

&lt;p&gt;In the DataModel module, go to the &lt;code&gt;defaultModel&lt;/code&gt; constant and replace the &lt;code&gt;startingPlayers&lt;/code&gt; and &lt;code&gt;startingEvents&lt;/code&gt; dictionaries with empty dictionaries (&lt;code&gt;Dict.empty&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;defaultModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;input_user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_possible_event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_poss_event_elem_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_field_with_tab_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UserNameField&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dragged_player_position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emptyPlayerPosition&lt;/span&gt;
    &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;D&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now delete the &lt;code&gt;startingPlayers&lt;/code&gt; and &lt;code&gt;startingEvents&lt;/code&gt; dictionaries found in the same module. Log in and take a look at how it looks now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8lgstxcy0irizo69uq24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8lgstxcy0irizo69uq24.png" alt="no other players" width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahh… nice and sparkly.&lt;/p&gt;

&lt;p&gt;Now we are ready to apply the same 5 easy steps we used to add login functionality to fetching all user names with our newly minted login token:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assemble our SelectionSets for the query&lt;/li&gt;
&lt;li&gt;Assemble our query request&lt;/li&gt;
&lt;li&gt;Assemble our query response handling&lt;/li&gt;
&lt;li&gt;Test it out&lt;/li&gt;
&lt;li&gt;Do a happier dance to 'Staying Alive' by the BeeGees because it works!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 5 is still my favorite.&lt;/p&gt;

&lt;p&gt;When we put together our GraphQL query for &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt;, we didn't need a step 1 to assemble any custom SelectionSets because all we were getting back was a String, and this decoding was handled directly in the root field SelectionSet auto-generated by elm-graphql. However, for our query for &lt;code&gt;allUserNames&lt;/code&gt;, we are going to do some SelectionSet wrangling to make sure the data comes back in a form that is easily consumable by our application's model.&lt;/p&gt;

&lt;p&gt;First, remember that the user names coming back from allUserNames is a list of strings. However, in our model, we track the set of all players in an Elm Dict.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;Players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Dict&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An Elm Dict has a nice convenience function to populate it from a List called &lt;code&gt;fromList&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;fromList&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;comparable&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Dict&lt;/span&gt; &lt;span class="n"&gt;comparable&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;fromList&lt;/code&gt; takes a list of tuples that are composed of a "comparable" key and an arbitrary value. Hmm… this is not exactly what we are getting back from our GraphQL query. Rather, we are getting back a list of comparable UserNames (Strings). For us to easily populate our Players Dict, we will have to transform our SelectionSet of UserNames to a SelectionSet of tuples of type (UserName, Player). No problem.&lt;/p&gt;

&lt;p&gt;To accomplish this, we will use a SelectionSet function called &lt;code&gt;map&lt;/code&gt;. &lt;code&gt;map&lt;/code&gt; takes the &lt;code&gt;decodeTo&lt;/code&gt; type of a SelectionSet and transforms it to another &lt;code&gt;decodeTo&lt;/code&gt; type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;typeLock&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;typeLock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;a&lt;/code&gt; represents the incoming &lt;code&gt;decodeTo&lt;/code&gt; type and &lt;code&gt;b&lt;/code&gt; represents the outgoing &lt;code&gt;decodeTo&lt;/code&gt; type. As noted above, the type we want to transform to is a tuple of type (UserName, Player). Let's first go to our DataModel module and create a new type alias for this type and call it PlayerAssociation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, lets to go our Bridge module and update our imports so we have what we need to work with; note that some of these are updated imports and some are new:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;DataModel&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;UserName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Operation&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RootMutation&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;RootQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Graphql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;SWP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Query&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;Query&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create a root field query that will perform the SelectionSet transformation we described above using &lt;code&gt;SelectionSet.map&lt;/code&gt;. Let's call this query &lt;code&gt;queryAllUserNames&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;queryAllUserNames&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;RootQuery&lt;/span&gt;
&lt;span class="n"&gt;queryAllUserNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SelectionSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;user_names&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;
                    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newPlayer&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;user_names&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we used a constructor called &lt;code&gt;newPlayer&lt;/code&gt; to help us generate new players easily. We are now done with step 1.&lt;/p&gt;

&lt;p&gt;In step 2, as per normal, we will assemble our query request. The mutation request we created earlier relied on the custom key that all instances of Shall We Play? use to create and log in new players. However, this custom key, thankfully, does not have permission to grab the user name list. To grab the user name list, we need an authorized login token. Let's create a request called &lt;code&gt;requestAllUserNames&lt;/code&gt; that takes this token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;requestAllUserNames&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;requestAllUserNames&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queryRequest&lt;/span&gt; &lt;span class="n"&gt;endpointURL&lt;/span&gt; &lt;span class="n"&gt;queryAllUserNames&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withHeader&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorization"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to call this new request from the Main module, we'll need to expose this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="kt"&gt;Bridge&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestAllUserNames&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are now done with Step 2.&lt;/p&gt;

&lt;p&gt;Step 3 will require the biggest changes to the application, all within the Main module. As with all commands, we are going to need a Msg variant so we know when the command has completed. This particular message, shall we call it &lt;code&gt;ReceivedUserNames&lt;/code&gt;, will return with the result of the query, which will hopefully be a list of UserNames... wait, I mean, a list of PlayerAssociations… nice, right? Let's add this message, which takes a Result, to our Msg variants list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ReceivedUserNames&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, of course, Elm will not let us get away with not handling this message in our &lt;code&gt;update&lt;/code&gt; function; be sure to specify a model handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;ReceivedUserNames&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromReceivedUserNames&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our model handler for &lt;code&gt;ReceivedUserNames&lt;/code&gt;, we will need to create a new Dict of players. Luckily, thanks to our SelectionSet wrangling, our data is coming back to us in the exactly the form we need to easily create our Players Dict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;updateModelFromReceivedUserNames&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;PlayerAssociation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt;
&lt;span class="n"&gt;updateModelFromReceivedUserNames&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;player_associations&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromList&lt;/span&gt; &lt;span class="n"&gt;player_associations&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A red light should have gone off when you noticed I had no error handling here, right? OK. Move along, move along.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are almost done assembling our puzzle pieces. They are fitting together very nicely, by the way. We now need to create the command that sends the query request. But before we can do that, we need to update the Bridge import to include our new request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;Bridge&lt;/span&gt; &lt;span class="k"&gt;exposing&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestAllUserNames&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requestCreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the tradition of naming our command after the GraphQL query, let's call our command &lt;code&gt;allUserNames&lt;/code&gt; and pass in the token we need from the currently logged in player:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;allUserNames&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="kt"&gt;ReceivedUserNames&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestAllUserNames&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have our command ready, now all we need to do is discuss when we will call it. Thinking back to the login flow, a player provides their user name, then their password. Then we send off the createAndOrLoginPlayer mutation and receive back the &lt;code&gt;LoggedInPlayer&lt;/code&gt; response, where we parse the result and store the login token. I think it makes sense to request all user names right when the token comes back with the &lt;code&gt;LoggedInPlayer&lt;/code&gt; message.&lt;/p&gt;

&lt;p&gt;Let's look at the current implementation of the LoggedInPlayer message handler in the &lt;code&gt;update&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We receive the message response, which is of type &lt;code&gt;Result (Http.Error Token) Token&lt;/code&gt;. We don't know at this point if we actually have a valid token so we can't call our &lt;code&gt;allUserNames&lt;/code&gt; command here. Looks like we need a command handler to deconstruct the response and retrieve the token, just like the &lt;code&gt;updateModelFromLoggedInPlayer&lt;/code&gt; model handler does. Update the &lt;code&gt;LoggedInPlayer&lt;/code&gt; message handler with a new command handler called &lt;code&gt;commandFromLoggedInPlayer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="kt"&gt;LoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;updateModelFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
   &lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;commandFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the details of the &lt;code&gt;commandFromLoggedInPlayer&lt;/code&gt; command handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;commandFromLoggedInPlayer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;commandFromLoggedInPlayer&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
        &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;allUserNames&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;

        &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the token is part of the response, we call the &lt;code&gt;allUserNames&lt;/code&gt; command with the token and await the juicy details. Note that we wouldn't necessarily need to do any error handling here, because the model handler is also looking at the response and could deal with the error there. Just sayin'.&lt;/p&gt;

&lt;p&gt;That's it. Step 3 is done. Time for step 4. I don't know about you, but my stomach is telling me I'm anxious to see the results. Let's give it shot, shall we?&lt;/p&gt;

&lt;p&gt;If you haven't been developing with the application running (which I do recommend, as you know), go ahead and launch the app now. Log in and see if you have a user list!&lt;/p&gt;

&lt;p&gt;Here is what I see:&lt;/p&gt;

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

&lt;p&gt;And on my screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fldkf2jg27f4rc2ctzyd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fldkf2jg27f4rc2ctzyd4.png" alt="real other user names" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woot!! Step 5 here I come! Go ahead, click on the link. You know you want to! &lt;a href="https://www.youtube.com/watch?v=fNFzfwLM72c"&gt;'Staying Alive' by the BeeGees&lt;/a&gt;. 🕺🎊🕺 🎉🕺.&lt;/p&gt;

&lt;p&gt;Congratulations for completing this tutorial!&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrospective and Conclusion
&lt;/h2&gt;

&lt;p&gt;Let's review what we have accomplished over the course of this article. In part 1 you were introduced to a starter JAMstack site for scheduling game nights with friends called Shall We Play?. Shall We Play?, an Elm application, had rudimentary features, but was not backed by any identity management or data storage, making it shiny but of no real value.&lt;/p&gt;

&lt;p&gt;You then learned about FaunaDB, a database built from the ground up for the serverless, JAMstack architecture. We leveraged FaunaDB's native support for GraphQL and built-in identity management to construct a secure GraphQL schema to back Shall We Play?. We developed these services independent of Shall We Play?, knowing that if we designed a good schema, Shall We Play? would be able to easily interface with this service.&lt;/p&gt;

&lt;p&gt;In part 2 we turned our sites to the Shall We Play? application and interfaced it with our GraphQL service using an Elm package called elm-graphql. This integration required us to introduce passwords to the login flow, and otherwise only required a few new messages to account for the client-server interactions via GraphQL. Thanks to the intuitive design of elm-graphql, we used the same concepts we knew from GraphQL to easily build out our interface.&lt;/p&gt;

&lt;p&gt;Shall We Play? now has secure login and can fetch a list of all registered players. While this is not enough of an improvement to make it good at scheduling gaming events, it is certainly a great example of the power and flexibility of the triumvirate of Elm, GraphQL, and FaunaDB.&lt;/p&gt;

&lt;p&gt;While what we have covered is not a complete solution by any means, you should see a clear path to leveraging these technologies to get you the rest of the way simply and securely.&lt;/p&gt;

&lt;p&gt;Thanks for joining me!&lt;/p&gt;

</description>
      <category>fauna</category>
      <category>elm</category>
      <category>graphql</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>FaunaDB, GraphQL, and Elm, A Tutorial for JAMstack, Part 1</title>
      <dc:creator>Dirk Johnson</dc:creator>
      <pubDate>Tue, 21 Jul 2020 13:51:43 +0000</pubDate>
      <link>https://dev.to/xeticode/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-1-57f8</link>
      <guid>https://dev.to/xeticode/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-1-57f8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;[Note: this tutorial was written by commission for &lt;a href="https://fauna.com?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;Fauna, Inc&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you are reading this tutorial, something about it caught your eye. Perhaps it was the reference to Elm, a delightful language for reliable web apps. Perhaps it was GraphQL, which is an abstract query language and service for your backend APIs. Or perhaps it was FaunaDB, a full-featured, cloud-based datastore built for serverless computing. Hopefully it was all three!&lt;/p&gt;

&lt;p&gt;This tutorial will cover how to bring all three of these capable technologies together as a cohesive solution for writing JAMstack applications.&lt;/p&gt;

&lt;p&gt;Oops, I just dropped another term on you: “JAMstack”. Let's provide further explanation for all these terms, starting with JAMstack.&lt;/p&gt;

&lt;h3&gt;
  
  
  JAMstack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://jamstack.org/"&gt;JAMstack&lt;/a&gt; is an approach to architecting your web applications. It is not opinionated about what technologies you use to do this, other than requiring Javascript (J), APIs (A), and Markup (M).&lt;/p&gt;

&lt;p&gt;The core JAMstack architecture builds upon static content enhanced by client-side Javascript and serviced by microservice APIs. Notice that there is no mention of a tightly-coupled web application behind your site!  This means your entire application (with the exception of your microservice functions,) can be cached and delivered by a Content Delivery Network (CDN). This simplified application architecture leads to better performance, higher security, and straightforward scaling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless Computing
&lt;/h3&gt;

&lt;p&gt;While browsers are getting more and more capable, to provide security and persistent, global data storage for your client, you still need to back your JAMstack applications with server-side services. However, rather than backing your client with a monolithic backend application server requiring development, deployment, and support cycles, in the JAMstack architecture, we use "serverless" microservices which are accessed directly or through stateless functions. These functions and microservices run in the cloud, and require little to no support on your part.&lt;/p&gt;

&lt;p&gt;I realize all of this sounds wonderful at a high level, and that discerning developers are going to need to go deeper to be confident of the advantages of the JAMstack architecture, but for the moment, accept the coolness, and join me in discovering how to leverage some technologies custom fitted for JAMstack; please welcome FaunaDB, GraphQL, and Elm.&lt;/p&gt;

&lt;h3&gt;
  
  
  FaunaDB
&lt;/h3&gt;

&lt;p&gt;Behind every data query is a data store. Choosing the right data store for your application architecture is, in my opinion, one of the most important architectural decisions you will make for an enterprise-level application. There are many considerations to choosing the right data-store, such as the ability to impose data integrity assurances and constraints, data security, reliable backup-and-restore, ease of scaling, performance, and the list goes on.&lt;/p&gt;

&lt;p&gt;And in today's JAMstack architectures, there are new considerations like schema flexibility, minimal operational investment, data consistency, global low latency, and, of course, ease of backing a microservice architecture. Whew!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fauna.com?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;FaunaDB&lt;/a&gt; is a database built from the ground-up to address all of these checkbox items and more. One that I am particularly excited about is FaunaDB’s native GraphQL service which makes implementing a GraphQL interface as simple as defining your schema, importing it, and fleshing out the resolvers. Zap!&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL
&lt;/h3&gt;

&lt;p&gt;Applications and services need to communicate with each other. As with all effective communication, each side of the conversation needs to listen to and speak the same language. &lt;a href="https://graphql.org/learn/"&gt;GraphQL&lt;/a&gt; is both a language and a service that facilitates querying for data, mutating data, and even subscribing to messages about data. Those familiar with JSON, an extremely popular exchange format for structured data, should feel right at home with GraphQL, as its type structures are expressed in a similar format.&lt;/p&gt;

&lt;p&gt;One of GraphQL's benefits is the ability to not only provide a schema for the shape of your data, but also the types of your data (which is very nice for Elm). It also allows you to dynamically limit the data members returned from your structured data, thus reducing the total size of the data passed over the wire, especially when compared to other data-exchange interfaces such as REST.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elm
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://elm-lang.org"&gt;Elm&lt;/a&gt; is a strongly typed, functional language that transpiles to Javascript. Because of its type guarantees and pure, functional approach, it boasts an amazing compiler with very friendly error reporting, and a near perfect absence of runtime errors (by real-world measurements).&lt;/p&gt;

&lt;p&gt;Elm is also an architecture for web applications (lovingly referred to as The Elm Architecture, or TEA). The key concepts of this architecture are a centralized Model for your data, a View (HTML) purely driven by updates to the Model, and an &lt;code&gt;update&lt;/code&gt; function that responds to specific messages from the DOM (or a worker, or an XHR request, etc.), which then updates the Model, which then triggers an update to the View, and so on. This clean, reactive design pattern is found in some form in other frameworks such as Redux and Vuex; however, coupling it with a pure, functional language makes this pattern much more natural so architecting your own application is intuitive, allowing you to focus on what makes your project special.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Triumvirate for JAMstack
&lt;/h3&gt;

&lt;p&gt;Each of these technologies, FaunaDB, GraphQL, and Elm, are great technologies on their own, but bringing them together creates an even more powerful combination. FaunaDB boasts powerful features with an amazing ease of setup and management in the serverless space. On the client side, you have Elm, with its strong runtime guarantees built upon a simple, reactive architecture. And, bringing these two together in a well designed, typed, data exchange is GraphQL. Together, each layer of the JAMstack is both fun and profitable. And isn’t that why we do this job – so we can have fun?&lt;/p&gt;

&lt;p&gt;So… let’s go play!&lt;/p&gt;

&lt;h2&gt;
  
  
  Shall We Play?
&lt;/h2&gt;

&lt;p&gt;In this 2 part article, you are going to learn how to bring these technologies together in a unified, secure, JAMstack architecture. In part 1, we will focus on FaunaDB and it’s native GraphQL support by building out our schema and identity management architecture. In part 2, we will focus on Elm, and, more specifically, on a package called &lt;a href="https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/"&gt;elm-graphql&lt;/a&gt;, that will allow us to easily interface an Elm application with the backend services we implemented using FaunaDB.&lt;/p&gt;

&lt;p&gt;However, before we even get started, we will first need an Elm JAMstack application ready and waiting to be integrated with a backend service. As luck would have it, there is one waiting and ready for us called "Shall We Play?". &lt;a href="https://stoic-tereshkova-0e1d9c.netlify.app"&gt;Shall We Play?&lt;/a&gt; is a not-so-full-featured site for scheduling game nights with friends.&lt;/p&gt;

&lt;p&gt;For this introduction to Shall We Play?, you can visit the basic, &lt;a href="https://stoic-tereshkova-0e1d9c.netlify.app"&gt;deployed version&lt;/a&gt; of the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging Into Shall We Play?
&lt;/h3&gt;

&lt;p&gt;Since Shall We Play? does not currently have a secure login, all that is necessary to sign in right now is a user name. If that user name exists, you will be logged in as that user; if it does not, it will be created.&lt;/p&gt;

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

&lt;p&gt;Go ahead and enter any user name you'd like and hit return or click on the login button.&lt;/p&gt;

&lt;p&gt;The likelihood is that you chose a user name that did not exist. If that is the case, then you should see a view similar to the following:&lt;/p&gt;

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

&lt;p&gt;As should be expected when logging in with a new account, Shall We Play? tells you that you have organized 0 events and that you are invited to 0 events.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you did choose a user name that existed (against all odds), just log out and log back in with a new user name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below the logout panel you will see a list of "All Other Players". This is a list of all registered players (except for yourself, of course). &lt;/p&gt;

&lt;p&gt;The "Events" section below the players list is also empty. This should always correspond to the event summary reported at the top.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your First Event
&lt;/h3&gt;

&lt;p&gt;So, you want to play &lt;a href="http://www.starfleetgames.com"&gt;Star Fleet Battles&lt;/a&gt; with your friends Solo and Charlie – how do you start a new event? To the right, under the summary header is text that says "Drag a player to start an event". Cool, let's do that. Go ahead and start dragging "Charlie".&lt;/p&gt;

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

&lt;p&gt;As you drag "Charlie", you will see a dialog pop up. Drop "Charlie" on this dialog. Go ahead and drag "Solo" over as well. Add a creative title, description, and venue.  Set a date for the event, then click "Save".&lt;/p&gt;

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

&lt;p&gt;You should now see your first event under "Events". The number of events you have organized should also be reported as 1. Notice how "Charlie" and "Solo" have yellow backgrounds; this is because they have not yet accepted their invitation from you.&lt;/p&gt;

&lt;p&gt;Log out of your account by clicking on the logout button and log back in as Charlie and accept the invitation by clicking on "Update to I Am Going".&lt;/p&gt;

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

&lt;p&gt;You should now see Charlie's "Going?" status set to "Yes" with a green background.&lt;/p&gt;

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

&lt;p&gt;Log out of Charlie's account and log back in as yourself. You should now see "Charlie" with a green background.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Peeking Under The Hood
&lt;/h3&gt;

&lt;p&gt;There are a few more features to discover about Shall We Play?, but not much more. And for the curious, feel free to peek under the hood at the &lt;a href="https://github.com/xeticode/shallweplay"&gt;Elm code&lt;/a&gt;. We will go into far more detail later on regarding how Shall We Play? is architected, but at this point, it could be fun to take an unguided tour.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As you explore the code for Shall We Play? you will notice that there is no pre-render step for this simple application, which is sometimes considered a hallmark feature of a JAMstack site. Please note that there are two solid static site generators for Elm that I am aware of (and have used). The first is inspired by &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt;, called &lt;a href="https://korban.net/elm/elmstatic/"&gt;Elmstatic&lt;/a&gt; by Alex Korban (who has also authored a great &lt;a href="https://korban.net/elm/book/"&gt;Elm book&lt;/a&gt;). The second is inspired by &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;, called &lt;a href="https://elm-pages.com/"&gt;Elm Pages&lt;/a&gt; by Dillon Kearns. In either case, I did not want to add to the complexity of a very simple application, so I chose to keep Shall We Play? minimal, while still keeping to the tenets of JAMstack, that is, deploying completely from a CDN and being backed by a multi-region, zero-operation database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Securing Our Login with FaunaDB
&lt;/h2&gt;

&lt;p&gt;Shall We Play? is nice, but it has a few issues. First, it is not very useful. Other people logging into a different application instance will not see any of the events that you invited them to. And if you reload the page, all of your scheduled events go away. Oops! By moving to FaunaDB as your backend data store, you will be able to persist your data so that everyone using the site will see the same data and feel comfortable that their data is going to be there when they visit again.&lt;/p&gt;

&lt;p&gt;The second issue is that Shall We Play? is not secure; if anyone knows your user name, they can log in as you. And, if they log in with any name, they can see yours and everyone else's user names, so there is not even the comfort of "security through obscurity" (which, as the saying goes, "is no security at all").&lt;/p&gt;

&lt;p&gt;The most important issue to solve is the insecure login and so, will be the primary issue we address in this tutorial. Once we have added secure login, you will have all the tools in your tool belt that you need to add saving events to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Registration And Login Use Case
&lt;/h3&gt;

&lt;p&gt;FaunaDB's native integration with GraphQL as well as its identity management and attribute-based access control (ABAC) will allow us to provide an elegant solution to securely logging into our application. But first, we are going to put on our thinking caps and think through what we need to do to allow a user to register and login, and then access player user name data. If we don't get this right, we risk exposing data to unauthorized clients and peers. So let's get it right.&lt;/p&gt;

&lt;p&gt;First, we need to acknowledge that our client is untrusted. Anything our client has or says cannot be trusted. Yes, it's true. The reason is, and it's a simple reason, that in the web application world, everything our client application knows and sees is accessible by the user, including uninvited users. This goes for images, JavaScript code (as obfuscated as it may be), data in memory; everything is available to the uninvited user.&lt;/p&gt;

&lt;p&gt;Now let's think about the data store. We could approach data security by being miserly and not let anyone have it. But then that wouldn't be a very useful data store. Data is meant to be consumed, responsibly, of course. So what we need to do is define which data and data operations are safe to share with potentially uninvited users, and which data and data operations can be shared with authenticated and authorized users, which we will call "players".&lt;/p&gt;

&lt;p&gt;Finally, let's create a use case for how Shall We Play? will behave when registering and logging in a new player. We'll start by reviewing how Shall We Play? currently does it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A new player goes to the Shall We Play? website and sees the login prompt. The new player enters a new user name and clicks on the login button. A new account is created and the player is logged in, where they can see the user names of all other registered players.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a nice, simple approach, but to secure the login process, we need to require a password. Let’s update this use case by adding a password to the login flow:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A new player goes to the Shall We Play? website and sees the login prompt. (At this point, they are, by default, untrusted and therefore considered uninvited.) The new player enters a new user name and clicks on the login button. The password field is then presented and the new player enters a password and clicks on the login button again. A new account is created and the player is logged in where they can see the user names of all other registered players. (At this point, the new player is a trusted player.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This new use case tells us what we need to know to build our permissions structure for logging in and sharing player data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to allow untrusted players to create and/or login to an account&lt;/li&gt;
&lt;li&gt;We need to hide player data from untrusted players, but make user names accessible to trusted players once they log in&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Perfect!&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Our Initial GraphQL Schema
&lt;/h3&gt;

&lt;p&gt;Now that we know what data, operations, and permissions we need to support for registration and login, we can start to define our GraphQL schema. Go ahead and create a schema file with a proper name, ending with the suffix &lt;code&gt;.gql&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While this tutorial does not require you to be an expert in &lt;a href="https://graphql.org/learn"&gt;GraphQL&lt;/a&gt;, having a cursory understanding of GraphQL schemas, queries, and mutations will help tremendously.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you took time earlier to look at the underlying Elm code, you would have noticed that the Player type has two fields: &lt;code&gt;user_name&lt;/code&gt; of type &lt;code&gt;UserName&lt;/code&gt; (which, under the hood, is a &lt;code&gt;String&lt;/code&gt;) and &lt;code&gt;member_since&lt;/code&gt; of type &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;So on the GraphQL side we will follow suit and, in our new schema file, define a Player type with a &lt;code&gt;user_name&lt;/code&gt; field of type &lt;code&gt;String!&lt;/code&gt; and a &lt;code&gt;member_since&lt;/code&gt; field of type &lt;code&gt;Int!&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;member_since&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;!&lt;/code&gt; means the field value is non-nullable (i.e., required to have a non-null value).&lt;/p&gt;

&lt;p&gt;The next thing we need is a GraphQL mutation we can use to register a new player and/or log a player into the application. This mutation will need to support the new player use case we outlined above as well as support a returning player logging in (or rejecting them if the password is wrong). This means we will only need to define one mutation for both registration and login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the &lt;code&gt;user_name&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; parameters to the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; call are required and the return type is a String that cannot be null. This string will be a very important token which represents both the identity of the now logged in player as well as what data they have permission to access.&lt;/p&gt;

&lt;p&gt;Finally, to meet our requirements outlined above, we will define a GraphQL query that can only be called by a logged in (trusted) player, and that can only return player user names and nothing else about a player:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are confused by this notation with the &lt;code&gt;!&lt;/code&gt; both outside and inside the array, you would read this as "the array is non-nullable, but can be empty, and if the array does have values, they must be Strings, no nulls allowed."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is idiomatic to provide a query of the form &lt;code&gt;allType: [Type!]&lt;/code&gt; that returns all records of a certain type, for each of the types in the schema. However, an &lt;code&gt;allPlayers&lt;/code&gt; query would not be useful to us for this tutorial, because we do not want a query that allows the return of any/all properties of a player. Rather, we just need to get back a list of user names.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Adding FaunaDB GraphQL Directives To Our Schema
&lt;/h3&gt;

&lt;p&gt;Our GraphQL schema is now complete in that it represents all we need in order to register and log in a new player, however, due to FaunaDB's tight integration with GraphQL, there is more that we can add to the schema that will help. FaunaDB’s GraphQL Directives automate the creation of database resources such as collections, indexes, and functions. These directives save us a lot of time by creating what we would otherwise have to create manually. All GraphQL Directives start with an &lt;code&gt;@&lt;/code&gt;. FaunaDB provides several custom directives but we will only concern ourselves with two: &lt;code&gt;@unique&lt;/code&gt; and &lt;code&gt;@resolver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One of the things we will need to ensure is that no two players have the same user name. FaunaDB defines unique constraints like this through Indexes. In order to tell FaunaDB to create an index to ensure that the  &lt;code&gt;user_name&lt;/code&gt; field remains unique, we will add the &lt;code&gt;@unique&lt;/code&gt; directive to the &lt;code&gt;user_name&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;member_since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to make a tweak to the mutation and query we have defined in our schema. FaunaDB will evaluate our schema when it is imported and create some default queries and mutations, but our specific query and mutation will require us to define a User Defined Function (UDF) for each. These UDFs will be used to perform the business logic surrounding registration and login as well as specifically returning just the player data that the logged in player is authorized to see.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At this point you might ask why FaunaDB doesn’t just provide the registration and login logic for us as this is such a common feature? Good question! The reason is that the business policies surrounding registration and login can be complicated and are highly variable between different use cases. FaunaDB, rather, provides you with the building blocks necessary to create whatever policies you need. More on that later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When UDFs are attached to a query or mutation, they are called resolvers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;create_andor_login_player&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;all_user_names&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the &lt;code&gt;@resolver&lt;/code&gt; takes a &lt;code&gt;name&lt;/code&gt; parameter; this is the name of the UDF that FaunaDB will create for us when this schema is imported. The UDFs that are auto-created will, by default, throw an error when called. This is to remind us that we actually have to update these functions with our own business logic, which we will do shortly.&lt;/p&gt;

&lt;p&gt;We are now ready to import our new schema into our brand new database... wait... what database?&lt;/p&gt;

&lt;h3&gt;
  
  
  Signing Up For Your FaunaDB Account
&lt;/h3&gt;

&lt;p&gt;In order to proceed, we are going to need a database for Shall We Play?. Fauna has &lt;a href="https://dashboard.fauna.com/accounts/register?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;a free tier&lt;/a&gt; that allows you to take full advantage of FaunaDB’s features, with a generous daily usage quota. If you would like to follow along, and you haven’t already signed up for your free account, you can &lt;a href="https://dashboard.fauna.com/accounts/register?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;go directly to the registration page&lt;/a&gt;, log in with your GitHub or Netlify account, or use your email to create a new Fauna account.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Creating The FaunaDB Database
&lt;/h3&gt;

&lt;p&gt;Now that you have a Fauna account, let’s create the database for Shall We Play?:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your FaunaDB account; you should be brought to your FaunaDB Console Home&lt;/li&gt;
&lt;li&gt;Create a new database by clicking “New Database” in the upper-left
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foqao8zpwprn0cxqdhhga.png" alt="Alt Text" width="800" height="817"&gt;
&lt;/li&gt;
&lt;li&gt;Let’s name the database "swp", nice and simple. Save the new database.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You will be brought to the DB Overview for your new database.&lt;/p&gt;

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

&lt;p&gt;Notice the tabs to the left for collections, indexes, and functions. We will visit these in a bit. Also notice there are tabs for an interactive FQL shell, GraphQL management, and security management. We will be visiting all of these tabs before we are done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documents, Collections, Indexes, and Functions
&lt;/h3&gt;

&lt;p&gt;As noted before, the core of any communication is speaking the same language. In the tech world, that means understanding acronyms and terms in their respective contexts. In that light, let’s review a few terms in the context of FaunaDB: Documents, Collections, Indexes, and Functions.&lt;/p&gt;

&lt;p&gt;First, if your background is SQL, there &lt;a href="https://docs.fauna.com/fauna/current/start/fql_for_sql_users?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;is a nice section&lt;/a&gt; in the documentation drawing comparisons between FaunaDB and SQL. If this is for you, take a look.&lt;/p&gt;

&lt;p&gt;A Document is an editable record that stores related data surrounding a single concept, like a Player or a Book or an Author. It references these data by keys or field names, similar to how a JSON Object works. It is similar in concept to a row in a SQL table. It will always have an identifier or reference.&lt;/p&gt;

&lt;p&gt;A Collection is a grouping of documents. It serves to categorize the documents it holds, though there is no constraint on what the structure of its constituent documents must look like. Indeed, the documents within a single collection need not have any fields in common (though ensuring they do, at least in part, makes having different collections much more useful).&lt;/p&gt;

&lt;p&gt;An Index facilitates flexible data searches and sorts on a single collection. Documents in a collection are always accessible by the document’s reference; however, retrieving documents by their data fields requires an index. Indexes also serve to enforce constraints, like unique values within a common field or fields, and they are inherently sorted.&lt;/p&gt;

&lt;p&gt;FaunaDB Functions are bits of code written in FQL (the Fauna Query Language). Functions can be used to enforce secure and authorized access to data, to automate maintenance, and to enforce business logic. When functions are used as resolvers for GraphQL queries and mutations, they are called User Defined Functions (UDFs).&lt;/p&gt;

&lt;p&gt;For further review of these terms and many others, please see the &lt;a href="https://docs.fauna.com/fauna/current/glossary?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;FaunaDB Glossary&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing our GraphQL Schema
&lt;/h3&gt;

&lt;p&gt;Now that we have learned these new terms, let’s do something with them; let’s import our GraphQL schema into our freshly created database. As a review, our GraphQL schema looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;member_since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;create_andor_login_player&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;all_user_names&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the schema you have ready to import looks like this (and only this) and that its file name ends in &lt;code&gt;.gql&lt;/code&gt;. Now lets import:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Console Home of your "swp" database and click on the “GRAPHQL” tab
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmczmw7qmdfco449n3wsg.png" alt="Alt Text" width="800" height="444"&gt;
&lt;/li&gt;
&lt;li&gt;Import your GraphQL schema by clicking on “IMPORT SCHEMA” and selecting your schema file from the file selection dialog&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your schema imports correctly, you should now see a GraphQL Playground which will allow you to test your GraphQL service.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;If you received an error importing your schema, review your schema’s contents, make sure it is identical to the one listed above, and try again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the GraphQL Playground up, click on the “SCHEMA” tab in grey to the right. This is what your schema looks like after FaunaDB imported your schema and messaged it for you.&lt;/p&gt;

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

&lt;p&gt;Notice you still see your Player type with &lt;code&gt;user_name&lt;/code&gt; and &lt;code&gt;member_since&lt;/code&gt; fields, but it also has a few more fields called &lt;code&gt;_id&lt;/code&gt; and &lt;code&gt;_ts&lt;/code&gt;, which are leveraged by FaunaDB internally to track your record over time.&lt;/p&gt;

&lt;p&gt;Also notice that you actually have four mutations you can call, one of which is your custom mutation called &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt;. And your &lt;code&gt;allUserName&lt;/code&gt; query is there along with another automatically provided for you by FaunaDB, because, in this case, Fauna knows best.&lt;/p&gt;

&lt;p&gt;Now visit the “COLLECTIONS” tab on the left. Notice that based on the schema you imported, FaunaDB automatically created a Player collection for you.&lt;/p&gt;

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

&lt;p&gt;Now visit the “INDEXES” tab. Again, based on the schema you imported, and more specifically, based on the &lt;a class="mentioned-user" href="https://dev.to/unique"&gt;@unique&lt;/a&gt; directive you placed on the &lt;code&gt;user_name&lt;/code&gt; field of Player, FaunaDB automatically created an index for you that will let you search by &lt;code&gt;user_name&lt;/code&gt; and also ensure that any inserted user names will be unique.&lt;/p&gt;

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

&lt;p&gt;Finally, visit the “FUNCTIONS” tab. Here you will see two functions created for our two resolvers. The names should correspond to the ones you specified in your schema.&lt;/p&gt;

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

&lt;p&gt;Take a look at their FQL code – though you may not understand FQL per se, by just reading them you should get a good idea as to what they do – they abort execution with a message that we need to actually add real behavior to these UDFs.&lt;/p&gt;

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

&lt;p&gt;Don’t worry, that part is coming up real soon.&lt;/p&gt;

&lt;p&gt;But first, we need to discuss exactly how we are going to make sure our data is safe from uninvited users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating The Permissions Structure In FaunaDB
&lt;/h3&gt;

&lt;p&gt;We will be leveraging FaunaDB’s flexible attribute-based access control (ABAC) to secure our application. This access control model is quite deep and nuanced, but also extremely powerful and flexible. I will not attempt to provide you a complete explanation of all its features and interactions, but will rather use specific examples relevant to our project to explain how the ABAC model will work for us.&lt;/p&gt;

&lt;h4&gt;
  
  
  First Question: What Do I Know?
&lt;/h4&gt;

&lt;p&gt;The doorway into FaunaDB’s attribute-based access control system is always through a “secret”. If FaunaDB can’t verify what you know, then it won’t let you in. There are 2 types of secrets: Tokens and Keys. Tokens are identities that are tied to a specific document in a specific collection. They are usually tied to a collection that conceptualizes a real individual like “user” or “customer”. Tokens are generated by “logging in” with the proper credentials (password).&lt;/p&gt;

&lt;p&gt;Keys, on the other hand, are global secrets independent of any collection in your database. They are not generated through logging in, but are created by the database administrator, and their distribution should be carefully controlled. Both types of secrets are important and have different use cases as you will see next.&lt;/p&gt;

&lt;p&gt;The astute reader will have already realized where in our use case we will need a key and where we will need a token. Lets review the requirements of our use case:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to allow untrusted players to create and/or login to an account&lt;/li&gt;
&lt;li&gt;We need to hide player data from untrusted players, but make user names accessible to trusted players once they log in&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, for the first requirement, we will need a custom key for untrusted players. We will need to make sure this key can only create an account and/or log in to the application. And for the second requirement, we will need a token, gained when logging in, to provide access to player user names.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Second Question: What Can I Do?
&lt;/h4&gt;

&lt;p&gt;All Keys are tied to Roles, and Roles dictate what actions we can take on which resources. Looking at the first requirement of our use case, we need our key to be able to call the &lt;code&gt;create_andor_login_player&lt;/code&gt; function, so we will need to tie our key to a role that can do this. Let’s call that role &lt;code&gt;bootstrap&lt;/code&gt;:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Third Question: What Can My Functions Do?
&lt;/h4&gt;

&lt;p&gt;Remember we said that roles dictate what actions we can take on which resources? Our functions themselves need access to resources as well. So, in this case, we need a role for our &lt;code&gt;create_andor_login_player&lt;/code&gt; function. To determine which actions our function will need to take on which resources, lets diagram the flow of logic for this function and see what resources it uses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client calls &lt;code&gt;create_andor_login_player&lt;/code&gt; with a user name and password&lt;/li&gt;
&lt;li&gt;The function searches for a Player record with the user name provided using an index&lt;/li&gt;
&lt;li&gt;If there is no Player record with that user name, then we create a Player with that user name and password&lt;/li&gt;
&lt;li&gt;We attempt to login with the player (either a newly created Player or an existing one) using the password&lt;/li&gt;
&lt;li&gt;If the login is successful, we return the login token to the client&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, it looks like we will need to (1) read (use) an index (called &lt;code&gt;unique_Player_user_name&lt;/code&gt;) to search for a player by &lt;code&gt;user_name&lt;/code&gt;. It also looks like we will need to (2) read the Player the index may find, and finally, we will need to (3) create a new Player if the index finds none. So lets create a role called &lt;code&gt;register&lt;/code&gt; that has permission to do these three things:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Setting Up Your Permissions With FQL
&lt;/h4&gt;

&lt;p&gt;We’ve outlined secure permissions for logging in. I know we still need to set up the permissions for calling our &lt;code&gt;all_user_names&lt;/code&gt; UDF, but I’m anxious to get what we have just designed set up and tested in our GraphQL Playground. So let’s do that, shall we?&lt;/p&gt;

&lt;p&gt;But first, a little more about FQL. FQL is a concise, functional, query language native to FaunaDB. Anything you can do with the database can be done in FQL. I’m not going to be teaching you FQL in this tutorial, but we will be using it. The language is descriptive enough that you should get the idea of what we are doing from reading the code and my explanations. However, if you’d like to learn more about FQL before (or after) proceeding, I recommend you start with their &lt;a href="https://docs.fauna.com/fauna/current/tutorials/?utm_source=DevTo&amp;amp;utm_medium=referral&amp;amp;utm_campaign=WritewithFauna_FaunaDB-GraphQL-Elm_DJohnson"&gt;tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will be entering our FQL in the web-based shell for our "swp" database, so let’s get into the shell first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your FaunaDB account; you should be brought to your FaunaDB Console Home&lt;/li&gt;
&lt;li&gt;Go to the DB Overview for your "swp" database by clicking on the name of the database&lt;/li&gt;
&lt;li&gt;Go to the shell console by clicking on the SHELL tab to the left&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Dominating most of the page is the log and the editor areas; the log is on top and the code goes in the editor at the bottom. If this is the first time you have used the shell, you will see 3 lines of code entered for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Paginate(Collections());
Paginate(Indexes());
Paginate(Databases());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go ahead and run this code by clicking on “RUN QUERY” (you can also run the code when focused in the editor using Cmd+return). You should see output in the log similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Paginate(Collections());
Paginate(Indexes());
Paginate(Databases());

[
  {
    "data": [
      Collection("Player")
    ]
  },
  {
    "data": [
      Index("unique_Player_user_name")
    ]
  },
  {
    "data": []
  }
]

&amp;gt;&amp;gt; Time elapsed: 109ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The return data is contained within an array which begins and ends with square brackets. As there were three calls, there were three JSON-like objects returned inside this array, each having a field named “data”. The first call asked for a list of all collections; notice that the first data point has a list (array) with your Player collection. The second call asked for a list of all indexes; notice that the second data point has a list with your &lt;code&gt;unique_Player_user_name&lt;/code&gt; index. Finally, the third call asked for a list of the child databases in our "swp" database, of which we have none. (We will not be covering child databases in this tutorial.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As I introduce new code, I will first show you the code, then provide an explanation, and then instruct you to enter the code into the editor and run the query. Be sure to read the explanation first before executing the code. Understanding what you are doing before actually doing it is an important pattern to remembering what you learn.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s start fleshing out our permissions by first creating our &lt;code&gt;bootstrap&lt;/code&gt; role. Let’s take a look at the FQL code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateRole({
  name: "bootstrap",
  privileges: [
    {
      resource: Function('create_andor_login_player'),
      actions: {
        call: true
      }
    }
  ]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The description of the role is contained in an object. It has &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;privileges&lt;/code&gt; properties. The name we have chosen is “bootstrap”, and the privileges indicate that this role has permission to call the &lt;code&gt;create_andor_login_player&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Go ahead and enter the code and execute the query; be sure to replace any code that might be in the editor already.&lt;/p&gt;

&lt;p&gt;The core of the output should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "ref": Role("bootstrap"),
  "ts": 1590968733065000,
  "name": "bootstrap",
  "privileges": [
    {
      "resource": Ref(Ref("functions"), "create_andor_login_player"),
      "actions": {
        "call": true
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what the role record looks like. It has a unique reference (“ref”), a timestamp (“ts”), a name, and our privileges. We won’t always review the log output of our FQL commands, but always look them over and make sure you understand the gist of it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: You can clear out the log by clicking on the “CLEAR” button at the top of the page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let’s create our custom key that is tied to this new role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateKey({
  name: "Bootstrap Key",
  role: Role("bootstrap")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating keys is pretty straight forward: choose a role and give it a name.&lt;/p&gt;

&lt;p&gt;Go ahead and enter the code and execute the query.&lt;/p&gt;

&lt;p&gt;The core of the output should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "ref": Key("267083179018420748"),
  "ts": 1590969218195000,
  "name": "Bootstrap Key",
  "role": Role("bootstrap"),
  "secret": "zzA20468euAbCdEMOlvgSa8xQvJLRBQH7BfXh4iu",
  "hashed_secret": "$2a$05$/OmiXQiSTDpuqr1KLpv/S.5VOfu6tYwB6FdPGnCrtZEWUnz8QcGhW"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The output from this command is very important to save&lt;/strong&gt;, at least one part of it – the &lt;code&gt;secret&lt;/code&gt;. The secret is the actual key that our Elm client will use to create and log in players. This is the only time the key will ever be displayed by FaunaDB.  If you lose this secret, you will have to create a new one – there is no way to recover it.&lt;/p&gt;

&lt;p&gt;Save this secret somewhere safe; we will need it later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The secret listed above in this tutorial is not a real key – it has been changed to protect the innocent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have now set up the first half of the permissions structure we outlined above. Let’s continue with the second half by creating the role our UDF will use to access our index and read and create players:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateRole({
  name: "register",
  privileges: [
  {
    resource: Collection("Player"),
    actions: {
      create: true,
      read: true
    }
  },
  {
    resource: Index("unique_Player_user_name"),
    actions: {
      read: true
    }
  }
  ]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;register&lt;/code&gt; role is a little more complex than the last role we created. Instead of specifying privileges for a function, we are specifying privileges for our Player collection (create and read permissions), and for our &lt;code&gt;unique_Player_user_name&lt;/code&gt; index (read permissions).&lt;/p&gt;

&lt;p&gt;Go ahead and enter the code and execute the query.&lt;/p&gt;

&lt;p&gt;Now we need to update our placeholder UDF created for us by the import of our GraphQL schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update(Function("create_andor_login_player"), {
  name: "create_andor_login_player",
  body: Query(Lambda(["user_name", "password"],
              Let({
                    match: Match(Index("unique_Player_user_name"), Var("user_name")),
                    player: If(
                        Exists(Var("match")),
                        Get(Var("match")),
                        Create(Collection("Player"), {
                          credentials: { password: Var("password") },
                          data: {
                            user_name: Var("user_name"),
                            member_since: ToMillis(Now())
                          }
                        })
                      ),
                    login: Login(Select("ref", Var("player")), { password: Var("password") })
                  },
                  Select("secret", Var("login"))
              )
            )
        ),
  role: Role("register")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woah!  There is a lot going on here.  Don’t panic.  Let’s break it down.&lt;/p&gt;

&lt;p&gt;First you will notice that we are actually updating our function as opposed to creating it (as we created the new roles and key). That is because this function already exists, so we need to modify it.&lt;/p&gt;

&lt;p&gt;The core of the function is in the &lt;code&gt;body&lt;/code&gt; field. When we create a function, the function wraps what is called a Lambda function. A Lambda function is basically an unnamed function. In this case, FQL uses Lambda functions to specify function behavior. When we designed our permissions structure, we actually went over the flow of this function – let’s review what we wrote &lt;em&gt;in the context of what we see above&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client calls &lt;code&gt;create_andor_login_player&lt;/code&gt; with a user name and password; &lt;em&gt;those parameters are passed into the &lt;code&gt;Lambda&lt;/code&gt; function&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The function searches for a Player record with the user name provided using an index. &lt;em&gt;This is done with the &lt;code&gt;Match&lt;/code&gt; built-in function, which is using the &lt;code&gt;unique_Player_user_name&lt;/code&gt; index&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;If there is no Player record with that user name, then we create a Player with that user name and password. &lt;em&gt;The &lt;code&gt;Exists&lt;/code&gt; built-in function tests whether the &lt;code&gt;Match&lt;/code&gt; call returns anything. If it doesn’t, it creates the player with the built-in &lt;code&gt;Create&lt;/code&gt; call. Notice how in the &lt;code&gt;Create&lt;/code&gt; call, the password is passed in as credentials for this specific player&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;We attempt to login with the player (either a newly created Player or an existing one) using the password. &lt;em&gt;This is done with the &lt;code&gt;Login&lt;/code&gt; built-in function&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;If the login is successful, we return the login token to the client. &lt;em&gt;The &lt;code&gt;Select&lt;/code&gt; built-in function returns the secret, which is the token from the result of the &lt;code&gt;Login&lt;/code&gt; call&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, notice that the role for this function is set to &lt;code&gt;register&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Go ahead and enter the code and execute the query.&lt;/p&gt;

&lt;p&gt;Looking at our two diagrams above, I think we have covered everything. Now we are ready to test our &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; GraphQL mutation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing Our Permissions with GraphQL Playground
&lt;/h4&gt;

&lt;p&gt;We are now going to test our &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; GraphQL mutation. We will do this from the GraphQL Playground found under the “GRAPHQL” tab; go there now.&lt;/p&gt;

&lt;p&gt;The GraphQL Playground is a neat tool that lets you query your GraphQL service, and push against your GraphQL schema. On the left, you have a GraphQL query editor, on the right you have the output. And further to the right you have the “DOCS” and “SCHEMA” tabs. When you first imported your schema, we took a look at the “SCHEMA” tab. Go ahead and look at the “DOCS” tab now.&lt;/p&gt;

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

&lt;p&gt;The “DOCS” tab shows you a different view of your schema than the “SCHEMA” tab. It presents your queries and mutations in the form of documentation that is useful for assisting you building complex queries. With more complex schemas than ours, this is a life-saver. Notice there is a search bar at the top so you can even search for that one query you can’t seem to get right. Go ahead and close the “DOCS” tab.&lt;/p&gt;

&lt;p&gt;We are now going to create a mutation operation to test our schema and permissions. This operation will come from the GraphQL Playground “client”. As mentioned before, our Elm client will have to make this mutation call using our custom key. So, to test our permissions, we will need the GraphQL Playground client to use this key as well. At the bottom of the query editor is a footer called “QUERY VARIABLES”. Expose the “QUERY VARIABLES” section by clicking on the footer.&lt;/p&gt;

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

&lt;p&gt;You will see an HTTP “authorization” header with a default key using basic encoding. We will replace this key with our custom key in “Bearer” format (non-encoded format). Insert your custom key into this template and replace the headers object with this new one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer your-custom-key-here"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now enter the following mutation in the query editor, but don’t execute it just yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"example_user_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"example_password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mutation operation calls the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; query with a user name of “example_user_name” and a password of “example_password”. When this query is executed, it will trigger the resolver that backs this query, passing in the user name and password. If all goes well, the UDF will create a new record in the Player collection with this user name and return a player token.&lt;/p&gt;

&lt;p&gt;In the center between the query editor and the log is a “play” button. Go ahead and execute this mutation by clicking on the “play” button.&lt;/p&gt;

&lt;p&gt;Assuming all went well, your output should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"createAndOrLoginPlayer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fnEDtOiSt-CCAb00k_rewAIHaEzzJe5lKGBcrBpEdChNiYPEcXk"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The return value of the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; call is found within a &lt;code&gt;data&lt;/code&gt; object. The return value is the player token generated from the &lt;code&gt;Login&lt;/code&gt; call. We did it!  Congratulations! That should feel very good.&lt;/p&gt;

&lt;p&gt;Let’s feel even better - let’s go take a look at the Player collection under the “COLLECTIONS” tab.  You should see your newly created player.&lt;/p&gt;

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

&lt;p&gt;Notice that the credentials that were used to create the user are not shown here. Credentials are a special, encrypted field in FaunaDB that will never be returned.&lt;/p&gt;

&lt;p&gt;OK, one more test. Run the query one more time. This should log in your player again, returning a different token, but &lt;strong&gt;not&lt;/strong&gt; create a new record. Do you still see only one record? Nice.&lt;/p&gt;

&lt;h4&gt;
  
  
  Completing The Permissions Setup
&lt;/h4&gt;

&lt;p&gt;Now that we have the first part of our permissions working, we need to design and implement the second part, which is having the logged in player fetch a list of all user names. Now that we are practiced, this shouldn’t take us too long, but I do need to share one more aspect about Roles that will help us.&lt;/p&gt;

&lt;p&gt;As you saw previously, Roles are used by Keys and Functions to give them access to resources, and, more specifically, to specify what actions these Keys and Functions can perform on these resources. Keys and Functions actually have a &lt;code&gt;role&lt;/code&gt; field, which ties them to a Role. Tokens, on the other hand, require a different method for associating themselves with Roles; Tokens rely on Role Memberships.&lt;/p&gt;

&lt;p&gt;When a role is created, along with the permissions, a list of memberships can be provided. Each membership is associated with a single collection. In the simplest configuration of a membership, any member of this collection, as long as they have a valid login token, is associated with this role, and has the permissions ascribed to it.&lt;/p&gt;

&lt;p&gt;With this new found feature of roles, let’s design the final portion of our player permissions:&lt;/p&gt;

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

&lt;p&gt;This diagram looks much like the first diagram except instead of a key, there is a player token combined with a membership for the player collection. These tie into the &lt;code&gt;logged-in&lt;/code&gt; role which has permissions to call the &lt;code&gt;all_user_names&lt;/code&gt; resolver. As the resolver needs its own permissions, it ties into a role called &lt;code&gt;all_user_names&lt;/code&gt;. (Why not use the same name as the function?) This role grants read permissions on the Player collection as well as uses a new index called &lt;code&gt;all_user_names&lt;/code&gt; which only has access to the &lt;code&gt;user_name&lt;/code&gt; field values of the Player collection.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For those already familiar with GraphQL and FaunaDB, you may have addressed the issue of limiting access to field data on a document in a different way. Once such way would be breaking out restricted data into a separate type and creating an &lt;code&gt;allType:[Type!]&lt;/code&gt; query which FaunaDB supports with no UDF required. This is also a valid approach. The value of creating a custom index and UDF, as I have done, is that our custom index only requires 1 read to resolve and is therefore faster and more efficient than using the &lt;code&gt;allType&lt;/code&gt; query which internally maps over all documents to generate its result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We could create &lt;code&gt;all_user_names&lt;/code&gt; index through FQL as we did the one before, but let’s create it this time through the Web Console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your FaunaDB account; you should be brought to your FaunaDB Console Home&lt;/li&gt;
&lt;li&gt;Go to the DB Overview for your "swp" database by clicking on the name of the database&lt;/li&gt;
&lt;li&gt;Go to the Indexes page by clicking on the “INDEXES” tab to the left&lt;/li&gt;
&lt;li&gt;Start a new Index by clicking on the “New Index” link at the top&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Look at the image below and make sure your index definition looks the same:&lt;/p&gt;

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

&lt;p&gt;Of course, the collection we will be searching is the Player collection. For the name of the index, we can use the same name as the function that will be using the index. This index does not have any search terms like the &lt;code&gt;unique_Player_user_name&lt;/code&gt; does because rather than isolate a specific subset of the collection, we want all the user names in the collection. And finally, because we want to be sure the &lt;code&gt;all_user_names&lt;/code&gt; function can only get at the &lt;code&gt;user_name&lt;/code&gt;data, we will list this single field in the “Values” section. Note how the editor puts &lt;code&gt;data&lt;/code&gt; before the &lt;code&gt;user_name&lt;/code&gt; field name; this is because the actual data that is returned from this search will be inside a &lt;code&gt;data&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Once you have confirmed your index settings look like those above, save the index.&lt;/p&gt;

&lt;p&gt;We now need to create the &lt;code&gt;all_user_names&lt;/code&gt; role. We can also use the Web Console to create Roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the “SECURITY” tab and take a moment to notice our “Bootstrap Key” we created above.&lt;/li&gt;
&lt;li&gt;Click on the “MANAGE ROLES” link and take a moment to notice our “bootstrap” and “register” roles&lt;/li&gt;
&lt;li&gt;Start a new Role by clicking on the “NEW ROLE” link&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Look at the image below and make sure your role definition looks the same:&lt;/p&gt;

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

&lt;p&gt;Referring back to our permissions diagram should help make sense of this screen. We give our role the same name as the function it services. We then only need read access to the Player collection and the &lt;code&gt;all_user_names&lt;/code&gt; index.&lt;/p&gt;

&lt;p&gt;When you are sure your settings look the same, save the Role.&lt;/p&gt;

&lt;p&gt;We will now return to the FQL shell to update the &lt;code&gt;all_user_names&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update(Function("all_user_names"), { name: "all_user_names",
  body: Query(Lambda([],Select("data", Paginate(Match(Index("all_user_names"), []))))),
  role: Role("all_user_names")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;all_user_names&lt;/code&gt; function uses the built-in &lt;code&gt;Match&lt;/code&gt; function to grab all the user names using the &lt;code&gt;all_user_names&lt;/code&gt; index. Whenever we request a list of items, we are required to use pagination so we don’t shoot ourselves in the foot. &lt;code&gt;Paginate&lt;/code&gt; returns a data structure that lets us page through results in small chunks, 64 documents by default. (In this tutorial, 64 user names at a time will be plenty so we will not take time to explore the full power of pagination.) As mentioned when we set up the index, the data will be returned in a &lt;code&gt;data&lt;/code&gt; field, so we use the built-in &lt;code&gt;Select&lt;/code&gt; function to extract the array of user names from this field. Of course, we tie this function to the &lt;code&gt;all_user_names&lt;/code&gt; roll.&lt;/p&gt;

&lt;p&gt;Go ahead and enter the code and execute the query.&lt;/p&gt;

&lt;p&gt;We now only have one more resource to create: the &lt;code&gt;logged-in&lt;/code&gt; role that our player token will access through its membership in the Player collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateRole({
  name: "logged-in",
  privileges: [
  {
    resource: Function('all_user_names'),
    actions: {
      call: true
    }
  }
  ],
  membership: [{
    resource: Collection("Player")
  }]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is new here is the &lt;code&gt;membership&lt;/code&gt; field. This field takes an array of Membership definitions. Memberships are very flexible, and a lambda function can be provided to qualify further the terms of membership. For our example today, we will use the simplest form of membership by simply defining that membership in the Player collection is all that is needed to be attached to this role (when presenting a valid token, of course).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Food for thought: why is the &lt;code&gt;privileges&lt;/code&gt; field name plural, but the &lt;code&gt;membership&lt;/code&gt; field name singular when they are both arrays? Perhaps we will never know.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go ahead and enter the code and execute the query.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Final Permissions Test
&lt;/h4&gt;

&lt;p&gt;We are now ready to perform the second part of our permissions test – whether a player token has access to all the user names in the Player collection. Can you taste the anticipation? I can.&lt;/p&gt;

&lt;p&gt;To perform this test, let’s start from the very beginning and create a new player and get back a new player token. Return to the GraphQL Playground.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sometimes when I return to the GraphQL Playground, there is a new tab there, but my previous tab(s) are there, too.  Just delete any blank tabs that may be there if they are confusing to you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your setup from our previous test is gone, go back through the instructions above and make sure you are using our custom key for the bearer token in the headers. Go ahead and create a new player with the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; mutation, passing in different values from before. Here is an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreateAndOrLoginPlayer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createAndOrLoginPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"cool_user_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"even_cooler_password"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get back a response similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"createAndOrLoginPlayer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qqEDtPCdvjABCDF0k_rewAINr729XiQJBmm-sqvuTAv9hJTWYB0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Be sure to save the return string from this call&lt;/strong&gt; – it is the player token we will need in the next step.&lt;/p&gt;

&lt;p&gt;Now that we have a new player and a new player token, we can now test our &lt;code&gt;allUserNames&lt;/code&gt; query. Open a new tab and change the “authorization” header for the new tab to use the new player token in the form of a “Bearer” token as with the custom key.&lt;/p&gt;

&lt;p&gt;Now enter the following query in the query editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AllUserNames&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUserNames&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query is much simpler than the mutation before as it simply calls a parameterless query and waits for the return values.&lt;/p&gt;

&lt;p&gt;Now go ahead and execute the query; if all goes well, you should see two user names returned!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allUserNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"cool_user_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"example_user_name"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two user names, just like we expected! (Insert 🎆 fireworks 🎇 here.)&lt;/p&gt;

&lt;p&gt;But… not to celebrate too early, shall we run an experiment? In our testing we have tested that the custom key and player token do most certainly have permission to perform their intended behaviors. But what if we were to switch the token for the key? Can the custom key fetch user names? Can a player token be used to create a new player?&lt;/p&gt;

&lt;p&gt;Let’s give it a go, shall we?&lt;/p&gt;

&lt;p&gt;Return to the GraphQL Playground tab where you executed the &lt;code&gt;allUserNames&lt;/code&gt; query and replace the player token in the “authorization” header with the custom key and rerun the query.  What do you see? This is what I see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Insufficient privileges to perform the action."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"permission denied"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far so good. Now go to the first tab where you ran the &lt;code&gt;createAndOrLoginPlayer&lt;/code&gt; mutation, and replace the custom key in the “authorization” header for the player token and rerun the mutation. What do you see? This is what I see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"errors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Insufficient privileges to perform the action."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"permission denied"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have now verified we have a secure setup for creating and logging in players, and limiting access to user names to only trusted players.&lt;/p&gt;

&lt;p&gt;Security is a good feeling, isn’t it?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The solution we have just implemented for identity management is secure but limited. FaunaDB's identity management feature set is capable of providing much more robust identity management for both service-to-service and stateless client architectures. Rather than forcing the developer into an opinionated solution, FaunaDB provides the building blocks for you to either roll your own, as we have done (in part), or to easily tie into 3rd party identity management providers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;a href="https://dev.to/dirkbj/faunadb-graphql-and-elm-a-tutorial-for-jamstack-part-2-2eec"&gt;part 2 of our tutorial&lt;/a&gt;, we are going to focus on the Shall We Play? Elm application, and, more specifically, the elm-graphql package. Using elm-graphql, we will update the application to use our new GraphQL service which provides secure login and authorized access to player data.&lt;/p&gt;

&lt;p&gt;I can hardly wait!  See you then.&lt;/p&gt;

</description>
      <category>fauna</category>
      <category>elm</category>
      <category>graphql</category>
      <category>jamstack</category>
    </item>
  </channel>
</rss>
