<?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: Kendall Strautman</title>
    <description>The latest articles on DEV Community by Kendall Strautman (@kendallstrautman).</description>
    <link>https://dev.to/kendallstrautman</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%2F205907%2F125cf86c-19ad-44d6-a4c0-d70eb95b32f4.jpg</url>
      <title>DEV Community: Kendall Strautman</title>
      <link>https://dev.to/kendallstrautman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kendallstrautman"/>
    <language>en</language>
    <item>
      <title>Index Signatures in Typescript</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Wed, 25 Nov 2020 01:21:24 +0000</pubDate>
      <link>https://dev.to/kendallstrautman/typescript-index-signatures-2c70</link>
      <guid>https://dev.to/kendallstrautman/typescript-index-signatures-2c70</guid>
      <description>&lt;p&gt;This is a pattern I've found incredibly helpful of late. Let's say you have a collection of fruit in a basket. You may make a type for all the possible fruits. 🍐🍍🍈🥭🍒🥝🍇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Fruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pomegranate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;persimmon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jackfruit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say the basket is represented by an object literal, consisting of key-value pairs, the key being the fruit id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruitBasket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jackfruit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pomegranate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every fruit basket will be different, and random to a degree. They will all contain different amounts of fruit, although we expect the baskets to contain only the fruits outlined in the &lt;code&gt;Fruit&lt;/code&gt; type. To create an interface for the fruit basket, we need to use an index signature in the interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Fruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pomegranate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pear&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;persimmon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guava&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jackfruit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FruitBasket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;Fruit&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruitBasket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FruitBasket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the fruit basket can have an innumerable amount of fruit items, the keys can all be unique numbers or ids and the fruit will be safely typed. &lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;I find this pattern helpful when needing to type objects or  components where they may have a prop or key-value pair  where I don't know the key ahead of time. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could take this a step further, say I don't know exactly what kind of fruit is acceptable, or perhaps there are different iterations of fruit baskets, one for fall, spring, and winter fruits. We can adjust the fruit basket interface to accept a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ClassicFruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;banana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strawberry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TropicalFruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pineapple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mango&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;papaya&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lychee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FruitBasket&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classicBasket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FruitBasket&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ClassicFruit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tropicalBasket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FruitBasket&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TropicalFruit&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, we could swap out the specifics of the fruit, depending on the type of basket.&lt;/p&gt;

&lt;p&gt;Dive deeper into this in the &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types-and-index-signatures"&gt;TS documentation&lt;/a&gt;! Happy coding 🤖&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Custom Field Plugins in TinaCMS</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Mon, 17 Feb 2020 19:51:30 +0000</pubDate>
      <link>https://dev.to/tinacms/custom-field-plugins-in-tinacms-2578</link>
      <guid>https://dev.to/tinacms/custom-field-plugins-in-tinacms-2578</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/tinacms/tinacms-how-to-make-a-custom-field-component-5gab"&gt;previous post&lt;/a&gt;, we learned how to create a custom field component and register it to the sidebar. With that baseline, let's go full circle on the topic of custom fields in TinaCMS. In this short but sweet post 🧁, we’ll cover how to &lt;em&gt;turn a field component into a field plugin.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Field Plugin vs. Field Component
&lt;/h2&gt;

&lt;p&gt;Plugins &lt;strong&gt;extend functionality in the CMS&lt;/strong&gt;; field plugins allow us to create and register custom fields. &lt;em&gt;There are a few reasons why you may want to create a field plugin.&lt;/em&gt; With a custom field, you can completely control the editing experience and functionality. If the primary fields provided by Tina don't fit your use case, &lt;strong&gt;you can fill the gaps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A field component is just one piece of a field plugin (&lt;a href="https://tinacms.org/blog/custom-field-plugins#field-plugin-interface"&gt;more on this later&lt;/a&gt;). A custom field component can achieve the same functionality as a plugin. But if you plan on reusing the custom field on different forms, it is recommended to take the extra steps to make a plugin 🔌.&lt;/p&gt;

&lt;p&gt;Creating field plugins helps confine complex logic to a single module. This makes it easier to update or swap out custom field functionality later down the line. Using &lt;strong&gt;the plugin API makes our 'higher-level' code more reusable&lt;/strong&gt; and contained, keeping the fields independent from the core CMS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For those who want to dig deeper, this approach seeks to embody the &lt;a href="https://stackify.com/dependency-inversion-principle/"&gt;Dependency Inversion Principle&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting Started 👏
&lt;/h2&gt;

&lt;p&gt;To follow along, you should have a custom field component set-up with a Tina form. If not, you can get some more context from the previous post: &lt;a href="https://tinacms.org/blog/custom-field-components"&gt;how to create a custom field component&lt;/a&gt;. In the following examples, I am using the same &lt;a href="https://github.com/kendallstrautman/llama-filters"&gt;llama-filters&lt;/a&gt; 🦙 demo from our previous post.&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;two steps to adding a field plugin to the CMS&lt;/strong&gt;. First, we'll define the field component object and register it with the CMS. Next, we'll use the field plugin in a form definition so we can edit content in the sidebar with our fancy custom field plugin.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to see a &lt;em&gt;working example&lt;/em&gt;? Check out the &lt;a href="https://github.com/tinacms/tina-starter-grande/blob/master/src/fields/authors.js"&gt;Authors Field Plugin&lt;/a&gt; from the Tina Grande Starter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1. Add the Field Plugin to the CMS
&lt;/h3&gt;

&lt;p&gt;To register the custom field as a plugin with the CMS, we’ll need to head to the file where we can access the CMS instance. In the Next.js &lt;a href="https://github.com/kendallstrautman/llama-filters/blob/master/pages/_app.js"&gt;demo&lt;/a&gt;, we’ll look at &lt;code&gt;_app.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// _app.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tina&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TinaCMS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tinacms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GitClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tinacms/git-client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="cm"&gt;/*
 ** 1. Import the custom field component
 */&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/RangeInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="cm"&gt;/*
 ** 2. Define the field plugin
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customFieldPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;range-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Site&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TinaCMS&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;GitClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/___tina&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;overlay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="cm"&gt;/*
     ** 3. Register the plugin with the cms
     */&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customFieldPlugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll want to import the custom field component and then register the plugin with the CMS directly. Notice how we import the &lt;code&gt;RangeInput&lt;/code&gt; component created in the &lt;a href="https://tinacms.org/blog/custom-field-components"&gt;previous post&lt;/a&gt;. This is the custom &lt;em&gt;field component&lt;/em&gt; that we're now attaching to a &lt;em&gt;field plugin&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re working with Gatsby, this &lt;a href="https://tinacms.org/docs/gatsby/custom-fields/"&gt;looks slightly different&lt;/a&gt;. &lt;em&gt;Hint&lt;/em&gt;: you’ll head to the &lt;strong&gt;gatsby-browser.js&lt;/strong&gt; file to access the CMS instance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Field Plugin Interface
&lt;/h4&gt;

&lt;p&gt;Let's break down the field plugin further. The interface below should provide some insight into all that can go into creating a field plugin. When you register a field plugin with Tina, it expects an object with a similar shape.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FieldPlugin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;?(&lt;/span&gt;
    &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;allValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
  &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
  &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
  &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At a minimum, field plugins &lt;strong&gt;require a name and a component.&lt;/strong&gt; The &lt;code&gt;name&lt;/code&gt; is used to reference the custom field in form definitions (&lt;a href="https://tinacms.org/blog/custom-field-plugins#2-use-the-custom-field-in-a-form"&gt;more on this later&lt;/a&gt;). The &lt;code&gt;Component&lt;/code&gt; is what is actually rendered in the sidebar.&lt;/p&gt;

&lt;p&gt;You can see that there are additional configuration functions and options. &lt;em&gt;Note that the properties with a question mark are optional.&lt;/em&gt; These options are incredibly useful for creating fields that require &lt;em&gt;&lt;a href="https://tinacms.org/docs/fields/custom-fields#validate-optional"&gt;validation&lt;/a&gt;, parsing, or formatting&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To see a more &lt;strong&gt;complex example&lt;/strong&gt;, checkout the documentation on creating an &lt;a href="https://tinacms.org/docs/gatsby/custom-fields/"&gt;email field&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Use the custom field in a form
&lt;/h3&gt;

