<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Brett Jephson</title>
    <description>The latest articles on Forem by Brett Jephson (@brettjephson).</description>
    <link>https://forem.com/brettjephson</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%2F287132%2F2d088f9d-b5f1-400b-add0-f4189a6f53ba.jpg</url>
      <title>Forem: Brett Jephson</title>
      <link>https://forem.com/brettjephson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/brettjephson"/>
    <language>en</language>
    <item>
      <title>2020 goals so far</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Tue, 28 Jul 2020 20:16:18 +0000</pubDate>
      <link>https://forem.com/brettjephson/2020-goals-so-far-3cco</link>
      <guid>https://forem.com/brettjephson/2020-goals-so-far-3cco</guid>
      <description>&lt;p&gt;At the beginning of the year I set myself &lt;a href="https://dev.to/brettjephson/5-goals-for-2020-2kg2"&gt;5 goals for 2020&lt;/a&gt;. I had meant to write this update halfway through the year but it has been delayed. Better late than never.&lt;/p&gt;

&lt;p&gt;What a difference 7 months makes. All the way back at the beginning of January, when no one was talking about covid-19, I set myself the following 5 goals for the year ahead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Less commuting&lt;/strong&gt; - work from home at least 3 of 5 work days every week&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Music&lt;/strong&gt; - master 6 bluegrass banjo songs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading&lt;/strong&gt; - read 26 books&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writing&lt;/strong&gt; - write 12 technical posts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drawing&lt;/strong&gt; - draw 3 portraits&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Less commuting
&lt;/h2&gt;

&lt;p&gt;This one was already in motion when the world completely changed. I had requested and been approved for working from home 3 days a week to help with child care. Then lockdown hit and the whole company have been working from home ever since. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Status:&lt;/em&gt; Achieved&lt;/p&gt;

&lt;h2&gt;
  
  
  Music
&lt;/h2&gt;

&lt;p&gt;This is still in progress. I've improved my banjo playing and I play nearly every day. Even if it is for a few minutes some days. So far I have Cripple Creek going at a decent pace, I'm improving the speed of Worried Man Blues and then have a few songs I'm trying to improve at: Foggy Mountain Breakdown, John Hardy, Man of Constant Sorrow and Old Joe Clark. If I can improve my pace a bit I might still make that goal.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Status:&lt;/em&gt; In progress - 2 / 6&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading
&lt;/h2&gt;

&lt;p&gt;This year I started reading at a much higher pace than last year. With audio books and some graphic novels, I've already hit my 26 book goal for the year. My stretch goal will be to keep that up for the rest of the year and hopefully hit about 50 books for the whole year.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Status:&lt;/em&gt; Achieved&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing
&lt;/h2&gt;

&lt;p&gt;You win some and you lose some. My reading progress has been a win but my writing has not been great. &lt;/p&gt;

&lt;p&gt;I haven't written anything meaningful for a while and certainly haven't kept up a good routine. Even my twitter activity has slowed recently. I started the year with 3 articles in quick succession and this post is an attempt to kickstart things.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Status:&lt;/em&gt; In progress - 4 / 12&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawing
&lt;/h2&gt;

&lt;p&gt;My goal for the year is to draw 3 portraits.&lt;/p&gt;

&lt;p&gt;Not kept up the habit of drawing regularly. I mostly just do some drawing with my daughter and haven't really progressed with portraiture in the way I'd have liked.&lt;/p&gt;

&lt;p&gt;Need to look at how I can add this into my daily habits.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Status:&lt;/em&gt; Not progressed - 0 / 3&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The year has obviously been a very strange one. Very difficult for everyone and really tragic for many. In light of the situation, this all feels pretty trivial but all-in-all my progress on these goals has been good.&lt;/p&gt;

