<?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: Hossomi</title>
    <description>The latest articles on DEV Community by Hossomi (@hossomi).</description>
    <link>https://dev.to/hossomi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F789258%2F43fee4d8-85ee-49c7-a462-440c7259a279.jpg</url>
      <title>DEV Community: Hossomi</title>
      <link>https://dev.to/hossomi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hossomi"/>
    <language>en</language>
    <item>
      <title>Frontline: Running Something</title>
      <dc:creator>Hossomi</dc:creator>
      <pubDate>Sat, 05 Nov 2022 21:01:25 +0000</pubDate>
      <link>https://dev.to/hossomi/frontline-running-something-mie</link>
      <guid>https://dev.to/hossomi/frontline-running-something-mie</guid>
      <description>&lt;p&gt;Hello everyone! You have probably noticed by now that I am not a consistent writer. It is finally time to run and see something!&lt;/p&gt;

&lt;p&gt;Today we will implement the most basic of all: a CRA client talking to an HTTP server to display something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article&lt;/strong&gt; | &lt;a href="https://github.com/hossomi/tamiyo" rel="noopener noreferrer"&gt;Repository&lt;/a&gt; | &lt;a href="https://github.com/hossomi/tamiyo/compare/833dcd9...bfb83c5" rel="noopener noreferrer"&gt;Changes&lt;/a&gt; | &lt;a href="https://github.com/hossomi/tamiyo/tree/bfb83c50072c05c7e676b2ad8550933985966197" rel="noopener noreferrer"&gt;Final commit&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Server
&lt;/h2&gt;

&lt;p&gt;The server is the simplest piece: an &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; HTTP server that returns &lt;code&gt;Hello world&lt;/code&gt; on GET. We start by installing Express in the server workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn workspace @tamiyo/server add express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we write the server in &lt;code&gt;index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

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

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening at port 8000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basics of Express is really simple and intuitive, so I probably don't need to explain the code above. To run, we can build and manually run the built script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn tsc &lt;span class="nt"&gt;--build&lt;/span&gt;
yarn workspace @tamiyo/server node build/index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command will transpile Typescript into Javascript as we discussed in the last article. The second will run the transpiled Javascript file using Yarn's module resolution, required since we use workspaces.&lt;/p&gt;

&lt;p&gt;We can test our server with &lt;code&gt;curl&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;curl http://localhost:8000/api
Hello world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Client
&lt;/h2&gt;

&lt;p&gt;The client is a basic &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;CRA&lt;/a&gt; application that we will modify to get a message to display from our server. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ First of all, we will disable Yarn's Plug'n'Play (PNP) resolution:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;set &lt;/span&gt;config nodeLinker node
yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Although there are sources on the internet saying that it should, I could not make Workspaces + PNP + CRA work properly. I decided to not spend more time on that and focus on actual development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We will replace our current client with code generated with CRA:&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="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; client
yarn create react-app client &lt;span class="nt"&gt;--template&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our old client had some important configuration discussed in the last article. In &lt;code&gt;package.json&lt;/code&gt;, the name was changed and &lt;code&gt;type&lt;/code&gt; was removed. Put them back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@tamiyo/client"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- Change back&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1.0"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;private"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- Put back&lt;/span&gt;
  &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;...&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;tsconfig.json&lt;/code&gt;, we extracted most of the properties to &lt;code&gt;tsconfig.common.json&lt;/code&gt;. So we can revert it, keeping only the few additional properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;extends"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;../tsconfig.common.json"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compilerOptions"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rootDir"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outDir"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;build"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Additional properties:&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lib"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dom"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dom.iterable"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;esnext"&lt;/span&gt;
    &lt;span class="pi"&gt;],&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noEmit"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jsx"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;react-jsx"&lt;/span&gt;
  &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, you should be able to run the template and run it in your browser (CRA will open itself) by running the &lt;code&gt;start&lt;/code&gt; script with Yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn workspace @tamiyo/client start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrating
&lt;/h2&gt;

