imsus/laravel-starter-kit · Archived

inertia-vue-development

Develops Inertia.js v3 Vue client-side applications.

First seen Jun 18, 2026

Installation

$ npx skills add imsus/laravel-starter-kit --skill inertia-vue-development

Summary

  • Develops Inertia.js v3 Vue client-side applications.
  • Activates when creating Vue pages, forms, or navigation; using <Link>, <Form>, useForm, useHttp, useLayoutProps, or router; working with deferred props, prefetching, optimistic updates, instant visits, or polling; or when user mentions Vue with Inertia, Vue pages, Vue forms, or Vue navigation.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from imsus/laravel-starter-kit.

npx skills add imsus/laravel-starter-kit

Browse all from imsus/laravel-starter-kit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License MIT
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

LicenseMIT
More metadata
author
laravel

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 11,609 B
  • docs SUMMARY.md 378 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

Inertia Vue Development

When to Apply

Activate this skill when:

  • Creating or modifying Vue page components for Inertia
  • Working with forms in Vue (using <Form>, useForm, or useHttp)
  • Implementing client-side navigation with <Link> or router
  • Using v3 features: deferred props, prefetching, optimistic updates, instant visits, layout props, HTTP requests, WhenVisible, InfiniteScroll, once props, flash data, or polling
  • Building Vue-specific features with the Inertia protocol

Documentation

Use search-docs for detailed Inertia v3 Vue patterns and documentation.

Basic Usage

Page Components Location

Vue page components should be placed in the resources/js/pages directory.

Page Component Structure

<!-- Basic Vue Page Component -->

<script setup>
defineProps({
  users: Array,
});
</script>

<template>
  <div>
    <h1>Users</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

Client-Side Navigation

Basic Link Component

Use <Link> for client-side navigation instead of traditional <a> tags:

<!-- Inertia Vue Navigation -->

<script setup>
import { Link } from "@inertiajs/vue3";
</script>

<template>
  <div>
    <Link href="/">Home</Link>
    <Link href="/users">Users</Link>
    <Link :href="`/users/${user.id}`">View User</Link>
  </div>
</template>

Link with Method

<!-- Link with POST Method -->

<script setup>
import { Link } from "@inertiajs/vue3";
</script>

<template>
  <Link href="/logout" method="post" as="button"> Logout </Link>
</template>

Prefetching

Prefetch pages to improve perceived performance:

<!-- Prefetch on Hover -->

<script setup>
import { Link } from "@inertiajs/vue3";
</script>

<template>
  <Link href="/users" prefetch> Users </Link>
</template>

Programmatic Navigation

<!-- Router Visit -->

<script setup>
import { router } from "@inertiajs/vue3";

function handleClick() {
  router.visit("/users");
}

// Or with options
function createUser() {
  router.visit("/users", {
    method: "post",
    data: { name: "John" },
    onSuccess: () => console.log("Done"),
  });
}
</script>

<template>
  <Link href="/users">Users</Link>
  <Link href="/logout" method="post" as="button">Logout</Link>
</template>

Form Handling

Form Component (Recommended)

The recommended way to build forms is with the <Form> component:

<!-- Form Component Example -->

<script setup>
import { Form } from "@inertiajs/vue3";
</script>

<template>
  <Form action="/users" method="post" #default="{ errors, processing, wasSuccessful }">
    <input type="text" name="name" />
    <div v-if="errors.name">{{ errors.name }}</div>

    <input type="email" name="email" />
    <div v-if="errors.email">{{ errors.email }}</div>

    <button type="submit" :disabled="processing">
      {{ processing ? "Creating..." : "Create User" }}
    </button>

    <div v-if="wasSuccessful">User created!</div>
  </Form>
</template>

Form Component With All Props

<!-- Form Component Full Example -->

<script setup>
import { Form } from "@inertiajs/vue3";
</script>

<template>
  <Form
    action="/users"
    method="post"
    #default="{
      errors,
      hasErrors,
      processing,
      progress,
      wasSuccessful,
      recentlySuccessful,
      setError,
      clearErrors,
      resetAndClearErrors,
      defaults,
      isDirty,
      reset,
      submit,
    }"
  >
    <input type="text" name="name" :value="defaults.name" />
    <div v-if="errors.name">{{ errors.name }}</div>

    <button type="submit" :disabled="processing">
      {{ processing ? "Saving..." : "Save" }}
    </button>

    <progress v-if="progress" :value="progress.percentage" max="100">
      {{ progress.percentage }}%
    </progress>

    <div v-if="wasSuccessful">Saved!</div>
  </Form>
</template>

Form Component Reset Props

The <Form> component supports automatic resetting:

  • resetOnError - Reset form data when the request fails
  • resetOnSuccess - Reset form data when the request succeeds
  • setDefaultsOnSuccess - Update default values on success

Use the search-docs tool with a query of form component resetting for detailed guidance.

<!-- Form with Reset Props -->

<script setup>
import { Form } from "@inertiajs/vue3";
</script>

<template>
  <Form
    action="/users"
    method="post"
    reset-on-success
    set-defaults-on-success
    #default="{ errors, processing, wasSuccessful }"
  >
    <input type="text" name="name" />
    <div v-if="errors.name">{{ errors.name }}</div>

    <button type="submit" :disabled="processing">Submit</button>
  </Form>
</template>

Forms can also be built using the useForm composable for more programmatic control. Use the search-docs tool with a query of useForm helper for guidance.

useForm Composable

For more programmatic control or to follow existing conventions, use the useForm composable:

<!-- useForm Composable Example -->

<script setup>
import { useForm } from "@inertiajs/vue3";

const form = useForm({
  name: "",
  email: "",
  password: "",
});

