mcpField
L
laravel-inertia-vue

laravel-inertia-vue

github.com/jasim-k開発0157 回インストール33 週間前に更新
リポジトリ

laravel-inertia-vue について

laravel-inertia-vueは、Laravel、Inertia.js、Vue 3を使うモノリシックアプリ開発向けのスキルです。優先度別のルールで、ページ、フォーム、ナビゲーション、共有データ、レイアウト、アップロード、応用パターンを扱います。

主な機能

  1. 016カテゴリにわたる24ルール
  2. 02型付きInertiaページコンポーネント
  3. 03フォームとバリデーションのパターン
  4. 04ナビゲーションと共有データの指針
  5. 05永続・ネストレイアウト
  6. 06アップロードと応用ページパターン

活用シーン

  1. 01型付きInertiaページコンポーネントの作成
  2. 02フォーム送信とバリデーションの処理
  3. 03認証情報とフラッシュデータの共有
  4. 04アップロード、ポーリング、無限スクロールの実装

インストール

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

$npx skills add https://github.com/jasim-k/laravel-agent-skills --skill laravel-inertia-vue

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

AGENTS.md
metadata.json
README.md
rules/
_sections.md
_template.md
form-dirty-tracking.md
form-file-uploads.md
form-progress-indicator.md
form-reset-handling.md
form-transform-data.md
form-useform-basic.md
form-useform-hook.md
form-validation-errors.md
layout-persistent.md
nav-external-links.md
nav-link-component.md
nav-preserve-state.md
nav-programmatic.md
nav-replace-history.md
page-component-structure.md
page-default-layout.md
page-head-management.md
page-partial-reloads.md
page-props-typing.md
page-scroll-preservation.md
shared-app-config.md
shared-auth-user.md
shared-flash-messages.md
shared-ziggy-routes.md

詳細

Laravel + Inertia.js + Vue 3

Laravel、Inertia.js、Vue 3 を使用したモダンなモノリシックアプリケーション構築のための包括的なパターンです。シームレスなフルスタック開発のための 30 以上のルールを収録しています。

適用するタイミング

以下の場合に、これらのガイドラインを参照してください。

  • Vue 3 で Inertia のページコンポーネントを作成するとき
  • useForm コンポーザブルでフォームを扱うとき
  • 共有データと認証を管理するとき
  • 永続レイアウトを実装するとき
  • ページ間を移動するとき

優先度別ルールカテゴリー

優先度カテゴリー影響度プレフィックス
1ページコンポーネント重大page-
2フォームとバリデーション重大form-
3ナビゲーションとリンク高nav-
4共有データ高shared-
5レイアウト中layout-
6ファイルアップロード中upload-
7高度なパターン低advanced-

クイックリファレンス

1. ページコンポーネント(重大)
  • page-props-typing - Laravel からのページプロパティの型指定
  • page-component-structure - 標準的なページコンポーネントのパターン
  • page-head-management - Head によるタイトルとメタタグの管理
  • page-default-layout - ページへのレイアウトの割り当て
2. フォームとバリデーション(重大)
  • form-useform-basic - useForm の基本的な使い方
  • form-validation-errors - Laravel のバリデーションエラーの表示
  • form-processing-state - フォーム送信状態の処理
  • form-reset-preserve - フォームデータのリセットと保持
  • form-transform - 送信前のデータ変換
3. ナビゲーションとリンク(高)
  • nav-link-component - ナビゲーションに Link を使用
  • nav-preserve-state - スクロール位置と状態の保持
  • nav-partial-reloads - 変更があった部分だけを再読み込み
  • nav-replace-history - 履歴の置き換えと追加
4. 共有データ(高)
  • shared-auth-user - 認証済みユーザーへのアクセス
  • shared-flash-messages - フラッシュメッセージの処理
  • shared-global-props - グローバルプロパティへのアクセス
  • shared-typescript - 共有データの型指定
5. レイアウト(中)
  • layout-persistent - 永続レイアウトのパターン
  • layout-nested - ネストされたレイアウト
  • layout-default - デフォルトレイアウトの割り当て
  • layout-conditional - 条件付きレイアウト