&lt;p&gt;The last step for today is modifying our client to make a request to our server and display the response on screen. This request should be made by the &lt;code&gt;App&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setText&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setText&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;// [...]&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="c1"&gt;// [...]&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be easy if you already know React hooks. Here is a quick explanation anyway:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We use &lt;a href="https://beta.reactjs.org/apis/react/useState" rel="noopener noreferrer"&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/a&gt; to define a state variable &lt;code&gt;text&lt;/code&gt; with initial value &lt;code&gt;Loading...&lt;/code&gt;. &lt;code&gt;setText&lt;/code&gt; should be used to update its value.&lt;/li&gt;
&lt;li&gt;We use &lt;a href="https://beta.reactjs.org/apis/react/useEffect" rel="noopener noreferrer"&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/a&gt; with an empty array in the second argument to run an effect only once when the component is mounted.&lt;/li&gt;
&lt;li&gt;This effect makes the request using &lt;code&gt;fetch&lt;/code&gt;, parses the response as text using and store it in the &lt;code&gt;text&lt;/code&gt; state variable, triggering a component re-render since the state changed.&lt;/li&gt;
&lt;li&gt;The actual component renders &lt;code&gt;text&lt;/code&gt; on screen, which will now be &lt;code&gt;Hello world&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, if you start the server and open the client, you will see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi4uspxp99l3xwmdxooq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi4uspxp99l3xwmdxooq.png" alt="Client without proxying displays an HTML instead of the server message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This happens because the client is actually making the request to the CRA development server that is serving the client pages, and not our server! In production these two servers would be the same, but we are not there yet.&lt;/p&gt;

&lt;p&gt;CRA provides a solution for this in development: &lt;a href="https://create-react-app.dev/docs/proxying-api-requests-in-development/" rel="noopener noreferrer"&gt;proxying&lt;/a&gt;. We can easily enable this in &lt;code&gt;client/package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@tamiyo/client"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.1.0"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;private"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;proxy"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8000"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- Proxy to here&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, the CRA development server will proxy unknown requests (i.e. that are not requesting a client page) to our server that is running on port 8000. Restarting the client and trying again, you should finally see this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvjz4hjd3zhghsv7fzfq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvjz4hjd3zhghsv7fzfq.png" alt="Client with proxying displays the server message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The shared library
&lt;/h2&gt;

&lt;p&gt;Remember we have a &lt;code&gt;shared&lt;/code&gt; workspace, where we will place common code? Now is a good time to link it to both client and server. For starters, let's just define two variables in &lt;code&gt;shared/index.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GREETER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hossomi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GREETING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello world!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GREETER&lt;/code&gt; will be used by the client and &lt;code&gt;GREETING&lt;/code&gt; will be returned by the server. Since they are all Yarn workspaces and Yarn handles them as packages, we can install the shared library as any other package:&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;yarn workspace @tamiyo/server add @tamiyo/shared
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn workspace @tamiyo/client add @tamiyo/shared
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A small change in &lt;code&gt;shared/package.json&lt;/code&gt; is also necessary so that Typescript can correctly find sources inside the shared library module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@tamiyo/shared"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;packageManager"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn@3.2.0"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;build/index.js"&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- Add this&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now change our server's &lt;code&gt;index.ts&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GREETING&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tamiyo/shared&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// [...]&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And the client &lt;code&gt;App.tsx&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GREETER&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tamiyo/shared&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// [...]&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;GREETER&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After rebuilding and restarting our applications, we can verify that both client and server are using the variables from the shared library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feihl9yxibki9unoluvyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feihl9yxibki9unoluvyr.png" alt="Client and server uses variables from the shared library"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality of life
&lt;/h2&gt;

&lt;p&gt;Today, we had to run some quite verbose commands to start our client and server. To make our lives easier, we can put them in Yarn scripts in the parent &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tamiyo"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;version"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scripts"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;build"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tsc&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--verbose"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clean"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tsc&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--clean"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start:server"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;workspace&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;@tamiyo/server&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;start"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start:client"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;workspace&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;@tamiyo/client&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;start"&lt;/span&gt;
  &lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to define a &lt;code&gt;start&lt;/code&gt; script in &lt;code&gt;server/package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@tamiyo/server"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scripts"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yarn&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;build/index.js"&lt;/span&gt;
  &lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now run &lt;code&gt;yarn build&lt;/code&gt; to transpile Typescript, &lt;code&gt;yarn start:server&lt;/code&gt; to start the server and &lt;code&gt;yarn start:client&lt;/code&gt; to start the client, much shorter commands! CRA even has hot reload in development mode, so changing client code while it is running will automatically update in the browser. I will investigate how to do the same for the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;We have a basic client-server application running, but we are using plain HTTP. In the next step, I will get started on GraphQL. It is a new world to me, so I am not sure an entire article will be needed. If it turns out simpler than I expect, I can also explore MTG JSON data sets.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>Frontline: Preparing Grounds</title>
      <dc:creator>Hossomi</dc:creator>
      <pubDate>Sun, 14 Aug 2022 05:14:41 +0000</pubDate>
      <link>https://dev.to/hossomi/frontline-preparing-grounds-1ml7</link>
      <guid>https://dev.to/hossomi/frontline-preparing-grounds-1ml7</guid>
      <description>&lt;p&gt;Hello everyone! A long time after the first post, it's time to roll up the sleeves and start coding.&lt;/p&gt;

