Hey!
This week I've got a new article for you on composable patterns.
You can read it here: 7 Composable Design Patterns
I'm also hard at work on the composable patterns course!
I'm planning to do an early access launch next week, with the full course available in early 2025. It will be a similar format as Clean Components Toolkit:
If you're interested in getting early access (and a special discount), you can sign up for the waitlist here: Composable Patterns Course Early Access
And if you haven't yet filled out the State of Vue.js Survey, please do! It takes less than 5 minutes and helps people in the community understand what you all want from the Vue ecosystem.
We've also got a new episode of the podcast on security with Jakub Andrzejewski.
And of course, we've got some tips and more.
Enjoy!
— Michael
With Nuxt Content 2 we can customize how Markdown gets rendered in our Nuxt 3 apps by creating our own custom Prose
components.
We do get code highlighting built-in through Shiki, but I already have a custom theme for Prism.
So I needed to create a custom ProseCode
component that used PrismJS to render the code blocks from my Markdown:
<template><pre :class="`language-${language}`"><code v-html="highlighted"></code></pre></template>
import Prism from 'prismjs';const { code = '', language = null, filename = null, highlights = [] } = defineProps<{code?: string;language?: string | null;filename?: string | null;highlights?: Array<number>;}>();const highlighted = language? Prism.highlight(code,Prism.languages[language],language): code;
When we place this component in ~components/content
and name it ProseCode
, Nuxt Content knows to use it when rendering code blocks from Markdown.
We get a few props, and then use PrismJS
to highlight it. This is all done on the server too, so our code is already highlighted before it hits the client.
Note: the formatting inside of the pre
tag looks weird because it will preserve any formatting, including newlines. Moving the code
element to the next line and indenting would cause the code rendered to the page to also have an extra newline and a few spaces in front of it.
You can create custom Prose
components for most elements.
If you want some styles to apply specifically to slot content, you can do that with the :slotted
pseudo-selector:
<style scoped>/* Add margin to <p> tags within the slot */:slotted(p) {margin: 15px 5px;}</style>
You can also use :global
to have styles apply to global scope, even within the <style scoped>
block:
<style scoped>:global(body) {margin: 0;padding: 0;font-family: sans-serif;}</style>
Of course, if you have lots of global styles you want to add, it's probably easier to just add a second <style>
block:
<style scoped>/* Add margin to <p> tags within the slot */:slotted(p) {margin: 15px 5px;}</style><style>body {margin: 0;padding: 0;font-family: sans-serif;}</style>
Check out the docs for more info.
It took me a very long time to realize this, but anything in your component that is reactive can be watched. This includes computed refs as well:
const first = ref('Michael');const last = ref('Thiessen');const fullName = computed(() => `${first.value} ${last.value}`);watchEffect(() => console.log(fullName.value));
Maybe it's just me, but for some reason this wasn't all that intuitive at first for me.
With the Options API it looks like this:
export default {computed: {someComputedProperty() {// Update the computed prop},},watch: {someComputedProperty() {// Do something when the computed prop is updated}}};
You can watch:
Security is a topic that is often overlooked in the frontend world. But at least for you all - no longer! To make sure we cover Security for Vue and Nuxt applications as broad as possible, Michael and Alex are joined by Jakub Andrzejewski, who is not only a Senior Frontend Developer but also author of the Nuxt Security Module. We cover not only the module but also how to avoid common security mistakes as a Vue developer and how to protect your applications from vulnerabilities, and which are the most common ones.
Of course, we can't miss out on the State of Vue.js Survey, which is currently running and was co-created by Jakub as well!
Besides talking about the Security and the State of Vue.js, we also discuss how Jakub got into Vue.js at first and how he perceived the transition to Vue 3 and the Composition API.
Watch on YouTube or listen on your favorite podcast platform.
Chapters:
In case you missed them:
A database is useless without any data.
But with Prisma, adding in seed data (or “dummy” data) is extremely easy.
In this article we’ll cover:
Check it out here: Prisma with Nuxt: Seeding the Database with Dummy Data (3 of 5)
We know that Nuxt is a fantastic tool.
But it has so many amazing features that it’s hard to keep track of them all.
That’s why I’ve compiled this giant list of 24 Nuxt tips for you — use them to save time and write better Nuxt apps.
We cover a lot of topics here, including:
Of course, there is so much more!
Check it out here: 24 Time-Saving Tips for Nuxt
Here are some upcoming events you might be interested in. Let me know if I've missed any!
The biggest Vue conference in the world! A two-day event with workshops, speakers from around the world, and socializing.
A great Vue conference, this year held in Tampa. Two days of conference talks, plus a day for workshops.
"If debugging is the process of removing software bugs, then programming must be the process of putting them in." — Edsger Dijkstra
If...Else
ComponentThe best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬
Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.
Ever thought about making an If...Else
component in Vue, despite having v-if
, v-else
, and v-else-if
?
Here's a quirky experiment that explores this idea:
<If :val="mainCondition"><template #true>Render if true</template><Else :if="false">Else if condition</Else><template #false>Otherwise render this</template></If>
This setup uses Compound Components, default and named slots, and even render functions to achieve a flexible If...Else
logic.
The If
component checks a condition and decides which slot (true
, false
, or Else
) to render.
The Else
component — a Compound Component — allows for an else if
condition.
I have a detailed write up about this component on my blog.
Here's a simplified version for a cleaner API:
<If :val="condition"><True>Truth</True><Else :if="elseCondition">Else slot</Else><False> What up false branch! </False></If>
This experiment is a fun way to dive deep into Vue's features like slots, reactivity, and component communication. While it might not replace the built-in directives, it's a great learning exercise and could inspire other creative component designs.
Check out the demo and maybe even try implementing your version: Vue If...Else Component Demo
Remember — experimenting with "weird" ideas is a fantastic way to deepen your understanding of Vue!
Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.
p.s. I also have a bunch of products/courses: