2026-03-29 21:10:10 +00:00
---
name: inertia-vue-development
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
description: "Develops Inertia.js v3 Vue client-side applications. Activates when creating Vue pages, forms, or navigation; using < Link > , < Form > , useForm, useHttp, setLayoutProps, 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."
2026-03-29 21:10:10 +00:00
license: MIT
metadata:
author: laravel
---
# Inertia Vue Development
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
## 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
2026-03-29 21:10:10 +00:00
## Documentation
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
Use `search-docs` for detailed Inertia v3 Vue patterns and documentation.
2026-03-29 21:10:10 +00:00
## Basic Usage
### Page Components Location
Vue page components should be placed in the `resources/js/pages` directory.
### Page Component Structure
<!-- Basic Vue Page Component -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< script setup >
import { Link } from '@inertiajs/vue3'
< / script >
< template >
< Link href = "/users" prefetch >
Users
< / Link >
< / template >
```
### Programmatic Navigation
<!-- Router Visit -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 >
```
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
## 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< 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 -->
```vue
< script setup >
withDefaults(defineProps({
title: String,
showSidebar: Boolean,
}), {
title: 'My App',
showSidebar: true,
})
< / script >
< template >
< header > {{ title }}< / header >
< aside v-if = "showSidebar" > Sidebar< / aside >
< main >
< slot / >
< / main >
< / template >
```
<!-- Setting Layout Props from Page -->
```vue
< script setup >
import { setLayoutProps } from '@inertiajs/vue3'
setLayoutProps({
title: 'Dashboard',
showSidebar: false,
})
< / script >
< template >
< h1 > Dashboard< / h1 >
< / template >
```
2026-03-29 21:10:10 +00:00
### Deferred Props
Use deferred props to load data after initial page render:
<!-- Deferred Props with Empty State -->
```vue
< 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
Use the `usePoll` composable to automatically refresh data at intervals. It handles cleanup on unmount and throttles polling when the tab is inactive.
<!-- Basic Polling -->
```vue
< script setup >
import { usePoll } from '@inertiajs/vue3'
defineProps({
stats: Object
})
usePoll(5000)
< / script >
< template >
< div >
< h1 > Dashboard< / h1 >
< div > Active Users: {{ stats.activeUsers }}< / div >
< / div >
< / template >
```
<!-- Polling With Request Options and Manual Control -->
```vue
< script setup >
import { usePoll } from '@inertiajs/vue3'
defineProps({
stats: Object
})
const { start, stop } = usePoll(5000, {
only: ['stats'],
onStart() {
console.log('Polling request started')
},
onFinish() {
console.log('Polling request finished')
},
}, {
autoStart: false,
keepAlive: true,
})
< / script >
< template >
< div >
< h1 > Dashboard< / h1 >
< div > Active Users: {{ stats.activeUsers }}< / div >
< button @click =" start " > Start Polling</ button >
< button @click =" stop " > Stop Polling</ button >
< / div >
< / template >
```
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
- `autoStart` (default `true` ) - set to `false` to start polling manually via the returned `start()` function
- `keepAlive` (default `false` ) - set to `true` to prevent throttling when the browser tab is inactive
2026-03-29 21:10:10 +00:00
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
### WhenVisible
2026-03-29 21:10:10 +00:00
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
Lazy-load a prop when an element scrolls into view. Useful for deferring expensive data that sits below the fold:
2026-03-29 21:10:10 +00:00
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
<!-- WhenVisible Example -->
2026-03-29 21:10:10 +00:00
```vue
< script setup >
import { WhenVisible } from '@inertiajs/vue3'
defineProps({
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
stats: Object
2026-03-29 21:10:10 +00:00
})
< / script >
< template >
< div >
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
< h1 > Dashboard< / h1 >
2026-03-29 21:10:10 +00:00
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
< WhenVisible data = "stats" :buffer = "200" >
2026-03-29 21:10:10 +00:00
< template #fallback >
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
< 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 >
2026-03-29 21:10:10 +00:00
< / template >
< / WhenVisible >
< / div >
< / template >
```
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
### InfiniteScroll
Automatically load additional pages of paginated data as users scroll:
<!-- InfiniteScroll Example -->
```vue
< script setup >
import { InfiniteScroll } from '@inertiajs/vue3'
defineProps({
users: Object
})
< / script >
< template >
< InfiniteScroll data = "users" >
< div v-for = "user in users.data" :key = "user.id" >
{{ user.name }}
< / div >
< / InfiniteScroll >
< / template >
```
The server must use `Inertia::scroll()` to configure the paginated data. Use the `search-docs` tool with a query of `infinite scroll` for detailed guidance on buffers, manual loading, reverse mode, and custom trigger elements.
2026-03-29 21:10:10 +00:00
## 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` )
feat: implement MCP server with tools, Post API tests, auth middleware
- Create TryPostServer MCP server with 17 tools:
Post (List, Get, Create, Delete), Hashtag (List, Create, Update, Delete),
Label (List, Create, Update, Delete), Workspace (Get),
ApiKey (List, Create, Delete)
- Create AuthenticateMcpToken middleware (logs in workspace owner)
- Register mcp.auth middleware alias in bootstrap/app.php
- Create routes/ai.php with mcp.trypost.test subdomain
- Add PostApiTest with 6 tests (list, show, create, delete, isolation)
- Fix PostApiTest assertions for pagination/resource wrapping
- 704 tests passing, frontend build passing
2026-03-29 23:30:36 +00:00
- 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