&lt;p&gt;Before anything else, I like to prepare the project structure and build. The logical first step is installing Yarn and Typescript and get it to build &lt;em&gt;anything&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article&lt;/strong&gt; | &lt;a href="https://github.com/hossomi/tamiyo"&gt;Repository&lt;/a&gt; | &lt;a href="https://github.com/hossomi/tamiyo/compare/0e32e22...833dcd9"&gt;Changes&lt;/a&gt; | &lt;a href="https://github.com/hossomi/tamiyo/tree/833dcd989529e5b8baca85055348160c479c9168"&gt;Final commit&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Yarn
&lt;/h2&gt;

&lt;p&gt;To install Yarn, it is recommended to use &lt;a href="https://nodejs.org/api/corepack.html"&gt;Corepack&lt;/a&gt;, bundled with Node starting in 16.10. It seems to be an all-in-one package manager, and it already includes Yarn out of the box. All you need to do is run &lt;code&gt;corepack enable&lt;/code&gt; (since it is experimental and disabled by default) and then &lt;code&gt;yarn init -2&lt;/code&gt; to initialize a new project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ &lt;code&gt;-2&lt;/code&gt; ensures that it uses &lt;a href="https://yarnpkg.com"&gt;Yarn 2+ (modern)&lt;/a&gt;, required to work with zero-installs. More on it later!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As I mentioned, I want to use Yarn workspaces to organize modules. Each module needs its own &lt;code&gt;package.json&lt;/code&gt; file, so let's start with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦tamiyo
 ┣ 📂client
 ┃ ┗ 📜package.json
 ┣ 📂server
 ┃ ┗ 📜package.json
 ┣ 📂shared
 ┃ ┗ 📜package.json
 ┗ 📜package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;package.json&lt;/code&gt; content is mostly the usual, the difference being that the parent file contains a &lt;code&gt;workspaces&lt;/code&gt; field specifying where the workspaces are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="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;"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;"tamiyo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageManager"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn@3.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspaces"&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;"server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"shared"&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;For the modules, we are prefixing their package names with &lt;code&gt;@tamiyo&lt;/code&gt; for consistency. The client file for example is 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;"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;"@tamiyo/client"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageManager"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn@3.2.0"&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;Running &lt;code&gt;yarn install&lt;/code&gt; makes sure we've setup correctly, and you'll notice it creates some files. The &lt;code&gt;yarn.lock&lt;/code&gt; is well known, and the others are related to Yarn's &lt;a href="https://yarnpkg.com/features/zero-installs"&gt;zero-installs&lt;/a&gt;: &lt;code&gt;.yarnrc.yml&lt;/code&gt;, &lt;code&gt;.pnp.cjs&lt;/code&gt; and the &lt;code&gt;.yarn&lt;/code&gt; directory. With all these checked into the repository, you no longer need to run this command unless dependencies change (hence zero installs)! Read the documentation for more advantages of this mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Typescript
&lt;/h2&gt;

&lt;p&gt;Let's get started with Typescript! The first thing to do is to install it with &lt;code&gt;yarn add -D typescript&lt;/code&gt;. It will install the &lt;code&gt;tsc&lt;/code&gt; CLI tool that we can run with &lt;code&gt;yarn tsc&lt;/code&gt; to compile Typescript code into Javascript, making it runnable in broswers, node and the like.&lt;/p&gt;

&lt;p&gt;Typescript is organized in projects, indicated by a &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html"&gt;&lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/a&gt; file along with various project settings. It can also be divided into smaller subprojects, which pairs well with the Yarn workspaces we are using! We just have to place a &lt;code&gt;tsconfig.json&lt;/code&gt; file in each workspace as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦tamiyo
 ┣ 📂client
 ┃ ┣ 📜package.json
 ┃ ┗ 📜tsconfig.json
 ┣ 📂server
 ┃ ┣ 📜package.json
 ┃ ┗ 📜tsconfig.json
 ┣ 📂shared
 ┃ ┣ 📜package.json
 ┃ ┗ 📜tsconfig.json
 ┣ 📜package.json
 ┗ 📜tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The root &lt;code&gt;tsconfig.json&lt;/code&gt; is special: it has a &lt;a href="https://www.typescriptlang.org/docs/handbook/project-references.html"&gt;&lt;code&gt;references&lt;/code&gt;&lt;/a&gt; property specifying the subprojects, which in our case are the workspaces. We also specify &lt;code&gt;"include": []&lt;/code&gt; so that the root project doesn't build anything, since it's not a module itself.&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;"references"&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;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./shared"&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;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./client"&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;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./server"&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;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="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 workspaces are where actual code resides, so their &lt;code&gt;tsconfig.json&lt;/code&gt; contains compiler options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noFallthroughCasesInSwitch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"composite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isolatedModules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see their meaning in the &lt;a href="https://www.typescriptlang.org/tsconfig"&gt;TSConfig reference&lt;/a&gt;. It's important to note that &lt;code&gt;composite: true&lt;/code&gt; is required when using Typescript subprojects. To avoid repeating all those properties in each workspace, we can extract them to a common &lt;code&gt;tsconfig.common.json&lt;/code&gt; and make the workspaces extend them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./tsconfig.common.json&lt;/span&gt;