&lt;p&gt;I've probably had some spare time that wasn't expected due to lockdown. In particular, I have found that playing the banjo has definitely helped me find something calming to get through these limbo days. Not sure my partner and daughter would feel the same.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Designing Graphql Schemas: Connections</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Thu, 20 Feb 2020 19:59:09 +0000</pubDate>
      <link>https://forem.com/brettjephson/designing-graphql-schemas-connections-3hn4</link>
      <guid>https://forem.com/brettjephson/designing-graphql-schemas-connections-3hn4</guid>
      <description>&lt;p&gt;As part of my &lt;a href="https://www.swyx.io/writing/learn-in-public/" rel="noopener noreferrer"&gt;learning in public&lt;/a&gt; drive for the new year, I thought I'd write down some notes as I take in &lt;a href="https://twitter.com/nikgraf" rel="noopener noreferrer"&gt;Nik Graf's&lt;/a&gt; egghead.io course on &lt;a href="https://egghead.io/courses/designing-graphql-schemas-99db" rel="noopener noreferrer"&gt;Designing GraphQL Schemas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This will be a series of short posts based on my notes. I'm continuing here with some notes on pagination and connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;Limiting the amount of data returned is best done by following the connections spec defined for Relay and now widely used by other (non-Relay) GraphQL solutions.&lt;/p&gt;

&lt;p&gt;This means pagination is represented by a cursor-based connection, which looks something like this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aCursor"&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="n"&gt;edges&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;cursor&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;node&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;id&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;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="n"&gt;pageInfo&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;startCursor&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;endCursor&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;hasNextPage&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;hasPreviousPage&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 the example, &lt;code&gt;item&lt;/code&gt; would return an &lt;code&gt;ItemConnection&lt;/code&gt;. It would accept arguments for &lt;code&gt;first&lt;/code&gt;, which is an integer limiting the number of results returned and analogous to &lt;code&gt;limit&lt;/code&gt; in many pagination systems, and &lt;code&gt;after&lt;/code&gt;, which is an opaque cursor. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cursor
&lt;/h2&gt;

&lt;p&gt;The first time I heard the words "opaque cursor" it sounded obscure and a bit complicated. &lt;/p&gt;

&lt;p&gt;A cursor is essentially something unique that points to a data item. This level of abstraction means you can store different information in a cursor and find slices of data in different ways. It might be that you need to slice the data by timestamp in one instance and by id in another. Or by some legacy information to adapt your existing rest api. A cursor allows for any of these options. &lt;/p&gt;

&lt;p&gt;These cursors are opaque because we normally encode them using base64 to make the data opaque. For example, we don't need to know that the cursor is defined from an id and a timestamp, we just need to know that it is a unique pointer to the data we are interested in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://facebook.github.io/relay/graphql/connections.htm" rel="noopener noreferrer"&gt;Take a look at the connection spec&lt;/a&gt; if you would like more of an explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edges
&lt;/h2&gt;

&lt;p&gt;The data is returned as an array of edge objects, which includes the cursor for the item and a node, which is the data item itself. &lt;/p&gt;

&lt;h2&gt;
  
  
  PageInfo
&lt;/h2&gt;

&lt;p&gt;As well as the set of edges, a connection also includes a page information object, with the start and end cursors for the particular page and boolean values for whether there is a next or previous page. &lt;/p&gt;

&lt;p&gt;The page information object is flexible and can be extended as needed, depending on the pagination needs for the data you are querying. This might include data filtering, for example.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Designing GraphQL Schemas: Mutations</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Fri, 17 Jan 2020 13:40:58 +0000</pubDate>
      <link>https://forem.com/brettjephson/designing-graphql-schemas-mutations-3ibo</link>
      <guid>https://forem.com/brettjephson/designing-graphql-schemas-mutations-3ibo</guid>
      <description>&lt;p&gt;As part of my &lt;a href="https://www.swyx.io/writing/learn-in-public/" rel="noopener noreferrer"&gt;learning in public&lt;/a&gt; drive for the new year, I thought I'd write down some notes as I take in &lt;a href="https://twitter.com/nikgraf" rel="noopener noreferrer"&gt;Nik Graf's&lt;/a&gt; egghead.io course on &lt;a href="https://egghead.io/courses/designing-graphql-schemas-99db" rel="noopener noreferrer"&gt;Designing GraphQL Schemas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This will be a series of short posts based on my notes. I'm continuing here with some notes on mutations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;It is a good convention to begin the mutation's name with a verb to describe the change it makes, e.g. &lt;code&gt;deleteRecords&lt;/code&gt;, &lt;code&gt;createPage&lt;/code&gt;, &lt;code&gt;updateItem&lt;/code&gt;. Use camel case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input