6. ファイルアップロード(中)
  • upload-basic - ファイルアップロードの基本
  • upload-progress - アップロード進行状況の追跡
  • upload-multiple - 複数ファイルのアップロード
7. 高度なパターン(低)
  • advanced-polling - リアルタイムポーリング
  • advanced-prefetch - ページのプリフェッチ
  • advanced-modal-pages - ページとしてのモーダル
  • advanced-infinite-scroll - 無限スクロール

基本パターン

TypeScript を使用したページコンポーネント

<script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3'

interface Post {
  id: number
  title: string
  excerpt: string
  created_at: string
  author: {
    id: number
    name: string
  }
}

interface Props {
  posts: {
    data: Post[]
    links: { url: string | null; label: string; active: boolean }[]
  }
  filters: {
    search?: string
  }
}

const props = defineProps<Props>()
</script>

<template>
  <Head title="Posts" />

  <div class="container mx-auto py-8">
    <h1 class="text-2xl font-bold mb-6">Posts</h1>

    <div class="space-y-4">
      <article
        v-for="post in props.posts.data"
        :key="post.id"
        class="p-4 bg-white rounded-lg shadow"
      >
        <Link :href="route('posts.show', post.id)">
          <h2 class="text-xl font-semibold hover:text-blue-600">
            {{ post.title }}
          </h2>
        </Link>
        <p class="text-gray-600 mt-2">{{ post.excerpt }}</p>
        <p class="text-sm text-gray-400 mt-2">By {{ post.author.name }}</p>
      </article>
    </div>
  </div>
</template>
useForm を使用したフォーム

<script setup lang="ts">
import { Head, Link, useForm } from '@inertiajs/vue3'

interface Category {
  id: number
  name: string
}

interface Props {
  categories: Category[]
}

const props = defineProps<Props>()

const form = useForm({
  title: '',
  body: '',
  category_id: '',
})

function submit() {
  form.post(route('posts.store'), {
    onSuccess: () => form.reset(),
  })
}
</script>

<template>
  <Head title="Create Post" />

  <form @submit.prevent="submit" class="max-w-2xl mx-auto py-8">
    <div class="mb-4">
      <label for="title" class="block font-medium mb-1">Title</label>
      <input
        id="title"
        v-model="form.title"
        type="text"
        class="w-full border rounded px-3 py-2"
      />
      <p v-if="form.errors.title" class="text-red-500 text-sm mt-1">
        {{ form.errors.title }}
      </p>
    </div>

    <div class="mb-4">
      <label for="category" class="block font-medium mb-1">Category</label>
      <select
        id="category"
        v-model="form.category_id"
        class="w-full border rounded px-3 py-2"
      >
        <option value="">Select a category</option>
        <option v-for="cat in props.categories" :key="cat.id" :value="cat.id">
          {{ cat.name }}
        </option>
      </select>
      <p v-if="form.errors.category_id" class="text-red-500 text-sm mt-1">
        {{ form.errors.category_id }}
      </p>
    </div>

    <div class="mb-4">
      <label for="body" class="block font-medium mb-1">Content</label>
      <textarea
        id="body"
        v-model="form.body"
        rows="10"
        class="w-full border rounded px-3 py-2"
      />
      <p v-if="form.errors.body" class="text-red-500 text-sm mt-1">
        {{ form.errors.body }}
      </p>
    </div>

    <div class="flex gap-4">
      <button
        type="submit"
        :disabled="form.processing"
        class="px-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50"
      >
        {{ form.processing ? 'Creating...' : 'Create Post' }}
      </button>

      <Link :href="route('posts.index')" class="px-4 py-2 border rounded">
        Cancel
      </Link>
    </div>
  </form>
</template>
永続レイアウト

<script setup lang="ts">
import { Link, usePage } from '@inertiajs/vue3'
import { computed } from 'vue'

const page = usePage()
const auth = computed(() => page.props.auth as { user: { name: string } })
</script>

<template>
  <div class="min-h-screen bg-gray-100">
    <nav class="bg-white shadow">
      <div class="container mx-auto px-4 py-3 flex justify-between">
        <Link href="/" class="font-bold">My App</Link>
        <span>Welcome, {{ auth.user.name }}</span>
      </div>
    </nav>

    <main class="container mx-auto px-4 py-8">
      <slot />
    </main>
  </div>
