mcpField
V
vue-nuxt

vue-nuxt

github.com/martinholovsky開発48227 回インストール47 週間前に更新
リポジトリ

vue-nuxt について

JARVIS AI Assistant の HUD に焦点を当てた、Vue 3・Nuxt 3 開発向けスキルガイドです。セキュリティ、性能、TypeScript を重視し、レスポンシブなコンポーネントやサーバールート、3D UI のテスト・入力サニタイズ・デプロイ確認のパターンを扱います。

主な機能

  1. 01Vue 3 Composition API と TypeScript
  2. 02Nuxt サーバールートとセキュリティ設定
  3. 03入力検証と HTML サニタイズ
  4. 04リアクティブ性能の最適化と遅延読み込み
  5. 05コンポーネントテストとセキュリティ検証

活用シーン

  1. 01JARVIS HUD コンポーネントと 3D シーンの構築
  2. 02検証付き API ルートの実装
  3. 03動的コンテンツの XSS リスク低減
  4. 04デプロイ前の型・脆弱性・ビルド確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/martinholovsky/claude-skills-generator --skill vue-nuxt

インストール後、Claude Code で/vue-nuxtを入力して読み込まれたか確認します。

同梱ファイルreferences/advanced-patterns.mdreferences/security-examples.md

詳細

Vue 3 / Nuxt 3 開発スキル

ファイル構成:このスキルは分割構成を採用しています。高度なパターンとセキュリティの例については、references/を参照してください。

1. 概要

このスキルでは、Vue 3とNuxt 3を使用してJARVIS AI アシスタントのユーザーインターフェースを構築するための知識を提供します。セキュリティを最優先する開発手法を取り入れながら、レスポンシブで高パフォーマンスな3D HUDインターフェースを作成することに重点を置いています。

リスクレベル:中 - ユーザー入力を処理し、動的コンテンツを表示します。XSSの攻撃経路となる可能性があります。

主な用途:

  • JARVISインターフェース向けのリアクティブな3D HUDコンポーネントの構築
  • 初期読み込み時のパフォーマンス向上を目的としたサーバーサイドレンダリング
  • クライアントサイドの状態管理の統合
  • ユーザー入力とAPIレスポンスの安全な処理

2. 主な責務

2.1 基本原則
  1. TDDを優先:実装前にテストを作成します。レッド/グリーン/リファクタリングのサイクルで進めます。
  2. パフォーマンスを考慮:最適なリアクティビティを実現するため、computed、shallowRef、遅延読み込みコンポーネントを使用します。
  3. Composition APIを優先:TypeScriptの型推論とコード構成を改善するため、<script setup>を使用したVue 3 Composition APIを使用します。
  4. サーバーサイドのセキュリティ:機密性の高い処理にはNuxtのサーバールートを活用し、シークレットをクライアントに公開しません。
  5. リアクティブな状態の安全性:状態の破損を防ぐため、適切な型を指定してref()とreactive()を使用します。
  6. 入力のサニタイズ:ユーザー入力は、表示または処理する前に必ずサニタイズします。
  7. パフォーマンスの最適化:3D HUDのパフォーマンスを高めるため、遅延読み込み、コード分割、効率的なリアクティビティを実装します。
  8. 型安全性:コンパイル時にエラーを検出できるよう、TypeScriptを全体で徹底します。
  9. セキュアなデフォルト設定:CSPヘッダーを設定し、危険な機能はデフォルトで無効にします。

3. 技術スタックとバージョン

3.1 推奨バージョン
パッケージバージョンセキュリティに関する注意
Vue^3.4.0リアクティビティが改善された最新の安定版
Nuxt^3.12.4+重大:CVE-2024-34344のRCEを修正
@nuxt/devtools^1.3.9+重大:CVE-2024-23657を修正
vite^5.0.0セキュリティパッチ適用済みの最新バージョン
3.2 セキュリティ上重要な依存関係
{
  "dependencies": {
    "nuxt": "^3.12.4",
    "vue": "^3.4.0",
    "dompurify": "^3.0.6",
    "isomorphic-dompurify": "^2.0.0"
  },
  "devDependencies": {
    "@nuxt/devtools": "^1.3.9",
    "eslint-plugin-vue": "^9.0.0",
    "eslint-plugin-security": "^2.0.0"
  }
}