&lt;/h2&gt;

&lt;p&gt;It is best to provide a single, non-nullable input object to a mutation. This makes it easier to add arguments. &lt;/p&gt;

&lt;p&gt;The convention for an input is it should follow the name of the mutation  but with the postfix &lt;code&gt;Input&lt;/code&gt;. So the input for a &lt;code&gt;createPage&lt;/code&gt; mutation would be &lt;code&gt;CreatePageInput&lt;/code&gt;. Use Pascal case because they define an input type.&lt;/p&gt;

&lt;p&gt;For 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;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreatePageInput&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Payload
&lt;/h2&gt;

&lt;p&gt;A mutation should also return a single, non-nullable payload object. A payload can then return any data relevant to the enacted mutation.&lt;/p&gt;

&lt;p&gt;The convention for a payload is it should again follow the name of the mutation but with the postfix &lt;code&gt;Payload&lt;/code&gt;. So the payload for a &lt;code&gt;createPage&lt;/code&gt; mutation would be &lt;code&gt;CreatePagePayload&lt;/code&gt;. Use Pascal case because they define a type.&lt;/p&gt;

&lt;p&gt;For 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;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreatePagePayload&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;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Here is how we would put all those parts together in our 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;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;createPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreatePageInput&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CreatePagePayload&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is how we would use the mutation:&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;CreatePageMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;CreatePageInput&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="n"&gt;createPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$input&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="n"&gt;page&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="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;



</description>
      <category>graphql</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Designing Graphql Schemas: Queries</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Fri, 17 Jan 2020 12:29:09 +0000</pubDate>
      <link>https://forem.com/brettjephson/designing-graphql-schemas-2lep</link>
      <guid>https://forem.com/brettjephson/designing-graphql-schemas-2lep</guid>
      <description>&lt;p&gt;As part of my &lt;a href="https://www.swyx.io/writing/learn-in-public/" rel="noopener noreferrer"&gt;learning in public&lt;/a&gt; drive for the new year, I thought I'd write down some notes as I take in &lt;a href="https://twitter.com/nikgraf" rel="noopener noreferrer"&gt;Nik Graf's&lt;/a&gt; egghead.io course on &lt;a href="https://egghead.io/courses/designing-graphql-schemas-99db" rel="noopener noreferrer"&gt;Designing GraphQL Schemas&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This will be a series of short posts based on my notes. Starting, in this post, with some good practice for queries and naming fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;Managing the fields in a big GraphQL schema comes down to maintaining good naming conventions that make modification and evolution easy.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Be specific
&lt;/h3&gt;

&lt;p&gt;Fields should have specific names. For example, if we name a field image and its value is the url of the image of type String:&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;Product&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;image&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We might run into problems if we then want to add more fields relating to the image such as a text alternative or description. If we want to change the image field to an Image type with several fields it would cause a breaking change for our clients.&lt;/p&gt;

&lt;p&gt;Being specific from the beginning makes the change a lot easier:&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;Product&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;imageUrl&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can more easily make the change we want without the risk of angry clients wondering why their api broke:&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;Image&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;url&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;altText&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;Product&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;imageUrl&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="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reason&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;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;}'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Optional Arguments
&lt;/h3&gt;

&lt;p&gt;In a query, optional arguments can cause issues.&lt;/p&gt;

&lt;p&gt;For example, you might want to query a page by id or by slug. To do this, we could make both arguments optional:&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;page&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="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slug&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;Page&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 want to return a page based on either the id or the slug but what happens if we get neither or both? By making these values optional either of these cases is possible.&lt;/p&gt;

&lt;p&gt;An alternative is to name multiple queries that take different arguments. Based on our page 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;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;page&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="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="n"&gt;pageBySlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&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;Page&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 prevents those problematic cases and makes it clearer to the client what arguments the query expects.&lt;/p&gt;

