<?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: Christian Lobaugh</title>
    <description>The latest articles on DEV Community by Christian Lobaugh (@codelobaugh).</description>
    <link>https://dev.to/codelobaugh</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%2F326624%2Fe44a95f2-5cb1-4e02-a79a-cc0430f77d1c.jpg</url>
      <title>DEV Community: Christian Lobaugh</title>
      <link>https://dev.to/codelobaugh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codelobaugh"/>
    <language>en</language>
    <item>
      <title>How to move your Gatsby blog to a sub folder</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Wed, 26 Feb 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/how-to-move-your-gatsby-blog-to-a-sub-folder-nl9</link>
      <guid>https://dev.to/codelobaugh/how-to-move-your-gatsby-blog-to-a-sub-folder-nl9</guid>
      <description>&lt;p&gt;Based on the title of this article, you are likely expecting one of two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to host your Gatsby blog from a sub folder of an existing site.&lt;/li&gt;
&lt;li&gt;How to rearrange the pages and folders within an existing Gatsby site.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This blog post will cover option number two and I will keep option number one as a potential future article.  If you need information on that topic now, I suggest researching Gatsby’s pathPrefix configuration as a good place to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to rearrange your Gatsby files and folders
&lt;/h2&gt;

&lt;p&gt;Moving the files and folders in a Gatsby site requires a little knowledge of how Gatsby creates pages and requires you to consider what other changes may be needed as a result of your moves.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to create pages in Gatsby
&lt;/h3&gt;

&lt;p&gt;With Gatsby there are 2 primary ways to create pages on a site: adding pages to the pages folder and with the gatsby-node.js file.&lt;/p&gt;

&lt;p&gt;The first, and most easily understood, way to create pages with Gatsby is using the pages folder. Gatsby will create a web page for each file in the pages folder. This is best suited to pages that are individual or unique. A good example would be an About page, or a 404 page. This also works with sub-folders. If you want a page at /pets/whiskers then simply create a file at /pages/pets/whiskers.&lt;/p&gt;

&lt;p&gt;The second, and more powerful, way to create web pages, is the gatsby-node.js file. In this file, more advanced page creation takes place that can query various data structures and build pages based on the data it retrieves. For example, on a blog site, this is typically where the blog posts would be created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to rearrange things
&lt;/h3&gt;

&lt;p&gt;Now that I’ve explained the basics of how Gatsby creates pages, I’m going to walk though a move. I want to expand my site to be more than just a blog, and include different areas, but since I used a blog starter, the blog index is located at the root of my site. Now I want the index to be at the /blog URL and for a home page to be at the root. To achieve that, I will need to do a little rearranging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the current structure of my site&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/index.html - home, which is the blog index page showing the most recent blog posts
/archive.html - the blog archive page where you can see links to all the blog posts
/404.html - the 404 page.
/blog/ - all blog pages are stored under the blog sub-folder
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What I want the structure to be:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/index.html - new home page with intro, etc. (coming later - using blog index for now)
/404.html - no changes to the 404 page location
/blog/index.html - move the blog index under the blog sub-folder
/blog/archive/html - move the blog archive under the blog sub-folder
/blog/ - no changes to the blog articles.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In simple terms - I need to move the index and archive files under the blog sub-folder and create a new root index page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beware!&lt;/strong&gt; When moving pages, consider more than the moving of the pages themselves, but also any references to those pages. The most important references are navigation links and any external links we may have created that point to our site. Moving a page without addressing these issues results in broken links and images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Moving the pages&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Since my &lt;a href="http://Sanity.io"&gt;Sanity.io&lt;/a&gt; CMS, already has my blog entries separated in its own structure called ‘Blog Posts’, I don’t need to make any changes to Sanity. This this will be a Gatsby only change.&lt;/p&gt;

&lt;p&gt;Also, since my blog posts are already written to the blog sub-folder on my site, my blog posts don’t need any changes either, which means I won’t need to update my gatsby-config where the blog posts are created.&lt;/p&gt;

&lt;p&gt;The leaves only two pages that I need to move to the blog sub-folder: the Blog index and Blog archive. As these files are in the /pages folder, to move them I simply need to to create a new /pages/blog sub-folder and then move these files there. I will then need to have a new index page at the root of my site to represent my home page. For now I’m going to leave a copy of the blog index there so the page is not blank, and I will come back to add a new homepage at a later time.&lt;/p&gt;

&lt;p&gt;Once I copy the index.js to /blog/index.js, I need to make some changes to the /blog/index.js. The first thing I need to do is to rename the graphql query. Gatsby requires that all graphql queries within a project have a unique name, and so if I do not change the name I will get a compile error as I will have two pages that share a query name.&lt;/p&gt;

&lt;p&gt;Current index query&lt;/p&gt;

