All RPGs and Storygames by Tod Foley are now available at DrivethruRPG and RPGnow. Bring these games to your table!
Drupal isn’t known as a particularly lightweight content management system and that is one of the reasons we love it, right? It is meant to handle large amounts of complex content. A problem occurs when you have a site that is just flush with content of different types, how do you get users to it? Navigation can only get you so far sometimes. We have personally seen this on everything from large-scale publishing sites to medical practice sites.
Drupal is a very popular open source Web Content Management system. One of its key characteristics is that it owns both the back-end repository where content is stored and the front-end where content is rendered. In CMS parlance this is typically called a “coupled” CMS because the front-end and the back-end are coupled together.
Historically, the coupled nature of Drupal was a benefit most of the time because it facilitated a fast time-to-market. In many cases, customers could just install Drupal, define their content types, install or develop a theme, and they had a web site up-and-running that made it easy for non-technical content editors to manage the content of that web site.
But as architectural styles have shifted to “API-first” and Single Page Applications (SPAs) written in client-side frameworks like Angular and React and with many clients finding themselves distributing content to multiple channels beyond web, having a CMS that wants to own the front-end becomes more of a burden than a benefit, hence the rise of the “headless” or “de-coupled” CMS. Multiple SaaS vendors have sprung up over the last few years, creating a Content-as-a-Service market which I’ve blogged about before.
Drupal has been able to expose its content and other operations via a RESTful API for quite a while. But in those early days it was not quite as simple as it could be. If you have a team, for example, that just wants to model some content types, give their editors a nice interface for managing instances of those types, and then write a front-end that fetches that content via JSON, you still had to know a fair amount about Drupal to get everything working.
Last summer, Acquia, a company that provides enterprise support for Drupal headed up by Drupal founder, Dries Buytaert, released a new distribution of Drupal called Reservoir that implements the “headless CMS” use case. Reservoir is Drupal, but most of the pieces that concern the front-end have been removed. Reservoir also ships with a JSON API module that exposes your content in a standard way.
I was curious to see how well this worked so I grabbed the Reservoir Docker image and fired it up.
The first thing I did was create a few content types. Article is a demo type provided out-of-the-box. I added Job Posting and Team Member, two types you’d find on just about any corporate web site.
My Team Member type is simple. It has a Body field, which is HTML text, and a Headshot field, which is an image. My Job Posting type has a plain text Body field, a Date field for when the job was posted, and a Status field which has a constrained list of values (Open and Closed).
With my types in place I started creating content…
Something that jumped out at me here was that there is no way to search, filter, or sort content. That’s not going to work very well as the number of content items grows. I can hear my Drupal friends saying, “There’s a module for that!”, but that seems like something that should be out-of-the-box.
Next, I jumped over to the API tab and saw that there are RESTful endpoints for each of my content types that allow me to fetch a list of nodes of a given type, specific nodes, and the relationships a node has to other nodes in the repository. POST, PATCH, and DELETE methods are also supported, so this is not just a read-only API.
Reservoir uses OAuth to secure the API, so to actually test it out, I grabbed the “Demo app” client UUID, then went into Postman and did a POST against the /oauth/token endpoint. That returned an access token and a refresh token. I grabbed the access token and stuck it in the authorization header for future requests.
Here’s an example response for a specific “team member” object.
My first observation is that the JSON is pretty verbose for such a simple object. If I were to use this today I’d probably write a Spring Boot app that simplifies the API responses further. As a front-end developer, I’d really prefer for the JSON that comes back to be much more succinct. The front-end may not need to know about the node’s revision history, for example.
Another reason I might want my front-end to call a simplified API layer rather than call Drupal directly is to aggregate multiple calls. For example, in the response above, you’ll notice that the team member’s headshot is returned as part of a relationship. You can’t get the URL to the headshot from the Team Member JSON.
If you follow the field_headshot “related” link, you’ll get the JSON object representing the headshot:
The related headshot JSON shown above has the actual URL to the headshot image. It’s not the end of the world to have to make two HTTP calls for every team member, but as a front-end developer, I’d prefer to get a team member object that has exactly what I need in a single response.
One of the things that might help improve this is support for GraphQL. Reservoir says it plans to support GraphQL, but in the version that ships on the Docker image, if you try to enable it, you get a message that it is still under development. There is a GraphQL Drupal module so I’m sure this is coming to Reservoir soon.
Many of my clients are predominantly Java shops–they are often reluctant to adopt technology that would require new additions to their toolchain, like PHP. And they don’t always have an interest in hiring or developing Drupal talent. Containers running highly-specialized Drupal distributions, like Reservoir, could eventually make both of these concerns less of an issue.
In addition to Acquia Reservoir, there is another de-coupled Drupal Distribution called Contenta, so if you like the idea of running headless Drupal, you might take a look at both and see which is a better fit.
At GDC 2018 the director will reveal how the team worked to make a Jason player feel overpowered, and the large team of counselors feel very under-powered, while still having the experience feel fair. ...
So obviously, the pendulum of progress stopped swinging on my game. As much as I tried to prevent it, pressing obligations just wouldn’t take a back seat (nor would the burglars who, a few weeks ago, stole 90% of my wardrobe and who last week stole my monitor). So after a string of hectic weekends and even crazier weeks, this weekend has been pretty wide open for doing whatever I want to do. And not a moment too soon!
So after doing all the other things I try to do with my weekends, I finally loaded up the ol’ Inform 7 IDE and started working on my game. To get me back in the swing of things, so to speak, I started reading through what I’d already written. It was an interesting experience.
Strangely, what impressed me most was stuff I had done that I have since forgotten I learned how to do. Silly little things, like actions I defined that actually worked, that had I tried to write them today, probably would have had me stumped for a while. Go me! Except, erm, I seem to have forgotten more than I’ve retained.
I also realized the importance of commenting my own code. For instance, there’s this snippet:
A thing can be attached or unattached. A thing is usually unattached. A thing that is a part of something is attached.
The problem is, I have no idea why I put it in there – it doesn’t seem relevant to anything already in the game, so I can only imagine that I had some stroke of genius that told me I was going to need it “shortly” (I probably figured I’d be writing the code the next night). So now, there’s that lonely little line, just waiting for its purpose. I’m sure I’ll come across it some day; for now, I’ve stuck in a comment to remind myself to stick in a comment when I do remember.
It reminds me of all the writing I did when I was younger. I was just bursting with creativity when I was a kid, constantly writing the first few pages of what I was sure was going to be a killer story. And then I’d misplace the notebook or get sidetracked by something else, or do any of the million other things that my easily distracted self tends to do. Some time later, I’d come across the notebook, read the stuff I’d written and think, “Wow, this is great stuff! Now… where was I going with it?” And I’d never remember, or I’d remember and re-forget. Either way, in my mother’s attic there are piles and piles of notebooks with half-formed thoughts that teem with potential never to be fulfilled.
This situation – that of wanting to resume progress but fumbling to pick up the threads of where I left off – has me scouring my memory for a term I read in Jack London’s Call of the Wild. There was a part in the book where Buck’s owner (it’s late, his name has escaped me) has been challenged to some sort of competition to see if Buck can get the sled moving from a dead stop. I seem to remember that the runners were frozen to the ground. I thought the term was “fast break” or “break fast” or something to that effect, but diligent (does 45 seconds count as diligent?) searching has not confirmed this or provided me with the right term. Anyway, that’s how it feels tonight – I feel as if I’m trying to heave a frozen sled free from its moorings.
The upside is, I am still pleased with what I have so far. That’s good because it means I’m very likely to continue, rather than scrap it altogether and pretend that I’ll come up with a new idea tomorrow. In the meantime, I’ll be looking for some SnoMelt and a trusty St. Bernard to get things moving again.
So I didn’t get as much coding done over the weekend as I had hoped, mainly because the telephone company *finally* installed my DSL line, which meant I was up til 5:30 Saturday am catching up on the new episodes of Lost. That, in turn, meant that most of the weekend was spent wishing I hadn’t stayed up until such an ungodly hour, and concentration just wasn’t in the cards.
However, I did get some stuff done, which is good. Even the tiniest bit of progress counts as momentum, which is crucial for me. If the pendulum stops swinging, it will be very hard for me to get it moving again.
So the other day, as I was going over the blog (which really is as much a tool for me as it is a way for me to share my thoughts with others), I realized I had overlooked a very basic thing when coding the whole “automatically return the frog to the fuschia” bit…
As the code stood, if the player managed to carry the frog to another room before searching it, the frog would get magically returned to the fuschia. This was fairly simple to resolve, in the end – I just coded it so that the game moves (and reports) the frog back to fuschia before leaving the room. I also decided to add in a different way of getting the key out of the frog – in essence, rewarding different approaches to the same problem with success.
Which brings me to the main thrust of today’s post. I have such exacting standards for the games I play. I love thorough implementation. My favorite games are those that build me a cool gameworld and let me tinker and explore, poking at the shadows and pulling on the edges to see how well it holds up. A sign of a good game is one that I will reopen not to actually play through again, but to just wander around the world, taking in my surroundings. I’ve long lamented the fact that relatively few games make this a rewarding experience – even in the best games, even slight digging tends to turn up empty, unimplemented spots.
What I am coming to appreciate is just how much work is involved in the kind of implementation I look for. Every time I pass through a room’s description, or add in scenery objects, I realize just how easy it is to find things to drill down into. Where there’s a hanging plant, there’s a pot, dirt, leaves, stems, wires to hang from, hooks to hang on, etc. Obviously, unless I had all the time in the world, I couldn’t implement each of these separately, so I take what I believe to be the accepted approach and have all of the refer to the same thing. Which, in my opinion, is fine. I don’t mind if a game has the same responses for the stems as it does for the plant as a whole, as long as it has some sort of relevant response. Even so, this takes a lot of work. It might be the obsessive part of me, but I can’t help but think “What else would a person think of when looking at a hanging plant?”
Or, as I’ve come to think of it: WWBTD?What Would Beta Testers Do?
I’ve taken to looking at a “fully” implemented room and wondering what a player might reasonably (and in some cases unreasonably) be expected to do. This is a bit of a challenging process for me – I already know how my mind works, so trying to step outside of my viewpoint and see it from a blind eye is hard. I should stop for a second to note that I fully intend to have my game beta tested once it reaches that point, but the fewer obvious things there are for testers to trip over, the more time and energy they’ll have for really digging in and trying to expose the weaknesses I can’t think of.
I’ve found one resource that is both entertaining and highly informative to me: ClubFloyd transcripts. ClubFloyd, for the uninitiated (a group among which I count myself, of course) is a sort of cooperative gaming experience — if anyone who knows better reads this and cares to correct what may well be a horrible description, by all means!– where people get together on the IFMud and play through an IF title. The transcripts are both amusing and revealing. I recently read the Lost Pig transcript and it was quite interesting. The things people will attempt to do are both astonishing and eye-opening. In the case of Lost Pig (which, fortunately, I had already played before reading the transcript), what was even more amazing was the depth of the game itself. I mean, people were doing some crazy ass stuff – eating the pole, lighting pants on fire, and so on. And it *worked*. Not only did it work, it was reversible. You obviously need the pole, so there’s a way to get it back if, in a fit of orc-like passion, you decide to shove it in down Grunk’s throat.
Anyway, my point is, the transcripts gave me a unique perspective on the things people will try, whether in an effort to actually play the game, to amuse themselves, or to amuse others. Definitely good stuff to keep in mind when trying to decide, say, the different ways people will try to interact with my little porcelain frog.Other Stuff I Accomplished
So I coded in an alternate way to deal with the frog that didn’t conflict with the “standard” approach. I also implemented a few more scenery objects. Over the course of the next few days, I’m going to try to at least finish the descriptions of the remaining rooms so that I can wander around a bit and start really getting to the meat of it all. I also want to work on revising the intro text a bit. In an effort to avoid the infodumps that I so passionately hate, I think I went a little too far and came away with something a bit too terse and uninformative. But that’s the really fun part of all of this – writing and re-writing, polishing the prose and making it all come together.
Whattaya know. Midnight again. I think I’m picking up on a trend here.
Grrr… I’ve been so bogged down in work and client emergencies that progress on the game is at a temporary (no, really! Only temporary) standstill. I’ve managed to flesh out a few more room and scenery descriptions, but have not accomplished anything noteworthy in a few days. Hopefully after this week most of the fires on the work front will be extinguished, and I’ll have time to dive into the game this weekend.
(She says to no one, since there’s been one hit on this blog since… it started.)