Skip to content

Latest commit

 

History

History
1250 lines (857 loc) · 34.3 KB

slides.md

File metadata and controls

1250 lines (857 loc) · 34.3 KB
layout highlighter css colorSchema transition
shiki
unocss
dark
fade-out

Harnessing the power of the Nuxt Content Module

With Selemon Brahanu
VueJS Kenya
October 19th 2023

layout: intro growX: 10 growY: 90 style: 'padding-left: 8rem;'

Selemon Brahanu

Front-End Engineer
Speaker at VueJs Kenya.
Creator of Windi UI , Nuxt UI Vue and MarkQuest
Open source contributor.


layout: 'center' class: 'text-center' growX: 50 growY: 10

Nuxt Content Module

- What is the Nuxt Content Module ✨?

The Nuxt Content Module is an official module created by the Nuxt team that provides a powerful data layer for your Nuxt 3 application.

It enables you to write your content in the `content` directory and fetch them using an API with a MongoDB like syntax with the help of the queryContent() composable.

It supports various formats that you can write your content in such as:

  • Markdown
  • JSON
  • YAML
  • CSV
  • etc


layout: 'center' class: 'text-center' growX: 50 growY: 10

Installation

- There are 4 ways of installing the Nuxt Content Module ✨

Using the CLI

```bash pnpm add @nuxt/content ```

Using the nuxi CLI

```bash npx nuxi module add @nuxt/content ```

Using the Nuxt Devtools

Using the Nuxtr VSCode extension


layout: 'center' class: 'text-center' growX: 50 growY: 10

Configuration

Add the module

// nuxt.config.ts file

export default defineNuxtConfig({
  modules: ["@nuxt/content"]
})

Configuration

The Nuxt Content module can be configured anyway you like as long as you know what you want.

What can be configured?

The Content APIs

Markdown configs e.g Anchor Links, plugins etc

Themes

Sources


layout: 'center' class: 'text-center' growX: 50 growY: 10

Content

- What is the content directory?

This is where we write our content using a file which has a `.md` extension

The content module has a feature that NuxtJs and NextJs share.

That feature is known as file-based routing but in our case we will call it content-based routing because we are using the content directory.

Where each file is a path generated by the content module according to the directory structure

`content/index.md` is the same as `pages/index.vue` in the sense that they both resolve to '/'

`content/blog/index.md` and `pages/blog/index.vue` both resolve to '/blog'


layout: 'center' class: 'text-center' growX: 50 growY: 10

Content

- How do we write our content in a .md file?

Let's start from the top

1. Front-matter

The Front-matter uses the YAML syntax with key-value pairs to provide meta-data to pages.

---
title: 'Nuxt Content Module Talk'
description: 'Selemondev is giving a talk about the Nuxt Content Module'
head:
  meta:
    - name: 'keywords'
      content: 'nuxt-content, vuejs-kenya, nuxt3'
    - name: 'author'
      content: 'Selemondev'
---

Under the hood the useContentHead() composable is utilized to set the page's meta-data


layout: 'center' class: 'text-center' growX: 50 growY: 10

Content

That becomes this:

<head>
    <meta charset="UTF-8">
    <meta name="description" content="Selemondev is giving a talk about the Nuxt Content Module">
    <meta name="keywords" content="nuxt-content, vuejs-kenya, nuxt3">
    <meta name="author" content="Selemondev">
    
    <title>Nuxt Content Module Talk</title>
</head>

If you want to use images in your markdown, you can place the images in the `public` directory and use it as such:

![VueJs-Kenya](/vuejs-kenya.png)

or you can check out the Nuxt Content Assets module built by Dave Stewart for relative media path references.


layout: 'center' class: 'text-center' growX: 50 growY: 10

Fetch

- How do we fetch our contents?

By using the useAsyncData() composable provided by Nuxt together with the queryContent() composable provided by the Nuxt Content module

const { data } = useAsyncData(() => queryContent('/'))

The queryContent() composable provides us with methods for querying and fetching our contents.

These methods include:

  • find() - Returns all the content
  • only() - Returns only the selected subset of fields
  • findOne()
  • without() - Returns the result with a subset of fields removed


layout: 'center' class: 'text-center' growX: 50 growY: 10

Fetch

  • limit() - Returns all only the number of result(s) specified
  • count() - Returns the numbers of articles of a given path
  • skip() - Skip the specified number of results
  • where() - Filter the results by query
  • etc

const { data } = useAsyncData(() => 
queryContent('/')
.only(['author', "_path", "title", "description", "date"])
.sort({
  date: -1
})
.limit(1)
.find()
)
const { data } = useAsyncData(() => 
queryContent('/blog')
.only(['author', "_path", "title", "description", "date"])
.count()
)

layout: 'center' class: 'text-center' growX: 50 growY: 10

Fetch

- How do we fetch our contents?

By using the ContentQuery renderless component by the Nuxt Content module.

<template>
  <div>
    <ContentQuery query="/blog" :only="['_path', 'title', 'description', 'date']" v-slot="{ data }">
      <pre>{{  data  }}</pre>
    </ContentQuery>
  </div>
</template>

The ContentQuery renderless component shortens the access to the queryContent() composable.


layout: 'center' class: 'text-center' growX: 50 growY: 10

Rendering

- How do we render our content?

By using the ContentDoc component provided by the Nuxt Content module.

The ContentDoc component fetches and display the markdown component based on the current path.

<template>
  <div class="m-auto">
    <ContentDoc class="dark:text-white " />
  </div>
</template>

layout: 'center' class: 'text-center' growX: 50 growY: 10

Components

- What are the components provided by the Nuxt Content module?

ContentList

This component fetches a list of documents and allows you to render them by using slots:

<template>
  <div>
    <ContentList path="/blog" :only="['_path']"  v-slot="{ list }">
      <pre>{{  list  }}</pre>
    </ContentList>
  </div>
</template>

layout: 'center' class: 'text-center' growX: 50 growY: 10

Components

ContentNavigation

This component is a renderless component that shortens the access to the navigation.

<template>
  <div>
    <ContentNavigation path="/blog"  v-slot="{ navigation }">
      <pre>{{  navigation  }}</pre>
    </ContentNavigation>
  </div>
</template>

ContentSlot

This component makes it easier to use Markdown syntax in your Vue components.


layout: 'center' class: 'text-center' growX: 50 growY: 10

Q/A

Q/A

Questions?

Challenge

Homework


layout: intro class: text-center pb-5 growX: 50 growY: 120

Thank You!