18 Prompts for Vue.js and Nuxt: Components, Composables, and Routing

18 Prompts for Vue.js and Nuxt: Components, Composables, and Routing\n\nVue.js has evolved from a lightweight framework into a full-featured ecosystem, and Nuxt has become the go-to meta-framework for building production-grade applications. But even experienced developers sometimes spend hours debugging reactive state, structuring composables, or fine-tuning route guards. That is where large language models (LLMs) can act as an on-demand pair programmer — if you know how to phrase the request.\n\nThis article provides 18 ready-to-use prompts that cover the most common Vue.js and Nuxt tasks: from component design and composable patterns to routing and state management with Pinia. Each prompt is specific, copy-paste ready, and accompanied by an explanation of which problem it solves, plus a real usage example. Whether you are building a SaaS dashboard, a content site, or a complex enterprise app, these prompts will save you time and help you avoid anti-patterns.\n\n### Why Prompts Matter for Vue.js and Nuxt Development\n\nA well-crafted prompt does more than generate code — it encodes best practices. Vue.js 3 (Composition API), Nuxt 3 (auto-imports, file-based routing, server routes), and the surrounding ecosystem (Pinia, Vue Router, Vitest) have specific conventions. A generic “write a component” prompt can yield jQuery-style spaghetti; a precise prompt that specifies Composition API, <script setup>, TypeScript, and proper reactivity yields production-ready code.\n\nAccording to the official Vue.js documentation, the Composition API was introduced to enable better logic reuse and type inference (vuejs.org/guide/extras/composition-api-faq). Nuxt 3 documentation highlights that file-based routing and auto-imports reduce boilerplate significantly (nuxt.com/docs/getting-started/routing). These are not just buzzwords — they are architectural decisions. The prompts below reflect those decisions.\n\n### Part 1: Component Design Prompts\n\n1. Build a reusable data table component\n- Task: Generate a generic <DataTable> component with sorting, filtering, and pagination.\n- Explanation: Data tables are ubiquitous in dashboards. This prompt forces the LLM to think about props, slots, and emit events.\n- Prompt:\n \n Create a Vue 3 component using `<script setup>` and TypeScript. It should accept a `columns` array (each with `key`, `label`, `sortable`), and a `rows` array. Include client-side sorting by clicking column headers, a text filter input that filters rows by all columns, and pagination with configurable page size (default 10). Emit a `row-click` event. Use `computed` for filtered and sorted data. Do NOT use any external library except Vue itself.\n\n- Usage example: After pasting this prompt, the LLM returns a complete single-file component that you can drop into your Nuxt project’s components/ folder.\n\n2. Design a modal dialog with named slots\n- Task: Create a modal component with header, body, and footer slots.\n- Explanation: Modals need accessible markup, transition animations, and keyboard handling.\n- Prompt:\n \n Write a Vue 3 `<BaseModal>` component with three named slots: `header`, `body`, `footer`. It should have a `modelValue` prop for visibility (v-model support). Add a `<Transition>` for fade effect, close on `Escape` key, and close when clicking outside. Use `teleport` to `body`. Write in `<script setup>` with TypeScript.\n\n- Usage example: The generated component can be reused across any Nuxt page — just import and pass content via slots.\n\n3. Generate a form input with validation\n- Task: Build a reusable input component that integrates with VeeValidate or custom validation.\n- Explanation: Forms are everywhere; a consistent input component improves UX.\n- Prompt:\n \n Create a Vue 3 component `<FormInput>` that accepts `label`, `type` (text, email, password), `modelValue`, `error` (string). It should display a label, an input field, and an error message below. Add a `password` toggle button for password type. Use `computed` to toggle input type. Emit `update:modelValue`. Style with scoped CSS — minimal, clean.\n\n- Usage example: Wrap this component in a form and use v-model on each field; validation errors can be passed from a parent or a validation library.\n\n4. Create a lazy-loaded image component\n- Task: Implement an image that loads only when visible (Intersection Observer).\n- Explanation: Performance matters — lazy loading reduces initial page weight.\n- Prompt:\n \n Write a Vue 3 component `<LazyImage>` with props `src`, `alt`, `placeholder` (optional). Use `IntersectionObserver` inside `onMounted` to set `src` only when the element enters the viewport. Show a placeholder or blur effect until loaded. Handle errors gracefully (show fallback). Use `<script setup>` and TypeScript.\n\n- Usage example: Replace all <img> tags in your Nuxt blog with <LazyImage> to improve Lighthouse scores.\n\n5. Build a theme toggle (dark/light) component\n- Task: Create a switch that toggles CSS custom properties.\n- Explanation: Dark mode is a common feature; this prompt ensures proper reactivity and persistence.\n- Prompt:\n \n Create a Vue 3 component `<ThemeToggle>`. It should use a `ref` `isDark` initialized from `localStorage`. On change, toggle a `dark` class on `<html>` and save to `localStorage`. Use a sun/moon icon (SVG inline). The component should be a simple button. Use `<script setup>`.\n\n- Usage example: Put <ThemeToggle> in your Nuxt layout default.vue and add corresponding CSS variables.\n\n### Part 2: Composables and Logic Reuse Prompts\n\n6. Write a useFetch composable with loading and error states\n- Task: Create a generic composable for API calls.\n- Explanation: Nuxt has useFetch built-in, but sometimes you need a custom version for a specific API client.\n- Prompt:\n \n Write a Vue 3 composable `useApi` that takes a URL and optional options (method, headers, body). Return reactive `data`, `error`, `loading`, and an `execute` function. Use `ref` and `watchEffect` to fetch when URL changes. Handle HTTP errors (non-2xx). Write in TypeScript.\n\n- Usage example: Use const { data, loading } = useApi('/api/users') in any component.\n\n7. Create a composable for debounced search\n- Task: Implement debounce logic for search inputs.\n- Explanation: Debouncing prevents excessive API calls.\n- Prompt:\n \n Write a composable `useDebounce` that takes a `ref` source and a delay (default 300ms). Return a `computed` value that updates only after the source stops changing for `delay` ms. Use `watch` and `setTimeout`/`clearTimeout`. Write in TypeScript.\n\n- Usage example: const debouncedQuery = useDebounce(searchQuery, 300) — then watch debouncedQuery to trigger API call.\n\n8. Build a useLocalStorage composable\n- Task: Persist reactive state to localStorage.\n- Explanation: Many apps need to remember user preferences.\n- Prompt:\n \n Write a composable `useLocalStorage` that takes a key and default value. Return a `ref` that syncs with `localStorage` — read on init, write on change. Use `watch` with `{ deep: true }` for objects. Handle JSON serialization. Write in TypeScript.\n\n- Usage example: const theme = useLocalStorage('theme', 'light') — changes persist across page reloads.\n\n9. Create a composable for media queries\n- Task: Reactive breakpoint detection.\n- Explanation: Responsive components need to know viewport size.\n- Prompt:\n \n Write a composable `useMediaQuery` that takes a CSS media query string (e.g., '(min-width: 768px)'). Return a `ref` boolean that updates when the query matches. Use `window.matchMedia` and addEventListener for 'change'. Clean up in `onUnmounted`. Write in TypeScript.\n\n- Usage example: const isDesktop = useMediaQuery('(min-width: 1024px)') — conditionally render sidebar.\n\n10. Write a useClickOutside composable\n- Task: Detect clicks outside a given element (for dropdowns).\n- Explanation: A common pattern for closing popovers.\n- Prompt:\n \n Write a composable `useClickOutside` that takes a `ref` to an element and a callback. Add a `mousedown` listener on `document` that checks if the target is outside the element. Clean up in `onUnmounted`. Write in TypeScript.\n\n- Usage example: `<template ref=

← All posts

Comments