function submit() {
  form.post("/users", {
    onSuccess: () => form.reset("password"),
  });
}
</script>

<template>
  <form @submit.prevent="submit">
    <input type="text" v-model="form.name" />
    <div v-if="form.errors.name">{{ form.errors.name }}</div>

    <input type="email" v-model="form.email" />
    <div v-if="form.errors.email">{{ form.errors.email }}</div>

    <input type="password" v-model="form.password" />
    <div v-if="form.errors.password">{{ form.errors.password }}</div>

    <button type="submit" :disabled="form.processing">Create User</button>
  </form>
</template>

Inertia v3 Features

HTTP Requests

Use the useHttp hook for standalone HTTP requests that do not trigger Inertia page visits. It provides the same developer experience as useForm, but for plain JSON endpoints.

<!-- useHttp Example -->

<script setup>
import { useHttp } from "@inertiajs/vue3";

const http = useHttp({
  query: "",
});

function search() {
  http.get("/api/search", {
    onSuccess: (response) => {
      console.log(response);
    },
  });
}
</script>

<template>
  <input v-model="http.query" @input="search" />
  <div v-if="http.processing">Searching...</div>
</template>

Optimistic Updates

Apply data changes instantly before the server responds, with automatic rollback on failure:

<!-- Optimistic Update with Router -->

<script setup>
import { router } from "@inertiajs/vue3";

function like(post) {
  router
    .optimistic((props) => ({
      post: {
        ...props.post,
        likes: props.post.likes + 1,
      },
    }))
    .post(`/posts/${post.id}/like`);
}
</script>

Optimistic updates also work with useForm and the <Form> component:

<!-- Optimistic Update with Form Component -->

<template>
  <Form
    action="/todos"
    method="post"
    :optimistic="
      (props, data) => ({
        todos: [...props.todos, { id: Date.now(), name: data.name, done: false }],
      })
    "
  >
    <input type="text" name="name" />
    <button type="submit">Add Todo</button>
  </Form>
</template>

Instant Visits

Navigate to a new page immediately without waiting for the server response. The target component renders right away with shared props, while page-specific props load in the background.

<!-- Instant Visit with Link -->

<script setup>
import { Link } from "@inertiajs/vue3";
</script>

<template>
  <Link href="/dashboard" component="Dashboard">Dashboard</Link>

  <Link href="/posts/1" component="Posts/Show" :page-props="{ post: { id: 1, title: 'My Post' } }">
    View Post
  </Link>
</template>

Layout Props

Share dynamic data between pages and persistent layouts:

<!-- Layout Props in Layout -->

<script setup>
import { useLayoutProps } from "@inertiajs/vue3";

const layout = useLayoutProps({
  title: "My App",
  showSidebar: true,
});
</script>

<template>
  <header>{{ layout.title }}</header>
  <aside v-if="layout.showSidebar">Sidebar</aside>
  <main>
    <slot />
  </main>
</template>

<!-- Setting Layout Props from Page -->

<script setup>
import { setLayoutProps } from "@inertiajs/vue3";

setLayoutProps({
  title: "Dashboard",
  showSidebar: false,
});
</script>

<template>
  <h1>Dashboard</h1>
</template>

Deferred Props

Use deferred props to load data after initial page render:

<!-- Deferred Props with Empty State -->

<script setup>
defineProps({
  users: Array,
});
</script>

<template>
  <div>
    <h1>Users</h1>
    <div v-if="!users" class="animate-pulse">
      <div class="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
      <div class="h-4 bg-gray-200 rounded w-1/2"></div>
    </div>
    <ul v-else>
      <li v-for="user in users" :key="user.id">
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

Polling

Automatically refresh data at intervals:

<!-- Polling Example -->

<script setup>
import { router } from "@inertiajs/vue3";
import { onMounted, onUnmounted } from "vue";

defineProps({
  stats: Object,
});

let interval;

onMounted(() => {
  interval = setInterval(() => {
    router.reload({ only: ["stats"] });
  }, 5000);
});

onUnmounted(() => {
  clearInterval(interval);
});
</script>

<template>
  <div>
    <h1>Dashboard</h1>
    <div>Active Users: {{ stats.activeUsers }}</div>
  </div>
</template>

WhenVisible

Lazy-load a prop when an element scrolls into view. Useful for deferring expensive data that sits below the fold:

<!-- WhenVisible Example -->

<script setup>
import { WhenVisible } from "@inertiajs/vue3";

defineProps({
  stats: Object,
});
</script>

<template>
  <div>
    <h1>Dashboard</h1>

    <WhenVisible data="stats" :buffer="200">
      <template #fallback>
        <div class="animate-pulse">Loading stats...</div>
      </template>

      <template #default="{ fetching }">
        <div>
          <p>Total Users: {{ stats.total_users }}</p>
          <p>Revenue: {{ stats.revenue }}</p>
          <span v-if="fetching">Refreshing...</span>
        </div>
      </template>
    </WhenVisible>
  </div>
</template>

Server-Side Patterns

Server-side patterns (Inertia::render, props, middleware) are covered in inertia-laravel guidelines.

Common Pitfalls

  • Using traditional <a> links instead of Inertia's <Link> component (breaks SPA behavior)
  • Forgetting that Vue components must have a single root element
  • Forgetting to add loading states (skeleton screens) when using deferred props
  • Not handling the undefined state of deferred props before data loads
  • Using <form> without preventing default submission (use <Form> component or @submit.prevent)
  • Forgetting to check if <Form> component is available in your Inertia version
  • Using router.cancel() instead of router.cancelAll() (v3 breaking change)
  • Using router.on('invalid', ...) or router.on('exception', ...) instead of the renamed httpException and networkError events