Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: json

  • Using JSON with Hugo

    Using JSON with Hugo

    I know I’ve been talking about Hugo a lot, but the whole reason I say and wrapped my head around it was that I wanted to make a website using JSON.

    Making something out of the JSON API in WordPress isn’t easy, and I decided to start with something hard. I thought I would make a Multisite network to be the back end of my site, and then call the JSON API to generate the content.

    Why?

    It doesn’t make my site (much) faster, though it makes it more cacheable. Mostly what it does is lets me separate church and state. I can use WordPress to write content, and then call it however I want. That would be Hugo. If I build the site via Hugo locally, then every time I generate the files it can pull in the data on the fly.

    Enable the API

    This is easy. Install WordPress 4.4 and install v2 of the Rest API plugin. I also installed Jetpack for reasons of using Calypso.

    You absolutely have to use the Rest API plugin. WordPress 4.4 adds in some of the bits, but the API plugin gives you the actual endpoints. You’ll need these later.

    Call the API

    This was also easy. Kind of. Making a jquery file that called the content was fairly straightforward but… Making it responsive and reactive was hard.

    What I really wanted to do was have some web app, js powered without node, that just called the data and kept the url structure. And for that what I need is a JSON client.

    It was incredibly hard to find how to make a static HTML website powered by JSON. I’d see Rachel Baker’s presentation on making a WordPress theme with the JSON API but that wasn’t what I wanted to do. I mean, in a way it was. The theme itself was what I wanted, but I didn’t want to run it with WordPress.

    I did a lot of research and finally stumbled onto restful.js by marmelab. I read their blog post on the product and it looked like what I wanted. I needed something that would run without Node.js since I wanted to do this on Apache.

    Consuming a RESTful Web Service Dynamically

    And this is when I starting banging my head against a table. None of the solutions I’d found were working for me. Nothing. Rachel was right. I was in a bit over my head. Oh she was nice enough not to say it that way, but they way she looked at me was very Jewish Mom of her.

    In order to stop feeling useless, I decided to learn Hugo. It had come up a few times on my search for a dynamic static site. Hugo has LiveReload which, if you’re familiar with most static generators, is pretty cool. The idea is the pages rebuild as you edit the content (or theme) files.

    If you run hugo server locally on your laptop, you can see this today. Hugo upped the ante by tossing in the ability to run it on the server and the ability to watch the data files. It also has the ability to call JSON remotely.

    I feel it’s important to note that you cannot trigger that LiveReload when you’re using external URLs. But anytime you edit a file and LiveReload is triggered, Hugo will read the URL content from your cache. If you’ve disabled cache, it will download it fresh. Don’t disable cache unless you have an unlimited API. And no, I don’t know how long the cache is good for.

    Sadly, OAuth or other authentication methods are not working yet, but for now that’s okay because I’d been in over my head for so long, I stepped back.

    Understanding JSON First

    Okay fine. Once I realized I’d tried to do too much at first, I went back to that static filmography I had.

      {
      	"role": "actor",
        "title": "White Christmas",
        "slug": "white-christmas",
        "type": "Movie",
        "character": "Phil Davis",
        "notes": null,
        "dates": 1954
      }
    

    This is basic stuff. A simple chunk by chunk. And to call the file in a shortcode, I did this:

    {{ range $.Page.Site.Data.filmography }}
    	{{ if eq $role .role }}
    		<li>{{ .title }}: <strong>{{ .character }}</strong> </li>
    	{{ end }}
    {{ end }}
    

    Actually I did a lot more but you get the idea. And if you’re wondering about the if statement at the top, it’s so I can pass a parameter to my shortcode:

    {{< filmography role="actor" >}}

    It took me longer than I’d like to figure that out. At first I had multiple filmography files (actor, writer, producer) and I was trying to look through them all. In the end, I realized this simple JSON and a simple call was better.

    A Little More JSON

    There was another case, though. I had lists of episodes compiled into separate JSON files, one per show. This is logical and maintainable after all, but it meant I couldn’t use the same logic loop in the same way.

    What I really needed was to loop through $.Page.Site.Data.episodes.SHOWNAME in order to get the data from that show. And I couldn’t add on a variable to my range call.

    But as it happens, Hugo is clever and if I say {{ range $.Page.Site.Data.episodes }} it will give me the file episodes.json if that exists. But if there happens to be a folder called episodes then it will give me all the JSON files in there.

    I read through the data documentation on Hugo a few times to understand the hierarchy but it breaks down really logically:

    ├── data
    |   ├── episodes
    |   |   ├── continum.json
    |   |   └── fringe.json
    |   |   └── sense8.json
    |   ├── movies.json
    |   ├── musicals.html
    

    Data {dot} episodes {dot} continum

    And if I ran this:

    {{ range $.Page.Site.Data.episodes }}
    	<li>{{ .show }}<li>
    {{ end }}
    

    Then I got this:

    • continum
    • fringe
    • sense8

    I already knew I could do a range within a range, and finally I came up with this:

    {{ $show := $.Page.Params.show }}
    
    {{ range $.Page.Site.Data.episodes }}
    	{{ if eq .show $show }}
    		<li>{{ .title }}</li>
    	{{ end }}
    {{ end}}
    

    The shortcode checks the post it’s on and, if the Front Matter has ‘show’ defined, it will give me a list of all titles (episode titles) for that show.

    I added in an extra check for the season parameter. This one is passed through the shortcode:

    {{< episodelist season="1" >}}

    And that, in turn is called in the shortcode above the output for title:

    {{ range where .episodes "season" "==" $season }}

    So nothing will display unless the show in the JSON file matches the show on the page with the shortcode, and the season matches the one defined in the shortcode.

    Now I actually have a more robust check. If no season is defined, it shows all episodes (useful for one-season shows, right?). But you get the idea.

    How Did This Help?

    Remember my JSON example before? Here’s what it looks like for Fringe:

    {
    "show" : "fringe",
    "episodes": [
      {
        "epnum": "1",
        "season": "1",
        "title": "Pilot",
        "slug": "pilot",
        "airdate": "2008-09-08T22:00:00.000Z",
        "rating": "5",
        "summary": "Walter gets a cow named Gene to experiment on ethically."
      },
      ...
    ]}
    

    Instead of just started with those naked chunks, I have a definition of the show name (fringe – lowercase because I want to compare it to other lowercase things and I’m lazy) and the definition of a section for episodes. That’s the whole reason why that call for seasons works the way I want it to.

    This helped me to understand and visualize JSON. By taking a simple JSON list (the filmography) I learned the basics of connecting code and content. Then by taking the more complex scenario, where I needed nested data, I understood that relationship.

    The next step will be making a simple WordPress site and calling the JSON remotely. Obviously I have to figure out how to trick it into making fake permalinks, but baby steps. Baby steps.

  • Beginning to Understand JSON

    Beginning to Understand JSON

    Themes without php …

    Dynamic content without page requests …

    What about Multisite without Multisite?

    These are all things I’ve heard when people talk about the JSON REST API and how it’s the next greatest thing in WordPress. Well great, but what is it?

    REST stands for representational state transfer. It’s actually the juice that’s been powering the web since forever. RESTful systems generally run over HTTP (hypertext transfer protocol) and use the agreed upon language to get and put data. REST gives you a way to read and write data programmatically. You’ve been using it for years without even realizing it.

    This means our question isn’t what is it, but why do we want it or care about it?

    The WordPress REST API is a nice way to get at the data from WordPress without having to load all the heavy parts of WordPress. It’s useful for things like mobile apps, which don’t need to load everything, just the data, and it’s faster.

    Now, yes, WordPress has an API, called XML-RPC, and it sucks. You’ve used it already if you use the iOS app. We also have APIs like RSS, but that’s pretty much read only. The reasons that the current implementation of XML-RPC sucks are myriad, but basically it’s due to security, abuse, sanitization, and weight. It’s powerful but expensive and risky.

    The JSON API being added to WordPress aims to simplify and secure all that.

    Want to get your site’s posts? Simply send a GET request to url.com/wp-json/posts. Update user with ID 4? Send a POST request to url.com/wp-json/users/4. Get all posts with the search term “awesome”? GET url.com/wp-json/posts?filter[s]=awesome. It’s that easy.

    The WP API is very simply the interface to make it easier to get at your data. That’s it. How it does it is incredibly complicated. What it does is simple.

    Make it easier to get at my data without loading WordPress itself.

    What I dig the most about it is this idea.

    Take a website running backbone js that calls the JSON API from your WordPress site. Say frontend.com and backend.com are your URLs. You blog on backend.com and use WordPress normally. Your readers will visit a non WordPress site on frontend.com….

    Go on then. Hack the front end.

    It’s not WordPress, so unless you introduce an endpoint that puts you at risk, you have a way to protect your content. Plus now you can upgrade your blog all you want without having to worry really about taking your blog down.

    Obviously this isn’t perfect. By not using WordPress on the front end you won’t have access to a lot of features from plugins. Like related posts. And then again, maybe you can use related posts. Maybe you can even us Jetpack’s related posts.

    Mind? Blown.

    If everything WordPress can do the JSON API can do, then there’s nothing I can’t do. I can make any site where I run WordPress on the backend and anything I want on the front end. And now I can separate my site data, run by WordPress, and my theme and it’s options. I can dry run theme changes and layouts using my live data. I can tell the JSON API frontend.com site to ignore all posts with a special status, tell testend.com to use them, and draft posts.

    Migrations become easier. Who cares where the backend is, as long as the API frontend.com page can call what it calls.

    WordPress is becoming more and more of an application, and that is why we can all be excite about being at REST.