</description>
      <category>graphql</category>
    </item>
    <item>
      <title>5 Goals for 2020</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Tue, 31 Dec 2019 16:04:55 +0000</pubDate>
      <link>https://forem.com/brettjephson/5-goals-for-2020-2kg2</link>
      <guid>https://forem.com/brettjephson/5-goals-for-2020-2kg2</guid>
      <description>&lt;p&gt;In a previous post I wrote &lt;a href="https://dev.to/brettjephson/my-2019-46k7"&gt;my review of 2019&lt;/a&gt;. Here I wanted to set a few goals for myself for 2020. &lt;/p&gt;

&lt;p&gt;I'll revisit these later in the year to see how I'm doing and which goals I've kept to and whether things have changed as the year has gone on.&lt;/p&gt;

&lt;h1&gt;
  
  
  Less commuting
&lt;/h1&gt;

&lt;p&gt;This one is my main goal for 2020. I currently travel by train to work. The train journey is just over an hour each way but add in the journey to and from the train station and I spend almost 4 hours a day commuting. &lt;/p&gt;

&lt;p&gt;I do work from home on an irregular basis but my goal for this year is to make remote working a consistent part of my schedule. My goal is to &lt;strong&gt;work from home at least 3 of 5 work days every week&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'd love to hear suggestions on how to approach the subject with a manager. What are your thoughts on working remotely? In an organisation that isn't primarily remote, does this affect your chances of promotion?&lt;/p&gt;

&lt;h1&gt;
  
  
  Music
&lt;/h1&gt;

&lt;p&gt;I turned 40 this year and got a new banjo as a gift. I've been learning to play it ever since. I'm currently practicing the basic techniques (rolls) but my goal is to have mastered &lt;strong&gt;6 bluegrass songs&lt;/strong&gt; to a good level by the end of 2020.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reading
&lt;/h1&gt;

&lt;p&gt;I talked about using the Goodreads reading challenge as a motivator in my review of 2019. &lt;/p&gt;

&lt;p&gt;I intend to use the same tool again for 2020. I have completed 24 books in 2019. That might get to 25 if I can finish the one I'm currently reading by midnight.&lt;/p&gt;

&lt;p&gt;In 2020, I'm setting my target a bit higher: &lt;strong&gt;26 books&lt;/strong&gt; (fiction/short stories). As a bonus goal, I want to include at least 4 philosophy, technical or non-fiction books.&lt;/p&gt;

&lt;h1&gt;
  
  
  Writing
&lt;/h1&gt;

&lt;p&gt;At the beginning of 2019, I set myself a challenge to do some more learning in public and be better at passing on knowledge to the web dev community. &lt;/p&gt;

&lt;p&gt;I ended up writing several chapters for a book and course published by Packt, &lt;a href="https://courses.packtpub.com/courses/html-css" rel="noopener noreferrer"&gt;The HTML and CSS Workshop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This has motivated me to write and create more content but not necessarily another book. I hope to focus more on writing blog posts and articles.&lt;/p&gt;

&lt;p&gt;My goal for 2020 is to write &lt;strong&gt;12 technical posts&lt;/strong&gt;. I intend to use this platform to post for now although I might actually get round to creating my own blog if I can keep to this goal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Drawing
&lt;/h1&gt;

&lt;p&gt;I am not terrible at drawing and I have been looking for hobbies that I can do away from the glare of the computer screen. I mostly doodle and draw in a cartoon-style. I want to improve at drawing and get better at a more realistic, sketching style. My goal for the year is to &lt;strong&gt;draw 3 portraits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Happy New Year and good luck with your goals for 2020!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>My 2019</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Mon, 30 Dec 2019 23:09:21 +0000</pubDate>
      <link>https://forem.com/brettjephson/my-2019-46k7</link>
      <guid>https://forem.com/brettjephson/my-2019-46k7</guid>
      <description>&lt;p&gt;My review of 2019:&lt;/p&gt;