</template>

<script setup lang="ts">
import AppLayout from '@/Layouts/AppLayout.vue'

defineOptions({ layout: AppLayout })
</script>

<template>
  <h1>Dashboard</h1>
</template>
Laravel コントローラー
<?php

namespace App\Http\Controllers;

use App\Http\Requests\StorePostRequest;
use App\Models\Post;
use App\Models\Category;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class PostController extends Controller
{
    public function index(): Response
    {
        return Inertia::render('Posts/Index', [
            'posts' => Post::with('author:id,name')
                ->latest()
                ->paginate(10),
            'filters' => request()->only('search'),
        ]);
    }

    public function create(): Response
    {
        return Inertia::render('Posts/Create', [
            'categories' => Category::all(['id', 'name']),
        ]);
    }

    public function store(StorePostRequest $request): RedirectResponse
    {
        $post = Post::create([
            ...$request->validated(),
            'user_id' => auth()->id(),
        ]);

        return redirect()
            ->route('posts.show', $post)
            ->with('success', 'Post created successfully.');
    }

    public function show(Post $post): Response
    {
        return Inertia::render('Posts/Show', [
            'post' => $post->load('author', 'category'),
        ]);
    }
}
共有データ(HandleInertiaRequests)
<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;
use Inertia\Middleware;

class HandleInertiaRequests extends Middleware
{
    public function share(Request $request): array
    {
        return array_merge(parent::share($request), [
            'auth' => [
                'user' => $request->user() ? [
                    'id' => $request->user()->id,
                    'name' => $request->user()->name,
                    'email' => $request->user()->email,
                ] : null,
            ],
            'flash' => [
                'success' => $request->session()->get('success'),
                'error' => $request->session()->get('error'),
            ],
        ]);
    }
}
フラッシュメッセージコンポーネント

<script setup lang="ts">
import { usePage } from '@inertiajs/vue3'
import { computed, ref, watch } from 'vue'

const page = usePage()
const flash = computed(() => page.props.flash as { success?: string; error?: string })
const visible = ref(false)
let timer: ReturnType<typeof setTimeout> | null = null

watch(flash, (newFlash) => {
  if (newFlash.success || newFlash.error) {
    visible.value = true
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      visible.value = false
    }, 3000)
  }
}, { deep: true })
</script>

<template>
  <div v-if="visible" class="fixed top-4 right-4 z-50">
    <div
      v-if="flash.success"
      class="bg-green-500 text-white px-4 py-2 rounded shadow"
    >
      {{ flash.success }}
    </div>
    <div
      v-if="flash.error"
      class="bg-red-500 text-white px-4 py-2 rounded shadow"
    >
      {{ flash.error }}
    </div>
  </div>
</template>

使い方

詳しい説明とコード例については、個別のルールファイルを参照してください。

rules/form-useform-basic.md
rules/page-props-typing.md
rules/layout-persistent.md

プロジェクト構成

laravel-inertia-vue/
├── SKILL.md                 # This file - overview and examples
├── README.md                # Quick reference guide
├── AGENTS.md                # Integration guide for AI agents
├── metadata.json            # Skill metadata and references
└── rules/
    ├── _sections.md         # Rule categories and priorities
    ├── _template.md         # Template for new rules
    ├── page-*.md            # Page component patterns (6 rules)
    ├── form-*.md            # Form handling patterns (8 rules)
    ├── nav-*.md             # Navigation patterns (5 rules)
    ├── shared-*.md          # Shared data patterns (4 rules)
    └── layout-*.md          # Layout patterns (1 rule)

参考資料

ライセンス

MIT ライセンス。このスキルは、教育および開発目的で現状のまま提供されます。

メタデータ

  • バージョン:1.0.0
  • 最終更新日:2026-03-17
  • メンテナー:Jasim K
  • ルール数:6 カテゴリーにわたる 24 のルール
  • 技術スタック:Laravel 12+、Inertia.js 2.0+、Vue 3.3+、TypeScript 5+

コメント