← back to blog

Migrating Trailhead to Nuxt 3

In this post I share how I approached migrating Trailhead to Nuxt 3: the decisions, the stumbles and what I’d do differently next time. No fluff — straight to what matters.

# Context

The starting point was simple on the surface, but full of details under the hood. I wanted a predictable base, easy to test, that wouldn’t force me to relearn everything for each new feature.

The core idea was to isolate logic in composables/ and keep components as dumb as possible — presentation only.

# Hands on

In practice, the heart of it lived in a single composable. Notice how state and actions come out together, ready for any component to consume:

// composables/useGroups.ts
export function useGroups() {
  const groups = ref<Group[]>([])

  async function load() {
    groups.value = await request(endpoint, GroupsQuery)
  }

  return { groups, load }
}

Tip: start with the smallest step that delivers value. The rest comes later — and almost always simpler than you imagined.

The takeaways I kept from this snippet:

  • State close to the logic, far from the UI.
  • Typing early avoids 80% of the annoying bugs.
  • A small test today is worth an afternoon of debugging tomorrow.

# Conclusion

In the end, what unblocks a project is rarely the newest technology — it’s the decision to keep things simple and testable. If this post saved you a few minutes, it was worth it. 🚀

← back to blog