Skip to content

Instantly share code, notes, and snippets.

@thomasweitzel
Last active November 7, 2024 00:24
Show Gist options
  • Save thomasweitzel/d1d4e60bfddd71442cb9d87f07fbc85b to your computer and use it in GitHub Desktop.
Save thomasweitzel/d1d4e60bfddd71442cb9d87f07fbc85b to your computer and use it in GitHub Desktop.

How to use Vue.js in a Tailwind CSS styled Hugo blog post

Since I don't want to include the Vue.js JavaScript code in every page, I control it with a parameter in the post's frontmatter.

---
vue: 2
---

The head template has to include a conditional section that only gets activated if the parameter is set to either 2 (Vue version 2) or 3 (Vue version 3). Only then is the Vue.js JavaScript code loaded.

It looks like this:

Image of blog post

The example below shows how a set of cards is rendered, controlled only by values in a JavaScript array.

Additionally, I've included a request to get a random Kanye West quote.

<!-- Add to your head.html template (or wherever you fill your head section) -->
{{ if eq .Params.Vue 3 }}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
{{ else if eq .Params.Vue 2 }}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
{{ end }}
---
title: "How to use Vue.js in a Hugo blog post"
description: "Shows possibilities of using Vue.js without build step in a blog post."
date: "2020-03-29"
vue: 2
---
# Vue.js in a Hugo blog post
<div id="cards" class="bg-blue-50 rounded-md">
<div class="max-w-md sm:max-w-xl lg:max-w-6xl mx-auto lg:px-12 py-8">
<div class="text-xl text-gray-900">Popular destinations</div>
<div class="text-gray-600">A selection of great work-friendly cities with lots to see and explore.</div>
<div class="flex flex-wrap -mx-4">
<div class="mt-6 w-full px-4 lg:w-1/2 xl:w-1/2" v-for="destination in destinations">
<div class="flex items-center rounded-md bg-white shadow-md overflow-hidden">
<img class="h-40 w-40 flex-shrink-0" :src="destination.img" :alt="destination.name"/>
<div class="px-6 py-4">
<div class="text-lg font-semibold text-gray-800">{{ destination.name }}</div>
<div class="text-gray-600">${{ destination.avg }} / night average</div>
<div class="mt-4">
<a href="#" class="text-indigo-500 hover:text-indigo-400 font-semibold">Explore {{ destination.props }} properties</a>
<div class="mt-1">
<div class="mt-2 flex flex-center">
<svg v-for="i in 5" :class="i <= destination.rating ? 'text-yellow-300' : 'text-gray-200'" class="h-4 w-4 fill-current" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
<path d="M 23.946579,9.08402 C 23.818193,8.67059 23.47675,8.36928 23.065767,8.30686 L 16.095645,7.24705 12.978431,0.63656 C 12.794616,0.2468 12.415276,0 12.000001,0 11.584654,0 11.205313,0.2468 11.021571,0.63656 L 7.9045757,7.24697 0.93423529,8.30678 C 0.52325253,8.36928 0.18173676,8.67059 0.05342285,9.08395 -0.07489106,9.49738 0.03210994,9.95117 0.32954508,10.25452 L 5.3732856,15.39922 4.182163,22.66507 C 4.111969,23.0935 4.280217,23.52642 4.6162044,23.7819 4.8062748,23.92646 5.0314061,24 5.2576285,24 5.4312596,24 5.6056181,23.9567 5.7652831,23.86884 l 6.2346459,-3.43013 6.234572,3.43013 c 0.16061,0.0884 0.336496,0.13047 0.510709,0.13116 0.601927,-9.1e-4 1.089578,-0.51179 1.089578,-1.14188 0,-0.0877 -0.0095,-0.17318 -0.02735,-0.25517 l -1.180793,-7.20365 5.04374,-5.14478 c 0.297508,-0.30335 0.404509,-0.75714 0.276195,-1.1705 z"/>
</svg>
<span class="ml-2 text-gray-600 text-sm truncate"> {{ destination.reviews }} reviews</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="max-w-md sm:max-w-xl lg:max-w-6xl mx-auto lg:px-12 py-8 items-center text-center justify-center">
<span class=" text-lg font-semibold">{{ quote }}</span>
<span> - Kanye West</span>
</div>
</div>
</div>
<script>
const app = new Vue({
el: '#cards',
data: {
destinations: [
{ name: 'Toronto', img: '//picsum.photos/250?id=1', avg: '120', props: 42, rating: 5, reviews: 255, },
{ name: 'Seattle', img: '//picsum.photos/250?id=2', avg: '135', props: 67, rating: 3, reviews: 102, },
{ name: 'New York', img: '//picsum.photos/250?id=3', avg: '180', props: 156, rating: 4, reviews: 1962, },
{ name: 'Huston', img: '//picsum.photos/250?id=4', avg: '110', props: 23, rating: 1, reviews: 387, },
],
quote: 'Loading ...',
},
methods: {
getQuote: function () {
fetch('https://api.kanye.rest')
.then(response => response.json())
.then(data => this.quote = data.quote);
}
},
created() {
this.getQuote();
},
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment