---
name: coding-vue3-vuetify
description: Build production-grade Vue 3 + TypeScript + Vuetify 3 interfaces with architectural rigor. Use when creating Vue components, pages, layouts, Pinia stores, or API modules. Enforces strict typing, Composition API patterns, Material Design 3 aesthetics, and bulletproof data handling.
---

This skill crafts Vue 3 + Vuetify 3 code that is architecturally sound, type-safe to the bone, and visually polished. Every component should feel like it belongs in a production codebase that senior engineers would be proud to maintain.

The user provides: $ARGUMENTS (component specs, page requirements, feature requests, or architectural questions).

## Architectural Thinking

Before writing a single line, establish clarity:

- **Component Identity**: Is this a Page, Layout, Reusable Component, Composable, Store, or API Module? Each has distinct patterns.
- **Data Gravity**: Where does state live? Props flow down, events bubble up. Pinia for cross-component state. `provide/inject` for deep hierarchies.
- **Scroll Strategy**: Which container owns the scroll? Never the body. Always explicit. Always controlled.
- **Failure Modes**: What happens when data is `null`? Empty array? Network timeout? Design for the unhappy path first.

**CRITICAL**: Production code anticipates chaos. Type everything. Guard everything. Gracefully degrade everything.

## Core Dogma

### TypeScript Absolutism
- `<script setup lang="ts">` — the ONLY acceptable incantation
- `any` is forbidden — use `unknown` + type guards, generics, utility types
- Every prop, emit, ref, and API response wears its type proudly
- Types live in `@/types/`, organized by domain: `user.d.ts`, `order.d.ts`

### Composition API Purity
- `ref`, `reactive`, `computed`, `watchEffect` — master these four
- `shallowRef`, `readonly`, `toRaw` — know when to reach for optimization
- Lifecycle via `onMounted`, `onUnmounted` — never mix Options API
- Pinia stores: typed state, typed getters, typed actions — no exceptions

### Vuetify 3 + Material Design 3
- ALL UI through Vuetify components — no raw HTML for UI elements
- Theme-aware always — `rgb(var(--v-theme-surface))`, never `#ffffff`
- `useDisplay()` for responsive logic — breakpoints are first-class citizens
- Density matters — `density="compact"` for data-heavy interfaces

### Layout Philosophy
```
┌─────────────────────────────────┐
│  Toolbar (flex-shrink-0)        │
├─────────────────────────────────┤
│                                 │
│  Content Area                   │
│  (flex-grow-1, overflow-y-auto) │
│  (min-height: 0) ← CRITICAL     │
│                                 │
├─────────────────────────────────┤
│  Footer (flex-shrink-0)         │
└─────────────────────────────────┘
```
- **No body scroll** — viewport locked, content scrolls in containers
- **Flexbox trap**: `flex-grow-1` children MUST have `min-height: 0`
- **Sticky elements**: filters, table headers — always visible during scroll

## Data Robustness Patterns

Treat all external data as hostile:

```typescript
// Defensive access
const userName = user?.profile?.name ?? 'Unknown'

// Array safety
const items = Array.isArray(response.data) ? response.data : []

// Existence guards in templates
<template v-if="user">{{ user.name }}</template>
<v-empty-state v-else />
```

## UI State Trinity

Every data-driven view handles THREE states:

| State | Component | Never Do |
|-------|-----------|----------|
| **Loading** | `v-skeleton-loader` | Show stale data or blank screen |
| **Empty** | `v-empty-state` with action | Leave white void |
| **Error** | Snackbar + retry option | Silent failure |

## Table & List Commandments

- `fixed-header` on every `v-data-table` — non-negotiable
- Truncated text gets `v-tooltip` — users deserve full content on hover
- 100+ items? `v-virtual-scroll` — DOM nodes stay constant
- Column widths explicit — no layout lottery

## Anti-Patterns (NEVER)

- `.js` files in a TypeScript project
- `any` without a blood oath and written justification
- Hardcoded colors: `color="#1976d2"` → `color="primary"`
- Body-level scrolling in SPA layouts
- Tables without fixed headers
- Truncated text without tooltips
- Empty states that are literally empty
- Loading states that freeze the UI
- API calls without error handling

## Reference Files

Consult these for implementation details:

| Need | Read |
|------|------|
| Advanced TypeScript patterns | `reference/typescript-rules.md` |
| Complex layout structures | `reference/layout-patterns.md` |
| API client architecture | `reference/api-patterns.md` |
| Tables, lists, forms, feedback | `reference/ui-interaction.md` |

## Project Anatomy

```
src/
├── api/          # Axios instance + modules
├── components/   # Shared components
├── composables/  # Reusable hooks
├── layouts/      # Page shells
├── pages/        # Route views
├── plugins/      # Vuetify, Pinia, Router
├── store/        # Pinia stores
├── styles/       # Global SCSS
├── types/        # Type definitions
└── utils/        # Pure functions
```

## Output Protocol

1. State the architectural approach (2-3 sentences)
2. List files to create with their purposes
3. Implement each file completely — no placeholders, no TODOs
4. Verify against the anti-patterns list
5. Call out any assumptions or trade-offs made

---

Remember: You're not writing code that works. You're writing code that works, scales, maintains, and delights. Every `ref` is typed. Every edge case is handled. Every loading state is beautiful. This is what production-grade means.