&lt;h2&gt;
  
  
  Career
&lt;/h2&gt;

&lt;p&gt;This year has been one of hits and misses when it comes to work.&lt;/p&gt;

&lt;p&gt;I started the year working at King (Candy Crush Saga, etc) as a senior web developer in their shared tech department. I had only been there 6 months when they made a number of people redundant around March/April and I was left looking for a new role. &lt;/p&gt;

&lt;p&gt;Having secured a role with JustGiving, I had a month off, which led to an opportunity to write some chapters of a book. I will talk about that later.&lt;/p&gt;

&lt;p&gt;I joined JustGiving at the beginning of May as a senior frontend developer. I have mostly been working on their crowdfunding product. &lt;/p&gt;

&lt;p&gt;The frontend is Typescript and React. This role has given me my first experience of GraphQL, which is a skill I have enjoyed picking up. &lt;/p&gt;

&lt;p&gt;I work on a small team with two junior and two senior frontend developers and it has given me the opportunity to try out some new tech, visit conferences and help with recruiting. All things I wasn't doing in my freelance roles prior to 2019.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading
&lt;/h2&gt;

&lt;p&gt;Since my daughter was born, 4 years ago, the time I've spent reading has been reduced to near zero. Very occasionally, I have picked up a novel, read the same passage again and again while distractions have mounted up all around me and, finally, given up a few pages in.&lt;/p&gt;

&lt;p&gt;At the very end of 2018 and the beginning of 2019, I decided to try something a bit different. I thought I'd try to change my reading habits in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I set myself a reading challenge on Goodreads. &lt;/li&gt;
&lt;li&gt;I decided to focus on collections of short stories.&lt;/li&gt;
&lt;li&gt;I thought I'd give audio books a try.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reading Challenge
&lt;/h3&gt;

&lt;p&gt;I wanted to use the reading challenge to record my progress and push me to meet a target. I set the number of books for the year at 20. I hadn't read anywhere near that number of books in the previous year.&lt;/p&gt;

&lt;p&gt;As we reach the end of 2019, &lt;a href="https://www.goodreads.com/user_challenges/16462211" rel="noopener noreferrer"&gt;Goodreads tells me I have read 24 books&lt;/a&gt;. That means I've completed 22 books more than last year. The experiment has been a success! &lt;/p&gt;

&lt;p&gt;I still have a book on the go coming in to the last few days of 2019. I am hoping to get to 25 books for the year.&lt;/p&gt;

&lt;p&gt;In 2020, my aim is to improve on this. I will set my target to 26 for 2020. One book every two weeks. Anything over that will be a nice bonus.&lt;/p&gt;

&lt;h3&gt;
  
  
  Short Stories
&lt;/h3&gt;

&lt;p&gt;I chose to concentrate on collections of short stories because I wanted to be able to read in short bursts and still get to the end of a complete piece of art. &lt;/p&gt;

&lt;p&gt;I have always found good short stories inspiring. When done well the lean nature of a short story, the intensity and purity as a literary form, has occasionally left me in awe.&lt;/p&gt;

&lt;p&gt;I didn't stick completely to short stories over the year but found some collections I loved. Collections by Carys Davies (Some New Ambush, The Redemption of Galen Pike) and Angela Carter (The Bloody Chamber) stood out and 15 of the 25 books I've read have been short story collections. &lt;/p&gt;

&lt;p&gt;I think I will try to mix things up a bit more next year. I want to read some philosophy and non-fiction books, something I haven't done in a while, as well as some more short story collections and a few more novels. &lt;/p&gt;

&lt;p&gt;Finding good and interesting short story collections now seems to be a part of the challenge for 2020.&lt;/p&gt;

&lt;h3&gt;
  
  
  Audio Books
&lt;/h3&gt;

&lt;p&gt;On work days, I spend a lot of time commuting. This year I thought I would give audio books a go via an Audible subscription. &lt;/p&gt;

&lt;p&gt;I thought this would give me some time to just sit back and listen to a story well told.&lt;/p&gt;

