Power Up Your Jamstack With the New Nuxt
By: Maya Shavin
Tags: Programming, Vueje, Vue, JavaScript, Nuxtjs

You Write the Content, Nuxt Takes Care of Rendering

The Nuxt content module, @nuxt/content , is a new module developed by Benjamin Canac from the Nuxt team. At the time of writing this post, Nuxt Content release is version 1.4.1.

In short, this content module acts as a Git-based headless CMS (content management service) to fetch and handle content from different file types located in a local project directory, to use in your Nuxt application.

To start using Nuxt Content, run one of the following commands:

yarn add @nuxt/content



#OR

npm i @nuxt/content

Then add the module to the modules list in nuxt.config.js :

modules: [

'@nuxt/content'

]

And the module is ready for you to use.

A simple way to use

By default, the Nuxt engine will use content/ part as the main directory for all the Markdown files.

The content module globally injects the $content function instance to our application so we can use it to fetch content from a given path directly. For example, we can retrieve a list of blog posts from content/blog directory, as below:

This $content instance receives two arguments: path and an additional object options , which provides extra configuration for the module to override the default settings for that given path. For instance, we only need to enable deep: true to fetch files from subdirectories, as in the following code:

Or to fetch a single file, we can either pass the file name to the path argument or directly as options :

Both approaches are legitimate. $content() returns a chain sequence of type QueryBuilder . We then can call its method fetch() to start retrieving the content using Promise.

When fetch() resolves, it returns either an object (if path is a single file path), or an array of objects (if path is a directory). Each object has a similar structure as in the screenshot below, with the auto-generated properties as body (the main content), createdAt , dir , extension , path , slug (name of the file), toc (table of contents), and updatedAt .

Once we have the return content object, we can simply use the nuxt-content component in the template section to display the content's body:

That’s it. The content module will take care of the rendering and have your page content displayed, as in the below example:

As you can see from the screenshot, Nuxt Content only displays the content with the most basic stylings (i.e. no styling), to avoid creating complexity when applying CSS style customization. Nuxt provides us with the .nuxt-content class selector for the <nuxt-content> component, and we can start customizing the styles from there, such as:

And our content page now looks much more organized

And that’s it. We have our content from a Markdown file rendered to a page using Nuxt Content module with only three simple steps:

Fetch the content using $content().fetch() . Render the fetched content using <nuxt-content> and its prop document accordingly. Add CSS styles to the displayed content using the class selector .nuxt-content .

Great? Indeed. So any other unique features Nuxt Content offers besides?

Search and filter content results

Since Nuxt Content is using LokiJS and MongoDB-like query syntax, we can achieve high performance in searching and filtering a certain set of content results with a sequence chain of methods. For example, if we want to pick only the title , slug , and updatedAt properties of each content object and sort the posts by the edit time (in descending order), we can do so as follows:

Here only receives an array of keys to pick from each returned content object and sortBy accepts two arguments, a key to sort and the sorting direction.

You can also filter for posts that match certain condition(s) using where , such as:

Or you can perform a full-text search on a field with search(key, value) :

Also, you can implement pagination by limiting the results received by limit() :

You can explore other useful chaining methods in Nuxt Content documentation and LokiJS for query syntax supported in these methods.

Note: All the sequence chaining has to end with fetch() to collect the needed data through Promise API.

Code highlighting with PrismJS

Nuxt Content uses PrismJS as its built-in handler for code highlighting in Markdown content. The default theme is pretty decent; however, we can always install prism-themes and chose a different theme from the available theme list (24 different themes) to use in our application:

yarn add prism-themes

Then define the desired theme under content.markdown.prism field in nuxt.config.js , as shown in the example below:

And your rendered content with code highlighting will look like this:

Beautiful, isn’t it? No more complicated workaround for supporting code highlighting for Markdown. Also, you can always create your custom theme as the prism-themes repo is open-source.

YAML inside Markdown

One nice feature of Nuxt Content is the ability to support YAML front matter block within a Markdown file, as long as it appears at the top and takes the valid form of YAML set between triple-dashed lines:

---

title: Hello World description: Hello to Nuxt content demo img: nuxt_demo/DSC00856

author: Maya Shavin

---

The Nuxt Content module will inject these fields as properties into the content object passed to document of the nuxt-content component, as shown in the example below:

Writing YAML block inside the Markdown file enables us to easily add more custom information, such as author details, for a blog post.

Autogenerating table of content

When fetching a Markdown file, Nuxt content autogenerates a table of content (TOC), which consists of all the heading titles inside the file. The TOC is an array and appears as a property of the return content object. Each element of the toc array is an object with three main fields:

id — the heading title itself in lowercase and free of whitespace, for linking

— the heading title itself in lowercase and free of whitespace, for linking depth — type of heading (1=h1, 2 =h2, etc.)

— type of heading (1=h1, 2 =h2, etc.) text — the actual text of the heading title

Here’s an example of a Markdown file with the following content:

# Hello World



## Hello Heading 1



Lorem ipsum dolor sit amet

Nuxt Content will generate TOC as the following:

And from this TOC structure, we can build and display our TOC component accordingly.

Awesome. What else?

It’s all about hooks!

Currently, Nuxt Content offers two main hooks:

content:file:beforeInsert allows adding extra data to a document before storing it for rendering. For example, it is useful to add external logic, like reading time calculation on build time, hence optimizing the client-side performance.

allows adding extra data to a document before storing it for rendering. For example, it is useful to add external logic, like reading time calculation on build time, hence optimizing the client-side performance. content:update when a content file is updated. This hook is useful when you want to implement hot-reload or live-edit.

We can add the desired hooks by using the hooks properties in nuxt.config.js , as in the following example:

And that’s all we need. Now the documents fetched will also have an additional field readingTime indicating how much time it takes to read the blog post, and all of these are done entirely on the build time. No extra work needed on the client side, even for reading time calculation.

Cool, isn’t it? With these features, we can set up a fully static site, either a blog or an ecommerce store using Markdown files and Nuxt only.

Indeed, these are not the only features Nuxt Content can offer. And making a performant and beautiful static site requires a combination of efficient tools, in which Nuxt and Nuxt Content is the core.