These are small brochure/marketing sites with complex configuration on each page and a handful of collections i.e. a blog or some services pages. Ironically, the blog posts are the easy part. After all, there are usually only a couple fields required for a blog post. Obvious examples would be an author field, a posting date, a title and the body. Out of the box Netlify CMS works very well with Gatsby for this. In the CMS config you just need to set up a "folder collection", which just means you define some fields and each time you make a new one or update it in the admin, a new markdown file is created or updated, respectively. Using just a couple plugins and a graphQL query, you can source them into your blog template and reference them as properties on an object. As for the body of the post, that's actually saved as the body of the markdown document itself. This is easily picked up and transformed to html that you can also request be added to your data object. You can then just use dangerouslySetInnerHTML to stick the html string right into your template (don't worry, remark.js is used by gatsby-transformer-remark[1] to sanitize it). Along the way, you'll have to deal with a couple of nested values like data.markdownRemark.title. Bam! You've got a working, re-useable blog post template. In the CMS admin, you can log in, click the blog collection on the left, then pound the "new blog" button and save them all day. The only other caveat I forgot to mention is that you have to do a bit of work in gatsby-node.js to programmatically create pages, but that only requires an hour tops with the docs and an example to reference to get it working really well.

Now, here's where the fun starts. Nowadays, most clients would like a level of configuration that goes a little bit further than a plain text box, right? That's really where things start to get sticky. Since you mentioned it, I'll use an FAQ as an example. With Netlify CMS + Gatsby, the best way to do this is probably to create a folder collection like I mentioned before with blog posts. That way, we can query all of them together and use them in any component we like. Here's where we hit a bit of a catch-22. What if I want to configure a heading and overview text for my FAQ? I can't add meta fields to collections themselves, so I have to put them somewhere else, presumably in a specific file in a file collection. This is a confusing experience for a non-tech savvy user, not to mention that it makes writing previews in the CMS more difficult. Now, some people might disagree with this approach altogether and opt to use a combination of list[2] and object[3] widgets in one file collection. That way, they can have their FAQ list right next to their FAQ "heading" and "subheading" fields. But if you do that, querying this information now becomes painful. You'll probably have to query by absolute file path to get the markdown node itself, then you'll have to de-structure content from one extra level deep in your data object, then once you've finally got your array, you'll have to map over it, then set the markdown body into the corresponding FAQ section. "Whatever, that's not that bad", you may be thinking, but here's the problem with that: nested markdown fields in frontmatter aren't transformed into HTML by gatsby-transformer-remark. You now have to manually go through and transform markdown to html yourself on a case-by-case basis in gatsby-node.js every time you want to use long-form text that requires formatting.

There are many other, smaller issues, but I think this is the most glaring. Granted, there are ways to work around this in Gatsby e.g. fragments or schema customization, but they all require intermediate to advanced knowledge of graphQL and Gatsby. Even as that knowledge becomes more commonplace, it's still just unnecessary extra labor. One could also argue that this is a problem with the netlify-cms source plugin or gatsby-transformer-remark, but I would suggest that regardless of how things are sourced, the presentation of content in the CMS itself is what's really broken here.

I hope this helps!

[0] https://remark.js.org
[1] https://www.gatsbyjs.org/packages/gatsby-transformer-remark/
[2] https://www.netlifycms.org/docs/widgets/#list
[3] https://www.netlifycms.org/docs/widgets/#object