&lt;p&gt;I have to admit this has not been entirely successful. I find it difficult to stay awake when listening to some audio stories on the train. Having said that, I did find Chernobyl interesting and Stephen Fry's Mythos was excellent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing
&lt;/h2&gt;

&lt;p&gt;In April, I was approached by an acquisition editor working for Packt about working on a book. I had planned to do more in the way of content creation for years. This seemed like a great opportunity. &lt;/p&gt;

&lt;p&gt;I was between jobs and had a month ahead of me with no full time work. It seemed like good timing. I will admit it took a lot more effort than I had expected to come up with 5 acceptable chapters for a book on the fundamentals of HTML and CSS.&lt;/p&gt;

&lt;p&gt;In December, after a long process of writing and editing, the book was released on &lt;a href="https://courses.packtpub.com/courses/html-css" rel="noopener noreferrer"&gt;Packt's new courses platform&lt;/a&gt; and on &lt;a href="https://www.amazon.co.uk/gp/product/1838824537" rel="noopener noreferrer"&gt;Amazon UK&lt;/a&gt; and on &lt;a href="https://www.amazon.com/HTML-CSS-Workshop-Interactive-Approach/dp/1838824537" rel="noopener noreferrer"&gt;Amazon US&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am proud it has been published and I hope to do more writing. It is a skill I really want to get better at. Hence this article and I hope several more in 2020. &lt;/p&gt;

&lt;p&gt;In 2019, I got an &lt;a href="https://www.amazon.co.uk/Brett-Jephson/e/B082NWPRH3/ref=dp_byline_cont_book_2" rel="noopener noreferrer"&gt;author page on Amazon&lt;/a&gt;. In 2020, I hope to add to it.&lt;/p&gt;

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

&lt;p&gt;It's been an interesting year, a lot has happened: the book, the change of job. I entered my 40s and I started playing banjo too.&lt;/p&gt;

&lt;p&gt;My daughter is about to turn 5 and it is great to see her growing and changing everyday. This year, she started the reception year at our local school and has become a lot more independent. She seems to be thriving and that is a joy to see.&lt;/p&gt;

&lt;p&gt;I look forward to 2020. I'm going to set myself some goals for the year that I hope I can keep to but I also don't want to push myself too far this year. Relaxing is something I find difficult at times. In middle age, I've come to realise it is better to sometimes take a moment and do nothing than to burn out while trying to fight fires of my own creation.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Some thoughts on side projects</title>
      <dc:creator>Brett Jephson</dc:creator>
      <pubDate>Mon, 09 Dec 2019 21:50:01 +0000</pubDate>
      <link>https://forem.com/brettjephson/some-thoughts-on-side-projects-io2</link>
      <guid>https://forem.com/brettjephson/some-thoughts-on-side-projects-io2</guid>
      <description>&lt;h3&gt;
  
  
  My new side project
&lt;/h3&gt;

&lt;p&gt;Yesterday, I turned 40. I had a lovely meal with my family, I ate some cake and I was given a banjo as a present.&lt;/p&gt;

&lt;p&gt;I've played guitar for more than 20 years and, while I don't feel like I'm starting from scratch, it is going to take time to get used to the little differences and the change in style that comes with playing a banjo.&lt;/p&gt;

&lt;p&gt;I'm sure there is a good analogy to be made that compares learning a new musical instrument and learning a new framework or programming language but I'll leave that for another day because, in this post, I want to explore a few thoughts about side projects.&lt;/p&gt;

&lt;p&gt;My new side project is learning the banjo. I love the sound of bluegrass banjo playing and I hope it will improve aspects of my guitar playing and my musical ability, in general. A change in perspective often works wonders.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal development
&lt;/h3&gt;

&lt;p&gt;A change in perspective. There are many reasons why I might start a new side project; to try out a new technology, to apply a pattern or coding paradigm I am not familiar with or to find a creative outlet not met by other aspects of my life. All of these can help to broaden my perspective. A side project can be a great tool for a developer's own development.&lt;/p&gt;

