Grav as Headless CMS

HI all. I’m new here and still finding my way around.

I want to use Grav as a headless CMS for GatsbyJS. I’m having a hard time figuring out how to source data from Grav?

I’m probably overlooking something simple, so if someone would be so kind as to please point me in the right direction in the docs?

Thanks a lot!

1 Like

I’ve never done that, but it’s something that was on my mind.
Can’t you simply parse all the .md files ?

1 Like

Yeah, that’s what I’ve been thinking too. I was just wondering if there’s another way. Like API endpoints or something like that?

I’ve been reading up in the Gatsby docs about .mdx files which is very new to me. It seems that React components can be included in these. I’m trying to figure out how all this can be made to work with Grav.

Have been trying to do the whole WP Rest API thing, but it’s frustrating to say the least. Grav seems so much more awesome. Plus, I also work with Laravel.

1 Like

Sorry if it’s off topic, but what did you find frustrating with wordpress API ?

For grav with Gatsby I think that you should be able to get both frontmatter and content.
But I have no clue if there is an API.

I don’t know either how you could handle the images if you want to use grav media.

1 Like

I was going through various tutorials using the WP REST API. Which in fact didn’t work out too bad.
What sucked was, stuff like images in posts or pages. And then of course, now with Gutenberg Blocks it’s a whole different ball game.

So then I came across the WP GraphQL plugin and various offshoots, WP GraphQL Gutenberg, etc. These are all still under development. I started working on something, but then after a recent update I’m running into issues.

It’s all a little above my experience level. I feel like a checkers player at a chess game. :laughing:

By creating Twig templates which output Grav pages as JSON you could come a long way. Learn how in https://learn.getgrav.org/16/content/content-types

Recently a new REST API plugin for GravCMS was released. Unfortunately you’ll have to dive into it’s code to find out how to use it though.

1 Like

Ah schweet! Thanks so much @bleutzinn.

Both those options look promising.

By creating Twig templates which output Grav pages as JSON you could come a long way. Learn how in https://learn.getgrav.org/16/content/content-types

That’s pretty neat!
Thank you!

1 Like

I kind of just stumbled upon Awesome Grav Stuff which includes a link to a rather lengthy and detailed article “Grav as Headless CMS Tied to Gatsby with GraphQL Schema”.

Thanks for that. I’ve seen that repository before. Also went through that article. It uses an extension for Grav that hasn’t been updated in 4 years though.

Getting some projects out the way, then I’m going to take fresh dive into Grav & Gatsby.

You are referring to Grav Pages as Data Plugin I assume. What it does is similar to outputting JSON via a template but instead of just the Markdown page content it outputs the entire Grav page object as a JSON encoded array.

Indeed that plugin hasn’t been updated in 4 years now but that need not be bad. It’s a very simple and stable plugin I think :wink:

Ah oki. Thanks for clearing that up.

If you go through the Gatsby docs and tutorials on www.gatsbyjs.org, their “introduction to Gatsby” tutorial describes using Markdown files as a source for content.

As far as I can make out, there are ways to fetch these files remotely.

I assume there must be a way to have Grav give access to it’s Markdown files?

There are some good suggestions in URL for plain markdown and I tried “alternative 2” but without luck.

I think there is no way to prevent Grav from parsing content from Markdown to HTML without resorting to a custom plugin.

But if I wanted to access the Markdown directly and use Grav just as a headless CMS, is this not possible?

Yes it is possible. But I think you need some custom PHP code to do it. In Grav custom PHP goes into a plugin.

So there’s no way to just gain direct access to the folder containing the markdown files?

@bjorn, Although I do not know much about your specific requirements, the rest-API of WP comes to mind.

Unfortunately, Grav doesn’t provide something similar to WP’s rest-api. The following is a simple attempt to create a ‘kind of’ api, using a plugin:

I tried the following using a fresh Grav 1.6.23 installation:

  • Install plugin devtools: $ bin/gpm install devtools
  • Create a new plugin: $ bin/plugin devtools newplugin
    • Answered some questions. I called the plugin ‘headless’
    • $ cd user/plugins/headless
    • $ composer update
  • The gist of ‘/user/plugins/headless/headless.php’ is:
    class HeadlessPlugin extends Plugin {
       const api = '/api/v1/pages/';
    
       /** The url of page being called */
       protected $pageUrl;
    
       // standard code omitted
    
      /**
       * Initialize the plugin
       */
      public function onPluginsInitialized()
      {
         // Don't proceed if we are in the admin plugin
         if ($this->isAdmin()) {
            return;
         }
    
         // Enable the main events we are interested in
         $lengthApi = strlen(self::api);
         $url = $this->grav['uri']->url();
    
         // If the API is being called
         if (substr($url, 0, strlen(self::api)) === self::api) {
            $this->pageUrl = substr($url, $lengthApi - 1);
    
            $this->enable([
               // Put your main events here
               'onPagesInitialized' => ['onPagesInitialized', 0]
            ]);
         }
      }
    
      /**
       * All pages have been initialized
       */
      public function onPagesInitialized($event)
      {
         $pages = $event['pages'];
         $page = $pages->find($this->pageUrl);
         $content = $page->content();
         echo ($content);
         die();
      }
    }
    
  • Browse to ‘localhost/api/v1/pages/typography’
  • The bare processed markdown of page '02.typography/default.md` should be send to client:
    <div class="notices yellow">
    <p>Details on the full capabilities of Spectre.css can be found in the <a href="https://picturepan2.github.io/spectre/elements.html">Official Spectre Documentation</a></p>
    </div>
    <p>The <a href="https://github.com/getgrav/grav-theme-quark">Quark theme</a> is the new default theme for Grav built with <a href="https://picturepan2.github.io/spectre/">Spectre.css</a> the lightweight, responsive and modern CSS framework. Spectre provides  basic styles for typography, elements, and a responsive layout system that utilizes best practices and consistent language design.</p>
    <h3>Headings</h3>
    <h1>H1 Heading <code>40px</code></h1>
    <h2>H2 Heading <code>32px</code></h2>
    <h3>H3 Heading <code>28px</code></h3>
    <h4>H4 Heading <code>24px</code></h4>
    <h5>H5 Heading <code>20px</code></h5>
    <h6>H6 Heading <code>16px</code></h6>
    
    etc.
    

Note:
This is only a simple starter to show what a plugin with a few lines of code could do.

Thanks @pamtbaau, that is very helpful!

If I am unable to remotely access the markdown files directly, it seems this is the kind of route I would need to take.

Learn how in https://learn.getgrav.org/16/content/content-types

After finally getting some time to RTFM a bit. This actually seems like the answer and looks fairly simple in theory.