4. 実装パターン

4.1 セキュアなコンポーネント構成
<script setup lang="ts">
// ✅ Type-safe props with validation
interface Props {
  hudData: HUDDisplayData
  userId: string
}

const props = defineProps<Props>()

// ✅ Emit events with typed payloads
const emit = defineEmits<{
  'update:status': [status: string]
  'command:execute': [command: JARVISCommand]
}>()

// ✅ Secure ref initialization
const displayState = ref<HUDState>({
  isActive: false,
  securityLevel: 'standard'
})
</script>

<template>
  
  <div class="hud-panel">
    <span v-text="props.hudData.title" />
  </div>
</template>
4.2 入力サニタイズのパターン
// composables/useSanitize.ts
import DOMPurify from 'isomorphic-dompurify'

export function useSanitize() {
  const sanitizeHTML = (dirty: string): string => {
    // ✅ Strict sanitization for any HTML content
    return DOMPurify.sanitize(dirty, {
      ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'span'],
      ALLOWED_ATTR: ['class']
    })
  }

  const sanitizeText = (input: string): string => {
    // ✅ Strip all HTML for plain text
    return DOMPurify.sanitize(input, { ALLOWED_TAGS: [] })
  }

  return { sanitizeHTML, sanitizeText }
}
4.3 セキュアなAPIルートのパターン
// server/api/jarvis/command.post.ts
import { z } from 'zod'

// ✅ Define strict schema for command validation
const commandSchema = z.object({
  action: z.enum(['status', 'control', 'query']),
  target: z.string().max(100).regex(/^[a-zA-Z0-9-_]+$/),
  parameters: z.record(z.string()).optional()
})

export default defineEventHandler(async (event) => {
  const body = await readBody(event)

  // ✅ Validate input against schema
  const result = commandSchema.safeParse(body)
  if (!result.success) {
    throw createError({
      statusCode: 400,
      message: 'Invalid command format'  // ✅ Generic error message
    })
  }

  // ✅ Process validated command
  const command = result.data

  // Never log sensitive data
  console.log(`Processing command: ${command.action}`)

  return { success: true, commandId: generateSecureId() }
})
4.4 セキュアな環境設定
// nuxt.config.ts
export default defineNuxtConfig({
  // ✅ Security headers
  routeRules: {
    '/**': {
      headers: {
        'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",
        'X-Content-Type-Options': 'nosniff',
        'X-Frame-Options': 'DENY',
        'X-XSS-Protection': '1; mode=block'
      }
    }
  },

  // ✅ Runtime config - secrets stay server-side
  runtimeConfig: {
    apiSecret: process.env.API_SECRET,  // Server only
    public: {
      apiBase: '/api'  // Client accessible
    }
  },

  // ✅ Disable devtools in production
  devtools: { enabled: process.env.NODE_ENV === 'development' }
})
4.5 3D HUDコンポーネントの統合
<script setup lang="ts">
// components/HUDDisplay.vue
import { TresCanvas } from '@tresjs/core'

const props = defineProps<{
  metrics: SystemMetrics
}>()

// ✅ Validate metrics before rendering
const validatedMetrics = computed(() => {
  return {
    cpu: Math.min(100, Math.max(0, props.metrics.cpu)),
    memory: Math.min(100, Math.max(0, props.metrics.memory)),
    status: sanitizeText(props.metrics.status)
  }
})
</script>

<template>
  <TresCanvas>
    <HUDMetricsDisplay :data="validatedMetrics" />
  </TresCanvas>
</template>

5. 実装ワークフロー(TDD)