&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compilerOptions"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es6"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strict"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;noFallthroughCasesInSwitch"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;module"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;commonjs"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moduleResolution"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;node"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolveJsonModule"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;composite"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;esModuleInterop"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isolatedModules"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skipLibCheck"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;
  &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# {module}/tsconfig.json&lt;/span&gt;
&lt;span class="pi"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;extends"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;../tsconfig.common.json"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compilerOptions"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rootDir"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outDir"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;build"&lt;/span&gt;
  &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, we should be able to build from the root directory. Let's put a simple file under the &lt;code&gt;src&lt;/code&gt; directory of each module to test it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// {module}/src/index.ts&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;yarn tsc --build --verbose&lt;/code&gt; should compile all the Typescript files and generate &lt;code&gt;.d.ts&lt;/code&gt; and &lt;code&gt;.js&lt;/code&gt; files under &lt;code&gt;{module}/build&lt;/code&gt; directories, as we instructed in the configuration. These files are what will be actually run by either Node, browser and the like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;Our project can at least be compiled! Next, it is time to get something up and running. As I mentioned, I will use Create React App to build our client, providing us a quick lift. We'll also see how we can implement and integrate our server with it.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>typescript</category>
      <category>yarn</category>
    </item>
    <item>
      <title>To the frontline!</title>
      <dc:creator>Hossomi</dc:creator>
      <pubDate>Fri, 20 May 2022 04:14:27 +0000</pubDate>
      <link>https://dev.to/hossomi/to-the-frontline-d26</link>
      <guid>https://dev.to/hossomi/to-the-frontline-d26</guid>
      <description>&lt;p&gt;Hello everyone! This is Hossomi, a Java backend developer trying to learn frontend. There probably is a multitude of people out there telling their own story of a similar journey, and mine is just one more of these. But anyway, sharing won't hurt, and someone might even enjoy!&lt;/p&gt;

&lt;p&gt;In this series, I will try to build and deploy a full-stack web application using languages, libraries and technologies I'm not very familiar with. I won't go wild on complexity because it's more of an exercise than anything serious, but I will take this chance to learn as much as I can and share the experience along the way.&lt;/p&gt;

&lt;p&gt;In this first post, I will introduce myself, my motivation and experiences. At the end, let's think a little about what to build!&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Motivation
&lt;/h2&gt;

&lt;p&gt;I have been a backend developer for a few years now, and I am still very satisfied with it. Since I started my tech career, I have worked with various programming languages (mainly, but not only, Java), frameworks, tools, services and other technologies. There is always so much to learn and so many possibilities!&lt;/p&gt;

&lt;p&gt;As one of those people who also code as a hobby, I have personal projects in which I have to deal with databases, web APIs, deployments and such. However, there is one aspect I was never able to even make a dent: GUI. Web applications running in a browser are popular nowadays, and only attainable with technologies that I have nearly zero knowledge.&lt;/p&gt;

&lt;p&gt;This gap in my skillset feels very crippling! Any project, personal or not, that required frontend skills is usually out of my reach. So I decided it was time to fill that gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  🥉 The bad experience
&lt;/h2&gt;

&lt;p&gt;This is not going to be my first time learning frontend. A few years ago, I wanted to make an application to help my brother manage his Magic the Gathering collection.&lt;/p&gt;

&lt;p&gt;I thought that a desktop application would be best, so looking around I came across &lt;a href="https://www.electronjs.org/"&gt;Electron&lt;/a&gt;. I didn't know any JavaScript or any of its frameworks and libraries at the time, but this could be a good opportunity to learn, right? Well, I quickly found out the hard way that JavaScript ecosystem can be absurdly overwhelming.&lt;/p&gt;

