Exclusive tips every week

Join 13,567+ other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

    Picture of Michael Thiessen

    👋Hey friend! I work hard to send you amazing stuff each week.

    — Michael

    I really love and enjoy reading these emails.

    You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.

    Fabian Beer

    Here's my latest newsletter

    🔥 (#205) Flatten Nuxt Content Routes, Mock Any Import, and more

    Hey!

    I hope you're having a wonderful week.

    Where I'm living in Waterloo, we've already had 140 cm of snow this February. That's almost as much snow in the last 3 weeks as we usually get in an entire winter.

    I'm so tired from shoveling snow 🥲

    This week I've been working on the lesson outlines for Mastering Nuxt while we get a new design done for the app that we build in the course.

    And as always, I've got some tips and articles for you!

    — Michael

    🔥 Flatten Nuxt Content Routes

    I wanted to organize my blog content into several folders:

    • Articles: content/articles/
    • Newsletters: content/newsletters/

    By default though, Nuxt Content would set up these routes to include those prefixes. But I want all of my routes to be at the root level:

    • Articles: michaelnthiessen.com/my-latest-article
    • Newsletters: michaelnthiessen.com/most-recent-newsletter

    We can do this manually for each Markdown file by overriding the _path property through it's frontmatter:

    ---
    title: My Latest Article
    date: today
    _path: "/my-latest-article"
    ---

    This is extremely tedious, error-prone, and generally annoying.

    Luckily, we can write a simple Nitro plugin that will do this transform automatically.

    Create a content.ts file in server/plugins/:

    export default defineNitroPlugin((nitroApp) => {
    nitroApp.hooks.hook('content:file:afterParse', (file) => {
    for (const prefix of ['/articles', '/newsletters']) {
    if (file._path.startsWith(prefix)) {
    // Keep the prefix so we can query based on it still
    file._original_dir = prefix;
    // Remove prefix from path
    file._path = file._path.replace(prefix, '');
    }
    }
    });
    });

    Nitro is the server that Nuxt uses internally. We can hook into it's processing pipeline and do a bit of tweaking.

    However, doing this breaks queryContent calls if we're filtering based on the path, since queryContent is looking at the _path property we've just modified. This is why we want to keep that original directory around.

    We can modify our queryContent calls to filter on this new _original_dir property:

    // Before
    queryContent('/articles')
    // After
    queryContent()
    .where({
    _original_dir: { $eq: '/articles' },
    });

    Pro tip: use nuxi clean to force Nuxt Content to re-fetch and re-transform all of your content.

    🔥 Directly accessing parent components (and why)

    Props down, events up. That's how your components should communicate — most of the time.

    But in rare cases, that just doesn't work.

    If you need direct access to the parent component, you should just use provide/inject to pass down the relevant value or method:

    import { provide } from 'vue';
    const someMethodInTheParent = () => {};
    provide('method', someMethodInTheParent)

    Then, inject it into the child component:

    import { inject } from 'vue';
    const method = inject('method');
    method();

    In Vue 2, you can also use the instance property $parent:

    // Tight coupling like this is usually a bad idea
    this.$parent.methodOnParentComponent();

    This is simpler, but leads to higher coupling and will more easily break your application if you ever refactor.

    You can also get direct access to the application root, the very top-most component in the tree, by using $root. Vue 2 also has $children, but these were taken out for Vue 3 (please don't use this one).

    When would these be useful?

    There are a few different scenarios I can think of. Usually, when you want to abstract some behaviour and have it work "magically" behind the scenes.

    You don't want to use props and events to connect up a component in those cases. Instead, you use provide/inject, $parent, or $root, to automatically connect the components and make things happen.

    (This is similar to the Compound Component pattern)

    But it's hard to come up with an example where this is the best solution. Using provide/inject is almost always the better choice.

    🔥 Mock Any Import in Nuxt

    One handy helper method in @nuxt/test-utils is mockNuxtImport.

    It's a convenience method to make it easier to mock anything that Nuxt would normally auto-import:

    import { mockNuxtImport } from '@nuxt/test-utils/runtime';
    mockNuxtImport('useAsyncData', () => {
    return () => {
    return { data: 'Mocked data' };
    };
    });
    // ...tests

    🎙️ #047 — A Vue at Alexander Lichter

    If you've listened to the last episode, you know what is coming next!

    It is time to get take a Vue at the other host of this podcast. Michael is asking Alex all around his past - from how we got into programming and web development, if university was worth it and how he got into the Nuxt Core Team.

    Also don't miss out how Minecraft is part of the history, what non-tech job Alex would do if programming wouldn't be in the cards, and why is GitHub account is over 14 years old.

    Watch on YouTube or listen on your favorite podcast platform.

    Chapters:

    In case you missed them:

    📜 Exploring Server Components in Nuxt

    You may have heard about server components, but there are some really interesting things you can do with them.

    In this article I explore a few really cool things we can do with server components.

    Check it out here: Exploring Server Components in Nuxt

    📅 Upcoming Events

    Here are some upcoming events you might be interested in. Let me know if I've missed any!

    Vuejs Amsterdam 2025 — (March 12, 2025 to March 13, 2025)

    The biggest Vue conference in the world! A two-day event with workshops, speakers from around the world, and socializing.

    Check it out here

    VueConf US 2025 — (May 13, 2025 to May 15, 2025)

    Giving a talk here on component patterns! A great Vue conference, this year held in Tampa. Two days of conference talks, plus a day for workshops.

    Check it out here

    MadVue 2025 — (May 29, 2025)

    It's time to get together in Madrid. Join for a full day of talks, activities, and networking with the Vue.js community and ecosystem.

    Check it out here

    💬 The real problem

    "Sometimes the problem is to discover what the problem is." — Gordon Glegg

    🧠 Spaced-repetition: Default Content with Slots

    The 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.

    You can provide fallback content for a slot, in case no content is provided:

    <!-- Child.vue -->
    <template>
    <div>
    <slot>
    Hey! You forgot to put something in the slot!
    </slot>
    </div>
    </template>

    This content can be anything, even a whole complex component that provides default behaviour:

    <!-- Child.vue -->
    <template>
    <div>
    <slot name="search">
    <!-- Can be overridden with more advanced functionality -->
    <BasicSearchFunctionality />
    </slot>
    </div>
    </template>

    Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.

    Sign up for it here.

    p.s. I also have a bunch of products/courses:

    Here's what others are saying

    I'm starting to think that your newsletter is one of the best things that happened to me this year. I just love these emails.
    Stanislaw Gregor
    I'm somewhere in the upper-middle level at Vue, and I never miss an email you and always find something cool when reading!
    Eduard Climov
    This is the first time where I'm actually enjoying email newsletters. I like your format a lot.
    Fahmi Alfituri
    You have great content in your emails. I seriously learn something from every one of them.
    Titus Decali
    Just wanted to say I enjoy these emails. They encourage me to constantly improve my craft. Fantastic work.
    Joe Radman
    Thanks for another beautiful tip 🙏
    Victor Martins Onuoha
    Loving these, and the spaced repetition.
    Mark Goldstein
    I really enjoy reading your emails, because I love Vue. Thanks for these emails.
    Arturo Espinoza
    I really love and enjoy reading these emails. You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.
    Fabian Beer
    THANK YOU! I did not know about the deep property, so I assumed you simply couldn't watch objects.
    Darryl Noakes
    I really must say you are doing a really great job. Now I am aware of a cleaner and more performant way to use Tailwind. Thanks a lot!
    Henry Eze
    Thank you so much, I really enjoy and appreciate your emails.
    Carlos Gonzalez
    Thanks for sharing great Vue tips.
    Fernando Navarro
    I really enjoy these tips.
    Martin H
    Thank you so much for the weekly Vue education. Thanks and live on longer to educate us more.
    Kabolobari Benakole
    I look forward to your emails every week. This week was something I knew, but I like to be reminded of. Thanks for keeping it up!
    Nathan Strutz
    Thank you for your weekly emails. I always look forward to learning a new tip about Vue or at least relearning old tips :)
    Colin Johnson
    I have really been enjoying your weekly emails, and I also got my two team members to join in on the fun as well.
    Keith Dawson
    Thank you for your newsletter, your explanations have very concise examples and I like it.
    Nicolas Decayeux
    Thanks A LOT for your great work!!! One of the few newsletters that I let pass!
    Martin Tillmann

    Want to level up your Vue skills?

    With over two million reads and 11,067 subscribers, you've come to the right place.

    Subscribe now to get exclusive insights and tips every week.