Turn a Bootstrap theme into a Manageable Content Website in no time

Written by Rudy Rigot in Engineering on March 19,2014

I often hear a lot of developers regretting that they often have to make a choice between either being able to manage content, or using cool front-end tools designed to make their lives easier, such as Bootstrap. It does feel intriguing to me that this kind of constraint takes so long to be overcome, and that content is often a barrier to entry against the most relevant front-end tools.

So today, I've decided to pick a Bootstrap3 theme I like, and to have fun making all of its content fully manageable thanks to prismic.io.

In case you've never heard of it: Bootstrap is an open-source solution built by Twitter, making it easy to build responsive front-ends, including a lot of various built-in components. It's really great to get an advanced front-end done very quickly, and you can find a huge amount of templates and themes for it online. It's also immensely popular: it is the single most forked and starred repository on GitHub.

prismic.io is a web software you can use to manage content in any kind of website or app. A prismic.io content repository comes with a REST API from which your website can query your content, and a Writing-Room where you can edit and manage your content. Get your beta invite today, they usually roll out within hours!

Step 1: let's pick a Bootstrap theme

To find a Bootstrap theme that I wanted to make manageable, I hung out on WrapBootstrap for a while, and eventually stumbled on exactly the kind of thrill I was going for: a really funky Bootstrap theme called "Me Flat".

A good reason why it caught my eye: it is filled with really cool visual effects, that will effortlessly be available out-of-the-box. Seriously, check them out on their live preview!

Step 2: let's create content

Creating the content repository, and getting the Writing-Room and the Content Query API up and running takes seconds: log into your prismic.io dashboard, and create a new repository, and... voila!

First: the content types

prismic.io is greatest at effortlessly managing documents, rather that just webpages; this means that you get to think of your project's elements as your "skills", your "works", etc. rather than distinct webpages. This enables you to reuse the same document on several webpages; for instance, on a product catalogue, the same product document could be used as an entry in a product list, as well as in your product's page, as well as in other products' "related" block, etc.

After careful thinking, I elected I'd go with 5 different content types:

  • skills: each containing just a title and a number, for the % of skills
  • stuff-i-do: each one being an entry in the "What I Do" section
  • work: each one being an entry in the "My Works" section
  • kind-of-work: because I wanted to make the little tabs in the "My Works" section manageable as well (in order to edit them, but also add new ones, delete obsolete ones, etc.)
  • homepage: this one would contain any title, lede, and page-specific fragment that I would like to manage on the page; there would be only one document of this type, that I'd bookmark with the bookmark name "homepage" to find it easily through prismic.io's API

Using the detailed documentation about how to write JSON content masks in prismic.io, I proceeded to write them all. If you've never seen a custom type definition, here's what the one for stuff-i-do looks like:

This is nothing technically fancy here, you're just telling prismic.io what you'd like each of your fragments to contain (in this case, a "title" and a "lede" fragment of the type StructuredText, and an "image" fragment of the type "Image").

If you're feeling even more curious, I've left a gist right here with all of the custom types that were used for this one project.

Second: the content

To make my content-writing easier, I've decided to create three collections that will appear in my writing-room's collection list. A collection is a subset of your content repository filtered on types and/or tags. For instance, today I'll create:

  • the "works" collection that filters all documents of the type work;
  • the "skills" collection that filters all documents of the type skill;
  • and the "stuff-i-do" collection that filters all documents of the type stuff-i-do.

Note: we could also be basing our collections on the document's tags, but that won't be needed for this project. Also, I decided not to create a collection on the types "homepage" and "kind-of-work", as we won't need to be accessing them very often.

Now, using all of my setup, I can create and publish all the content I need!

Step 3: setting the project up

The first thing to do when you're starting a prismic.io-based website from scratch with any technology, is to clone one of the starter projects listed on prismic.io's developer's portal, which will allow you to benefit from all relevant helpers out-of-the-box and to be immediately operational. Today, I've decided to build my project with PHP, and on the PHP page, I could find that the starter project for a plain (framework-less) PHP project is available to fork and/or clone on GitHub. So, let's start with this!

git clone https://github.com/prismicio/php-plain-starter.git yourprojectname
cd yourprojectname

Following the starter project's README file, you then need to install dependencies by running "composer install", and change the API endpoint in the resources/config.php file so this brand new project calls the right repository's API. If you set your API access to "public" in your writing-room, you won't need anything more at all to have a minimal fully-working unstyled website that lists the documents in your repository!

Then, to set the groundwork for our coming developments, we're going to delete all of the content of the public_html/index.php file, and replace it by this, so it's ready to receive the static webpage that we're going to turn into a manageable one:

One thing left to do: copy-pasting all of the useful template asset files into your project's public_html folder (in the case of our present theme: the css, assets, fonts, and js folders, as well as the contact.php file for the contact form landing page sending you an e-mail), and copy-pasting the content of the theme's static index.html webpage into our project's index.php file (right where we just left the "// static webpage will go here" comment).

Note: since there's only one page to this website, we won't be working with sub-files such as header.php or footer.php for this one project; but of course, you're free to do it if it's useful to you.