&lt;p&gt;Now that the plugin is registered with the CMS, we can use it in any form definition. Going back to the &lt;a href="https://github.com/kendallstrautman/llama-filters"&gt;llama-filters demo&lt;/a&gt;, let’s head to &lt;code&gt;index.js&lt;/code&gt; where the Tina form is configured. We need to &lt;strong&gt;update the form options&lt;/strong&gt; for our image saturation field to reference the field plugin &lt;code&gt;name&lt;/code&gt;, as opposed to calling the component directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;/*&lt;/span&gt;
** 1. Remove the import of the custom field component
&lt;span class="err"&gt;*/&lt;/span&gt;
- import RangeInput from '../components/RangeInput'
&lt;span class="p"&gt;import React from 'react'
import { useLocalJsonForm } from 'next-tinacms-json'
&lt;/span&gt;
export default function Index(props) {
  //...
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;const formOptions = {
&lt;/span&gt; fields: [
   /*
   ** 2. Reference the field plugin `name` instead
   **    of passing the custom component directly
   */
   {
     label: 'Image Saturation',
     name: 'saturation',
&lt;span class="gd"&gt;-    component: RangeInput
&lt;/span&gt;&lt;span class="gi"&gt;+    component: 'range-input'
&lt;/span&gt;   }
 ]
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="gh"&gt;Index.getInitialProps = async function() {
&lt;/span&gt;  //...
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt; With the plugin defined and registered with the CMS, you can reuse this field &lt;em&gt;ad infinitum&lt;/em&gt;. In my opinion, creating a field plugin helps maintain a consistent interface for defining forms. This way, the custom field works &lt;em&gt;behind the scenes&lt;/em&gt; as if it were a native Tina field, which is pretty slick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short and sweet, as promised 🍰
&lt;/h2&gt;

&lt;p&gt;This post, combined with the former, should give you all the building blocks to start making your own field plugins. Feel free to &lt;em&gt;dive into the documentation&lt;/em&gt; on &lt;a href="https://tinacms.org/docs/fields/custom-fields/"&gt;fields&lt;/a&gt; or &lt;a href="https://tinacms.org/docs/concepts/plugins"&gt;plugins&lt;/a&gt;. Make sure to &lt;strong&gt;share your groovy custom fields with us &lt;a href="https://twitter.com/tina_cms"&gt;@tina_cms&lt;/a&gt;&lt;/strong&gt; 🖖. Or, if you feel there is a fundamental field missing from Tina, &lt;a href="https://github.com/tinacms/tinacms/"&gt;open up a PR&lt;/a&gt; to contribute your custom field!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Make a Custom Field Component with TinaCMS</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Wed, 22 Jan 2020 00:03:37 +0000</pubDate>
      <link>https://dev.to/tinacms/tinacms-how-to-make-a-custom-field-component-5gab</link>
      <guid>https://dev.to/tinacms/tinacms-how-to-make-a-custom-field-component-5gab</guid>
      <description>&lt;p&gt;Form fields are the bread and butter of any CMS. While Tina provides a solid collection of fields 'out-of-the-box', you can also create your own. This post will show you the basic concepts of how to create custom field components and use them in the Tina sidebar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites 👩‍🏫&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Throughout the post, I'll refer to a few core TinaCMS concepts such as &lt;a href="https://tinacms.org/docs/concepts/forms"&gt;forms&lt;/a&gt;, the &lt;a href="https://tinacms.org/docs/concepts/sidebar"&gt;sidebar&lt;/a&gt;, and &lt;a href="https://tinacms.org/docs/concepts/fields"&gt;fields&lt;/a&gt;. It will be helpful to have some basic working knowledge of &lt;a href="https://tinacms.org/docs/getting-started/how-tina-works"&gt;&lt;strong&gt;how TinaCMS works&lt;/strong&gt;&lt;/a&gt; before reading. Feel free to refer to the &lt;a href="https://tinacms.org/docs/getting-started/introduction"&gt;documentation&lt;/a&gt; or read a post on using Tina with &lt;a href="https://www.gatsbyjs.org/blog/2019-12-20-integrate-tinacms-with-your-gatsby-website/"&gt;Gatsby&lt;/a&gt; or &lt;a href="https://tinacms.org/blog/using-tinacms-with-nextjs/"&gt;Next.js&lt;/a&gt; to get familiar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you create a custom field?
&lt;/h2&gt;

&lt;p&gt;Tina was intended to be fully customizable and extensible. Creating &lt;strong&gt;custom fields can provide precise control&lt;/strong&gt; over the sidebar configuration and styling, along with implementing unique field functionality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jj_6ji8a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/coo26fi3b1byvcx8zvpz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jj_6ji8a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/coo26fi3b1byvcx8zvpz.gif" alt="TinaCMS custom saturate field gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to jump ahead? Feel free to check out a &lt;strong&gt;&lt;a href="https://github.com/kendallstrautman/llama-filters"&gt;finished version&lt;/a&gt; of the custom range input field&lt;/strong&gt; seen in the gif above, or take a peak at a more complex &lt;a href="https://github.com/tinacms/tina-starter-grande/blob/master/src/fields/authors.js"&gt;&lt;em&gt;Authors&lt;/em&gt; field plugin&lt;/a&gt; in the Tina Grande repo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Two Methods — Let’s start simple
&lt;/h2&gt;

&lt;p&gt;There are two ways to add &lt;a href="https://tinacms.org/docs/fields/custom-fields"&gt;custom fields&lt;/a&gt; to Tina. The first approach involves &lt;em&gt;defining a React component and passing it into the &lt;code&gt;component&lt;/code&gt; property&lt;/em&gt; of a field definition. The Tina Team refers to this as an &lt;strong&gt;inline field component.&lt;/strong&gt; This option is more straightforward; it will be the method of focus in this post.&lt;/p&gt;

&lt;p&gt;The second approach involves defining a custom component, then registering that component as a &lt;a href="https://tinacms.org/docs/fields/custom-fields#2-creating-field-plugins"&gt;field plugin&lt;/a&gt; with the CMS. All the &lt;a href="https://tinacms.org/docs/concepts/fields"&gt;core fields&lt;/a&gt; provided by Tina are used as plugins.&lt;/p&gt;

&lt;p&gt;There are some advantages to creating a plugin versus an inline field — the main points being reusability and access to additional functions for parsing, validation etc. But &lt;strong&gt;for simpler cases&lt;/strong&gt;, when you need a custom field in just one form or don’t necessarily need validation, an inline field component will do just fine 👌.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a custom inline field
&lt;/h2&gt;

&lt;p&gt;Say we have a &lt;a href="https://tinacms.org/docs/concepts/forms"&gt;Tina Form&lt;/a&gt; set up for an &lt;em&gt;About Me&lt;/em&gt; page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; The examples below will be referencing a Next.js setup, but this approach can be applied to Gatsby as well.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;About Me Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background_color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Background Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We could add a custom inline field component to further organize the sidebar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Info Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="c1"&gt;// This is our custom inline field 👀&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="nx"&gt;Styles&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h4&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;,
&lt;/span&gt;     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background_color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Background Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Pretty cool huh?&lt;/em&gt; 🤩&lt;/p&gt;

&lt;p&gt;Notice how in all of the other field objects, the &lt;code&gt;component&lt;/code&gt; property is referencing a Tina field plugin, whereas &lt;strong&gt;with our custom inline field, we are passing in a React component.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b2Qk09Jr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e2hxin20x4c7a5o0hha2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b2Qk09Jr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e2hxin20x4c7a5o0hha2.png" alt="Custom Inline Field"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now this example component is super simple — a glorified label. This type of component can be helpful with organizing or customizing the sidebar, but &lt;em&gt;we can go further and pass in more complex fields&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Range Slider 🎨
&lt;/h2&gt;

&lt;p&gt;Say we had an image on the &lt;em&gt;About Me&lt;/em&gt; page and we wanted to be able to control some &lt;a href="https://css-tricks.com/almanac/properties/f/filter/"&gt;CSS filters&lt;/a&gt; on that image. The pen below shows all the CSS filters we have to play with.&lt;/p&gt;



&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/kendallstrautman/embed/WNbzLJZ?height=600&amp;amp;default-tab=css,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We can create a custom input field to provide editing control over these visual filters. &lt;strong&gt;Let’s make a custom field that controls image saturation.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Saturation in photography relates to the &lt;em&gt;intensity of particular colors in an image&lt;/em&gt;. A highly saturated image would be very bright, with colors bordering on neon. An image with low saturation would appear muted and grey.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1. Create the input field component
&lt;/h3&gt;

&lt;p&gt;To create a custom input field, we need to make a &lt;strong&gt;React component that takes input and updates data when the input is altered&lt;/strong&gt;. For this example, we are going to make a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range"&gt;range input field&lt;/a&gt; that handles the state of the saturation value and updates that state whenever the range control is slid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// An example of a custom range field component&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"saturation"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Image Saturation&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"saturation"&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"saturation"&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt;
            &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
            &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;
            &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;".1"&lt;/span&gt;
            &lt;span class="cm"&gt;/*
            ** This special input
            ** object sets essential
            ** input props: value,
            ** onChange, onFocus etc.
            */&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  👽 Take a closer look — Props:
&lt;/h4&gt;

&lt;p&gt;Notice this line, &lt;code&gt;{...props.input}&lt;/code&gt;. You may be wondering where this magical object with all of the necessary input props is coming from?&lt;/p&gt;

&lt;p&gt;When the custom field is registered with Tina, this &lt;strong&gt;input object&lt;/strong&gt; is passed in as a prop to the field. This object contains necessary data and callbacks for the input to function properly: &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#inputvalue"&gt;&lt;code&gt;value&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#inputname"&gt;&lt;code&gt;name&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#inputonchange"&gt;&lt;code&gt;onChange&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#inputonfocus"&gt;&lt;code&gt;onFocus&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#inputonblur"&gt;&lt;code&gt;onBlur&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If your custom component is not a standard &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input"&gt;HTML input element&lt;/a&gt;, you will need to manually pass in the necessary input props, as opposed to using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;spread operator&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;All of the props&lt;/strong&gt; passed to the field component are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;field&lt;/code&gt; — A reference to the &lt;a href="https://tinacms.org/docs/concepts/fields#field-definition"&gt;field definition&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;input&lt;/code&gt; — The object with data and callbacks for the field to set and update data. &lt;em&gt;Outlined above&lt;/em&gt; ☝️.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;meta&lt;/code&gt; — This provides &lt;a href="https://final-form.org/docs/react-final-form/types/FieldRenderProps#metaactive"&gt;metadata&lt;/a&gt; about the state of the field.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tinaForm&lt;/code&gt; — A reference to the form where this field is registerd.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://final-form.org/docs/react-final-form/api/Field#3-connect-the-callbacks-to-your-input"&gt;react-final-form documentation&lt;/a&gt; describes the &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;meta&lt;/code&gt; props incredibly well. When creating custom fields, you'll typically be accessing the &lt;code&gt;field&lt;/code&gt; and &lt;code&gt;input&lt;/code&gt; props.&lt;/p&gt;

&lt;h4&gt;
  
  
  Where should the custom field live?
&lt;/h4&gt;

&lt;p&gt;As we saw in the first example, we can pass in the custom field component directly via the &lt;code&gt;component&lt;/code&gt; property — &lt;code&gt;component: () =&amp;gt; &amp;lt;p&amp;gt;Hi&amp;lt;p&amp;gt;&lt;/code&gt;. But when we are creating more complex fields, we will most likely want to extract the field into its own function.&lt;/p&gt;

&lt;p&gt;In the example above, &lt;code&gt;RangeInput&lt;/code&gt; could be defined alongside the &lt;code&gt;AboutMe&lt;/code&gt; component where the Tina form is set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
** Custom field defined alongside
** component using a Tina Form
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JsonFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-tinacms-json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;AboutMe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Tina Form config&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/*
  ** RangeInput will be referenced
  ** in the custom field definition
  */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;AboutMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could also be defined in its own file and imported into the file where the Tina form options are configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
** Custom field definition kept in
** separate file and imported
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JsonFile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-tinacms-json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/RangeInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;AboutMe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Tina Form config&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/*
  ** RangeInput will be referenced
  ** in the custom field definition
  */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;AboutMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getInitialProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As with many things in development, the answer &lt;strong&gt;depends on your usecase&lt;/strong&gt; 😉. Feel free to reference this &lt;a href="https://github.com/kendallstrautman/llama-filters/blob/master/pages/Index.js"&gt;demo repo&lt;/a&gt; to see a working example structure for Next.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Add the value to the source data
&lt;/h3&gt;

&lt;p&gt;Now that the custom input field is defined, we need to add the &lt;code&gt;image_saturation&lt;/code&gt; value to our source data. The source data could be a Markdown or JSON file. If you already have a Tina Form set up, it should be linked with a data source, so head to that file.&lt;/p&gt;

&lt;p&gt;For our example, let's say we have a local JSON file called &lt;code&gt;about.json&lt;/code&gt;. This file contains the data used in the &lt;em&gt;About Me&lt;/em&gt; page. In it we can add the &lt;code&gt;image_saturation&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;The value can be any integer or floating point number that exists between the range defined in our &lt;code&gt;RangeInput&lt;/code&gt; component — 0 to 10, with a step of 0.1 (meaning each 'slide step' of the range increments or decrements the value by 0.1). As a saturation value, &lt;strong&gt;zero would be totally grayscale&lt;/strong&gt; or no color, so we can fill in something like 3 to get a more 'normal' look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Example&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;About&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Me&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;about.json&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="err"&gt;“name”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Koba&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Weasley”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;“hometown”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“Bend&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Oregon”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"background_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#B1BCBC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"image_saturation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you’re using Gatsby, you will &lt;strong&gt;need to update your GraphQL query&lt;/strong&gt; to get this new data. Add the &lt;code&gt;image_saturation&lt;/code&gt; field to your query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So now we have a source value that can be connected to the custom input field. This way, &lt;strong&gt;Tina can update the value in the source file&lt;/strong&gt; in sync with the changes picked up by the &lt;code&gt;RangeInput&lt;/code&gt; component.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Add the custom field to a Tina Form
&lt;/h3&gt;

&lt;p&gt;How about we wire up this custom field to Tina? 🎊&lt;/p&gt;

&lt;p&gt;In this step, we need to create the custom field definition and pass in the &lt;code&gt;RangeInput&lt;/code&gt; component inline. We'll go back to our &lt;em&gt;About Me&lt;/em&gt; page &lt;a href="https://tinacms.org/docs/gatsby/json#customizing-json-forms"&gt;form options&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;About Me Page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hometown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Page Styles&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="c1"&gt;// Pass `RangeInput` to the `component` property&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image Saturation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image_saturation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RangeInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background_color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Background Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the development server and you should see the custom &lt;code&gt;RangeInput&lt;/code&gt; field in the sidebar. If you slide it, you should see the value updating in &lt;code&gt;about.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Dynamically set the CSS filter
&lt;/h3&gt;

&lt;p&gt;If all went well, our custom input field should be wired up, but there's one last thing to do. We haven’t connected the &lt;em&gt;saturation value&lt;/em&gt; with a CSS filter to actually see an effect on the image.&lt;/p&gt;

&lt;p&gt;In order to do this, you’ll need to be using a &lt;a href="https://css-tricks.com/bridging-the-gap-between-css-and-javascript-css-in-js/"&gt;&lt;em&gt;CSS-in-JS&lt;/em&gt;&lt;/a&gt; framework so we can dynamically update the filter values through the component props. If you’re using Next.js, &lt;code&gt;styled-jsx&lt;/code&gt; works out-of-the-box and is pretty fantastic. Below is an example of the &lt;em&gt;saturation value&lt;/em&gt; being connected to the CSS filter with &lt;code&gt;styled-jsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
**  Example component for the
**  About Me page in Next.js
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-tinacms-json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;AboutMe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocalJsonForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt; &lt;span class="na"&gt;bgColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background_color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hi 👩‍🎤 my name is &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Currently gallivanting around &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hometown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* This is the image that will get the treatment */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"random-unsplash"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://source.unsplash.com/random/800x600"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Pass in the image_saturation value */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt; &lt;span class="na"&gt;jsx&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`
        img {
          filter: saturate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image_saturation&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;);
        }
      `&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Some other examples of awesome &lt;em&gt;CSS-in-JS&lt;/em&gt; frameworks are &lt;a href="https://www.styled-components.com/"&gt;styled-components&lt;/a&gt; and &lt;a href="https://emotion.sh/docs/introduction"&gt;emotion.js&lt;/a&gt;. Note that the above implementation for these alternative frameworks this will look slightly different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;p&gt;A good next step would be &lt;em&gt;adding styles to the custom &lt;code&gt;RangeInput&lt;/code&gt; component&lt;/em&gt;. You could use &lt;a href="https://tinacms.org/docs/fields/custom-fields#using-tina-styles"&gt;&lt;code&gt;@tinacms/styles&lt;/code&gt;&lt;/a&gt; to fit the vibe of other Tina fields ✌️. Or you could go wild and spice up the sidebar in your own way 🤠.&lt;/p&gt;

&lt;p&gt;If we wanted to reuse this component throughout the site, &lt;strong&gt;we could take a step further and make it into a &lt;a href="https://tinacms.org/docs/fields/custom-fields#2-creating-field-plugins"&gt;Field Plugin&lt;/a&gt;&lt;/strong&gt;. Stay tuned for a follow-up post that dives into creating custom Field Plugins, or swing by the &lt;a href="https://tinacms.org/docs/fields/custom-fields#2-creating-field-plugins"&gt;docs&lt;/a&gt; to get a head start.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Feel free to check out a &lt;strong&gt;&lt;a href="https://github.com/kendallstrautman/llama-filters"&gt;finished version&lt;/a&gt; of this custom range input field&lt;/strong&gt;, or take a peak at a more complex &lt;a href="https://github.com/tinacms/tina-starter-grande/blob/master/src/fields/authors.js"&gt;&lt;em&gt;Authors&lt;/em&gt; field plugin&lt;/a&gt; in the Tina Grande repo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Takeaways 🕺🏻
&lt;/h3&gt;

&lt;p&gt;Making custom field components for TinaCMS is incredibly exciting! Hopefully this post got your creative gears turning on the numerous variables to tinker with in the content editing experience.&lt;/p&gt;

&lt;p&gt;The biggest takeaway from this short exploration of custom fields is that &lt;strong&gt;you can put any React component into the sidebar&lt;/strong&gt;. This flexibility is very powerful; it opens the door for you to custom-tune the editing controls for a project depending on its unique needs. And while creating custom components may not be necessary all the time, simply knowing it’s an option is reassuring, if not inspiring.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Add and Delete Files with TinaCMS</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Tue, 10 Dec 2019 23:56:15 +0000</pubDate>
      <link>https://dev.to/tinacms/how-to-add-and-delete-files-with-tinacms-ae1</link>
      <guid>https://dev.to/tinacms/how-to-add-and-delete-files-with-tinacms-ae1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published on &lt;a href="https://tinacms.org/blog/add-and-delete-files/" rel="noopener noreferrer"&gt;TinaCMS.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://tinacms.org/blog/add-and-delete-files/#creating-new-files" rel="noopener noreferrer"&gt;Creating&lt;/a&gt; and &lt;a href="https://tinacms.org/blog/add-and-delete-files/#deleting-files" rel="noopener noreferrer"&gt;deleting&lt;/a&gt; content — two fundamental sides of the CMS coin. This article will cover how to set up this functionality with TinaCMS on a &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; site. But first, some overview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feif52e3qigq4jm45jrct.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Feif52e3qigq4jm45jrct.gif" alt="tinacms-add-new-blog-gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tina Overview — sidebar, forms, plugins
&lt;/h3&gt;

&lt;p&gt;When you install Tina, you immediately get access to a &lt;a href="https://tinacms.org/docs/concepts/sidebar" rel="noopener noreferrer"&gt;‘sidebar’&lt;/a&gt;. This sidebar is the main interface for editing and managing content with Tina&lt;/p&gt;

&lt;p&gt;To make content editable on your site, you need to register a &lt;a href="https://tinacms.org/docs/concepts/forms" rel="noopener noreferrer"&gt;form&lt;/a&gt; to Tina. Forms appear in the sidebar, displaying &lt;a href="https://tinacms.org/docs/concepts/fields" rel="noopener noreferrer"&gt;fields&lt;/a&gt; where you can edit content on the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tinacms.org/docs/concepts/plugins" rel="noopener noreferrer"&gt;Plugins&lt;/a&gt; extend the functionality of the core CMS. Behind the scenes, plugins do some big work with Tina. They register forms, create new screen views, and allow us to add new content. If you're interested to learn more, read this post on Tina's &lt;a href="https://tinacms.org/blog/dynamic-plugin-system/" rel="noopener noreferrer"&gt;dynamic plugin system&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating New Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Steps 🚶‍♀️
&lt;/h3&gt;

&lt;p&gt;These steps will be our journey-map for setting up content-creation functionality in a &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; website. They follow along with the &lt;a href="https://tinacms.org/docs/gatsby/creating-new-files" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; closely.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://tinacms.org/blog/add-and-delete-files#step-1-set-up-a-content-creator-plugin" rel="noopener noreferrer"&gt;Set-up a &lt;code&gt;content-creator&lt;/code&gt; plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tinacms.org/blog/add-and-delete-files#2-register-the-plugin-with-the-sidebar" rel="noopener noreferrer"&gt;Register the plugin with Tina&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tinacms.org/blog/add-and-delete-files#3-customize-the-create-form" rel="noopener noreferrer"&gt;Customize the &lt;code&gt;create-form&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tinacms.org/blog/add-and-delete-files#4-configure-defaults" rel="noopener noreferrer"&gt;Configure default data for the new file&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Where to add the plugin
&lt;/h3&gt;

&lt;p&gt;Before we get into the steps, we need to zoom out to consider the editing process in our site. As a developer, you get to decide when editors can create new content.&lt;/p&gt;

&lt;p&gt;To be more specific, &lt;strong&gt;you can register the &lt;code&gt;content-creator&lt;/code&gt; plugin on any component&lt;/strong&gt; in the site. When that component renders, editors will be able to create new content.&lt;/p&gt;

&lt;p&gt;You may want create a new blog only when you're on the blog list page. To do this, you'll register the plugin on the list component.&lt;/p&gt;

&lt;p&gt;If you always want to be able to create new blogs, you'll register the plugin on a component that is always rendered. Examples of this could be the &lt;code&gt;Layout&lt;/code&gt; or &lt;code&gt;Root&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consider the experience before you dig into code.&lt;/strong&gt; One of the incredible things about Tina is that you have this finite control, so use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set-up a content-creator plugin
&lt;/h2&gt;

&lt;p&gt;Okay, let’s get into it. In this step we are going to create a &lt;code&gt;content-creator&lt;/code&gt; plugin 👩‍🎨.&lt;/p&gt;

&lt;p&gt;There are different plugins for creating new markdown or JSON files. In this tutorial, we'll use &lt;code&gt;RemarkCreatorPlugin&lt;/code&gt; for markdown files. Feel free to read about the &lt;code&gt;JsonCreatorPlugin&lt;/code&gt; in the &lt;a href="https://tinacms.org/docs/gatsby/creating-new-files#1-add-content-creator-plugin" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Head to the component file where you want to add this plugin. This example will use the &lt;code&gt;Layout&lt;/code&gt; component. This way, &lt;strong&gt;the ability to create new posts is always available to the editor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The example below shows how to create an instance of a &lt;code&gt;RemarkCreatorPlugin&lt;/code&gt;. The basic information the plugin needs is a label, filename, and fields array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="cm"&gt;/*
** Layout.js
*/&lt;/span&gt;

&lt;span class="cm"&gt;/*
** 1. import RemarkCreatorPlugin to
**    construct a `content-creator` plugin.
*/&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemarkCreatorPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-tinacms-remark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="cm"&gt;/*
** 2. instantiate RemarkCreatorPlugin with
**    label, filename, and fields.
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreatePostPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RemarkCreatorPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

  &lt;span class="cm"&gt;/*
  ** LABEL: A simple action label displayed when editors
  ** interact with the + button in the sidebar.
  */&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Blog Post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="cm"&gt;/*
  ** FILENAME: A function whose return value
  ** should be the path to the new file.
  */&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="cm"&gt;/*
  ** FIELDS: An array of field objects defining the shape
  ** of the form to fill out when creating a new file.
  */&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;filename&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Filename&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content/blog/hello-world/index.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The full path to the new markdown file, relative to the repository root.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Formatting the path to the new file
&lt;/h3&gt;

&lt;p&gt;There are many ways you could set up the return value for the &lt;code&gt;filename&lt;/code&gt;. A helpful pattern to use could be to hard-code the directory path, and then 'slugify' the title. You can do this manually with Regex or use a handy package aptly called &lt;a href="https://www.npmjs.com/package/slugify" rel="noopener noreferrer"&gt;&lt;code&gt;slugify&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreatePostPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RemarkCreatorPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 'form' holds the data inputted by the 'create-form'&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`content/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how data submitted by the &lt;code&gt;create-form&lt;/code&gt; is being used. When a new file is created, you can have the editor enter a title, and then all the &lt;strong&gt;&lt;code&gt;create-form&lt;/code&gt; data is passed to the &lt;code&gt;filename&lt;/code&gt; function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can use the data from &lt;code&gt;create-form&lt;/code&gt; to creatively generate new file paths or populate default data (more on that later). Overall, formatting the &lt;code&gt;filename&lt;/code&gt; depends on the structure of your project. Pick a simple solution that makes sense to you or checkout more examples &lt;a href="https://tinacms.org/docs/gatsby/creating-new-files#4-formatting-the-filename--path" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Register the plugin with the sidebar
&lt;/h2&gt;

&lt;p&gt;In the previous step, we created the plugin, now we actually need to add it to the sidebar (and cms).&lt;/p&gt;

&lt;p&gt;If you haven't already, install the &lt;code&gt;tinacms&lt;/code&gt; package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add tinacms &lt;span class="o"&gt;||&lt;/span&gt; npm &lt;span class="nb"&gt;install &lt;/span&gt;tinacms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then import &lt;code&gt;withPlugin&lt;/code&gt; from &lt;code&gt;tinacms&lt;/code&gt;. &lt;code&gt;withPlugin&lt;/code&gt; is a &lt;a href="https://reactjs.org/docs/higher-order-components.html" rel="noopener noreferrer"&gt;higher-order component&lt;/a&gt; used for adding plugins to the CMS.&lt;/p&gt;

&lt;p&gt;Export the component and plugin using &lt;code&gt;withPlugin&lt;/code&gt; and you should now be able to add new posts from the Tina sidebar. The location of the new files will be based on the return value from the &lt;code&gt;filename&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Import withPlugin&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tinacms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RemarkCreatorPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-tinacms-remark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="cm"&gt;/*
      ** Nothing gets changed in the actual component
      ** to register the `content-creator` plugin
      */&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Create instance of `RemarkCreatorPlugin`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateBlogPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RemarkCreatorPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add New Blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`content/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Export the component &amp;amp; `content-creator` plugin&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;withPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CreateBlogPlugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start up your development server (&lt;code&gt;gatsby develop&lt;/code&gt;) and you should see a blue plus (+) icon in the top menu of the sidebar. Click it and you’ll see the &lt;code&gt;label&lt;/code&gt; you set in your plugin configuration. Try to create a new file! See what happens.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Troubleshooting Tip:&lt;/strong&gt; If you don't see the icon, check if the component where you added the plugin is actively rendered.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Customize The Create Form
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo9xnsetrsrc6t4yroz0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo9xnsetrsrc6t4yroz0j.jpg" alt="tinacms-create-form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our initial example, the &lt;code&gt;create-form&lt;/code&gt; only captured a title. We can add more fields to capture data that will populate the new file, such as the date and author.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreatePostPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RemarkCreatorPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Create Post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The title of your new post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The default will be today&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
     &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Who wrote this?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`content/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice the use of a &lt;code&gt;required&lt;/code&gt; property on the &lt;code&gt;title&lt;/code&gt; field. Use this to ensure you get all the required data necessary for creating the new file.&lt;/p&gt;

&lt;p&gt;Learn about the default &lt;a href="https://tinacms.org/docs/concepts/fields#field-types" rel="noopener noreferrer"&gt;fields&lt;/a&gt; to choose from in the documentation. If you're interested in creating a custom field, read more on that &lt;a href="https://tinacms.org/docs/fields/custom-fields" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Configure Defaults
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;RemarkCreatorPlugin&lt;/code&gt; can take additional information to populate default data into newly created files. For markdown, we can add default frontmatter values and a markdown body — see the example below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CreateBlogButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RemarkCreatorPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add New Post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

 &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`content/posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;

 &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The default will be today&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Who wrote this, yo?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;],&lt;/span&gt;

 &lt;span class="cm"&gt;/*
 ** 1. Add default frontmatter with data inputted
 **    through fields in the `create-form`
 */&lt;/span&gt;
 &lt;span class="na"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
   &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Kurt&lt;/span&gt; &lt;span class="nx"&gt;Vonnegut&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
 &lt;span class="p"&gt;}),&lt;/span&gt;

 &lt;span class="c1"&gt;// 2. Add a default markdown body&lt;/span&gt;
 &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postInfo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`New post, who dis?`&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the frontmatter and body functions receive the data captured by fields in the &lt;code&gt;create-form&lt;/code&gt;. Use the inputted values to populate the new file, or setup defaults if nothing was entered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting Files
&lt;/h2&gt;

&lt;p&gt;With the power to create, comes the power to delete 🧙‍♀️. I promise you this step is much simpler.&lt;/p&gt;

&lt;p&gt;Instead of adding a ‘delete’ plugin, we simply need to pass a &lt;code&gt;delete-action&lt;/code&gt; to the main form options.&lt;br&gt;
Head to a file where you have a Tina form configured in your project. This will typically be a template file that generates multiple posts, casestudies, etc. If you don’t have a Tina form configured in your project, learn more about creating forms with Gatsby+Tina &lt;a href="https://tinacms.org/docs/gatsby/manual-setup" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You don't want to give the editors the power to delete files that they shouldn't. So think about where you want this action to be available. For something like a blog, it makes sense to add the &lt;code&gt;delete-action&lt;/code&gt; to a blog template form. But it might not make sense to add the &lt;code&gt;delete-action&lt;/code&gt; to a form that edits global site configuration, for example.&lt;/p&gt;

&lt;p&gt;Below is an example blog template with the &lt;code&gt;delete-action&lt;/code&gt; added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Import `DeleteAction`&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;remarkForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DeleteAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-tinacms-remark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;markdownRemark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;markdownRemark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Add the `DeleteAction` to the form&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;BlogFormOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;DeleteAction&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;frontmatter.title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter the title of the post here&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;frontmatter.description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter the post description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;textarea&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;remarkForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BlogTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BlogForm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can import the &lt;code&gt;DeleteAction&lt;/code&gt; from &lt;code&gt;gatsby-tinacms-remark&lt;/code&gt; or &lt;code&gt;gatsby-tinacms-json&lt;/code&gt;, depending on your filetype. Then on your form options definition, add the action and that’s it!&lt;/p&gt;

&lt;p&gt;You can now access this &lt;code&gt;delete-action&lt;/code&gt; via the three-dot icon near the save button. Test it out! But make sure you don't delete a file that you need or can easily restore it if you do 🧞‍♂️.&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Creating (and Deleting)! 👩‍🎤
&lt;/h2&gt;

&lt;p&gt;Hopefully this tutorial gave you some insight into setting up two core bits of CMS functionality with Tina + Gatsby.&lt;/p&gt;

&lt;p&gt;If you run into trouble or have any questions, head over to the &lt;a href="https://community.tinacms.org/" rel="noopener noreferrer"&gt;Tina Forum&lt;/a&gt; for help. Stoked on TinaCMS? Please ⭐️ us on &lt;a href="https://github.com/tinacms/tinacms" rel="noopener noreferrer"&gt;Github&lt;/a&gt; or &lt;a href="https://twitter.com/Tina_cms" rel="noopener noreferrer"&gt;Tweet us&lt;/a&gt; 🐦 to show-off your Tina projects.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>gatsby</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using TinaCMS with Next.js</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Mon, 02 Dec 2019 19:08:31 +0000</pubDate>
      <link>https://dev.to/tinacms/using-tinacms-with-next-js-4ddf</link>
      <guid>https://dev.to/tinacms/using-tinacms-with-next-js-4ddf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 02-25-2022&lt;/strong&gt; - This post has been updated to reflect Tina, Next.js and how to get started!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This blog is a part of a series exploring the use of Next.js + Tina. In &lt;a href="https://dev.to/tinacms/creating-a-markdown-blog-with-next-js-52hk"&gt;Part I&lt;/a&gt;, we learned how to create a simple markdown-based blog with Next. In this post, we’ll add content editing capacity by configuring the site with TinaCMS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js Recap ▲
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; is &lt;strong&gt;a React “metaframework”&lt;/strong&gt; (a framework built on a framework) for developing web applications, built by the team at &lt;a href="https://vercel.com/"&gt;Vercel&lt;/a&gt;. Read &lt;a href="https://dev.to/blog/simple-markdown-blog-nextjs/"&gt;Part I&lt;/a&gt; to get familiar with Next.js basics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tina Overview 🦙
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://tina.io/"&gt;Tina&lt;/a&gt; is a Git-backed headless content management system that enables developers and content creators to collaborate seamlessly. With Tina, developers can create a custom visual editing experience that is perfectly tailored to their site.&lt;/p&gt;

&lt;p&gt;The best way to get a feel for how Tina works is to use it. We hope that by the end of this tutorial, you’ll not only learn how to use Tina, but also how Tina rethinks the way a CMS should work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s Get Started
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TjU7GfHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://tina.io/gif/tina-nextjs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TjU7GfHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://tina.io/gif/tina-nextjs.gif" alt="tinacms editing gif" width="640" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tutorial will show you how to install and &lt;strong&gt;configure Tina for editing content on a simple markdown-based blog&lt;/strong&gt; that was created in last week’s post. If you want to dig into how the base blog was made, read &lt;a href="https://dev.to/blog/simple-markdown-blog-nextjs/"&gt;Part I&lt;/a&gt; of this series.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Jump ahead to see the &lt;a href="https://github.com/perkinsjr/tina-simple-markdown"&gt;final repo here&lt;/a&gt;. Or check out the &lt;a href="https://dev.to/docs/setup-overview/"&gt;Tina documentation&lt;/a&gt; here&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Set up Locally 🏡
&lt;/h3&gt;

&lt;p&gt;Feel free to follow along and fit these guidelines to your own site or blog, or you can use the starter we created in the previous tutorial. In your terminal, navigate to where you would like this blog to live, then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# clone the repo&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/perkinsjr/brevifolia-next-2022 next-tina-blog

&lt;span class="c"&gt;# navigate to the directory&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;next-tina-blog

&lt;span class="c"&gt;# install dependencies &amp;amp; init Tina&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npx @tinacms/cli@latest init

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="k"&gt;do &lt;/span&gt;you want us to override your _app.js? Yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;npx @tinacms/cli@latest init&lt;/code&gt; command does a few things in your Next.js application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install all required dependencies for Tina&lt;/li&gt;
&lt;li&gt;Define a basic schema that is easily extendable, in the .tina directory&lt;/li&gt;
&lt;li&gt;Wrap your next.js application with Tina so that any page can be easily edited.&lt;/li&gt;
&lt;li&gt;Create example content in the demo directory.&lt;/li&gt;
&lt;li&gt;Edit the package.json to add scripts to launch tina (tina-dev, tina-build, tina-start)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A quick test
&lt;/h3&gt;

&lt;p&gt;Now that you have a basic Tina setup you can launch your application using the following command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Once you have launched the application you have a couple of new URLS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://localhost:3000/demo/blog/HelloWorld&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://localhost:4001/altair/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first URL brings you to a demo of TinaCMS, it will show you the power of Tina and also give you some informational links to check out. If you navigate to &lt;a href="http://localhost:3000/demo/blog/HelloWorld"&gt;http://localhost:3000/demo/blog/HelloWorld&lt;/a&gt;, you won't be able to edit right away. First, you need to enter edit mode. To enter edit mode, navigate to &lt;a href="http://localhost:3000/admin"&gt;http://localhost:3000/admin&lt;/a&gt;, select login. Then navigate back to &lt;a href="http://localhost:3000/demo/blog/HelloWorld"&gt;http://localhost:3000/demo/blog/HelloWorld&lt;/a&gt;. Selecting the pencil in the top left allows you to edit the title and the body of the page right in the frontend. When you hit save, that will save your changes to the Markdown file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to see your changes? Open up the file located at &lt;code&gt;/content/posts/HelloWorld.md&lt;/code&gt; and the changes you've made will be there! This works by using our Content API which will go into greater depth during this guide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second URL &lt;a href="http://localhost:4001/altair/"&gt;http://localhost:4001/altair/&lt;/a&gt; will launch a graphQL client that will allow you to interact and create queries which will be in this guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the shape of our content
&lt;/h2&gt;

&lt;p&gt;One key element of Tina is defining a schema that allows you to shape and interact with the content on the page. Opening up the project, you will see a folder called &lt;code&gt;.tina&lt;/code&gt; which contains a &lt;code&gt;schema.ts&lt;/code&gt; file. This file allows you to instruct Tina's Content API which content type to look for, how it should be labeled, and much more!&lt;/p&gt;

&lt;p&gt;Before you look at your current project, let's discuss how the content is shaped. Our schema can be broken down into three concepts: &lt;code&gt;collections&lt;/code&gt;, &lt;code&gt;fields&lt;/code&gt; and &lt;code&gt;references&lt;/code&gt;. Each one of them has its role:&lt;/p&gt;

&lt;h3&gt;
  
  
  Collections
&lt;/h3&gt;

&lt;p&gt;The top-level key in the schema is an array of &lt;em&gt;collections&lt;/em&gt;, a &lt;code&gt;collection&lt;/code&gt; informs the API about &lt;em&gt;where&lt;/em&gt; to save content. In our guide we are going to have a &lt;code&gt;posts&lt;/code&gt; collection but you also could have an &lt;code&gt;author&lt;/code&gt; and &lt;code&gt;pages&lt;/code&gt; collections, for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fields
&lt;/h3&gt;

&lt;p&gt;Fields instruct the Content API of the type expected for example, &lt;code&gt;text&lt;/code&gt;, as well as the queryable name and the name to display to your content team. Fields are an array of objects that are a child of collections. We use this to retrieve the content from the Markdown or JSON files, these fields should map to your &lt;em&gt;frontmatter&lt;/em&gt; , and we also use this to create the UI elements for editing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;fields:&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;label:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;label:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blog Post Body"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;isBody:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="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;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;This is an important concept, when you &lt;em&gt;reference&lt;/em&gt; another collection, you're effectively saying: "this document &lt;em&gt;belongs to&lt;/em&gt; that document". A great example of using a reference is &lt;em&gt;author&lt;/em&gt; as each post would have an author and you could have multiple authors, but you need to reference a particular author to the post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"collections"&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="s2"&gt;"author"&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="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;points&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;collection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"author"&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;blockquote&gt;
&lt;p&gt;Before we move on you can read more about content modeling in our &lt;a href="https://dev.to/docs/schema/"&gt;documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating your content Schema
&lt;/h2&gt;

&lt;p&gt;The blog provided from another blog post comes with four example blog posts that you are going to use to shape your content in your schema. You can find on any of the blog posts in the &lt;code&gt;posts&lt;/code&gt; directory, let us look at the front matter of the &lt;code&gt;bali.md&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Siddhartha Mukherjee&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2019-07-10T07:00:00.000Z'&lt;/span&gt;
&lt;span class="na"&gt;hero_image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/alfons-taekema-bali.jpg&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bali&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—body,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mind&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;soul'&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

The term &lt;span class="gs"&gt;**bristlecone pine**&lt;/span&gt; covers three ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, you have a few fields that you want to be able to edit as well as the body of the blog post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making changes to the Schema
&lt;/h3&gt;

&lt;p&gt;Open up the Tina &lt;code&gt;schema.ts&lt;/code&gt; file located at &lt;code&gt;/.tina/schema.ts&lt;/code&gt; To begin with underneath the object we provided, you need to replace the current collection with the content you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;{&lt;/span&gt;
  label: "Blog Posts",
  name: "post",
&lt;span class="gd"&gt;-  path: "content/posts"
&lt;/span&gt;&lt;span class="gi"&gt;+  path: 'posts',
&lt;/span&gt;  fields: [
    {
      type: "string",
      label: "Title",
      name: "title"
    },
    {
      type: "string",
      label: "Blog Post Body",
      name: "body",
      isBody: true,
    },
  ]
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have only replaced a single line so far, which is to update the &lt;code&gt;path&lt;/code&gt; to the correct location of the Blog content.&lt;/p&gt;

&lt;p&gt;Now you need to handle each field for your posts frontmatter, below is the finished file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineSchema } from '@tinacms/cli'

export default defineSchema({
  collections: [
    {
      label: 'Blog Posts',
      name: 'post',
      path: '_posts',
      fields: [
        {
          type: 'string',
          label: 'Title',
          name: 'title',
        },
        {
          type: 'string',
          label: 'Author',
          name: 'author',
        },
        {
          type: 'datetime',
          label: 'Date',
          name: 'date',
        },
        {
          type: 'string',
          label: 'Image',
          name: 'hero_image',
        },
        {
          type: 'string',
          label: 'Body',
          name: 'body',
          isBody: true,
        },
      ],
    },
  ],
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of things you might notice. First, you have a &lt;code&gt;type&lt;/code&gt; called &lt;code&gt;datetime&lt;/code&gt;, this works by providing a date picker for you to use, and will format the date and time.&lt;/p&gt;

&lt;p&gt;Second, there's a &lt;code&gt;string&lt;/code&gt; field called &lt;code&gt;body&lt;/code&gt; with &lt;code&gt;isBody&lt;/code&gt; set to true. By setting &lt;code&gt;isBody&lt;/code&gt; to true you're stating that this field is responsible for the main &lt;em&gt;body&lt;/em&gt; of the markdown file. There can only be one field with the &lt;code&gt;isBody: true&lt;/code&gt; property.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next steps
&lt;/h3&gt;

&lt;p&gt;Your Markdown files are now backed by a well-defined schema, this paves the way for us to query file content with GraphQL. You will notice that nothing has changed when navigating around the Next.js blog starter, this is because you need to update the starter to use your GraphQL layer instead of directly accessing the Markdown files. In the next section you will handle converting the frontend to use TinaCMS.&lt;/p&gt;

&lt;p&gt;Currently, the Next Blog Starter grabs content from the file system. But since Tina comes with a GraphQL API on top of the filesystem, you’re going to query that instead. Using the GraphQL API will allow you to use the power of TinaCMS, you will be able to retrieve the content and also edit and save the content directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the getStaticPaths query
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;getStaticPaths&lt;/code&gt; query is going to need to know where all of your markdown files are located, with your current schema you have the option to use &lt;code&gt;getPostList&lt;/code&gt; which will provide a list of all posts in your &lt;code&gt;posts&lt;/code&gt; folder. Make sure your local server is running and navigate to &lt;a href="http://localhost:4001/altair"&gt;http://localhost:4001/altair&lt;/a&gt; and select the Docs button. The Docs button gives you the ability to see all the queries possible and the variables returned:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0gvbWST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://tina.io/gif/altair_doc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0gvbWST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://tina.io/gif/altair_doc.gif" alt="Altair Doc example" width="880" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So based upon the &lt;code&gt;getPostList&lt;/code&gt; you will want to query the &lt;code&gt;sys&lt;/code&gt; which is the filesystem and retrieve the &lt;code&gt;filename&lt;/code&gt;, which will return all the filenames without the extension.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  getPostList {
    edges {
      node {
        sys {
          basename
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run this query in the GraphQL client you will see the following returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "getPostList": {
      "edges": [
        {
          "node": {
            "sys": {
              "basename": "bali.md"
            }
          }
        },
        {
          "node": {
            "sys": {
              "basename": "iceland.md"
            }
          }
        },
        {
          "node": {
            "sys": {
              "basename": "joshua-tree.md"
            }
          }
        },
        {
          "node": {
            "sys": {
              "basename": "mauritius.md"
            }
          }
        }
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding this query to your Blog.
&lt;/h3&gt;

&lt;p&gt;The query above can be used to create your dynamic paths, this happens inside of the &lt;code&gt;[slug].js&lt;/code&gt; file. When you open the file you will see a function called getStaticPaths at the bottom of the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove all the code inside of this function and you can update it to use your own code. The first step is to add an import to the top of the file to be able interact with your graphql layer. While you are there you can remove &lt;code&gt;glob&lt;/code&gt;, as you will no longer need it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;//other&lt;/span&gt; imports
&lt;span class="err"&gt;.....&lt;/span&gt;
+ import { staticRequest } from "tinacms";
&lt;span class="gd"&gt;- const glob = require('glob')
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;"What does staticRequest do?"&lt;/p&gt;

&lt;p&gt;It's just a helper function which supplies a query to your locally-running GraphQL server, which is started on port 4001. You can just as easily use fetch or an http client of your choice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside of the &lt;code&gt;getStaticPaths&lt;/code&gt; function you can construct your request to our content-api. When making a request Tina expects a query or mutation and then variables to be passed to the query, here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;staticRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// our query&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt; &lt;span class="c1"&gt;// any variables used by our query&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;getPostList&lt;/code&gt; query from earlier to build your dynamic routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function getStaticPaths() {
  const postsListData = await staticRequest({
    query: `
      query {
        getPostList {
          edges {
            node {
            sys {
              filename
              }
            }
          }
      }
    }
    `,
    variables: {},
  })
  return {
    paths: postsListData.getPostList.edges.map(edge =&amp;gt; ({
      params: { slug: edge.node.sys.filename },
    })),
    fallback: false,
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Quick break down of &lt;code&gt;getStaticPaths&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;getStaticPaths&lt;/code&gt; code takes the graphql query you created, because it does not require any &lt;code&gt;variables&lt;/code&gt; you can send down an empty object. In the return functionality, you map through each item in the &lt;code&gt;postsListData.getPostList&lt;/code&gt; and create a slug for each one.&lt;/p&gt;

&lt;p&gt;You now need to create one more query, this query will fill in all the data and give you the ability to make all your blog posts editable.&lt;/p&gt;

&lt;p&gt;Go ahead and test that your blog posts are still readable by navigating to one, for example &lt;a href="http://localhost:3000/blog/bali"&gt;http://localhost:3000/blog/bali&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the &lt;code&gt;getStaticProps&lt;/code&gt; query
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;getStaticProps&lt;/code&gt; query is going to deliver all the content to the blog, which is how it works currently. When you use the GraphQL API Tina will both deliver the content and give the content team the ability to edit it right in the browser.&lt;/p&gt;

&lt;p&gt;You need to query the following items from your content api:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;author&lt;/li&gt;
&lt;li&gt;date&lt;/li&gt;
&lt;li&gt;hero_image&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating your Query
&lt;/h3&gt;

&lt;p&gt;Using your local graphql client you can query the &lt;code&gt;getPostDocument&lt;/code&gt; using the path to the blog post in question, below is the skeleton of what you need to fill out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BlogPostQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$relativePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;getPostDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$relativePath&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="c"&gt;# data: {}  this is data you want to retrieve from your posts.&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;blockquote&gt;
&lt;p&gt;If you haven't used graphql before, you will notice a strange &lt;code&gt;$relativePath&lt;/code&gt; followed by &lt;code&gt;String!&lt;/code&gt;. This is a variable and the String! means that it must be a string and is required. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now fill in the relevant fields you need to query. Inside the data object add in the fields author , date , hero_image, title. You also want to retrieve the body of your blog posts, so you can add new content. You should have a query that looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BlogPostQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$relativePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;getPostDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$relativePath&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;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;hero_image&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;body&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;blockquote&gt;
&lt;p&gt;If you would like to test this out, you can add the following to the variables section at the bottom &lt;code&gt;{"relativePath": "bali.md"}&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Using contextual-editing
&lt;/h3&gt;

&lt;p&gt;You need to set up contextual-editing on your blog so that you can edit the content using our sidebar, similar to the demo at the beginning. First, you need to import &lt;code&gt;useTina&lt;/code&gt; hook at the top of the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//... all your imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTina&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tinacms/dist/edit-state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;What is &lt;code&gt;useTina&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useTina&lt;/code&gt; is a hook that can be used to make a piece of Tina content contextually editable. It is code-split, so that in production, this hook will simply pass through its data value. In edit-mode, it registers an editable form in the sidebar, and contextually updates its value as the user types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can now use your query that you created as a variable, this variable will be used both in your &lt;code&gt;getStaticProps&lt;/code&gt; and in your &lt;code&gt;useTina&lt;/code&gt; hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const query = `query BlogPostQuery($relativePath: String!) {
  getPostDocument(relativePath: $relativePath) {
    data {
      title
      date
      hero_image
      author
      body
    }
  }
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Replacing your getStaticProps
&lt;/h4&gt;

&lt;p&gt;To replace your getStaticProps you will be using the &lt;code&gt;staticRequest&lt;/code&gt; in a similar way to what you used in our &lt;code&gt;getStaticPaths&lt;/code&gt; code. &lt;/p&gt;

&lt;p&gt;The first thing to do is remove all the code you no longer need, this includes the &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;data&lt;/code&gt; variables and the &lt;code&gt;markdownBody&lt;/code&gt;, &lt;code&gt;frontmatter&lt;/code&gt; from your props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;export async function getStaticProps({ ...ctx }) {
&lt;/span&gt;  const { slug } = ctx.params
&lt;span class="gd"&gt;- const content = await import(`../../posts/${slug}.md`)
&lt;/span&gt;  const config = await import(`../../data/config.json`)
&lt;span class="gd"&gt;- const data = matter(content.default)
&lt;/span&gt;
  return {
    props: {
       siteTitle: config.title,
&lt;span class="gd"&gt;-      frontmatter: data.data,
-     markdownBody: data.content,
&lt;/span&gt;    },
  }
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have removed that from your code, you can use our &lt;code&gt;staticRequest&lt;/code&gt; to retrieve the data. The only difference this time is you actually need a variable to pass along named &lt;code&gt;relativePath&lt;/code&gt;, which is the slug. You will also need to send the variables along as a prop so you can use this in our &lt;code&gt;useTina&lt;/code&gt; hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`../../data/config.json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;staticRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;variables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;relativePath&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;siteTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Updating the client for &lt;code&gt;useTina&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Now that you are returning only two props from &lt;code&gt;getStaticProps&lt;/code&gt; you need to update your client code to use them. Remove the destructured elements and pass in &lt;code&gt;props&lt;/code&gt; to your client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BlogTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the &lt;code&gt;useTina&lt;/code&gt; hook to handle contextual editing. The useTina hook expects the query, variables and data. Which you can pass in from your props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { data } = useTina({
    query,
    variables: props.variables,
    data: props.data,
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This now means you have the ability to edit your content using Tina, but before you do that you need to update all of your elements to use your new Tina powered data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- if (!frontmatter) return &amp;lt;&amp;gt;&amp;lt;/&amp;gt;
&lt;/span&gt;  return (
&lt;span class="gd"&gt;-    &amp;lt;Layout siteTitle={siteTitle}&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+    &amp;lt;Layout siteTitle={props.siteTitle}&amp;gt;
&lt;/span&gt;      &amp;lt;article className={styles.blog}&amp;gt;
        &amp;lt;figure className={styles.blog__hero}&amp;gt;
          &amp;lt;Image
            width="1920"
            height="1080"
&lt;span class="gd"&gt;-            src={frontmatter.hero_image}
&lt;/span&gt;&lt;span class="gi"&gt;+            src={data.getPostDocument.data.hero_image}
&lt;/span&gt;&lt;span class="gd"&gt;-            alt={`blog_hero_${frontmatter.title}`}
&lt;/span&gt;&lt;span class="gi"&gt;+            alt={`blog_hero_${data.getPostDocument.data.title}`}
&lt;/span&gt;          /&amp;gt;
        &amp;lt;/figure&amp;gt;
        &amp;lt;div className={styles.blog__info}&amp;gt;
&lt;span class="gd"&gt;-          &amp;lt;h1&amp;gt;{frontmatter.title}&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+          &amp;lt;h1&amp;gt;{data.getPostDocument.data.title}&amp;lt;/h1&amp;gt; 
&lt;/span&gt;&lt;span class="gd"&gt;-          &amp;lt;h3&amp;gt;{reformatDate(frontmatter.date)}&amp;lt;/h3&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+          &amp;lt;h3&amp;gt;{reformatDate(data.getPostDocument.data.date)}&amp;lt;/h3&amp;gt;
&lt;/span&gt;        &amp;lt;/div&amp;gt;
        &amp;lt;div className={styles.blog__body}&amp;gt;
&lt;span class="gd"&gt;-          &amp;lt;ReactMarkdown children={markdownBody} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+          &amp;lt;ReactMarkdown children={data.getPostDocument.data.body} /&amp;gt;
&lt;/span&gt;        &amp;lt;/div&amp;gt;
&lt;span class="gd"&gt;-        &amp;lt;h2 className={styles.blog__footer}&amp;gt;Written By: {frontmatter.author}&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+        &amp;lt;h2 className={styles.blog__footer}&amp;gt;Written By: {data.getPostDocument.data.author}&amp;lt;/h2&amp;gt;
&lt;/span&gt;      &amp;lt;/article&amp;gt;
    &amp;lt;/Layout&amp;gt;
  )
&lt;span class="err"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test &amp;amp; Edit Content ✨
&lt;/h3&gt;

&lt;p&gt;If all went well, your blog posts will now be editable by Tina. Let's see it in action!&lt;/p&gt;

&lt;p&gt;Start up the dev server by running &lt;code&gt;yarn tina-dev&lt;/code&gt;, and open up a blog post in the browser. Go ahead and make edits, and then check the source file in a text editor. If you keep the browser and code editor open side-by-side, you should be able to watch the changes reflect in real time in both places!&lt;/p&gt;

&lt;p&gt;You had a problem though, your body is a tiny input box that doesn't support Markdown! You should fix this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Markdown Support
&lt;/h3&gt;

&lt;p&gt;To add markdown support you need to do two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tell Tina how to use a different component.&lt;/li&gt;
&lt;li&gt;Dynamically load the markdown component.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Update Tina Schema
&lt;/h4&gt;

&lt;p&gt;Open up your &lt;code&gt;schema.ts&lt;/code&gt; located in the &lt;code&gt;.tina&lt;/code&gt; folder. The great thing about Tina is you can extend the UI field for your exact needs, to do this you use &lt;code&gt;ui&lt;/code&gt; object and tell Tina the component you'd like to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;COMPONENT_NAME&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You want to use the markdown component so you can override your body and it should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;isBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;markdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Updating &lt;code&gt;_app.js&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Before opening up your &lt;code&gt;_app.js&lt;/code&gt; file, you need to install the markdown plugin from Tina.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add react-tinacms-editor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open up your &lt;code&gt;_app.js&lt;/code&gt; file, this is where you are going to use the &lt;code&gt;cmsCallback&lt;/code&gt; prop for the &lt;code&gt;TinaCMS&lt;/code&gt; component which allows you to extend the default functionality, add plugins, handle document creation, and more&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cmsCallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you are passing the &lt;code&gt;cms&lt;/code&gt; and now you can import our component you installed to add to the plugins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-tinacms-editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="nx"&gt;cms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MarkdownFieldPlugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your TinaCMS should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TinaCMS&lt;/span&gt;
            &lt;span class="nx"&gt;apiURL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;apiURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;cmsCallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                              &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-tinacms-editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="nx"&gt;cms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MarkdownFieldPlugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="p"&gt;})&lt;/span&gt;
                          &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;p&gt;Go ahead and launch your blog and you should be able to see a new markdown editor that allows you to pass in data. Well done! With some config and calling a few hooks, you can now edit all our blog posts with Tina. Checkout the &lt;a href="https://github.com/perkinsjr/tina-simple-markdown"&gt;final repo&lt;/a&gt;, you might consider doing the following&lt;/p&gt;

&lt;h2&gt;
  
  
  Where can you keep up to date with Tina?
&lt;/h2&gt;

&lt;p&gt;You know that you will want to be part of this creative, innovative, supportive community of developers (and even some editors and designers) who are experimenting and implementing Tina daily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tina Community Discord
&lt;/h3&gt;

&lt;p&gt;Tina has a community &lt;a href="https://discord.com/invite/zumN63Ybpf"&gt;Discord&lt;/a&gt; that is full of Jamstack lovers and Tina enthusiasts. When you join you will find a place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To get help with issues&lt;/li&gt;
&lt;li&gt;Find the latest Tina news and sneak previews&lt;/li&gt;
&lt;li&gt;Share your project with Tina community, and talk about your experience&lt;/li&gt;
&lt;li&gt;Chat about the Jamstack&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tina Twitter
&lt;/h3&gt;

&lt;p&gt;Our Twitter account (&lt;a href="https://twitter.com/tina_cms"&gt;@tina_cms&lt;/a&gt;) announces the latest features, improvements, and sneak peeks to Tina. We would also be psyched if you tagged us in projects you have built.&lt;/p&gt;

</description>
      <category>jamstack</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Creating a Markdown Blog with Next.js</title>
      <dc:creator>Kendall Strautman</dc:creator>
      <pubDate>Mon, 18 Nov 2019 20:49:25 +0000</pubDate>
      <link>https://dev.to/tinacms/creating-a-markdown-blog-with-next-js-52hk</link>
      <guid>https://dev.to/tinacms/creating-a-markdown-blog-with-next-js-52hk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;02.08.22&lt;/strong&gt;: This post has been updated to use Next 12 and it's latest features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next.js is a React "metaframework" (a framework built on a framework) for developing web applications. Next.js has become a popular choice for web developers due to its bootstrapped React environment (similar to &lt;code&gt;create-react-app&lt;/code&gt;) and its simple, file-based routing for writing backend code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next.js is simple and flexible.&lt;/strong&gt; Compared to a full-fledged static site generator, there are less prescriptive guide rails placed on developers in the implementation of an app or site. Due to this flexibility, this article shares just one perspective to approach building a simple, Markdown-based blog. Take what’s helpful, disregard the rest.&lt;/p&gt;




&lt;p&gt;If you'd like to skip ahead and reference final versions of the starter, feel free to checkout the &lt;a href="https://github.com/perkinsjr/brevifolia-next-2022"&gt;finished implementation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone the starter
&lt;/h2&gt;

&lt;p&gt;Let’s get started. I have provided a &lt;a href="https://github.com/perkinsjr/nextjs-starter-boilerplate"&gt;bare bones starter&lt;/a&gt; to use as a starting point for this tutorial. You can clone the project or check it out on &lt;a href="https://github.com/perkinsjr/nextjs-starter-boilerplate"&gt;github&lt;/a&gt; for reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// clone the repo from your terminal&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//github.com/perkinsjr/nextjs-starter-boilerplate my-nextjs-blog&lt;/span&gt;

&lt;span class="c1"&gt;// install the dependencies&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nextjs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt;

&lt;span class="c1"&gt;// start up the dev server&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;yarn&lt;/span&gt; &lt;span class="nx"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you clone the project and start the dev server, navigate to &lt;code&gt;http://localhost:3000/&lt;/code&gt; in your browser to see what you're working with.&lt;/p&gt;

&lt;p&gt;&lt;a href="/img/blog/next-blog-1.png" class="article-body-image-wrapper"&gt;&lt;img src="/img/blog/next-blog-1.png" alt="nextjs starter blog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it's pretty simple at the moment. If you look at the project in your code editor, you will see the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components/
data/
pages/
styles/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;Let’s look at the &lt;code&gt;pages/index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;
      &lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;siteTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;siteDescription&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogList&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`../data/config.json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;configData.title,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;configData.description,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see that you now have a &lt;code&gt;Layout&lt;/code&gt; component wrapping a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; with a &lt;code&gt;BlogList&lt;/code&gt; component — these are all the pieces that render our little starter so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Handling
&lt;/h2&gt;

&lt;p&gt;Next.js &lt;a href="https://nextjs.org/docs/basic-features/pages#pre-rendering"&gt;pre-renders&lt;/a&gt; every page, meaning it generates HTML for pages in advance. As of &lt;a href="https://nextjs.org/blog/next-9-3"&gt;Next.js 9.3&lt;/a&gt;, there are two ways to pre-render pages: &lt;strong&gt;static generation or server-side-rendering (SSR)&lt;/strong&gt;. Next.js is unique in that you can use either approach depending on the project.&lt;/p&gt;

&lt;p&gt;For this blog, you will implement static generation, this means HTML pages for each route will be generated at build time. Static generation allows pages to be cached by a CDN, improving performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;getStaticProps&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;In the initial example&lt;code&gt;index.js&lt;/code&gt;, notice the use of &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation"&gt;&lt;code&gt;getStaticProps&lt;/code&gt;&lt;/a&gt; below the component. This function allows you to fetch data and return it as props to your page component. The page will be rendered at &lt;strong&gt;build time&lt;/strong&gt; with the props from the return object in &lt;code&gt;getStaticProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is your bread and butter for retrieving page-level data in Next.&lt;/strong&gt; You can use &lt;code&gt;getStaticProps&lt;/code&gt; to fetch data from an external api, or as seen in this example, you can get a hold of local data sources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this method only works for components defined in the &lt;code&gt;pages/&lt;/code&gt; directory, i.e., &lt;code&gt;page&lt;/code&gt; components. You cannot use this method on child components, but you can pass down the data received to these child components, as you see being done with &lt;code&gt;Layout&lt;/code&gt; in the example above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Layout&lt;/code&gt; is being passed props such as the site title and description. If you look at the data in &lt;code&gt;data/config.json&lt;/code&gt;, you’ll see the values these props are referencing. Go ahead and change the site title to your project name, then watch it update in the header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layout &amp;amp; Styling
&lt;/h2&gt;

&lt;p&gt;To zoom out a little, the purpose of the &lt;code&gt;Layout&lt;/code&gt; component is to provide the visual skeleton for every page of the site. It typically will contain some sort of nav or header that shows up on most or all pages, along with a footer element. In your case you just have a header that contains the site title.&lt;/p&gt;

&lt;p&gt;Within &lt;code&gt;Layout&lt;/code&gt;, there is a &lt;code&gt;Meta&lt;/code&gt; component that contains all global styles along with anything needed to be put in the &lt;code&gt;head&lt;/code&gt; of the site for SEO or accessibility purposes. Note that the use of a &lt;code&gt;Layout&lt;/code&gt; component isn’t unique to Next.js; you’ll see it commonly used in Gatsby sites as well.&lt;/p&gt;

&lt;p&gt;One thing you may notice in the &lt;code&gt;Layout&lt;/code&gt; component is the use of component level CSS. &lt;strong&gt;Next.js works out of the box with&lt;/strong&gt; &lt;a href="https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css"&gt;&lt;strong&gt;component level css&lt;/strong&gt;&lt;/a&gt;. It’s super intuitive to use. All of the styles are scoped to the component, this means you don't have to worry about accidentally overriding a style somewhere else.&lt;/p&gt;

&lt;p&gt;Note that global styles and fonts are handled in the &lt;code&gt;globals.css&lt;/code&gt; found in the &lt;code&gt;styles&lt;/code&gt; directory, so if you want to change fonts, or add more global styles you can add it here. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the Posts Directory
&lt;/h2&gt;

&lt;p&gt;Now that you’re familiar with the structure of the project and Next.js fundamentals, let’s start adding the pieces and parts to get the Markdown blog up and running.&lt;/p&gt;

&lt;p&gt;First, add a new folder in the root of your project called &lt;code&gt;posts&lt;/code&gt;. You can add all your Markdown blog posts here. If you don’t already have content ready, just add a few dummy blog posts. I like to use &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt; for sample photos and &lt;a href="http://www.cupcakeipsum.com"&gt;Cupcake&lt;/a&gt;, &lt;a href="https://hipsum.co/"&gt;Hipsum&lt;/a&gt;, or &lt;a href="http://saganipsum.com/"&gt;Sagan Ipsum&lt;/a&gt; are my preferred text generators — keeps things interesting.&lt;/p&gt;

&lt;p&gt;Here’s an example filler blog post with some commonly used frontmatter values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A trip to Iceland&lt;/span&gt;
&lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Watson&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Crick&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2019-07-10T16:04:44.000Z'&lt;/span&gt;
&lt;span class="na"&gt;hero_image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/norris-niman-iceland.jpg&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;Brain is the seed of intelligence something incredible is waiting to be known.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, create a &lt;code&gt;public&lt;/code&gt; folder in the root. This is where you will keep images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processing Markdown Files
&lt;/h2&gt;

&lt;p&gt;Next, you need to install a few packages that will process your Markdown files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn add raw-loader gray-matter react-markdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/webpack-contrib/raw-loader"&gt;Raw Loader&lt;/a&gt; will process your Markdown files. &lt;a href="https://github.com/jonschlinkert/gray-matter"&gt;Gray Matter&lt;/a&gt; will parse your yaml frontmatter values. And &lt;a href="https://github.com/rexxars/react-markdown"&gt;React Markdown&lt;/a&gt; will parse and render the body of your Markdown files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Next.js Config
&lt;/h3&gt;

&lt;p&gt;Now that you’ve installed some packages needed to handle Markdown, you need to configure the use of the &lt;code&gt;raw-loader&lt;/code&gt; by creating a &lt;a href="https://nextjs.org/docs#custom-configuration"&gt;next.config.js&lt;/a&gt; file at the root of the project. In this file you will handle any custom configuration for webpack, routing, build &amp;amp; runtime config, export options, and a whole lot more. In your use case, you will simply be adding a webpack rule to use &lt;code&gt;raw-loader&lt;/code&gt; for processing all Markdown files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//next.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;md$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;raw-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pages &amp;amp; Dynamic Routing
&lt;/h3&gt;

&lt;p&gt;So you’re set up to use Markdown files in your project. Let’s start coding a blog template page that will render the content from these Markdown files in &lt;code&gt;posts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For some background knowledge, the &lt;code&gt;pages&lt;/code&gt; directory is special in Next.js. Each &lt;code&gt;.js&lt;/code&gt; file in this directory will respond to a matching HTTP request. For example, when the home page ('/') is requested, the component exported from &lt;code&gt;pages/index.js&lt;/code&gt; will be rendered. If you want your site to have a page at &lt;code&gt;/about&lt;/code&gt;, simply create a file named &lt;code&gt;pages/about.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is awesome for static pages, but you’d like to have a single template from which all blog posts will be built, sourcing the different data from each Markdown file. This means you need some sort of dynamic routing, such that unique blog posts utilizing the same template have ‘pretty’ urls and their own individual pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs#dynamic-routing"&gt;Dynamic routes&lt;/a&gt; in Next.js are identified by &lt;strong&gt;square brackets&lt;/strong&gt; &lt;code&gt;[]&lt;/code&gt; in the filename. Within these brackets you can pass a query parameter to the page component. For example, let’s create a new folder within &lt;code&gt;pages&lt;/code&gt; called &lt;code&gt;blog&lt;/code&gt;, then add a new file within that blog folder &lt;code&gt;[slug].js&lt;/code&gt;, you can use whatever is passed as this &lt;code&gt;slug&lt;/code&gt; parameter to dynamically access data. So if you visit &lt;code&gt;http://localhost:3000/blog/julius-caesar&lt;/code&gt;, whatever is returned from the &lt;code&gt;[slug].js&lt;/code&gt; page component will render, and will have access to that ‘slug’ query parameter, i.e. ‘julius-caesar’.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Markdown Data For the Blog Template
&lt;/h3&gt;

&lt;p&gt;With dynamic routing, you can make use of this slug parameter by passing in the filename of the blog post and then getting the data from the corresponding Markdown file via &lt;code&gt;getStaticProps&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;matter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gray-matter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactMarkdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-markdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../components/Layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BlogTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Render data from `getStaticProps`&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="nx"&gt;siteTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteTitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactMarkdown&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;markdownBody&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/article&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`../../posts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`../../data/config.json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;siteTitle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;markdownBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticPaths&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//get all .md files in the posts dir&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts/**/*.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;//remove path and extension to leave filename only&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogSlugs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;file&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/ /g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// create paths with `slug` param&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blogSlugs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`/blog/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notice in this example that we’re making use of &lt;code&gt;gray-matter&lt;/code&gt; and &lt;code&gt;ReactMarkdown&lt;/code&gt; to properly handle the YAML frontmatter and Markdown body.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;A zoomed out look at how this is working:&lt;/strong&gt; when you navigate to a dynamic route, .e.g. &lt;code&gt;http://localhost:3000/blog/julius-caesar&lt;/code&gt;, the BlogTemplate component in &lt;code&gt;pages/blog/[slug].js&lt;/code&gt; is passed the &lt;code&gt;params&lt;/code&gt; object &lt;code&gt;{ slug: ‘julius-caesar’ }&lt;/code&gt;. When the &lt;code&gt;getStaticProps&lt;/code&gt; function is called, that &lt;code&gt;params&lt;/code&gt; object is passed in through the context. You get a hold of that slug value and then go search for a file within the &lt;code&gt;posts&lt;/code&gt; directory that contains the same filename. Once you get the data from that file, you parse the frontmatter from the Markdown body and return the data. That data is passed down as props to the &lt;code&gt;BlogTemplate&lt;/code&gt; component which can then render that data as it needs.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;getStaticPaths&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;At this point, you may be more familiar with &lt;code&gt;getStaticProps&lt;/code&gt;, but this function should look new — &lt;code&gt;getStaticPaths&lt;/code&gt;. Since this template uses dynamic routes, you need to define a list of paths for each blog, so all the pages will be rendered statically at build time.&lt;/p&gt;

&lt;p&gt;In the return object from &lt;code&gt;getStaticPaths&lt;/code&gt;, &lt;strong&gt;two keys are required&lt;/strong&gt;: &lt;code&gt;paths&lt;/code&gt; and &lt;code&gt;fallback&lt;/code&gt;. &lt;code&gt;paths&lt;/code&gt; should return an array of pathnames and any &lt;code&gt;params&lt;/code&gt; used in the page name. For example the 'param' used in &lt;code&gt;/blog/[slug].js&lt;/code&gt; is 'slug'. You should only need to use &lt;code&gt;getStaticPaths&lt;/code&gt; for dynamic routing.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required"&gt;&lt;code&gt;fallback&lt;/code&gt; property&lt;/a&gt; allows you to control the behavior if a path is not returned from &lt;code&gt;getStaticPaths&lt;/code&gt;. You should set this to &lt;code&gt;false&lt;/code&gt; so that unreturned paths will show a 404 page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before the release of Next.js 9.3, this path generation for static export could be handled via &lt;a href="https://nextjs.org/docs/api-reference/next.config.js/exportPathMap"&gt;&lt;code&gt;exportPathMap&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Checkout the &lt;a href="//brevifolia-next-2022blob/master/pages/blog/%5Bslug%5D.js"&gt;[slug].js file&lt;/a&gt; in the final version of my starter blog to get another idea of how that blog data could be rendered and styles applied.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get Data For the Blog Index
&lt;/h3&gt;

&lt;p&gt;Let’s finish this simple blog off by adding in the proper data to the &lt;code&gt;BlogList&lt;/code&gt; component for the &lt;code&gt;Index&lt;/code&gt; page. Since you can only use &lt;code&gt;getStaticProps&lt;/code&gt; on page components, you will get a hold of all the blog data in the &lt;code&gt;Index&lt;/code&gt; component and then pass it down as a prop for &lt;code&gt;BlogList&lt;/code&gt; to render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getStaticProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;siteConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`../data/config.json`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;//get posts &amp;amp; context from folder&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Create slug from filename&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^.*&lt;/span&gt;&lt;span class="se"&gt;[\\\/]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="c1"&gt;// Parse yaml metadata &amp;amp; markdownbody in document&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;markdownBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
  &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;md$/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;allBlogs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be slightly complex to look at, but let’s take it one step at a time. Feel free to reference &lt;a href="https://blog.toukopeltomaa.com/next-js-markdown-blog#gets-posts-from-posts-folder"&gt;this blog&lt;/a&gt; for the original code. It uses a function provided by Webpack, &lt;a href="https://webpack.js.org/guides/dependency-management/#requirecontext"&gt;require.context()&lt;/a&gt;, that allows you to create your own ‘context’ based on three parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The directory to match within.&lt;/li&gt;
&lt;li&gt;A boolean flag to include or exclude subdirectories.&lt;/li&gt;
&lt;li&gt;A regular expression to match files against.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useSubdirectories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regExp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\.\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a ‘context’ allows us to create a space where you can &lt;strong&gt;pick out all the files matching a regular expression&lt;/strong&gt; from a particular directory, and manipulate them into manageable formats that are provided back to the component as props to be rendered.&lt;/p&gt;

&lt;p&gt;Now that you have all of the blog data, pass it as a prop to the &lt;code&gt;BlogList&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;
      &lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;siteTitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;siteDescription&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogList&lt;/span&gt; &lt;span class="nx"&gt;allBlogs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allBlogs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/section&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you are free to loop through the blogs and render the list within your &lt;code&gt;BlogList&lt;/code&gt; component as you need. Feel free to check out the &lt;a href="https://github.com/perkinsjr/brevifolia-next-2022/blob/master/components/BlogList.js"&gt;BlogList component&lt;/a&gt; in my starter to see how that data could be handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout the &lt;a href="https://github.com/perkinsjr/brevifolia-next-2022"&gt;final repo&lt;/a&gt;! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After setting up your blog or portfolio site, you’ll most likely need a content management system to make editing and updating your posts or data easier. Stay tuned for my next blog on setting up this starter with TinaCMS. In the meantime, you can check out our &lt;a href="https://dev.to/docs"&gt;documentation &lt;/a&gt;, or &lt;a href="https://github.com/perkinsjr/tina-simple-markdown"&gt;fork the finished Next+Tina blog&lt;/a&gt; to start playing with TinaCMS right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where can you keep up to date with Tina?
&lt;/h2&gt;

&lt;p&gt;You know that you want to be part of this creative, innovative, supportive community of developers (and even some editors and designers) who are experimenting and implementing Tina daily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tina Community Discord
&lt;/h3&gt;

&lt;p&gt;Tina has a community &lt;a href="https://discord.com/invite/zumN63Ybpf"&gt;Discord&lt;/a&gt; that is full of Jamstack lovers and Tina enthusiasts. When you join you will find a place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To get help with issues&lt;/li&gt;
&lt;li&gt;Find the latest Tina news and sneak previews&lt;/li&gt;
&lt;li&gt;Share your project with Tina community, and talk about your experience&lt;/li&gt;
&lt;li&gt;Chat about the Jamstack&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tina Twitter
&lt;/h3&gt;

&lt;p&gt;Our Twitter account (&lt;a href="https://twitter.com/tina_cms"&gt;@tina_cms&lt;/a&gt;) announces the latest features, improvements, and sneak peeks to Tina. We would also be psyched if you tagged us in projects you have built.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>jamstack</category>
    </item>
  </channel>
</rss>