5.1 ステップ1:最初に失敗するテストを書く

期待される動作を定義するテストを、必ず最初に作成します。

// tests/components/VoiceIndicator.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import VoiceIndicator from '@/components/VoiceIndicator.vue'

describe('VoiceIndicator', () => {
  it('displays idle state by default', () => {
    const wrapper = mount(VoiceIndicator)
    expect(wrapper.find('.indicator').classes()).toContain('idle')
    expect(wrapper.text()).toContain('Ready')
  })

  it('shows listening state when active', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    expect(wrapper.find('.indicator').classes()).toContain('listening')
    expect(wrapper.find('.pulse-animation').exists()).toBe(true)
  })

  it('emits cancel event on escape key', async () => {
    const wrapper = mount(VoiceIndicator, {
      props: { isListening: true }
    })
    await wrapper.trigger('keydown.escape')
    expect(wrapper.emitted('cancel')).toBeTruthy()
  })
})
5.2 ステップ2:テストを通すための最小限の実装

テストを通すのに必要な最小限のコードだけを記述します。

<script setup lang="ts">
const props = defineProps<{ isListening?: boolean }>()
const emit = defineEmits<{ 'cancel': [] }>()

const handleKeydown = (e: KeyboardEvent) => {
  if (e.key === 'Escape') emit('cancel')
}
</script>

<template>
  <div
    class="indicator"
    :class="isListening ? 'listening' : 'idle'"
    @keydown="handleKeydown"
    tabindex="0"
  >
    <span v-if="!isListening">Ready</span>
    <div v-else class="pulse-animation" />
  </div>
</template>
5.3 ステップ3:必要に応じてリファクタリング

テストに合格したら、動作を変えずにコードの品質を向上させます。リファクタリングのたびにテストを再実行してください。

5.4 ステップ4:全体の検証を実行
# Run all verification steps before committing
npx vitest run                    # Unit tests
npx eslint . --ext .vue,.ts       # Linting
npx nuxi typecheck                # Type checking
npm run build                     # Build verification

6. パフォーマンスパターン

6.1 派生状態にはcomputedプロパティを使用
// ❌ BAD - Recalculates in template on every render
<template>
  <div>{{ items.filter(i => i.active).length }} active</div>
</template>

// ✅ GOOD - Cached until dependencies change
const activeCount = computed(() => items.value.filter(i => i.active).length)
<template>
  <div>{{ activeCount }} active</div>
</template>
6.2 大きなオブジェクトにはshallowRefを使用
// ❌ BAD - Deep reactivity on large 3D data
const meshData = ref<MeshData>({ vertices: new Float32Array(100000), ... })

// ✅ GOOD - Shallow reactivity, manual trigger
const meshData = shallowRef<MeshData>({ vertices: new Float32Array(100000), ... })
// Trigger update explicitly
meshData.value = { ...newData }
triggerRef(meshData)
6.3 遅延読み込みにはdefineAsyncComponentを使用
// ❌ BAD - All components loaded upfront
import HeavyChart from '@/components/HeavyChart.vue'

// ✅ GOOD - Load only when needed
const HeavyChart = defineAsyncComponent(() =>
  import('@/components/HeavyChart.vue')
)

// With loading state
const HeavyChart = defineAsyncComponent({
  loader: () => import('@/components/HeavyChart.vue'),
  loadingComponent: LoadingSpinner,
  delay: 200
})
6.4 リストの最適化にはv-memoを使用

<div v-for="item in items" :key="item.id">
  <ExpensiveComponent :data="item" />
</div>


<div v-for="item in items" :key="item.id" v-memo="[item.id, item.updated]">
  <ExpensiveComponent :data="item" />
</div>
6.5 長いリストには仮想スクロールを使用
<script setup lang="ts">
import { useVirtualList } from '@vueuse/core'

const { list, containerProps, wrapperProps } = useVirtualList(
  items,
  { itemHeight: 50 }
)
</script>