&lt;p&gt;&lt;code&gt;query IndexPageQuery {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I change that to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;query BlogIndexPageQuery {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The next thing I need to check is my imports. Since I have moved this file down a directory, I will need to change my imports accordingly.&lt;/p&gt;

&lt;p&gt;Note: VSCode will often see you doing this and ask if you want to update the references. While this is a nice feature and will catch most of the needed changes, you should double check to be sure it is correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My references before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react' 
import {graphql} from ‘gatsby’
import {
  mapEdgesToNodes,
  filterOutDocsWithoutSlugs,
  filterOutDocsPublishedInTheFuture
} from ‘…/lib/helpers’
import BlogPostPreviewList from ‘…/components/blog-post-preview-list’
import Container from ‘…/components/container’
import GraphQLErrorList from ‘…/components/graphql-error-list’
import SEO from ‘…/components/seo’
import Layout from ‘…/containers/layout’
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My new references:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from ‘react’
import {graphql} from ‘gatsby’
import {
  mapEdgesToNodes,
  filterOutDocsWithoutSlugs,
  filterOutDocsPublishedInTheFuture
} from ‘…/…/lib/helpers’
import BlogPostPreviewList from ‘…/…/components/blog-post-preview-list’
import Container from ‘…/…/components/container’
import GraphQLErrorList from ‘…/…/components/graphql-error-list’
import SEO from ‘…/…/components/seo’
import Layout from ‘…/…/containers/layout’
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point I want to move the archive.js page to the blog directory and I will need to make the same references changes I did for the blog/index.js page (I won’t list these here). I do not need to change the query name as I moved this file, so there is no duplicate query name on the site.&lt;/p&gt;

&lt;p&gt;This move will cause an issue, however: it will break the Archive link in our nav menu, which is a good segue into the next changes I need to make.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External links and Nav changes&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Now that the pages are moved, it’s time to address any external links or nav changes that are needed. External links are not an issue, fortunately, as I am not changing the URL of any of my actual blog posts since they are not moving. If I were changing these, then I would need to set up redirects for any external links to prevent them from breaking.&lt;/p&gt;

&lt;p&gt;For the my nav menu, I want to add a new “Blog” link, and then I want to make it so that the “Archive” link only shows when the user is in the blog area of the site.&lt;/p&gt;
&lt;h3&gt;
  
  
  Edit the Nav menu
&lt;/h3&gt;

&lt;p&gt;There are 4 changes I need to make:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a new nav menu item called “Blog” that links to the blog root.&lt;/li&gt;
&lt;li&gt;Change the archive menu item to point to /blog/archive instead of /archive.&lt;/li&gt;
&lt;li&gt;Change any other links to /archive on the site to point to /blog/archive&lt;/li&gt;
&lt;li&gt;Make the archive link only show on pages under the /blog structure (not on the home page or other sections of the site that don’t yet exist).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  1. Add Blog to the nav menu
&lt;/h3&gt;

&lt;p&gt;Start by finding where in the code your nav is located. Most Gatsby sites will use a layout component and will have a header component inside the layout. That is the case for my blog starter - the file I need to edit is /web/src/components/header.js&lt;/p&gt;

&lt;p&gt;This is the file to begin with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {Link} from ‘gatsby’
import React from ‘react’
import Icon from ‘./icon’
import {cn} from ‘…/lib/helpers’
import styles from ‘./header.module.css’

const Header = ({onHideNav, onShowNav, showNav, siteTitle}) =&amp;gt; (
  &amp;lt;div className={styles.root}&amp;gt;
    &amp;lt;div className={styles.wrapper}&amp;gt;
      &amp;lt;div className={styles.branding}&amp;gt;
        &amp;lt;Link to='/'&amp;gt;{siteTitle}&amp;lt;/Link&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;button className={styles.toggleNavButton} 
        onClick={showNav ? onHideNav : onShowNav}&amp;gt; 
        &amp;lt;Icon symbol='hamburger' /&amp;gt; 
      &amp;lt;/button&amp;gt; 

      &amp;lt;nav className={cn(styles.nav, showNav &amp;amp;&amp;amp; styles.showNav)}&amp;gt; 
        &amp;lt;ul&amp;gt; 
          &amp;lt;li&amp;gt; &amp;lt;Link to='/archive/'&amp;gt;Archive&amp;lt;/Link&amp;gt; &amp;lt;/li&amp;gt; 
        &amp;lt;/ul&amp;gt; 
      &amp;lt;/nav&amp;gt; 
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
) 

export default Header
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Add a new nav menu item called “Blog” that links to the blog root&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;li&amp;gt;
  &amp;lt;Link to='/blog/'&amp;gt;Blog&amp;lt;/Link&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Change the archive menu item to point to /blog/archive instead of /archive&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Link to='/blog/archive'&amp;gt;Archive&amp;lt;/Link&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Change any other links to /archive on the site to point to /blog/archive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have a "browse more" link at the bottom of my blog index page that links to the archive page.&lt;/p&gt;

&lt;p&gt;I had to make a small change to /web/pages/blog/index.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;BlogPostPreviewList
  title='Latest blog posts'
  nodes={postNodes}
  browseMoreHref='/blog/archive/'
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Make the archive link only show on pages under the /blog structure (not on the home page or other sections of the site that don’t yet exist).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one is a little trickier ... There are several ways to do it. Here are a few ideas (not a comprehensive list):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a separate layout for the blog pages and have that layout pass a prop to the header component telling it to show the archive link.&lt;/li&gt;
&lt;li&gt;Create a separate header component and the layout determines which header to call based on the URL path.&lt;/li&gt;
&lt;li&gt;Create a conditional in the header that shows the archive link based on the URL path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these option are inherently better than the others. The strategy you choose should be dependent on the site structure and needs of your site. For example, if different sections of your site will have different layouts, each with a different Nav menu, then I would lean towards creating a different Blog header with the correct nav menu. In my situation, everything will be similar across my site, therefore I don’t want a separate blog header just to handle a small variation. Instead, I’m choosing to put a conditional on the archive link that is based on the URL.&lt;/p&gt;

&lt;p&gt;The first thing I need to do is programmatically identify the current page. Once I know that, I can add the conditional statement around the Archive Link.&lt;/p&gt;

&lt;p&gt;To determine the page, I pull the location info from &lt;code&gt;@reach/router.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start with an import&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { globalHistory as history } from ‘@reach/router’
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next get the location from history by defining a &lt;code&gt;const&lt;/code&gt;. I am going to change our component a little to support this by adding a return block (that is currently implied by the syntax).&lt;/p&gt;

&lt;p&gt;Current structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Header = ({onHideNav, onShowNav, showNav, siteTitle}) =&amp;gt; (
... )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;New:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Header = ({onHideNav, onShowNav, showNav, siteTitle}) =&amp;gt; {
  return (
  ... ) 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a little more verbose but it allows me to add an additional &lt;code&gt;const&lt;/code&gt;in a clean, easy to understand way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Header = ({onHideNav, onShowNav, showNav, siteTitle}) =&amp;gt; {
  const { location } = history
  return (
  ... )
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;My location object now has a pathway that contains the path without the url. I can easily use that to determine if the Archive link should be shown.&lt;/p&gt;

&lt;p&gt;Here is complete code for the nav area of my new header.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;nav className={cn(styles.nav, showNav &amp;amp;&amp;amp; styles.showNav)}&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;
      &amp;lt;Link to='/blog/'&amp;gt;Blog&amp;lt;/Link&amp;gt;
    &amp;lt;/li&amp;gt;
    {location.pathname.includes('/blog') &amp;amp;&amp;amp; 
      &amp;lt;li&amp;gt;
        &amp;lt;Link to='/blog/archive/'&amp;gt;Archive&amp;lt;/Link&amp;gt;
      &amp;lt;/li&amp;gt;
    }
  &amp;lt;/ul&amp;gt;
&amp;lt;/nav&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I will only see the Archive link on pages that begin with /blog.&lt;/p&gt;

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

&lt;p&gt;With my blog now in it's own folder, I am now free to add other areas to my site like a portfolio or a collection of epic dad jokes.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Add automatic cross posting from my Sanity/Gatsby Blog to Dev.to</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Thu, 30 Jan 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/add-automatic-cross-posting-from-my-sanity-gatsby-blog-to-dev-to-4ok</link>
      <guid>https://dev.to/codelobaugh/add-automatic-cross-posting-from-my-sanity-gatsby-blog-to-dev-to-4ok</guid>
      <description>&lt;p&gt;Knut (&lt;a href="https://twitter.com/kmelve"&gt;@kmelve&lt;/a&gt;) made the great suggestion to me recently that setting up cross posting of my blog posts to &lt;a href="http://Dev.to"&gt;Dev.to&lt;/a&gt; would reach a broader audience. Doing this manually is a bit cumbersome, so I had planned to automate the process, but had not researched the details yet. Knut, was kind enough to include a &lt;a href="https://tueri.io/blog/2019-06-06-how-to-automatically-cross-post-from-your-gatsbyjs-blog-with-rss/"&gt;great tutorial&lt;/a&gt;, however, and so I decided there was no time like the present.&lt;/p&gt;

&lt;p&gt;Therefore, today, as part of my personal #100DaysOfGatsby journey, I'm going to set up cross-posting of my blog to Dev.to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick history lesson - What is cross-posting?
&lt;/h2&gt;

&lt;p&gt;Cross-posting is a term for posting something in multiple places at the same time (or having automation that re-posts for you to the same effect). The term goes back to days when Usenet was the main internet forum. Usenet is split into a huge amount of areas for specific topics called newsgroups. When you wrote a message for Usenet, it was called a post. You posted your post to the newsgroup that was the most relevant, and if your message had relevance to other newsgroups as well, you could post it to multiple at the same time; this was called cross-posting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to today - how am I going to achieve this with my blog?
&lt;/h2&gt;

&lt;p&gt;The basic idea is that I will add an RSS feed to the blog, and then subscribe to that feed from my &lt;a href="http://Dev.to"&gt;Dev.to&lt;/a&gt; account. Dev.to will then monitor the RSS feed and create new articles for any new posts it sees on my site. Sounds simple right? Turns out it is a little more complicated when using Sanity due to the Portable Text objects. RSS wants HTML and not Portable Text. The extra work is a small price to pay, however, to get the awesome benefits of Portable Text.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Add canonical URLs to blog posts
&lt;/h3&gt;

&lt;p&gt;Despite its cryptic name, a canonical URL is simply a way for you to add information to a web page that indicates where the TRUE (or authoritative) source of that page is.&lt;/p&gt;

&lt;p&gt;Why is this important? Because it tells search pages where the primary content is found and that any cross-post is a legitimate copy. Setting your site as canonical for your posts means you get credit from Google, drives traffic to your site and builds your personal brand.&lt;/p&gt;

&lt;p&gt;Adding this to Gatsby is simple enough using a plugin aptly named &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-react-helmet-canonical-urls/"&gt;gatsby-plugin-react-helmet-canonical-urls&lt;/a&gt; (note: I’m using this plugin since I’m also using react-helmet. If you are not using react-helmet, there is a different plugin to use instead - &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-canonical-urls/"&gt;gatsby-plugin-canonical-urls&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I start by changing to the web directory of my mono-repo and then install the plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -save gatsby-plugin-react-helmet-canonical-urls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I will add the plugin configuration to web/gatsby.config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins: [
  {
    resolve: `gatsby-plugin-react-helmet-canonical-urls`,
    options: {
      // Change `siteUrl` to your domain 
      siteUrl: `https://christianlobaugh.com`,

      // Query string parameters are included by default.
      // Set `stripQueryString: true` if you don't want `/blog` 
      // and `/blog?tag=foobar` to be indexed separately
      stripQueryString: true
    }
  }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I have the canonical url added to the HEAD of all of my pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Add an RSS Feed to the site.
&lt;/h3&gt;

&lt;p&gt;As you would guess, Gatsby has a plugin for this as well - &lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-feed/"&gt;gatsby-plugin-feed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -save gatsby-plugin-feed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then I need to add the plugin configutation to web/gatsby-config.js.&lt;/p&gt;

&lt;p&gt;This is the most complex piece of the puzzle and requires the most heavy lifting. The basic steps are to write a query to get the data the RSS plugin needs, and then to serialize that data. Since I am using data from Sanity that is Portable Text, however, I will need to translate that portable text to HTML, which is an extra step. Fortunately Sanity provides a nice library that can do exactly that.&lt;/p&gt;

&lt;p&gt;I will start by installing it to my web directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -save @sanity/block-content-to-html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, I identify the data I need for Dev.to and then write my query to get the data from Sanity.&lt;/p&gt;

&lt;p&gt;It's important to note that &lt;strong&gt;gatsby-plugin-feed&lt;/strong&gt; has a defined set of values you can use. If you want to use anything different, you will need to use the &lt;strong&gt;"custom_elements"&lt;/strong&gt; field.&lt;/p&gt;

&lt;p&gt;Here's a breakdown of the data I think I need with the plugin variable names assigned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Site level data:
title [siteMetadata.title]
description [siteMetadata.description]
siteUrl [siteMetadata.siteUrl]
site_url: siteUrl [siteMetadata.siteUrl]

//Post level data:
title [allSanityPost.title]
url [allSanityPost.title.url]
guid [allSanityPost.title.url]
date [allSanityPost.publishedAt]
// The following fields are Portable text
// and will need to be converted to HTML
description [allSanityPost._rawExcerpt] 
custom_elements{content} [allSanityPost._rawBody]

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



&lt;p&gt;Now that I know what data I need, I will build my graphql query. A couple of notes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I'm pulling the site data from the siteMetadata block in the gatsby-config, not from Sanity. You can create these fields and pull them from Sanity if you prefer.&lt;/li&gt;
&lt;li&gt;Use your dev GraphiQL editor found at &lt;a href="http://localhost:8000/%5C_%5C_%5C_graphql"&gt;http://localhost:8000/\_\_\_graphql&lt;/a&gt; when you are running Gatsby in dev mode. This is invaluable for getting your queries correct before putting them in your code.&lt;/li&gt;
&lt;li&gt;Any time you are dealing with a portable text field, you should use the &lt;strong&gt;_raw&lt;/strong&gt; version of that field that Sanity provides. If there are references in your portable text you will need to add the &lt;strong&gt;resolveReferences&lt;/strong&gt; prop. (see my example below for usage)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Site level query:
query: ` {
 site {
  siteMetadata {
    title
    description
    siteUrl
    site_url: siteUrl
  }
}`

//Post level query
query: `{
  allSanityPost(sort: {fields: publishedAt, order: DESC}) {
    edges {
      node {
        _rawExcerpt
        _rawBody(resolveReferences: {maxDepth: 10})
        title
        publishedAt
        slug {
          current
        }
      }
    }
  }
}
`,  

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



&lt;p&gt;The last, and most complicated step, is to serialize this data properly for the RSS feed. Since a few of my fields are Portable Text objects and not strings this will require a bit of extra code to be added to my gatsby-config.js to convert these to HTML.&lt;/p&gt;

&lt;p&gt;I start by adding some needed libraries and functions to the top of the gatsby-config.js file. I am mostly needing &lt;strong&gt;PortableText&lt;/strong&gt; function from the &lt;a href="https://github.com/sanity-io/block-content-to-html"&gt;&lt;strong&gt;@sanity/block-content-to-html&lt;/strong&gt;&lt;/a&gt; library and the &lt;strong&gt;imageUrlBuilder&lt;/strong&gt; function from &lt;strong&gt;&lt;a href="https://github.com/sanity-io/image-url"&gt;@sanity/image-url&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now I can write the config for the &lt;strong&gt;gatsby-plugin-feed.&lt;/strong&gt; The code is fairly straight forward:&lt;/p&gt;

&lt;p&gt;Run the queries defined &lt;strong&gt;&amp;gt;&lt;/strong&gt; filter the posts &lt;strong&gt;&amp;gt;&lt;/strong&gt; iterate through the posts &lt;strong&gt;&amp;gt;&lt;/strong&gt; pull out needed fields and assign to appropriate feed variables.&lt;/p&gt;

&lt;p&gt;The tricky part is that I need to convert the Portable Text fields to HTML. The block-content-to-html library's PortableText funtion comes to the rescue. It knows how to handle the basic html styles, but needs some help with images, and with custom objects that I've added. I do this by adding serialization instructions to the Portable Text call.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: For my youtube-embed custom object I just add a link to the embedded video with a description. There may be a way to serialize this to a proper video container that will work with the RSS feed and will be read appropriately by Dev.to. It's simple enough to edit in the draft on DEV.to for now so I'm handing that code exercise off to Future Me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is my entire gatsby-config.js. See the &lt;em&gt;feeds&lt;/em&gt; section of the &lt;em&gt;gatsby-plugin-feed&lt;/em&gt; config section to see the main logic processing and the Portable Text serialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Load variables from `.env` as soon as possible
require("dotenv").config({
  path: `.env.${process.env.NODE_ENV || "development"}`
});

const clientConfig = require("./client-config");
const isProd = process.env.NODE_ENV === "production";

// for Portable Text Serialization
const PortableText = require("@sanity/block-content-to-html");
const imageUrlBuilder = require("@sanity/image-url");
const h = PortableText.h;
const imageUrlFor = source =&amp;gt; imageUrlBuilder(clientConfig.sanity).image(source);

// Helper functions for Portable Text
const { format, isFuture } = require("date-fns");

function filterOutDocsPublishedInTheFuture({ publishedAt }) {
  return !isFuture(publishedAt);
}

function getBlogUrl(publishedAt, slug) {
  return `/blog/${format(publishedAt, "YYYY/MM")}/${slug.current || slug}/`;
}

module.exports = {
  siteMetadata: {
    title: "Christian Lobaugh",
    siteUrl: "https://www.christianlobaugh.com",
    description: "The blog and website of Christian Lobaugh"
  },
  plugins: [
    "gatsby-plugin-postcss",
    "gatsby-plugin-netlify",
    "gatsby-plugin-react-helmet",
    {
      resolve: "gatsby-source-sanity",
      options: {
        ...clientConfig.sanity,
        token: process.env.SANITY_READ_TOKEN,
        watchMode: !isProd,
        overlayDrafts: !isProd
      }
    },
    {
      resolve: `gatsby-plugin-react-helmet-canonical-urls`,
      options: {
        // Change `siteUrl` to your domain
        siteUrl: `https://christianlobaugh.com`,

        // Query string parameters are inclued by default.
        // Set `stripQueryString: true` if you don't want `/blog`
        // and `/blog?tag=foobar` to be indexed separately
        stripQueryString: true
      }
    },
    {
      resolve: `gatsby-plugin-feed`,
      options: {
        query: `
        {
          site {
            siteMetadata {
              title
              description
              siteUrl
              site_url: siteUrl
            }
          }
        }
        `,
        feeds: [
          {
            serialize: ({ query: { site, allSanityPost = [] } }) =&amp;gt; {
              return allSanityPost.edges
                .filter(({ node }) =&amp;gt; filterOutDocsPublishedInTheFuture(node))
                .filter(({ node }) =&amp;gt; node.slug)
                .map(({ node }) =&amp;gt; {
                  const { title, publishedAt, slug, _rawBody, _rawExcerpt } = node;
                  const url = site.siteMetadata.siteUrl + getBlogUrl(publishedAt, slug.current);
                  return {
                    title: title,
                    date: publishedAt,
                    url,
                    guid: url,
                    description: PortableText({
                      blocks: _rawExcerpt,
                      serializers: {
                        types: {
                          code: ({ node }) =&amp;gt;
                            h("pre", h("code", { lang: node.language }, node.code))
                        }
                      }
                    }),
                    custom_elements: [
                      {
                        "content:encoded": PortableText({
                          blocks: _rawBody,
                          serializers: {
                            types: {
                              code: ({ node }) =&amp;gt;
                                h("pre", h("code", { lang: node.language }, node.code)),
                              mainImage: ({ node }) =&amp;gt;
                                h("img", {
                                  src: imageUrlFor(node.asset).url()
                                }),
                              authorReference: ({ node }) =&amp;gt; h("p", "Author: " + node.author.name),
                              youtube: ({ node }) =&amp;gt;
                                h(
                                  "a",
                                  {
                                    href: node.url
                                  },
                                  'Watch this video on YouTube'
                                )
                            }
                          }
                        })
                      }
                    ]
                  };
                });
            },
            query: `{
              allSanityPost(sort: {fields: publishedAt, order: DESC}) {
                edges {
                  node {
                    _rawExcerpt
                    _rawBody(resolveReferences: {maxDepth: 10})
                    title
                    publishedAt
                    slug {
                      current
                    }
                  }
                }
              }
            }
            `,
            output: "/rss.xml",
            title: "Christian Lobaugh - RSS Feed",
            // optional configuration to insert feed reference in pages:
            // if `string` is used, it will be used to create RegExp and then test if pathname
            // of current page satisfied this regular expression;
            // if not provided or `undefined`, all pages will have feed reference inserted
            match: "^/blog/"
          }
        ]
      }
    }
  ]
};

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



&lt;p&gt;Important Note: The RSS feed only works when your site is in production mode. You will not see it when you do a &lt;strong&gt;gatsby dev&lt;/strong&gt; , or &lt;strong&gt;npm run dev&lt;/strong&gt; , but only when you’ve done a &lt;strong&gt;gatsby build&lt;/strong&gt;. To see the RSS feed in your local dev environment, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gatsby build &amp;amp;&amp;amp; gatsby serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now you can see your rss.xml at &lt;a href="http://localhost:9000/rss.xml"&gt;localhost:9000/rss.xml&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Setup &lt;a href="http://dev.to"&gt;Dev.to&lt;/a&gt; to consume RSS feed
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;a href="https://Dev.to"&gt;Dev.to&lt;/a&gt; account&lt;/li&gt;
&lt;li&gt;Go to: Settings &amp;gt; Publishing from RSS or &lt;a href="https://dev.to/settings/publishing-from-rss"&gt;https://dev.to/settings/publishing-from-rss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add “RSS Feed URL” (for me that's. &lt;a href="https://christianlobaugh.com/rss.xml"&gt;https://christianlobaugh.com/rss.xml&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Check the box "Mark the RSS source as canonical URL by default"&lt;/li&gt;
&lt;li&gt;Uncheck the box "Replace self-referential links with DEV-specific links"&lt;/li&gt;
&lt;li&gt;Click “Submit” or "Update" (whichever you are offered)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now all of my blog posts are immediately posted to my DEV.to drafts folder for me to review before posting them live. I can give Dev.to admins permission to do this, but I'm going to hold off on that for now. I want to see how much editing that my drafts will need. Once I've confirmed that my RSS feed is creating posts where the edits are zero or minimal, then I will look at skipping the draft step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Review your blog posts on DEV.to
&lt;/h3&gt;

&lt;p&gt;Go to your Dev.to dashboard and you will see a list of posts. For the ones in draft mode, pull them up and review. If you are happy, edit the post and change the &lt;strong&gt;published:&lt;/strong&gt; field in the front-matter from false to true and then click &lt;strong&gt;save&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 - Bask in the glow of a &lt;a href="https://dev.to"&gt;Dev.to&lt;/a&gt; article that was (almost completely) auto generated from your blog
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;References that helped me create this:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tueri.io/blog/2019-06-06-how-to-automatically-cross-post-from-your-gatsbyjs-blog-with-rss/"&gt;https://tueri.io/blog/2019-06-06-how-to-automatically-cross-post-from-your-gatsbyjs-blog-with-rss/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-feed/"&gt;https://www.gatsbyjs.org/packages/gatsby-plugin-feed/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gatsbyjs.org/packages/gatsby-plugin-react-helmet-canonical-urls/"&gt;https://www.gatsbyjs.org/packages/gatsby-plugin-react-helmet-canonical-urls/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/kmelve/"&gt;https://gist.github.com/kmelve/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to add custom icons to your Sanity.io Studio's Portable Text</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Mon, 20 Jan 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/how-to-add-custom-icons-to-your-sanity-io-studio-s-portable-text-36jb</link>
      <guid>https://dev.to/codelobaugh/how-to-add-custom-icons-to-your-sanity-io-studio-s-portable-text-36jb</guid>
      <description>&lt;h2&gt;
  
  
  How to make your Portable Text Custom objects look more professional with custom icons
&lt;/h2&gt;

&lt;p&gt;If you followed my last blog post where I added a custom YouTube embed you may have noticed that the icon used by Sanity in the Portable Text editor was a bit bland. This is because it's the default icon. It works, but is not the most user friendly or professional looking (icon is inside the red box).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a66wmQgh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/e0548ef47c7bd5360f0e56025b84a84d3995796c-1127x110.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a66wmQgh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/e0548ef47c7bd5360f0e56025b84a84d3995796c-1127x110.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post I will show you how to change that icon to something better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - About the icon library
&lt;/h3&gt;

&lt;p&gt;Sanity studio uses the react-icons library which is found at &lt;a href="https://react-icons.netlify.com/#/"&gt;https://react-icons.netlify.com/&lt;/a&gt;. This provides a ton of icons from several of the most popular icon libraries around. A big advantage with this library is that you only load the icons you need, so the footprint is very small. It's important to note that Sanity is using an older version of this library and so it uses the older syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FaCode from 'react-icons/lib/fa/code'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's also important to note that Sanity does not have all of the icon sets the newer version does. Sanity only has the Font Awesome, Material Design, Typicons and Github Opticons. This is quite a lot of options, but if it's not enough for you, you can upgrade the react-icons library yourself and adjust your code accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Choose your icon
&lt;/h3&gt;

&lt;p&gt;You can see (and search) the list of icons at &lt;a href="https://react-icons.netlify.com/#/"&gt;https://react-icons.netlify.com/&lt;/a&gt;. For this example I'm going to add a video icon to my custom YouTube embed object. I'm choosing the icon called 'MdOndemandVideo'&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Identify the icon library
&lt;/h3&gt;

&lt;p&gt;There are several libraries of icons, and it's important to know which library you are using when importing the icon.&lt;/p&gt;

&lt;p&gt;The good news, is that this is really easy, as the library name is the first 2 characters of the icon name (in lowercase). In this case, that would be "md".&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Import the font to the code file where you need it
&lt;/h3&gt;

&lt;p&gt;I'll be editing youtube.js in this example. I will add the following to the top of the file (let vs-code intellisense help you git the right library name):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import MdOndemandVideo from 'react-icons/lib/md/ondemand-video'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 - Add a reference to the icon in the Studio object
&lt;/h3&gt;

&lt;p&gt;A studio object has a parameter icon that you can use to assign an icon to that object. It is assigned similar to name, or title, except that it accepts an icon type. Here is the what that looks like for my file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  icon: MdOndemandVideo,
  fields: [

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



&lt;h3&gt;
  
  
  Step 6 - Run your project in dev to test
&lt;/h3&gt;

&lt;p&gt;You really need to test as I've run across a couple of icons that don't work and a couple that display differently than the docs show. (There are enough icons to choose from that I don't find this a huge concern. If a specific icon doesn't work, I just choose another).&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping it up
&lt;/h3&gt;

&lt;p&gt;This is what my Portable Text editor looked like before (the red box is only there to hightlight the icon we are changing):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a66wmQgh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/e0548ef47c7bd5360f0e56025b84a84d3995796c-1127x110.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a66wmQgh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/e0548ef47c7bd5360f0e56025b84a84d3995796c-1127x110.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is what it looks like now?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6yIJXakW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/3b4ad1134e73ac49b9a61108fdaab13456f0faef-1128x99.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6yIJXakW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/3b4ad1134e73ac49b9a61108fdaab13456f0faef-1128x99.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, not only did I update the YouTube embed icon, but also the code block, image and author reference icons. A small change but one that greatly improves usability and looks much more professional.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus:
&lt;/h3&gt;

&lt;p&gt;This tip isn't just for your portable text editor. You can also decide on the icons you want to show on the desktop as well.&lt;/p&gt;

&lt;p&gt;Sanity is already doing this in the Sanity create blog starter.&lt;/p&gt;

&lt;p&gt;Here is the studio/deskStructure.js file that defines the desktop. You will see the icon imports at the top of the file and where they are used later to assign that icon to an Item. If you want to change or add icons, just import them and assign them in a similar manner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import S from '@sanity/desk-tool/structure-builder'
import MdSettings from 'react-icons/lib/md/settings'
import MdPerson from 'react-icons/lib/md/person'

const hiddenDocTypes = listItem =&amp;gt;
  !['category', 'author', 'post', 'siteSettings'].includes(listItem.getId())

export default () =&amp;gt;
  S.list()
    .title('Content')
    .items([
      S.listItem()
        .title('Settings')
        .icon(MdSettings)
        .child(
          S.editor()
            .id('siteSettings')
            .schemaType('siteSettings')
            .documentId('siteSettings')
        ),
      S.listItem()
        .title('Blog posts')
        .schemaType('post')
        .child(S.documentTypeList('post').title('Blog posts')),
      S.listItem()
        .title('Authors')
        .icon(MdPerson)
        .schemaType('author')
        .child(S.documentTypeList('author').title('Authors')),
      S.listItem()
        .title('Categories')
        .schemaType('category')
        .child(S.documentTypeList('category').title('Categories')),
      // This returns an array of all the document types
      // defined in schema.js. We filter out those that we have
      // defined the structure above
      ...S.documentTypeListItems().filter(hiddenDocTypes)
    ])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'd also reccommend checking out Sanity's documentation where they show a different place you can use icons in this fashion. &lt;a href="https://www.sanity.io/docs/icons-for-data-types"&gt;https://www.sanity.io/docs/icons-for-data-types&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adding embedded video to my Gatsby blog</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Sat, 18 Jan 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/adding-embedded-video-to-my-gatsby-blog-29n8</link>
      <guid>https://dev.to/codelobaugh/adding-embedded-video-to-my-gatsby-blog-29n8</guid>
      <description>&lt;h2&gt;
  
  
  Let's add some video
&lt;/h2&gt;

&lt;p&gt;As part of #100DaysOfGatsby I'm adding capabilities to my new Gatsby/Sanity blog. Today I'm going to add the ability to add embedded YouTube video to a Portable Text block. It would be easy enough to create a video field that could hold the YouTube ID and parameters and then use that on the page, but this would limit flexability as it would need to be put on the page at the same place or need complex formatting rules. However, if we can add a video embed as part of our main Portable Text block, then we can put a video wherever we like in the body of the blog post.&lt;/p&gt;

&lt;p&gt;I'd like to give a big shout out to Knut &lt;a class="comment-mentioned-user" href="https://dev.to/kmelve"&gt;@kmelve&lt;/a&gt;
 who's writings and videos seem to be my main source of learning and inspirtation. For this feature, I leaned hevily on this guide &lt;a href="https://www.sanity.io/guides/portable-text-how-to-add-a-custom-youtube-embed-block"&gt;https://www.sanity.io/guides/portable-text-how-to-add-a-custom-youtube-embed-block&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Extend our Sanity Studio code to have a youtube embed
&lt;/h3&gt;

&lt;p&gt;We will define a new object by creating a new schema file called /studio/schemas/objects/youtube.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// youtube.js
export default {
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  fields: [
    {
      name: 'url',
      type: 'url',
      title: 'YouTube video URL'
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next we will need to add a reference to this new object in our main schema object /studio/schemas/schema.js so that we can reference this type elsewere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import createSchema from 'part:@sanity/base/schema-creator'
import schemaTypes from 'all:part:@sanity/base/schema-type'
import author from './documents/author'
import category from './documents/category'
import post from './documents/post'
import siteSettings from './documents/siteSettings'
import bodyPortableText from './objects/bodyPortableText'
import bioPortableText from './objects/bioPortableText'
import excerptPortableText from './objects/excerptPortableText'
import mainImage from './objects/mainImage'
import authorReference from './objects/authorReference'
import youtube from './objects/youtube'

export default createSchema({
  name: 'blog',
  types: schemaTypes.concat([
    siteSettings,
    post,
    category,
    author,
    mainImage,
    authorReference,
    bodyPortableText,
    bioPortableText,
    excerptPortableText,
    youtube
  ])
})

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



&lt;p&gt;Now that we have defined the type in the schemas we can reference it in other schemas. Let's add this to our the main body portable text object which is at /studio/schemas/objects/bodyPortableText.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  name: 'bodyPortableText',
  type: 'array',
  title: 'Post body',
  of: [
    {
      type: 'block',
      title: 'Block',
      // Styles let you set what your user can mark up blocks with. These
      // corrensponds with HTML tags, but you can set any title or value
      // you want and decide how you want to deal with it where you want to
      // use your content.
      styles: [
        { title: 'Normal', value: 'normal' },
        { title: 'H1', value: 'h1' },
        { title: 'H2', value: 'h2' },
        { title: 'H3', value: 'h3' },
        { title: 'H4', value: 'h4' },
        { title: 'Quote', value: 'blockquote' }
      ],
      lists: [
        { title: 'Bullet', value: 'bullet' },
        { title: 'Number', value: 'number' }
      ],
      // Marks let you mark up inline text in the block editor.
      marks: {
        // Decorators usually describe a single property – e.g. a typographic
        // preference or highlighting by editors.
        decorators: [
          { title: 'Strong', value: 'strong' },
          { title: 'Emphasis', value: 'em' },
          { title: 'Underline', value: 'underline' },
          { title: 'Strike', value: 'strike-through' },
          { title: 'Code', value: 'code' }
        ],
        // Annotations can be any object structure – e.g. a link or a footnote.
        annotations: [
          {
            name: 'link',
            type: 'object',
            title: 'URL',
            fields: [
              {
                title: 'URL',
                name: 'href',
                type: 'url'
              }
            ]
          }
        ]
      },
      of: [{ type: 'authorReference' }]
    },
    // You can add additional types here. Note that you can't use
    // primitive types such as 'string' and 'number' in the same array
    // as a block type.
    {
      type: 'mainImage',
      options: { hotspot: true }
    },
    {
      type: 'code',
      title: 'Code block',
      options: { theme: 'github' }
    },
    {
      type: 'youtube'
    }
  ]
}

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



&lt;p&gt;Now we have the ability to embed a video. But it's not very friendly to the content editor as they don't see a preview of the video in the Studio. There's also some nice things we can do to extract the YouTube ID from the URL to make things a little cleaner. Lastly - we should add an ALT descriptor for accessibility.&lt;/p&gt;

&lt;p&gt;This is where we can see the true power behind having the Studio as a react app - we can add react components to extend it to our needs. In this case we are going to install &lt;code&gt;react-youtube&lt;/code&gt; and &lt;code&gt;get-youtube-id&lt;/code&gt;. The &lt;code&gt;react-youtube&lt;/code&gt; componet will display the component in the Studio for us using Sanity's preview method. (I won't get into the details of preview as that's more than I want to take on right now, but know that it can be quite powerful)&lt;/p&gt;

&lt;p&gt;Change to the /studio folder then install these components&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-youtube get-youtube-id
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's update our youtube.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import getYouTubeId from 'get-youtube-id'
import YouTube from 'react-youtube'

const Preview = ({value}) =&amp;gt; {
    const { url } = value
    const id = getYouTubeId(url)
    return (&amp;lt;YouTube videoId={id} /&amp;gt;)
}

export default {
  name: 'youtube',
  type: 'object',
  title: 'YouTube Embed',
  fields: [
    {
      name: 'url',
      type: 'url',
      title: 'YouTube video URL'
    },
    {
      name: 'alt',
      type: 'string',
      title: 'Alternative text',
      description: 'Important for SEO and accessiblity.',
      validation: Rule =&amp;gt; Rule.error('You have to fill out the alternative text.').required()
    }
  ],
  preview: {
    select: {
      url: 'url'
    },
    component: Preview
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we have the ability to embed a youtube video into the body block, and see the video previewed there. Here's a screenshot to show you the Block Editor in the Studio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5nEtUFhO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/5c1f0e25c5e01af21c0fe63b6fe3c29c6106e678-1089x794.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5nEtUFhO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/5c1f0e25c5e01af21c0fe63b6fe3c29c6106e678-1089x794.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Update our Gatsby front end code to be able to use the youtube embed
&lt;/h3&gt;

&lt;p&gt;To render the custom blocks in our portable text, we need to have Sanity's Portable Text Serializer package called @sanity/block-content-to-react installed. Since this part of the blog starter we started with, we already have this, so we are good to go. (I mention this in case someone is following along and is having trouble).&lt;/p&gt;

&lt;p&gt;We also will need the same react components we used in the studio. Change to the /web directory and install these&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-youtube get-youtube-id
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we will need to update the gatsby portable text component to add the serializers for this new type. In our case, that is the file /web/src/components/serializers.js. We will add imports for the two youtube helper components, then define how the youtube type should be handled by the serializer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import Figure from './Figure'
import Code from './Code'
import getYouTubeId from 'get-youtube-id'
import YouTube from 'react-youtube'

const serializers = {
  types: {
    authorReference: ({node}) =&amp;gt; &amp;lt;span&amp;gt;{node.author.name}&amp;lt;/span&amp;gt;,
    mainImage: Figure,
    code: Code,
    youtube: ({node}) =&amp;gt; {
      const { url } = node
      const id = getYouTubeId(url)
      return (&amp;lt;YouTube videoId={id} /&amp;gt;)
    }
  }
}

export default serializers

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



&lt;p&gt;Now our gatsby code knows how to handle the youtube type and we will see an embedded video.&lt;/p&gt;

&lt;p&gt;Here's an embedded video to show it in action!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/2ceM_tSus_M"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;a href="https://youtu.be/2ceM_tSus_M"&gt;Link to video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all for today. See you next time&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adding code blocks to Sanity.io Studio to improve blog</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Tue, 14 Jan 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/adding-code-blocks-to-sanity-io-studio-to-improve-blog-14p5</link>
      <guid>https://dev.to/codelobaugh/adding-code-blocks-to-sanity-io-studio-to-improve-blog-14p5</guid>
      <description>&lt;h2&gt;
  
  
  Adding code blocks to the blog
&lt;/h2&gt;

&lt;p&gt;Today, as part of my #100DaysOfGatsby personal challenge, I'm going to enhance the portable text editor Sanity provides us in the starter blog. I especially want to add support for code blocks, which are a critical thing to have on a dev blog. Once I have the studio updated I will upgrade my Gatsby code to support it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the studio
&lt;/h3&gt;

&lt;p&gt;Let's start with the Studio. In the code Sanity provides as part of its blog starter, there is a different portable text setup for different sections. One for the body, one for the excerpt and one for the author bio. This is good strategy as you don't necessarily want a full editing block for the excerpt, where you do for the body of the blog. I'm fine with the limited set in the bio and excerpt, but I want to have about everything possible for the blog body, so that is where I'm going to focus.&lt;/p&gt;

&lt;p&gt;Out of the box, I have Normal, H1 - H4, and quote for text styles. There are also Emphasis, Strong, bullet list, numbered list, html link, image and author reference. Here's what that looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6z9hGLC5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/77be3b1e65b3dfb07a3744d7a3c4ac57789b820e-889x143.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6z9hGLC5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/77be3b1e65b3dfb07a3744d7a3c4ac57789b820e-889x143.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sanity offers more annotations out of the box, however (code, underline and strike-through), so I'm going to add those immediately.&lt;/p&gt;

&lt;p&gt;In my project under studio/schemas/objects there is a file called "bodyPortableTest.js". That's the one we need to edit.&lt;/p&gt;

&lt;p&gt;Inside this file you will quickly see all the types listed broken out into sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;styles for text styles (H1, Quote, etc.)&lt;/li&gt;
&lt;li&gt;lists for the lists (unordered lists, numbered list)&lt;/li&gt;
&lt;li&gt;marks for other non-object things (decorators like strong, emphasis, underline, etc., annotations like link.)&lt;/li&gt;
&lt;li&gt;Lastly you can add custom objects to the end, which is where the image object is. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am going to add some new decorations that are built in. The current decorations are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decorators: [{title:'Strong', value:'strong'}, {title:'Emphasis', value:'em'}],
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I will change this to add the other built in decorators so that this section will now look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decorators: [
  {title: 'Strong', value: 'strong'}, 
  {title: 'Emphasis', value: 'em'},
  {title: "Code", value: "code" },
  {title: "Underline", value: "underline" },
  {title: "Strike", value: "strike-through" }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I have the following options:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---Hi_zL6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/6248c7cbef3d24281447b82070b5ba821e6dfdaa-979x145.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---Hi_zL6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/6248c7cbef3d24281447b82070b5ba821e6dfdaa-979x145.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an improvement, but we are still not there. Specifically with the code block. The out of the box option will change the text to a monospace font and add a different background color, which is an improvement. But it is not good for larger code blocks and does not have some of the extra nice features like a copy link, language display, and highlighting. Sanity has a plug-in built to use with their own docs, and give us the ability to use that as well, so I'm going to install it.&lt;/p&gt;

&lt;p&gt;Start by installing the needed plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sanity install @sanity/code-input
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'm going to leave the current code decorator as it might be useful but if you want to remove it, simply remove it from the decorator list we just used. It will now be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decorators: [
  {title: 'Strong', value: 'strong'}, 
  {title: 'Emphasis', value: 'em'},
  {title: "Underline", value: "underline" },
  {title: "Strike", value: "strike-through" }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I need to add the code object, which will make the code block show up in the "insert" list. To do this, add the following after the mainImage block near the bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  type: 'code'
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now stop and restart the studio&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sanity start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now you should see your code block option under insert:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AnQR7zYF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/66a5144590f73c7b4253bd0b0f7190ed17d132da-870x57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AnQR7zYF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/66a5144590f73c7b4253bd0b0f7190ed17d132da-870x57.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and be able to have a nice code editor plugin&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rd35Of1l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/65643113937fb676b616b31ffd9c13c2b3320a1e-1147x657.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rd35Of1l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/65643113937fb676b616b31ffd9c13c2b3320a1e-1147x657.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which will display nicely in your Studio&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8dPPyzmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/b92a1c232b43509785bc9a2608bae36a3e40b16a-964x230.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8dPPyzmk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/b92a1c232b43509785bc9a2608bae36a3e40b16a-964x230.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Upgrade Gatsby
&lt;/h3&gt;

&lt;p&gt;The downside to adding a new portable text type, is that our frontend doesn't know how to deal with it and so we have broken the front end build. Let's go update our Gatsby code to teach it to understand this type and to know how to display it properly.&lt;/p&gt;

&lt;p&gt;The Gatsby code is in the web folder, and the component that handles portable text is under the web/src/components folder and is predictably called portableText.js (You can look at the blogPost.js component to figure this out as well, just in case it is not completely obvious).&lt;/p&gt;

&lt;p&gt;When you look at the portableText.js, you see there is not much happening. It's basically pulling in the config info from your Sanity config, and the sanity code from sanity to handle the block content, and calling a third component called "serializers" - this is the file we want.&lt;/p&gt;

&lt;p&gt;The serializers.js file is where you define how the sanity block content handlers treat different blocks. The main thing you need to put here is how to handle any custom object you add. If you look at this one you will see there is already a &lt;strong&gt;mainImage&lt;/strong&gt; and an &lt;strong&gt;authorReference&lt;/strong&gt; defined (these are the 2 objects that are insertable in your sanity body block. To make my code block work, I need to add it here. I'm going to separate the code out to another component called code.js, so all I need to do here is add an import for ./code.js at the top of the file and then add a reference to the code block. Here is the resulting serializers.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import Figure from './Figure'
import Code from './Code'

const serializers = {
  types: {
    authorReference: ({node}) =&amp;gt; &amp;lt;span&amp;gt;{node.author.name}&amp;lt;/span&amp;gt;,
    mainImage: Figure,
    code: Code
  }
}

export default serializers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the new code.js component, I need to handle the output of the code block. I know from looking at the docs that the code plugin object has a language and a code prop, so that is what I will use to create my output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

export default ({ node }) =&amp;gt; {
  if (!node || !node.code) {
    return null;
  }
  const { language, code } = node;
  return (
    &amp;lt;div&amp;gt;
      language = {language}
      &amp;lt;pre&amp;gt;
        {code}
      &amp;lt;/pre&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

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



&lt;p&gt;Now my code is displayed a little nicer. But it's still not great. There is no syntax highlighting or much style at all. Fortunately, we are using react and there are a ton of react components that do exactly this. I choose react-syntax-highlighter because Knut did in his video where he walks through doing exactly what I'm doing here, and also because it was the first result in a google search. I may go back and research different options and choose something else later, but this works well for now. (If you want to see a quick video version of what I'm doing in this blog post I recommend &lt;a href="https://www.youtube.com/watch?v=asENbq3s1m8&amp;amp;feature=youtu.be"&gt;Knut's video on YouTube&lt;/a&gt; - it goes fast but is very close to what I'm doing here, and was where I learned most of what I know of this topic.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-syntax-highlighter"&gt;React-syntax-highlighter&lt;/a&gt; is the package I need. Change to the /web directory and install it with npm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install react-syntax-highlighter --save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then edit the serialzers.js to look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import SyntaxHighlighter from 'react-syntax-highlighter';

export default ({node}) =&amp;gt; {
  if (!node || !node.code) { return null }
  const {language, code} = node 
  return (
    &amp;lt;SyntaxHighlighter language={language || 'text'}&amp;gt;
      {code}
    &amp;lt;/SyntaxHighlighter&amp;gt;
  )
}

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



&lt;p&gt;You can read the docs on the component if you want to see all the options it has available and to make this look exactly to your taste. For me, this is perfect for now.&lt;/p&gt;

&lt;p&gt;The end result is nice looking code blocks (that you see in action on this page already)&lt;/p&gt;

&lt;p&gt;I think that is where I will stop. I'll likely revisit this in the future to add things like a copy button, code type, etc. but I want to move on to other things for now. I may want to choose a different component for that as well, and that will take some research.&lt;/p&gt;

&lt;p&gt;Next time I will plan to further extend the portable text by adding a video embed, and to improve on the image and the url abilities.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Improving the content editor for my basic Gatsby blog</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Fri, 10 Jan 2020 05:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/improving-the-content-editor-for-my-basic-gatsby-blog-17oo</link>
      <guid>https://dev.to/codelobaugh/improving-the-content-editor-for-my-basic-gatsby-blog-17oo</guid>
      <description>&lt;h2&gt;
  
  
  Creating a Gatsby Blog - upgrading setup
&lt;/h2&gt;

&lt;p&gt;Now that we have a blog, let's upgrade the Sanity Studio to give us more power and a better writing experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Download the repository and test
&lt;/h3&gt;

&lt;p&gt;Sanity’s starter gives you a mono repo that contains the gatsby site and the Sanity studio together. The gatsby site is under the web directory and the studio is h set the studio directory. When you run npm run dev from the root of the project it will run both in dev mode which includes hot reloading. This lets you edit the gatsby site and the studio and see them working together.&lt;/p&gt;

&lt;p&gt;Let's start by downloading the code. Do a git clone of our repository to our local dev environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone repository

cd respoitory

npm install

npm run dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;you should now be able to open 2 local browsers and see your web site at localhost:8000 and your studio at localhost:3333. Both have hot reloading so as you make changes to either, you will see those changes immediately in the browser.&lt;/p&gt;

&lt;p&gt;Once you have verified the site is running, Ctrl + C to stop the dev, so we can do some work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Upgrade Sanity
&lt;/h3&gt;

&lt;p&gt;We want to update the base Sanity code to make sure we are starting with the latest and greatest. To do this, we will change to the studio directory and then use the Sanity CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd studio

sanity upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 - Remove the side bar
&lt;/h3&gt;

&lt;p&gt;The side bar to the right of the studio is quite nice when you are new to Sanity, but at some point you will likely want to remove it. Fortunately, there is a link on the bar to take you to instructions on how to do that (&lt;a href="https://www.sanity.io/docs/remove-this-sidebar"&gt;https://www.sanity.io/docs/remove-this-sidebar&lt;/a&gt;). It's a simple change to the sanity config. (Note: My instructions differ slightly from the page above at this point as their instructions are currently incomplete. I've let them know and I expect they will correct this soon)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the sanity.json file located at the root of your studio folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Locate the parts array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the following object from the &lt;strong&gt;parts&lt;/strong&gt; section (remember to delete any trailing commas as well):&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "implements": "part:@sanity/default-layout/studio-hints-config",
  "path": "studioHintsConfig.js" 
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Delete the following from the &lt;strong&gt;plugins&lt;/strong&gt; section (remember to delete any trailing commas as well):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"@sanity/studio-hints"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the sanity.json file, then quit and restart the studio server with sanity start&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4 - Turbo charge the studio
&lt;/h3&gt;

&lt;p&gt;This is where the fun starts. Sanity’s studio is pretty nice out of the box, but we can add some really nice things to make it really special. I'm going to break these changes down over several posts but here is a quick list of what I'm looking at:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upgrade the block portable text options

&lt;ol&gt;
&lt;li&gt;Add better inline image than the one that comes with&lt;/li&gt;
&lt;li&gt;improve the URL to toggle external link or not&lt;/li&gt;
&lt;li&gt;add video embed&lt;/li&gt;
&lt;li&gt;add code block&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Split pane&lt;/li&gt;
&lt;li&gt;Additional view options

&lt;ol&gt;
&lt;li&gt;web preview&lt;/li&gt;
&lt;li&gt;seo/social preview&lt;/li&gt;
&lt;li&gt;accessibility preview&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;media helper&lt;/li&gt;
&lt;li&gt;seo auditing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first thing I'm going to tackle is a need I have for this specific post - support for code blocks inside the portable text editor. It's so much nicer to write and read code that is formatted well. I've not done this with Sanity yet, so hopefully this goes smoothly. I'll detail how this goes in my next post. If you are reading this post before I implement the code block, then forgive the poor formatting of my command line and code examples.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick take - Easy CMS editing from a phone?  No problem with Sanity</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Thu, 09 Jan 2020 05:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/quick-take-easy-cms-editing-from-a-phone-no-problem-with-sanity-2027</link>
      <guid>https://dev.to/codelobaugh/quick-take-easy-cms-editing-from-a-phone-no-problem-with-sanity-2027</guid>
      <description>&lt;h2&gt;
  
  
  Sanity studio is great at editing from your phone!
&lt;/h2&gt;

&lt;p&gt;I've only tried using a CMS from my phone once before and it was pretty miserable. I decided to try again today with Sanity as I was away from my laptop and wanting to edit. My original thought was to just use a markdown editor and then copy the content over later. Then it occurred to me that I might be able to use the Studio directly. Worked like a charm. Responsive layout of Studio made it easy to navigate and I didn't find myself frustrated or missing any functionality from the desktop version.&lt;/p&gt;

&lt;p&gt;And I'm not just talking about writing/editing a post. I was able to trigger my netlify build as well to update my Gatsby site.&lt;/p&gt;

&lt;p&gt;Maybe other CMSs have figured this out too, and everyone will give a collective yawn. Or maybe this is pretty slick.&lt;/p&gt;

&lt;p&gt;Which makes me ask - what is the proper way to write the plural version of CMS?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating a crazy fast blog, crazy fast using Gatsbyjs &amp; Sanity.io</title>
      <dc:creator>Christian Lobaugh</dc:creator>
      <pubDate>Tue, 07 Jan 2020 05:00:00 +0000</pubDate>
      <link>https://dev.to/codelobaugh/creating-a-crazy-fast-blog-crazy-fast-using-gatsbyjs-sanity-io-4gi8</link>
      <guid>https://dev.to/codelobaugh/creating-a-crazy-fast-blog-crazy-fast-using-gatsbyjs-sanity-io-4gi8</guid>
      <description>&lt;h1&gt;
  
  
  Creating a blog using Gatsbyjs &amp;amp; Sanity.io
&lt;/h1&gt;

&lt;h2&gt;
  
  
  #100daysofgatsby assignment 1 - Create a blog
&lt;/h2&gt;

&lt;p&gt;As part of #100daysofgatsby I’m creating a Gatsby blog. But since I’ve been using Gatsby a few months I’m going to go a little beyond the basics by using &lt;a href="http://sanity.io/"&gt;Sanity.io&lt;/a&gt; as the data source and then adding some really cool features to the Sanity Studio (Sanity’s content editor)&lt;/p&gt;

&lt;p&gt;Today I plan to take the first step which is to create the basic starter for Gatsby and Sanity. Sanity makes this crazy easy.&lt;/p&gt;

&lt;p&gt;Sanity has a great feature they’ve added recently called create. You pick from a few standard templates and then give Sanity your login and connect Sanity to your GitHub account and Netlfiy account and Sanity will scaffold the entire template out for you and even deploy it. At that point you can manage your blog via the Studio and never even touch any code! But that’s no fun -we are here to learn and play. Today we create the foundation and then tomorrow we will grab the code repository to change our content editor (Sanity calls this the Studio). I'll walk you through this step:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Create a basic blog using Sanity Create
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;a href="https://sanity.io/create"&gt;https://sanity.io/create&lt;/a&gt; in a browser.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ubUBbSL_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/b47672596cca198b99d2f8e5a13722f1b52efd67-935x833.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;You will be shown several options. You want the “Blog with Gatsby” project.&lt;/li&gt;
&lt;li&gt;Click “Start Project”&lt;/li&gt;
&lt;li&gt;You will now be asked to Sign In to Sanity, GitHub, and Netlify. If you don’t have accounts, then it will create them for you. The easiest way is to create a GitHub account first, and then you can use that account to Log in to both Sanity and Netlify.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hhaadOgY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/27762363263e4193200a3a1916f7682c3659f169-734x353.png" alt=""&gt; &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zq1IxggP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/1741bbd6399200ec9ada56bf3c6ca79bb186b8ce-725x326.png" alt=""&gt; &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CRadlIfk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.sanity.io/images/ugwlwrf9/production/dfa2f094e44eabc8ade840d49fea94b9c61a27f5-727x292.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;Once you’ve Logged In, you will be asked to name your project. It defaults to “Blog with Gatsby”, but let’s personalize it a bit - I call mine Christian Lobaugh. Note: The project name will determine the Netlify site name, which is why I chose the name I did.&lt;/li&gt;
&lt;li&gt;Next you will need to name the repository for git-hub. I suggest something descriptive and the default name is pretty good - “sanity-gatsby-blog”.&lt;/li&gt;
&lt;li&gt;Once you have connected to all 3 services and named your project and repository you click the “Create Project” button at the bottom of the page.&lt;/li&gt;
&lt;li&gt;You will now see Sanity start creating and deploying the different pieces of the site for you. It will tell you the progress and give you the Netlify links for your studio and blog page, as well as to your GitHub repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congrats - you now have a blog. If you log in to the studio you can update all the content and add new blog entries. If you didn’t already know, you need to redeploy the web site any time you make any content changes. There is a handy link on the Dashboard of the Studio to help you do that without needing to go to Netlify.&lt;/p&gt;

&lt;p&gt;The next step for me will be to work on updating the Studio to add some nice features to help create an awesome editing experience. I’ll save that for the my next post.&lt;/p&gt;

&lt;p&gt;Here's a list of things I plan to look at adding to the blog at this point (no promises, and in no specific order. Just things that look promising off the top of my head)&lt;/p&gt;

&lt;h4&gt;
  
  
  Sanity Studio
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Split preview&lt;/li&gt;
&lt;li&gt;Live preview (connected to local dev and/or Gatsby Preview) &lt;/li&gt;
&lt;li&gt;SEO preview&lt;/li&gt;
&lt;li&gt;Accessibility preview&lt;/li&gt;
&lt;li&gt;Media browser&lt;/li&gt;
&lt;li&gt;Expand Block Text schema to support inline images and external links&lt;/li&gt;
&lt;li&gt;SEO analysis&lt;/li&gt;
&lt;li&gt;Add custom colors and logo to studio&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Gatsby
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Gatsby Cloud preview&lt;/li&gt;
&lt;li&gt;Social Sharing&lt;/li&gt;
&lt;li&gt;Add TailwindCss and Emotion for CSS styling&lt;/li&gt;
&lt;li&gt;Add sidebar menu&lt;/li&gt;
&lt;li&gt;Add view by category (and/or tag)&lt;/li&gt;
&lt;li&gt;Add sitemap&lt;/li&gt;
&lt;li&gt;Add testing with Jest or similar&lt;/li&gt;
&lt;li&gt;Search using Algolia &lt;/li&gt;
&lt;li&gt;Google Analytics&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
