Gatsby React WSYIWYG CMS-Friendly Markdown
Tags: webdev, gatsby, jamstack, tutorial
Published: 2020-06-22 14:42:08

---
title: Gatsby React WSYIWYG CMS-Friendly Markdown
published: true
date: 2020-06-22 12:00:00 UTC
tags: webdev,gatsby,jamstack,tutorial
series: Playing With Gatsby
cover_image: https://katiekodes.com/images/header-gatsby-movable.png
canonical_url: https://katiekodes.com/gatsby-multi-level/
---

Come see how I built a **drag-and-drop** WSYIWYG CMS-ready web page with Gatsy and React.

---

I [mentioned before](https://katiekodes.com/gatsby-hello-world-variations/#indexmd-looks-different-than-im-used-to) that content management systems _(CMSes)_ for static site generators have gotten pretty fancy.

{%link https://dev.to/katiekodes/gatsby-react-minimum-viable-markdown-template-component-1e26 %}

[Magnolia CMS](https://documentation.magnolia-cms.com/display/DOCS62/Hello+Magnolia), [Stackbit](https://www.stackbit.com/), and [TinaCMS](https://tinacms.org/) all allow non-technical content authors drag and drop visual components around web pages in a semi-"what you see is what you get" _(WYSIWYG)_ editing experience that is probably [as close to Squarespace as the Jamstack comes right now](https://dev.to/katiekodes/jamstack-conf-takeaways-and-hopin-thoughts-54h3).

All these CMSes rely upon pages being built from data sources that can be treated as an outermost [object / dictionary / map](https://eloquentjavascript.net/2nd_edition/04_data.html#p_FolCMJfte3) with various values _(including more objects or [lists / arrays](https://eloquentjavascript.net/2nd_edition/04_data.html#p_Rl8msr9DUz))_ assigned to their keys.

---

## End goal HTML

Let's say I wanted a home page that looks like this:

![Screenshot of my home page before moving contents](https://katiekodes.com/images/screenshots/screenshot-gatsby-movable-2020-06/html-before-move.png)

<div>&nbsp;</div>

Example HTML might be:

```html
<html>
  <head></head>
  <body>
    <div class="hello-layout-wrapper">
      <div class="hello-layout-header">
        Header placeholder
      </div>
      <div class="hello-layout-main">
        <div class="pink-div">
          I did it!
        </div>
        <div class="task-list">
          <div class="task task-odd">
            <b>✓</b> <b>eat</b> <i>well</i>
          </div>
          <div class="task task-even">
            <b>X</b> <b>sleep</b> <i>soundly</i>
          </div>
          <div class="task task-odd">
            <b>✓</b> <b>jump</b> <i>high</i>
          </div>
          <div class="task task-even">
            <b>✓</b> <b>write</b>
          </div>
          <div class="task task-odd">
            <b>✓</b> <b>hydrate</b> <i>regularly</i>
          </div>
        </div> <!-- .task-list -->
        <div class="blue-div">
          Hello World
        </div>
      </div> <!-- .hello-layout-main -->
      <div class="hello-layout-footer">
        Footer placeholder
      </div>
    </div> <!-- .hello-layout-wrapper -->
  </body>
</html>
```

However, I also want it to be easy for an author to edit and re-order, and even add sections so that they look like this:

![Screenshot of my home page after moving contents](https://katiekodes.com/images/screenshots/screenshot-gatsby-movable-2020-06/html-after-move.png)

---

## Page data structure

### Design

Imagine hand-writing the following bulleted list in pencil, coloring it with markers, and cutting the paper horizontally at "section" breaks.

<div class="handwritten-font" markdown="block">

<ul>
	<li><b>template</b>:  <code>xyzzy</code></li>
	<li><b>sections</b>:
		<ul>
			<li><i>(this is 1 item in a list of sections)</i>
				<ul>
					<li><b>type</b>:  <code>SectionPink</code></li>
					<li><b>say</b>:  <code>I did it!</code></li>
				</ul>
			</li>
			<li><i>(this is 1 item in a list of sections)</i>
				<ul>
					<li><b>type</b>:  <code>SectionTaskList</code></li>
					<li><b>accomplishments</b>:
						<ul>
							<li><i>(this is 1 item in a list of accomplishments)</i>
								<ul>
									<li><b>task</b>:  <code>eat</code></li>
									<li><b>done</b>:  <code>true</code></li>
									<li><b>how</b>:  <code>well</code></li>
								</ul>
							</li>
							<li><i>(this is 1 item in a list of accomplishments)</i>
								<ul>
									<li><b>task</b>:  <code>sleep</code></li>
									<li><b>done</b>:  <code>false</code></li>
									<li><b>how</b>:  <code>soundly</code></li>
								</ul>
							</li>
							<li><i>(this is 1 item in a list of accomplishments)</i>
								<ul>
									<li><b>task</b>:  <code>jump</code></li>
									<li><b>done</b>:  <code>true</code></li>
									<li><b>how</b>:  <code>high</code></li>
								</ul>
							</li>
							<li><i>(this is 1 item in a list of accomplishments)</i>
								<ul>
									<li><b>task</b>:  <code>write</code></li>
									<li><b>done</b>:  <code>true</code></li>
								</ul>
							</li>
							<li><i>(this is 1 item in a list of accomplishments)</i>
								<ul>
									<li><b>task</b>:  <code>hydrate</code></li>
									<li><b>done</b>:  <code>true</code></li>
									<li><b>how</b>:  <code>regularly</code></li>
								</ul>
							</li>
						</ul>
					</li>
				</ul>
			</li>
			<li><i>(this is 1 item in a list of sections)</i>
				<ul>
					<li><b>type</b>:  <code>SectionBlue</code></li>
					<li><b>mention</b>:  <code>Hello World</code></li>
				</ul>
			</li>
		</ul>
	</li>
</ul>

</div>

This approach to structuring the data that I'll let my author edit makes it quite easy to imagine moving strips of paper up and down, rearranging them, right?

It'd also be pretty easy to add extra strips.

It'd be pretty easy to erase phrases and rewrite them as well.

---

### Computerization

Any plain-text punctuation standard optimized for storing [nested, ordered data](https://dev.to/katiekodes/intro-to-xml-and-json-2-datas-shape-3iji) in a way that is both human-readable and computer-readable would be a great way to digitize this craft-paper project.

{% link https://dev.to/katiekodes/intro-to-xml-and-json-2-datas-shape-3iji %}

#### JSON

Here's what it might look like in the [JSON punctuation standard](https://dev.to/katiekodes/intro-to-xml-and-json-6-json-30h3):

```json
{
   "template": "xyzzy",
   "sections": [
      {
         "type": "SectionPink",
         "say": "I did it!"
      },
      {
         "type": "SectionTaskList",
         "accomplishments": [
            {
               "task": "eat",
               "done": true,
               "how": "well"
            },
            {
               "task": "sleep",
               "done": false,
               "how": "soundly"
            },
            {
               "task": "jump",
               "done": true,
               "how": "high"
            },
            {
               "task": "write",
               "done": true
            },
            {
               "task": "hydrate",
               "done": true,
               "how": "regularly"
            }
         ]
      },
      {
         "type": "SectionBlue",
         "mention": "Hello World"
      }
   ]
}
```

{% link https://dev.to/katiekodes/intro-to-xml-and-json-6-json-30h3 %}

#### YAML

Here it is in the YAML punctuation standard, which is commonly used to store data as "front matter" at the top of "Markdown"-formatted files _(between a pair of `---` lines)_ in the world of static website generation:

```yaml
template: xyzzy
sections:
  - type: SectionPink
    say: I did it!
  - type: SectionTaskList
    accomplishments:
      - task: eat
        done: true
        how: well
      - task: sleep
        done: false
        how: soundly
      - task: jump
        done: true
        how: high
      - task: write
        done: true
      - task: hydrate
        done: true
        how: regularly
  - type: SectionBlue
    mention: Hello World
```

---

### Editing

This data might look pretty complicated for a non-technical author to edit by hand, but remember that they won't have to.

A CMS will write these data files for them based on the actions they take within the CMS's editor.

---

## Files

I'm up to 13 files now from my [original 2](https://dev.to/katiekodes/gatsby-minimum-viable-build-3n13).

{%link https://dev.to/katiekodes/gatsby-minimum-viable-build-3n13 %}

I think that makes it time to doodle out one of those little "folder structure" diagrams.  You can also [see the code on GitHub here](https://github.com/kkgthb/web-site-gatsby-04-movable).

```
.
├── src
│   ├── components
│   │   ├── indexSectionComponents.js
│   │   ├── layoutHello.js
│   │   ├── sectionBlue.js
│   │   ├── sectionPink.js
│   │   ├── sectionTaskList.js
│   │   └── task.js
│   ├── css
│   │   └── global.css
│   ├── pages
│   │   └── index.md
│   └── templates
│       └── xyzzy.js
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
└── package.json
```

---

### File:  `/src/pages/index.md`

#### Before authoring

```yaml
---
template: xyzzy
sections:
  - type: SectionPink
    say: I did it!
  - type: SectionTaskList
    accomplishments:
      - task: eat
        done: true
        how: well
      - task: sleep
        done: false
        how: soundly
      - task: jump
        done: true
        how: high
      - task: write
        done: true
      - task: hydrate
        done: true
        how: regularly
  - type: SectionBlue
    mention: Hello World
---
```

#### After authoring

```yaml
---
template: xyzzy
sections:
  - type: SectionBlue
    mention: Hello beautiful world.
  - type: SectionPink
    say: Wow, I did it!
  - type: SectionTaskList
    accomplishments:
      - task: stretch
        done: true
        how: gracefully
      - task: eat
        done: true
        how: well
      - task: write
        done: false
      - task: sleep
        done: false
        how: soundly
      - task: jump
        done: false
        how: high
      - task: hydrate
        done: true
        how: regularly
  - type: SectionPink
    say: I'm proud of me.
---
```

---

### File:  `/src/css/global.css`

```css
.pink-div {
	background-color: #d81b60;
	color: black;
}

.blue-div {
	background-color: #1e88e5;
	color: white;
}

.task.task-odd {
	background-color: #ffc107;
	color: black;
}

.task.task-even {
	background-color: #004d40;
	color: white;
}
```

Note that I color the individual tasks/accomplishments by their "odd" / "even" placement, not by anything inherent to their contents.

---

### File:  `/gatsby-browser.js`

```javascript
require('./src/css/global.css')
```

This file makes Gatsby actually pay attention to my CSS.

---

### File:  `/package.json`

```json
{
	"name" : "netlify-gatsby-test-04",
	"description" : "Does this really work?",
	"version" : "0.0.4",
	"scripts" : {
		"develop": "gatsby develop",
		"start": "npm run develop",
		"build": "gatsby build",
		"serve": "gatsby serve"
	},
	"dependencies" : {
		"gatsby": ">=2.22.15",
		"gatsby-source-filesystem": ">=2.3.11",
		"gatsby-transformer-remark": ">=2.8.15",
		"react": ">=16.12.0",
		"react-dom": ">=16.12.0"
	}
}
```

This didn't change from [the previous exercise](https://katiekodes.com/gatsby-hello-world-variations/#packagejson).

---

### File:  `/gatsby-config.js`

```javascript
module.exports = {
    plugins: [
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                name: `pages`,
                path: `${__dirname}/src/pages`,
            },
        },
		`gatsby-transformer-remark`
    ]
};
```

This didn't change from [the previous exercise](https://katiekodes.com/gatsby-hello-world-variations/#gatsby-configjs).

---

### File:  `/gatsby-node.js`

```javascript
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const urlSuffixIdea = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
      node,
      name: `suggestedURLSuffix`,
      value: urlSuffixIdea,
    })
  }
}

exports.createPages = async ({ graphql, getNode, actions }) => {
  const { createPage } = actions
  const queryResult = await graphql(`
	query {
	  allMarkdownRemark {
		  edges {
			node {
			  id,
			  fields {
				suggestedURLSuffix
			  }
			}
		  }
	  }
	}
  `)
  nodes = queryResult.data.allMarkdownRemark.edges
  nodes.forEach(({ node }) => {
	const freshNode = getNode(node.id);
    createPage({
	  path: node.fields.suggestedURLSuffix,
	  component: path.resolve(`./src/templates/${freshNode.frontmatter.template}.js`),
	  context: {
	    frontmatter: freshNode.frontmatter,
	  },
    })
  })
};
```

This changed very little from [the previous exercise](https://katiekodes.com/gatsby-hello-world-variations/#gatsby-nodejs).

I made a slight alteration to [the way I override `onCreateNode()`](https://katiekodes.com/gatsby-hello-world-variations/#overriding-oncreatenode) to make it more flexible about the "front matter" properties it encounters in my `.md` file(s) -- be sure to take a look at what I do with a variable I call `freshNode` _(thanks, Stackbit template authors, for the example)_.

---

### File:  `/src/templates/xyzzy.js`

```javascript
import React from "react"

import LayoutHello from '../components/layoutHello.js';
import sectionComponentTypeList from '../components/indexSectionComponents.js';

export default function Xyzzy({ pageContext }) {
  const sections = pageContext.frontmatter.sections;
  const SectionComponents = sections.map((section) => {
    let sectionType = section.type;
	let Component = sectionComponentTypeList[sectionType];
	return (
	  <Component section={section} />
	)
  });
  return (
    <LayoutHello>
	  <div className='xyzzy'>
	    {SectionComponents}
	  </div>
	</LayoutHello>
  )
}
```

The `Xyzzy` **React component** that I use as a "template" for `index.md` has changed a bit.

Instead of delegating content rendering to a `BasicDiv` React component, I delegate it to an array of React components that I refer to locally as `SectionComponents`.

I never actually wrote a file definining anything called `SectionComponents` _(or `Component`, for that matter, which also appears within a JSX tag in my code)_.

My ability to dynamically choose from among the React components I wrote called `SectionBlue`, `SectionPink`, and `SectionTaskList`, depending on what I find within the `type` sub-property of a given item within `sections` in my `index.md` front matter, depends upon some trickery within a file at `/src/components/indexSectionComponents.js`.

I also wrapped things in a "layout"-typed Gatsby component _(a component meant to wrap around other content instead of being placed inside it)_ named `LayoutHello` just to see how it works.

---

Let's move on to the rest of my components.  They're all thrown into a mess under `/src/components/*.js`, even though they do different things and serve at different "levels" of my page rendering.  This seems to be pretty standard in small Gatsby/React projects.

### File:  `/src/components/layoutHello.js`

```javascript
import React from "react"

export default function LayoutHello({ children }) {
  return (
    <div className="hello-layout-wrapper">
      <div className="hello-layout-header">Header placeholder</div>
      <div className="hello-layout-main">
	    { children }
      </div>
	  <div className="hello-layout-footer">Footer placeholder</div>
	</div>
  )
}
```

`LayoutHello`'s magic is in naming its input parameter `{ children }`.  That [turns a React component into a "layout component" in Gatsby](https://www.gatsbyjs.org/docs/layout-components/).

I used it to put a header & footer into my home page.


---

### File:  `/src/components/sectionBlue.js`

```javascript
import React from "react"

export default function SectionBlue(props) {
  return (
    <div className="blue-div">
	  {props.section.mention}
    </div>
  )
}
```

`SectionBlue` React components trust their calling code to send them object-typed details attached to an attribute named `section`, and to make sure that one of the properties of that object is named `mention`.

Lucky me I didn't make any typos in `index.md`'s front matter, like forgetting `mention`:

```yaml
- type: SectionBlue
  mention: Hello beautiful world.
```

Of course, the configuration file for a good CMS can help me specify `mention` as a required field for `SectionBlue` sections.  That would guarantee that no author ever forgets to write content for `mention`.

Also, I'm speaking a bit loosely about `index.md` as if `SectionBlue` knew anything about it.  It doesn't.  `index.md`'s contents are converted to Javascript objects by `createPages()` in `gatsby-node.js` long before `SectionBlue` becomes involved in rendering HTML for my web site.

---

### File:  `/src/components/sectionPink.js`

```javascript
import React from "react"

export default function SectionPink(props) {
  return (
    <div className="pink-div">
	  {props.section.say}
    </div>
  )
}
```

`SectionPink` React components trust their calling code to send them object-typed details attached to an attribute named `section`, and to make sure that one of the properties of that object is named `say`.

---

### File:  `/src/components/task.js`

```javascript
import React from "react"

export default function Task(props) {
  let checkboxSymbol;
  if (props.taskDetail.done) {
	checkboxSymbol = '✓';
  } else {
	checkboxSymbol = 'X';
  }
  const classes = `task ${props.alternatingClassName}`
  return (
    <div className={classes}>
	  <b>{checkboxSymbol}</b>
	  {' '}
	  <b>{props.taskDetail.task}</b>
	  { props.taskDetail.how && 
  	    <i>{' '}{props.taskDetail.how}</i>
	  }
    </div>
  )
}
```

`Task` React components trust their calling code to send them a simple plaintext value in an attribute named `alternatingClassName`, as well as object-typed details attached to an attribute named `taskDetail`, and to make sure that that object in turn has `task`, `done`, and possibly `how` properties of its own.

---

### File:  `/src/components/sectionTaskList.js`

```javascript
import React from "react"

import Task from './task.js';

export default function SectionTaskList(props) {
  const alternatingClassNames = ['task-odd', 'task-even']; // Per https://stackoverflow.com/a/45467474
  const tasks = props.section.accomplishments;
  const taskItems = tasks.map((taskToDo, index) =>
	<Task taskDetail={taskToDo} alternatingClassName={alternatingClassNames[index % alternatingClassNames.length]} />
  );
  return (
    <div className="task-list">    
	  {taskItems}
	</div>
  )
}
```

`SectionTaskList` React components trust their calling code to send them object-typed details attached to an attribute named `section`, and to make sure that one of the properties of that object is an array/list named `accomplishments`.

For each item found in `accomplishments`, `SectionTaskList` summons the `Task` React component, passing it the details of the item in question as `taskDetail`, and also passing it the phrase `task-odd` or `task-even`, [depending on where the item was found in `accomplishments`](https://stackoverflow.com/a/45467474).

---

### File:  `/src/components/indexSectionComponents.js`

```javascript
import SectionBlue from  './sectionBlue.js';
import SectionPink from  './sectionPink.js';
import SectionTaskList from  './sectionTaskList.js';

export default {
    SectionBlue,
    SectionPink,
    SectionTaskList
};
```

Finally, the only goal in life of `indexSectionComponents.js` is to make it easier for `Layout` to "look up" an appropriate React component from among `SectionBlue`, `SectionPink`, and `SectionTaskList` based on the data it finds in a Markdown-formatted file's front matter.

---

## Output

### HTML

#### Before authoring

The resulting page has the following HTML before my author changes any data:

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charSet="utf-8"/>
        <meta http-equiv="x-ua-compatible" content="ie=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
        <style data-href="/styles.ebc7626ff23287782a05.css">.pink-div{background-color:#d81b60;color:#000}.blue-div{background-color:#1e88e5;color:#fff}.task.task-odd{background-color:#ffc107;color:#000}.task.task-even{background-color:#004d40;color:#fff}</style>
        <meta name="generator" content="Gatsby 2.23.3"/>
        <link as="script" rel="preload" href="/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js"/>
        <link as="script" rel="preload" href="/styles-dd3841a4888192e20843.js"/>
        <link as="script" rel="preload" href="/app-d3bc4de7e5ad640ea7fa.js"/>
        <link as="script" rel="preload" href="/framework-4d07bacc3808af3f4337.js"/>
        <link as="script" rel="preload" href="/webpack-runtime-7db46c7381bf829cfc7b.js"/>
        <link as="fetch" rel="preload" href="/page-data/index/page-data.json" crossorigin="anonymous"/>
        <link as="fetch" rel="preload" href="/page-data/app-data.json" crossorigin="anonymous"/>
    </head>
    <body>
        <div id="___gatsby">
            <div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper">
                <div class="hello-layout-wrapper">
                    <div class="hello-layout-header">Header placeholder</div>
                    <div class="hello-layout-main">
                        <div class="xyzzy">
                            <div class="pink-div">I did it!</div>
                            <div class="task-list">
                                <div class="task task-odd">
                                    <b>✓</b> <b>eat</b>
                                    <i>
                                        <!-- -->well
                                    </i>
                                </div>
                                <div class="task task-even">
                                    <b>X</b> <b>sleep</b>
                                    <i>
                                        <!-- -->soundly
                                    </i>
                                </div>
                                <div class="task task-odd">
                                    <b>✓</b> <b>jump</b>
                                    <i>
                                        <!-- -->high
                                    </i>
                                </div>
                                <div class="task task-even"><b>✓</b> <b>write</b></div>
                                <div class="task task-odd">
                                    <b>✓</b> <b>hydrate</b>
                                    <i>
                                        <!-- -->regularly
                                    </i>
                                </div>
                            </div>
                            <div class="blue-div">Hello World</div>
                        </div>
                    </div>
                    <div class="hello-layout-footer">Footer placeholder</div>
                </div>
            </div>
            <div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div>
        </div>
        <script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/";/*]]>*/</script><script id="gatsby-chunk-mapping">/*<![CDATA[*/window.___chunkMapping={"app":["/app-d3bc4de7e5ad640ea7fa.js"],"component---src-templates-xyzzy-js":["/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js"]};/*]]>*/</script><script src="/webpack-runtime-7db46c7381bf829cfc7b.js" async=""></script><script src="/framework-4d07bacc3808af3f4337.js" async=""></script><script src="/app-d3bc4de7e5ad640ea7fa.js" async=""></script><script src="/styles-dd3841a4888192e20843.js" async=""></script><script src="/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js" async=""></script>
    </body>
</html>
```

#### After authoring

The resulting page has the following HTML after my author changes some data:

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charSet="utf-8"/>
        <meta http-equiv="x-ua-compatible" content="ie=edge"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
        <style data-href="/styles.ebc7626ff23287782a05.css">.pink-div{background-color:#d81b60;color:#000}.blue-div{background-color:#1e88e5;color:#fff}.task.task-odd{background-color:#ffc107;color:#000}.task.task-even{background-color:#004d40;color:#fff}</style>
        <meta name="generator" content="Gatsby 2.23.3"/>
        <link as="script" rel="preload" href="/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js"/>
        <link as="script" rel="preload" href="/styles-dd3841a4888192e20843.js"/>
        <link as="script" rel="preload" href="/app-d3bc4de7e5ad640ea7fa.js"/>
        <link as="script" rel="preload" href="/framework-4d07bacc3808af3f4337.js"/>
        <link as="script" rel="preload" href="/webpack-runtime-7db46c7381bf829cfc7b.js"/>
        <link as="fetch" rel="preload" href="/page-data/index/page-data.json" crossorigin="anonymous"/>
        <link as="fetch" rel="preload" href="/page-data/app-data.json" crossorigin="anonymous"/>
    </head>
    <body>
        <div id="___gatsby">
            <div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper">
                <div class="hello-layout-wrapper">
                    <div class="hello-layout-header">Header placeholder</div>
                    <div class="hello-layout-main">
                        <div class="xyzzy">
                            <div class="blue-div">Hello beautiful world.</div>
                            <div class="pink-div">Wow, I did it!</div>
                            <div class="task-list">
                                <div class="task task-odd">
                                    <b>✓</b> <b>stretch</b>
                                    <i>
                                        <!-- -->gracefully
                                    </i>
                                </div>
                                <div class="task task-even">
                                    <b>✓</b> <b>eat</b>
                                    <i>
                                        <!-- -->well
                                    </i>
                                </div>
                                <div class="task task-odd"><b>X</b> <b>write</b></div>
                                <div class="task task-even">
                                    <b>X</b> <b>sleep</b>
                                    <i>
                                        <!-- -->soundly
                                    </i>
                                </div>
                                <div class="task task-odd">
                                    <b>X</b> <b>jump</b>
                                    <i>
                                        <!-- -->high
                                    </i>
                                </div>
                                <div class="task task-even">
                                    <b>✓</b> <b>hydrate</b>
                                    <i>
                                        <!-- -->regularly
                                    </i>
                                </div>
                            </div>
                            <div class="pink-div">I&#x27;m proud of me.</div>
                        </div>
                    </div>
                    <div class="hello-layout-footer">Footer placeholder</div>
                </div>
            </div>
            <div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div>
        </div>
        <script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/";/*]]>*/</script><script id="gatsby-chunk-mapping">/*<![CDATA[*/window.___chunkMapping={"app":["/app-d3bc4de7e5ad640ea7fa.js"],"component---src-templates-xyzzy-js":["/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js"]};/*]]>*/</script><script src="/webpack-runtime-7db46c7381bf829cfc7b.js" async=""></script><script src="/framework-4d07bacc3808af3f4337.js" async=""></script><script src="/app-d3bc4de7e5ad640ea7fa.js" async=""></script><script src="/styles-dd3841a4888192e20843.js" async=""></script><script src="/component---src-templates-xyzzy-js-ca0f5fd88a2ff3c9c2f8.js" async=""></script>
    </body>
</html>
```

### Visual

#### Before authoring

The finished page looks roughly like this before authoring:

![Screenshot of my home page before moving contents](https://katiekodes.com/images/screenshots/screenshot-gatsby-movable-2020-06/html-before-move.png)

#### After authoring

And like this afterwards:

![Screenshot of my home page after moving contents](https://katiekodes.com/images/screenshots/screenshot-gatsby-movable-2020-06/html-after-move.png)

---

## Next steps

Pretty neat.

Next project:  setting up a CMS editing experience for `index.md`