Using a CMS for a portfolio is a given (or should be). As of today, there are dozens of choices for a CMS. Some of them are well known, like WordPress, while others have adopted the new query language GraphQL, come with out-of-the-box features or utilize a plugin system. I chose a CMS, with great out-of-the-box features built with GraphQL and REST APIs, called Cosmic JS. In this article I explain why I chose it and a step by step of how I built my portfolio using their platform.
There are free website builders and free standard CMS backends out there, sure, but I've used those before and I can tell you that if you are writing any sort of code for your portfolio, they become burdensome and bloated quite fast.
Clearly, for a developer, especially one that is frontend focused, you will need to create a site that is too customized for the free website builders out there. Also, I can say beyond a shadow of a doubt that you will end up hating WordPress and similar free standard CMS systems out there. They come with way to much crap to deal with - do you really want to deal with keeping plugins up to date? Yes, you will need plugins (see the amount of updates for a standard site required below).
This is just way too much mental overhead. Even for someone who codes web based apps, this is just too much... crap. If you're a content manager, you'll see how much less overhead there is and how easy Cosmic JS is to use as I go through how I created and am adding content to my portfolio.
Cosmic JS does have some some extensions for the content editing experience, but the out-of-the-box experience was elegant enough to not need them for this example. In addition, they provide an API packaged through NPM to make fetching the data super easy.
Hopefully, reducing that amount of cognitive resources was enough to convince you to use, but if it not, perhaps seeing how easy it was to set up, create content, ingest into my code, and maintain, may do the trick.
If you feel like following along, I built my project in React. I didn't feel I had much need for state management, so this is sans Redux or Mobx, but it wouldn't be difficult to add. If you aren't familiar with building for the modern frontend, you'll need to get Node and NPM. I have some dependencies in my project, like Chart.js, Semantic UI, and the API from Cosmic JS, so you'll need to add them as well.
Here's what I built and where to find the code:
First Things First
After you've finished that, you'll want to setup your Cosmic JS:
- From your dashboard, click the "Add New Bucket" button
- You can either start from scratch or use an "App", which is just a bucket that has some pre-purposed setup. For example, if you select a blog app, it will include posts as a "type" and will have some pre-made post "objects". In the end it doesn't really matter because you'll make some new types and objects either way.
That's it. The bucket is now available from your dashboard. You manage multiple buckets from there (like you should probably have a qa, staging, and prod if this is for more than a personal project, just saying...) and it's way easier than WP.
In my portfolio, I wanted to be able to "tag" things. What I mean, is that I wanted to be able to associate 1:1 and 1:many objects, like skills, languages, and tech for charts, but also to projects. Generally, in my experience with other CMS' I'd have to either get plugins or hack together something. Cosmic JS makes it easy, so lets do that:
- Click "Add Object Type"
- You can set a template for all the metafields you want for an object from this type to have, but I didn't know at the time so I just did the basic setting. For this lets just call the type technologies.
- Lets repeat for a projects type. This way we can add technologies as tags to any projects we have worked on.
- Now that we have a technology type, click it in the tree and we'll add a technology object.
- Call it whatever, I'll put React. I don't have any content cause it's just a tag. Repeat this for another technology you've worked with.
- Repeat step 4 with the projects type. Call it portfolio to start off with :)
- Here lets add metafields.
You'll probably want the following metafields at a minimum - Image, plain text area, and multiple objects relationship.
- I'd call the metafield by the same name as the type you'll be using for it, so technologies, then select it from the dropdown.
- Lastly, from the project type editor, select the two technologies you had created by clicking "Select Objects".
Next, Coding It Up
Alright, you've got some basic content to show. Wasn't that easy? Lets go to the code!
As stated in the prereqs, I'm running a basic React app. I've purposely avoided any state management like redux, instead opting for as simple an app as possible. For the view "page" that contains the list of projects, I'm using semantic-ui-react to build some cards that contain a main photo of the project, the name, details, and the tags we just created. Eventually, I expect that I'll be using tags to help filter, but for now they stand as a quick reference or tl;dr for the project. Lets take a look under the hood, shall we:
I'll start in the fashion of the data flow. In the highest container I have, App.js, I import the API library, that Cosmic JS has been nice enough to build and package through NPM. With only a couple configuration settings, you're ready to fetch whatever you need via their REST API. You'll see, in componentWillMount, I set up the configs for my instance of Cosmic JS, tell it the bucket I want, and give it a SUPER simple query of what I'm looking for from that bucket (the portfolio, duh). There's a bunch of options that the Comsic JS docs make easy to find, read, and follow, but in this case I decided to use "slug". Once those steps are done, all I have left to do is update the initial state of the project. Done.
So, what's left then? Really it's mostly standard from here on out. I pass the portfolioData as a prop, "data", down to the Portfolio container. Below, I loop through the data prop and build out the card widget by passing each "project" object we created back in Cosmic JS as a prop to Tile (I named it Tile to avoid mental record keeping of semantic ui's Card vs Card within my project).
Pretty simple. Last part, is to build out the "Tile" or "Card", with the help of semantic-ui-react (yarn add semantic-ui-react if you haven't yet). There's a couple helper methods here that I setup, but they aren't doing anything too crazy, just reaching down to the correct nested objects. Then, map the array of tags you need and use semantic-ui-react to make it look pretty (without a ton of your own styling) when put all together as a "card" with tags.
And that's it. Really. That's how simple it can be to get something like this:
However, Cosmic JS allows you to make way more complex structures too. Later I added a 1:1 metafield so I could do some cool graphs (Chart JS) about my level of expertise with each tech to do this:
I've tried out several CMS' of both standard and GraphQL and ones with plugins vs full-featured, and I'd recommend using Cosmic JS. It is one of the simpler to understand with a low learning curve, and one of the more pleasurable to use. The only advice I have is that you can't use built in formatting, esp. for production apps. Instead, you should use plain text metafields and use as many as needed for separate sections for whatever object you need. Otherwise, you'll have to parse it "dangerously", meaning that there could be script tags injected (even though this is SUPER unlikely, it's possible). However, that's totally fine, work-aroundable, and by far worth it.
If you're a content manager, it's so easy to create all sorts of different types, objects, relationships, etc. Not too mention, it's so easy to mix and match and create way more complex content - like the spider graphs showing my experience vs tags above. That's how versatile and easy Comsic JS makes it.