<template>
  
  <div v-bind="containerProps" class="h-[400px] overflow-auto">
    <div v-bind="wrapperProps">
      <div v-for="{ data, index } in list" :key="index">
        {{ data.name }}
      </div>
    </div>
  </div>
</template>
6.6 デバウンス付きウォッチャー
// ❌ BAD - Fires on every keystroke
watch(searchQuery, async (query) => {
  results.value = await searchAPI(query)
})

// ✅ GOOD - Debounced to reduce API calls
import { watchDebounced } from '@vueuse/core'

watchDebounced(
  searchQuery,
  async (query) => {
    results.value = await searchAPI(query)
  },
  { debounce: 300 }
)

// Alternative with manual debounce
watch(searchQuery, useDebounceFn(async (query) => {
  results.value = await searchAPI(query)
}, 300))

7. セキュリティ基準

7.1 既知の脆弱性(CVE調査)
CVE深刻度説明対策
CVE-2024-34344高テストコンポーネント経由のNuxt RCENuxt 3.12.4+に更新
CVE-2024-23657高Devtoolsのパストラバーサル/RCEdevtoolsを1.3.9+に更新
CVE-2023-3224重大開発サーバーのコードインジェクションNuxt 3.4.4+に更新し、開発サーバーを公開しないでください

参照:詳細な対策コードについてはreferences/security-examples.mdを参照してください。

5.2 OWASP Top 10 のカバー範囲
OWASP カテゴリーリスク緩和策
A01 Broken Access Control高サーバー側のルートガード、ミドルウェア認証
A03 Injection高Zod による入力検証、パラメーター化クエリ
A05 Security Misconfiguration中CSP ヘッダー、安全な nuxt.config
A07 XSS高v-text ディレクティブ、DOMPurify によるサニタイズ
5.3 入力検証フレームワーク
// ❌ DANGEROUS - Direct v-html with user input
<div v-html="userMessage" />

// ✅ SECURE - Sanitized HTML or plain text
<div v-html="sanitizeHTML(userMessage)" />
<span v-text="userMessage" />
5.4 認証ミドルウェア
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  const { authenticated } = useAuthState()

  if (!authenticated.value && to.meta.requiresAuth) {
    return navigateTo('/login')
  }
})

6. テストと品質

6.1 セキュリティテスト
// tests/security/xss.test.ts
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import HUDPanel from '@/components/HUDPanel.vue'

describe('XSS Prevention', () => {
  it('should sanitize malicious input', () => {
    const wrapper = mount(HUDPanel, {
      props: {
        title: '<script>alert("xss")</script>Hello'
      }
    })

    expect(wrapper.html()).not.toContain('<script>')
    expect(wrapper.text()).toContain('Hello')
  })
})
6.2 コンポーネントテスト
// tests/components/HUDDisplay.test.ts
describe('HUDDisplay', () => {
  it('validates metric bounds', () => {
    const wrapper = mount(HUDDisplay, {
      props: {
        metrics: { cpu: 150, memory: -10, status: 'active' }
      }
    })

    // Should clamp values to valid range
    expect(wrapper.vm.validatedMetrics.cpu).toBe(100)
    expect(wrapper.vm.validatedMetrics.memory).toBe(0)
  })
})

7. 一般的なパターン/ワークフロー

7.1 JARVIS HUD コンポーネントのワークフロー
  1. すべてのデータ構造についてTypeScript インターフェースを定義します
  2. 共有ロジック用のコンポーザブルを作成します
  3. Composition API を使用してコンポーネントを実装します
  4. コンポーネントの境界で入力検証を追加します
  5. XSS/インジェクションに対するセキュリティテストを作成します
  6. TresJS を介して3D シーンと統合します
7.2 API 統合ワークフロー
  1. リクエスト/レスポンス用のZod スキーマを定義します
  2. 検証を備えたサーバールートを作成します
  3. エラー処理を備えたクライアントコンポーザブルを実装します
  4. UI に読み込み/エラー状態を追加します
  5. エラーケースと境界条件をテストします