&lt;p&gt;Installing libraries and getting something on the screen is not difficult with a tutorial. But I had to go and overstep by a lot! Suddenly, I am learning JavaScript, React, Redux, Webpack, Babel and a bunch of other things that came along &lt;em&gt;all at the same time&lt;/em&gt;. Eventually, I cloned a boilerplate repository with all these preconfigured, but it was so &lt;em&gt;huge&lt;/em&gt; I couldn't even fathom.&lt;/p&gt;

&lt;p&gt;I was able to get slightly off the ground, learn a little of each of those technologies and get some things working on the screen. At some point, though, I realized I was blindly changing code until it barely worked as I wanted. The lack of understanding of the fundamentals was increasingly unproductive and demotivating. The code was so entangled that trying to learn properly now was difficult. Maybe it was time to step back and start smaller.&lt;/p&gt;

&lt;h2&gt;
  
  
  🥈 The better experience
&lt;/h2&gt;

&lt;p&gt;During the next few years, I had the chance to work with frontend again in my job in a much smaller scope. I learned about  &lt;a href="https://create-react-app.dev/"&gt;Create React App&lt;/a&gt; (CRA), an amazing tool for beginners that encapsulates many development aspects for a static web application. With CRA, I no longer had to worry about Webpack, for example, which is already a huge weight off my shoulders.&lt;/p&gt;

&lt;p&gt;Along the way, I realized that &lt;a href="https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367"&gt;I didn't need Redux&lt;/a&gt;. React's context API and hooks also came up to solve probably everything that I would use Redux for.&lt;/p&gt;

&lt;p&gt;Of course, I will have to come back for all these tools (or alternatives) eventually. This new approach worked for the applications I was working on at the time and allowed me to focus on fewer things.&lt;/p&gt;

&lt;h2&gt;
  
  
  🥇 The next experience
&lt;/h2&gt;

&lt;p&gt;Let's start with a very high level idea of what I will build and a few technologies to focus on.&lt;/p&gt;

&lt;p&gt;I still want to help my brother with Magic the Gathering (MTG), so here's some background. When a new set is about to be released, some local stores hold pre-relase tournaments. The cards are published beforehand so players can study and prepare, and my brother builds a spreadsheet with lots of information for that.&lt;/p&gt;

&lt;p&gt;I wrote a shell script that fetches the set data from &lt;a href="https://mtgjson.com/"&gt;MTG JSON&lt;/a&gt; and generate a CSV using &lt;a href="https://stedolan.github.io/jq"&gt;jq&lt;/a&gt; with all the data he needs, which he then copies over his spreadsheet with his formulae and formatting. He can't run the script (not a programmer) so I run it and give him the CSV. What about turning that into a more flexible, self-served web application?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎯 GOAL: display a set data from MTG JSON in a dynamic table and generate a CSV from it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the technical side, these are what I have in mind initially. Of course things can change along the way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Typescript.&lt;/strong&gt; I have tried it before, thinking that I would adapt easily coming from a statically typed main programming language, but I was wrong. I don't have demands pressuring me this time, so I believe I will be able to learn it properly now. I might not be too strict, though, it depends on how it goes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL.&lt;/strong&gt; MTG JSON has quite a lot of data for each set and card. A more flexible interface for querying those fields might be useful, and suitable use case to try GraphQL out at the API layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://mtgjson.com/mtggraphql"&gt;MTG JSON has a GraphQL API&lt;/a&gt; in beta available for supporters in case you are interested in such API (probably better than mine will be).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt; (and CRA). I will stick to it since I still have much to learn. I will also have more time and freedom to study and experiment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MUI Core.&lt;/strong&gt; I have used previous versions of Material UI and enjoyed it. The new v5 seems slightly different, but I think it is worth learning to develop UI quicker with a system behind it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Yarn.&lt;/strong&gt; &lt;a href="https://yarnpkg.com/features/workspaces"&gt;Workspaces&lt;/a&gt; sounds very nice for organization even though I won't be publishing packages out of the application. NPM is fine, I just think I can try something new here without shooting myself in the foot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Heroku.&lt;/strong&gt; The simplest application platform I know, yet very powerful. I have tested it a few times but never went too deep, I want to learn more about its capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other development aspects I haven't even thought about yet, I will come up with them along the way. This is enough to get us started!&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Ready, set, go!
&lt;/h2&gt;

&lt;p&gt;Keeping the MTG theme, I chose to name our application after the MTG character &lt;a href="https://mtg.fandom.com/wiki/Tamiyo"&gt;Tamiyo&lt;/a&gt;. She is a planeswalker that seeks and records knowledge throughout the multiverse. It somewhat fits the purpose of this application.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/hossomi/tamiyo"&gt;GitHub repository&lt;/a&gt; (at the time of this writing, empty) and stay tuned for next articles!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>typescript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