&lt;p&gt;From my experience, most successful coders are successful learners, first and foremost, but sometimes this drive can get a bit obsessive. If you find you are having to use your own spare time for personal development it might be time to ask some questions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is my day job lacking in some way?&lt;/li&gt;
&lt;li&gt;Does my job provide enough time or resources for continuous learning and development?&lt;/li&gt;
&lt;li&gt;Does my job fail to meet some need I might have for creativity or challenge?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lots of coders like to tinker outside work or treat code as a hobby as well as a form of income. I'm not saying you shouldn't have a side project but it is always worth questioning your motivations especially if that side project starts causing pressure on other parts of your life.&lt;/p&gt;

&lt;h3&gt;
  
  
  The danger of burnout
&lt;/h3&gt;

&lt;p&gt;Side projects can be fulfilling but they can become demanding on your time. I've seen a lot of articles recently about open source project maintainers burning out or finding it difficult to manage the demands they are put under by their community.&lt;/p&gt;

&lt;p&gt;I've found the danger of burnout is made worse when I feel like I might be letting someone else down. I'm happy to abandon a project that is mine alone. Fail fast and take some learnings. However, when there is someone who needs or expects your help it can be really difficult.  &lt;/p&gt;

&lt;p&gt;Earlier this year, I started a side project. I found myself in between jobs and I had the opportunity to write a few chapters for a book. I had wanted to do more writing for a long time. It looked like a great opportunity.&lt;/p&gt;

&lt;p&gt;The publishers were asking for three chapters from each of the authors. I thought it would take a month and I thought it would be finished before I started my new job. Estimation has never been my strong suit. Underestimating the work involved in a side project can be a real problem.&lt;/p&gt;

&lt;p&gt;This project, at times, did feel like it was becoming a bit too much for me to cope with. I underestimated how much time I could afford towards it. I underestimated the cost of context switching between work, family life and writing. I was trying to find small pockets of time to write on a train journey and it felt like I wasn't getting anywhere. &lt;/p&gt;

&lt;p&gt;It took longer than expected. At times it felt like I was reliving this wonderful Douglas Adams quote: "I love deadlines. I love the whooshing noise they make as they go by." over and over.&lt;/p&gt;

&lt;p&gt;I didn't want to let anyone down. I wanted to get the work done but I also felt it was starting to put pressure on my work and family life. I persevered and it meant asking for a lot of patience and kindness from my family.&lt;/p&gt;

&lt;p&gt;I don't have answers to a lot of these problems. My advice would be to choose side projects carefully and realise that your time is finite and ask a lot of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens when a side project becomes a burden to you or to your family?&lt;/li&gt;
&lt;li&gt;Will someone have to take on extra responsibilities for you to be able to complete the side project?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On one hand, it can be difficult to abandon something you have put a lot of effort into. On the other hand, burnout is a very real risk in our industry and your time is a precious thing. Use it wisely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this case, the journey has been difficult but the outcome has been a happy one. The book has just been released by Packt. It is called The HTML and CSS Workshop. It is available from Amazon (&lt;a href="https://www.amazon.co.uk/HTML-CSS-Workshop-Interactive-Approach/dp/1838824537/ref=sr_1_1?keywords=the+html+and+css+workshop&amp;amp;qid=1575367633&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;UK&lt;/a&gt; | &lt;a href="https://www.amazon.com/HTML-CSS-Workshop-Interactive-Approach/dp/1838824537/ref=sr_1_1?keywords=the+html+and+css+workshop&amp;amp;qid=1575367633&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;US&lt;/a&gt;) and through Packt as a &lt;a href="https://courses.packtpub.com/courses/html-css" rel="noopener noreferrer"&gt;workshop&lt;/a&gt;. It is a beginner-level book about HTML and CSS with lots of practical exercises. I'd love feedback on it if you get a chance to read it. I can even provide some referral links, if anyone is interested let me know in the comments.&lt;/p&gt;

&lt;p&gt;As I get older, I do find making space for side projects more and more of a problem. It is often difficult to balance work and life, let alone work, life and a side project. I'm hoping learning the banjo is a side project that better fits into that balance.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>webdev</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