8. よくある間違いとアンチパターン

8.1 重大なセキュリティ上のアンチパターン
禁止:サニタイズされていない入力に v-html を使用する

<div v-html="userProvidedContent" />


<div v-html="sanitizeHTML(userProvidedContent)" />


<span v-text="userProvidedContent" />
禁止:クライアントコードでシークレットを公開する
// ❌ DANGEROUS - Secret in public config
runtimeConfig: {
  public: {
    apiKey: process.env.API_KEY  // Exposed to client!
  }
}

// ✅ SECURE - Secrets stay server-side
runtimeConfig: {
  apiKey: process.env.API_KEY,  // Server only
  public: {
    apiBase: '/api'
  }
}
禁止:クライアント側の検証だけを信頼する
// ❌ DANGEROUS - Client-only validation
const handleSubmit = () => {
  if (isValidEmail(email.value)) {
    $fetch('/api/subscribe', { body: { email: email.value } })
  }
}

// ✅ SECURE - Server-side validation
// server/api/subscribe.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const result = emailSchema.safeParse(body)
  if (!result.success) {
    throw createError({ statusCode: 400, message: 'Invalid email' })
  }
  // Process validated email
})
8.2 パフォーマンス上のアンチパターン
回避:computed 内のリアクティブ配列
// ❌ BAD - Creates new array on every access
const filtered = computed(() => {
  return items.value.filter(i => i.active).sort()
})

// ✅ GOOD - Memoized with stable reference
const filtered = computed(() => {
  const result = items.value.filter(i => i.active)
  result.sort((a, b) => a.name.localeCompare(b.name))
  return result
})

9. クイックリファレンス

必須コマンド
# Development
npx nuxi dev --host  # Never expose to public network!

# Security audit
npm audit --audit-level=high
npx nuxi typecheck

# Production build
npx nuxi build
主要なコンポーザブル
// State management
const state = useState<T>('key', () => initialValue)

// Runtime config access
const config = useRuntimeConfig()

// Route navigation
const router = useRouter()
await navigateTo('/path')

13. デプロイ前チェックリスト

セキュリティ検証
  • Nuxt バージョン >= 3.12.4(CVE-2024-34344 の修正)
  • Devtools バージョン >= 1.3.9(CVE-2024-23657 の修正)
  • nuxt.config で CSP ヘッダーを設定済み
  • runtimeConfig.public にシークレットがない
  • すべてのユーザー入力を DOMPurify でサニタイズ済み
  • サーバールートで Zod スキーマによる検証を実施
  • 保護対象のルートに認証ミドルウェアを設定
  • 本番環境で Devtools を無効化
ビルド検証
  • npm audit で高または重大な脆弱性が検出されない
  • TypeScript のコンパイルが成功する
  • すべてのセキュリティテストが成功する
  • 本番ビルドがエラーなく完了する

14. まとめ

この Vue/Nuxt スキルでは、JARVIS AI アシスタント HUD インターフェースを構築するための安全なパターンを紹介します。

  1. セキュリティを最優先:常に入力をサニタイズし、サーバー側で検証し、CSP ヘッダーを使用します
  2. 型安全性:厳格な検証スキーマを用いて、コード全体で TypeScript を使用します
  3. パフォーマンス:Composition API、遅延読み込み、効率的なリアクティビティを活用します
  4. 保守性:明確なコンポーネント構造と、再利用のためのコンポーザブルを使用します

重要:JARVIS HUD は機密性の高いシステムデータを扱います。すべてのコンポーネントで、ユーザー入力は悪意がある可能性を前提に扱い、あらゆるデータ境界で検証してください。


参考資料:

  • references/advanced-patterns.md - 複雑なコンポーネントパターン
  • references/security-examples.md - セキュリティ実装の詳細

コメント