Part 4 - Extending the Landing Page with nuxt/content and Multilingual Support

In this tutorial, we'll extend our landing page with a multilingual content page that displays Markdown files using the nuxt/content module.

15.09.2024

Introduction

In the previous parts of this series, we set up a Nuxt project, configured i18n, and implemented a landing page. In this fourth part, we'll extend our application with a multilingual content page that displays Markdown files using the nuxt/content module. We'll add a button to the landing page that links to this new content page and ensure that the content is displayed in the correct language.

Prerequisites

Make sure you've completed the previous parts of this series:

  1. Part 1 - Creating a new project with Nuxt, TailwindCSS, NuxtContent, Nuxt i18n
  2. Part 2 - Configuring nuxt/i18n
  3. Part 3 - Implementing a Landing Page with Nuxt and i18n

Step-by-Step Guide

Step 1: Preparing the Translations

First, we'll extend our translation files with the new content. Open the files locales/en-US.json and locales/de-DE.json and add the following content:

en-US.json:

{
  "hero": {
    // ... existing translations ...
    "content_button": "View Content"
  },
  "content": {
    "title": "Content Page",
    "back_to_home": "Back to Home"
  }
}

de-DE.json:

{
  "hero": {
    // ... existing translations ...
    "content_button": "Inhalt anzeigen"
  },
  "content": {
    "title": "Inhaltsseite",
    "back_to_home": "Zurück zur Startseite"
  }
}

Step 2: Adding the Content Button to the Hero Component

Open the file components/Hero.vue and add the new button:

<template>
  <section class="bg-blue-600 text-white py-20">
    <div class="mx-auto px-4 w-full">
      <div class="flex justify-between items-center">
        <div class="w-2/3">
          <h1 class="text-5xl font-bold mb-4">{{ $t('hero.title') }}</h1>
          <p class="text-xl mb-8">{{ $t('hero.subtitle') }}</p>
          <div class="space-x-4">
            <button class="bg-white text-blue-600 py-2 px-6 rounded-full font-bold hover:bg-blue-100 transition duration-300">
              {{ $t('hero.cta') }}
            </button>
            <NuxtLink 
              :to="localePath('/content')" 
              class="bg-blue-500 text-white py-2 px-6 rounded-full font-bold hover:bg-blue-400 transition duration-300">
              {{ $t('hero.content_button') }}
            </NuxtLink>
          </div>
        </div>
        <div class="ml-auto">
          <LanguageSelector />
        </div>
      </div>
    </div>
  </section>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { useLocalePath } from 'vue-i18n-routing'
import LanguageSelector from './LanguageSelector.vue'

const { t } = useI18n()
const localePath = useLocalePath()
</script>

Step 3: Creating the Content Page

Create a new file pages/content.vue with the following content:

<template>
  <div class="container mx-auto px-4 py-8">
    <h1 class="text-3xl font-bold mb-4">{{ $t('content.title') }}</h1>
    <ContentDoc :path="contentPath" class="prose lg:prose-lg" />
    <NuxtLink 
      :to="localePath('/')" 
      class="mt-4 inline-block bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600 transition duration-300"
    >
      {{ $t('content.back_to_home') }}
    </NuxtLink>
  </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { useLocalePath } from 'vue-i18n-routing'
import { computed } from 'vue'

const { locale } = useI18n()
const localePath = useLocalePath()

const contentPath = computed(() => `/${locale.value}/content`)
</script>

Step 4: Creating Markdown Content

Create a new folder content in the root directory of your project. In this folder, we'll create Markdown files for our content.

Create a subfolder for each supported language in the content directory:

content/
  en/
    content.md
  de/
    content.md

Fill these files with the appropriate content in the respective language. For example:

content/en/content.md:

# Welcome to the Content Page

This is an example content rendered with nuxt/content.

## Features of nuxt/content

- Markdown support
- Automatic parsing
- Easy integration into Nuxt applications

Learn more about nuxt/content in the [official documentation](https://content.nuxtjs.org/).

content/de/content.md:

# Willkommen auf der Inhaltsseite

Dies ist ein Beispielinhalt, der mit nuxt/content gerendert wird.

## Funktionen von nuxt/content

- Markdown-Unterstützung
- Automatisches Parsing
- Einfache Integration in Nuxt-Anwendungen

Erfahre mehr über nuxt/content in der [offiziellen Dokumentation](https://content.nuxtjs.org/).

Step 5: Styling the Markdown Content

To ensure our Markdown content looks good, we'll add a TailwindCSS plugin:

npm install -D @tailwindcss/typography

Define this plugin in the tailwind.config.ts file (if this file doesn't exist yet, please create it in the root folder):

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/typography'),
  ],
}

Now we can add the prose TailwindCSS class to our ContentDoc tag. It should look like this:

<ContentDoc class="prose lg:prose-lg" />

Step 6: Testing the Multilingual Content Page

Start the development server with npm run dev and open http://localhost:3000 in your browser. You should now see the new "View Content" button on the landing page. Click on it to go to the content page, where you should see the rendered Markdown content in the currently selected language. Switch the language and check if the content updates accordingly.

Summary

In this fourth part of our series, we've successfully extended our landing page with a multilingual content page that displays Markdown files using the nuxt/content module. We've learned how to:

  1. Add a new button to the landing page that links to the content page
  2. Create a new page that displays the content of Markdown files
  3. Create and style Markdown content
  4. Manage multilingual content with nuxt/content and i18n
  5. Dynamically adapt the content page to the selected language

This extension provides a solid foundation for a multilingual content management system in your Nuxt application. In future tutorials, we could explore how to manage multiple content pages, add metadata to Markdown files, or implement more advanced features of nuxt/content.

You can find the code from this tutorial on Github.