Now, if you visit your local website, you should have that gorgeous static webpage right there, begging to be made manageable!

Step 4: content gets manageable!

Writing the api calls

We're going to start by writing the few API calls to fetch needed content, at the top of the file, where we've previously left a "// API calls will go here" comment.

There are several kinds of API calls. To get the homepage document itself, we can get it from its "homepage" bookmark, and there's a helper in the starter project for that; so it's as simple as:

$homepage = Prismic::getDocument($ctx->getApi()->bookmark('homepage'));

To get all the documents within a given collection, you just need to know that every collection is represented as a RESTful form in the API. You can think of calling a RESTful form pretty much like submitting a form online, but programmatically.

So, if we want to query the documents in the "skills" collection, it goes like this:

$skills = $ctx->getApi()->forms()->skills->ref($ctx->getRef())->submit();

Note the use of the ref function, which is indispensable to call before calling submit, in order to express what point in the repository's timeline you are querying. For instance, you are most likely querying within the presently live content, but you may want to be querying within a given future content release you have planned (with prismic.io, you can create content releases representing a future set of changes you will need to publish later, and you can add changes to this pending future content release). The fact that your ref used here is initialized once and passed in the $ctx context will allow you to preview all of your page in the future at once! Get more information about the logics behind refs in the introduction of prismic.io's API documentation.

Now, for any other kind of content query, such as querying over a type that is not configured as being the one of an existing collection, you will use prismic.io's powerful query predicates, which you can design on your repository's API browser.

To query over a type (for instance, the "kind-of-work" type, that we didn't set a collection for), you will learn in prismic.io's documentation that the matching predicate is written like this: [:d = at(document.type, "kind-of-work")]. Now that we're not querying within the boundaries of a collection, but within all of the repository, the name of the RESTful form to use is "everything" (it's the only form that is present in every repository):

$kindsofwork = $ctx->getApi()->forms()->everything->query('[[:d = at(document.type, "kind-of-work")]]')->ref($ctx->getRef())->submit();

Once fully written, our complete controller at the top of our page looks like this, and we have 5 variables ready to be used right in our template: the Document object $homepage, and the arrays of Document objects $skills, $works, $stuffido and $kindsofwork.

Inserting the managed content in the template

The main idea of how it works is very easy and quick to grasp from the "Kits and helpers" overview paragraph in prismic.io's documentation. Let's see a few example of how it works.

Starting with the top of the page, if we consider the title <h1>Hi, I am John Doe</h1>, a quick look at our good old friend the API browser will help refresh our memory on how we called things in our JSON mask:

So, in the document stored in the $homepage variable, we want the structured text fragment "homepage.page_title", in its text version, between <h1> tags. It couldn't get much easier than:

<h1><?php echo $homepage->getStructuredText('homepage.page_title')->asText() ?></h1>

When you want to loop through a document array, for instance to template the skills (which we had stored in the $skills variable), it simply looks like this:

Images are special, as prismic.io handles several "views" of different sizes for the same image, so that you always can work with a version of your image that best fits the design you're working on. If we want the URL of the "homepage.featured_image" image fragment, more precisely the one of the view you called "regular" while setting your JSON masks, both of those snippets work (the second one is a shorter way to write it):

<?php echo $homepage->getImage('homepage.featured_image')->getView('regular')->getUrl(); ?>
<?php echo $homepage->getImageView('homepage.featured_image', 'regular')->getUrl(); ?>

Finally, here's a way more powerful case: your PHP kit comes with HTML serialization out-of-the-box for all of your fragments; that means that you can call an asHtml() method on them, and it will return a nice HTML version (if it's on a StructuredText fragment, that includes all the formatting). It goes like this:

<?php echo $homepage->getStructuredText('homepage.page_lede')->asHtml($linkResolver) ?>

The only piece that might surprise you here is the $linkResolver variable we are passing, which is useful in the event of your structured text fragment containing an internal link to a document in your repository. In such cases, prismic.io can't know what the right URL on your website should be for that document, since you're the one in charge of your own front-office and URL strategy. So, the $linkResolver we're passing here is initialized in resources/config.php, and you should be the one customizing it; a basic one is provided in your starter project, which you should update as you add more pages to your website. More explanations about this are at the very bottom of prismic.io's API documentation.

Step 5: enjoy your custom manageable content website with no constraint!

By the time you're done replacing all the little static bits in your code that you want manageable, you're done! Next step I should consider: replacing all that "lorem ipsum" content I left in my repository, and that's about it!

Now, you get to effortlessly update your list of projects when you have new ones, or update your skills when you feel bolder; and since you get to enjoy all of prismic.io's feature out of the box, you can even plan future content releases you can push changes to, and preview them right in your website (this works out-of-the-box for any website based on prismic.io's starter project).

You can have a look at the entire code for this example on its GitHub repository, and also have a look at the result once hosted; and if you're still not sure how what something you mean to do gets done, always feel free to ask for help in the "Ask us anything" box in your writing-room!

Have fun with your project!

Rudy Rigot

Rudy is developer evangelist, and promote prismic.io to our developer community.