Skip to content
Public repository for tota.sk—an NPO in Slovakia cherishing the Rusyn culture.
Vue CSS JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets
components
layouts
middleware
pages
plugins
server
static
store
.editorconfig
.gitignore
README.md
nuxt.config.js
package-lock.json
package.json

README.md

tota.sk

This is the public repository for tota.sk—an NPO in Slovakia cherishing the Rusyn culture.

I wanted to make this repo public to share few examples of how I used:

  • Nuxt.js—the Vue.js framework to build statically generated website and single page app
  • Kentico Kontent—the headless CMS to manage the content

Contents

If you have any questions about the code or examples, feel free to create an issue.

Build Setup

# install dependencies
$ npm ci

# serve with hot reload at localhost:3000
$ npm run dev

# build for production and launch server
$ npm run build
$ npm run start

# generate static project
$ npm run generate

For detailed explanation on how things work, check out Nuxt.js docs.

Examples of use

Rendering project detail (Rendering dynamic pages of one type)

Each project detail has its own page. Review this section, if you’d like to render dynamic pages of the same type (e.g. articles, blog posts,…).

Getting project detail data

All projects are stored as a structured content in Kentico Kontent. We’ll get data as a structured JSON via Kentico Kontent Delivery API and “load” it to a Vuex Store. Here’s how it’s done for project detail:

Project detail template

The template for project detail is located at pages/projekt/_id.vue. Nuxt has a convention how to name/categorize page templates to generate routes in a desired way (in my case I was looking for routes tota.sk/projekt/{project-detail}.

Here are extra notes on what is happening inside the file:

  • using pug templating instead of HTML
  • fetching project detail asynchronously
  • loading project’s state via Vue’s computed property
  • head() cannot access computed project state in a template, so we’re accessing the store directly to fill in project’s meta data
  • project’s content is stored as a Rich-text with couple of nested components. We’ll cover the rendering of Rich-text in the following example.

Rendering Rich-text components

Content model

In Kentico Kontent, you can extend Rich-text editor functionality with custom inline Components. With Components, you’ll both create more appealing content for visitors and you’ll still get nicely structured response from Delivery API.

I use components a lot. If you take a look at this project, there couple of Components within the Rich-text: Image with Caption, YouTube Video, Point-of-sale list, Publication Info. (Here’s the list of all used Rich-text components).

There are couple of ways, how you can go about rendering the components, we’ll cover the two ways we tried.

Resolving components with kentico-kontent-nuxt-module (and kontent-delivery-sdk-js)

kentico-kontent-nuxt-module is “wrapping” kontent-delivery-sdk-js and gives you tools to ease the work with JS SDK in Nuxt.js app. With this toolset, you need to:

We have tried this approach at first, and it was fine; we were able to write all Rich-text components this way. What we didn’t like so much with this approach was that with JS SDK you have to write resolvers as interpolated string. This way, content-heavy components got less maintainable templates. And on top of that we weren’t using Vue’s native component approach (yeah, we wanted to marry Vue components with Kentico Kontent components). So we rewrote resolvers into Vue components the following way:

Rendering Kentico Kontent components as Vue components

@vit-svoboda wrote kontent-rich-text-for-vue—an NPM package to help you resolve/render Kontent’s rich-text components as Vue components. Let me walk you through how to render components. I’ll use “Project” content type as an example as it includes a lot of components:

  • set rich_text_components in project store
  • write a Rich text component that you want to be rendered (take an inspiration from the list of Rich-text components in this project)
  • write a Vue component that will keep the list of all your Rich text components to be rendered. Here's mine—rich-text-component.vue.
  • use it all in Project Vue template:
    • import { RichText } from 'kontent-rich-text-for-vue' and use it in a <template> section
    • in <script> section take a look at: componets, richTextComponent, provide ()

Custom list of projects

There is a list of projects at homepage. These projects don’t have any automatic ordering (e.g. sort by date desc), but they’re custom-ordered based on agency’s preferences.

Content model (Custom list in Kentico Kontent)

In Kentico Kontent, I’ve created a “Project list” content type (see its definition). The “Project list” has one “Linked items” element element accepting only the “Project” content type. This way you can update the order of the project anytime in Kentico Kontent.

Getting the list of projects

All projects are stored as a structured content in Kentico Kontent. We’ll get data as a structured JSON via Kentico Kontent Delivery API and “load” it to a Vuex Store. Here’s how it’s done for project detail:

Projects list — Vue component

Vue component is located at pages/components/projects-list.vue; as a component it’s used at pages/index.vue

Combining Single-page application (SPA) and server-side rendered content

Almost all the projects at tota.sk were offline projects (e.g. this book). But one project—translit—is different. It’s an online project, a single page application to transliterate Rusyn language from Cyrillic script to Latin alphabet and vice versa.

Here’s the thing. By default, Nuxt.js can work in one of the two modes—as a Universal SSR (Server-side rendering) or an SPA (single page application). You have to choose one mode and I’ve chosen Universal SSR (for SEO reasons + I wanted to generate a static site).

I though it may be an issue if I’d like to run client-side JavaScript while the whole repo is in Server-side Rendering (SSR) mode. Fortunately, the Nuxt has a <client-only> component that let’s you wrap another component that is supposed to be executed at client side.

Take a look at how it’s used in code:

By the way, if you’d ever need a transliteration script, it’s also available on GitHub as an open-source NPM package—translit.

Generating static site and sitemap

Static site

When you’re running Nuxt.js in Universal SSR mode, generating a static site is easy—you call npm run generate. You will get a static HTML file for each page you have. However, the static generation is not including dynamic pages by default.

In this project, majority of content are dynamic pages (projects and articles, in particular). If I wanted to generate static files of them, I had to include the routes in nuxt.config.js file. Here’s the official documentation and here’s how I adjusted my nuxt.config.js file. There are two promises calling for a list of projects and for a list of articles.

Sitemap

I have used @nuxtjs/sitemap package to auto-generate a Sitemap. This module will generate sitemap.xml for those pages that are known, i.e. not for the dynamic pages. But if you set the routes as we already did to generate a static site, you are all set.

By the way, the module is rather robust and I’m only using a portion of it. However, if you’d like to take a look at my config, take a look at nuxt.config.js file.

Adding Cookie Consent

I have decided to use the cookieconsent NPM package. It seemed to have a lot configuration options. However, the JavaScript configuration has to be executed at client side (I have talked about Server vs. Client server rendering elsewhere).

Here’s the documentation of how you can run client-side JS in SSR mode. Here’s how I have included the configuration in the master template.

Schema.org metadata

Lazy-loading images

Special thanks

@vit-svoboda for making it happen. He helped me a lot with JavaScript + he has done done an awesome Vue module for parsing Kentico Kontent’s Rich-text components.

License

Feel free to get inspired by the code snippets. All other content (written content and logotypes related to tota agentura) are copyrighted.

You can’t perform that action at this time.