Getting Started
Usage
Learn how to create a type-safe action client, define validated server actions, and call them from Vue components with useAction.
Usage
Using nuxt-safe-action is a three-step process: create a client, define actions, and use them in components.
1. Create an Action Client
Create a reusable action client in your server utilities:
server/utils/action-client.ts
import { createSafeActionClient } from '#safe-action'
export const actionClient = createSafeActionClient({
handleServerError: (error) => {
console.error('Action error:', error.message)
return error.message
},
})
2. Define an Action
Create a file in server/actions/ that default-exports an action:
server/actions/greet.ts
import { z } from 'zod'
import { actionClient } from '../utils/action-client'
export default actionClient
.schema(z.object({
name: z.string().min(1, 'Name is required'),
}))
.action(async ({ parsedInput }) => {
return { greeting: `Hello, ${parsedInput.name}!` }
})
3. Use in a Component
Import the action from the virtual module and use it with the useAction composable:
app/components/GreetForm.vue
<script setup lang="ts">
import { greet } from '#safe-action/actions'
const { execute, data, isExecuting, hasSucceeded, validationErrors } = useAction(greet, {
onSuccess({ data }) {
console.log(data.greeting) // fully typed!
},
onError({ error }) {
console.error(error)
},
})
</script>
<template>
<form @submit.prevent="execute({ name: 'World' })">
<button :disabled="isExecuting">
{{ isExecuting ? 'Loading...' : 'Greet' }}
</button>
<p v-if="hasSucceeded">{{ data?.greeting }}</p>
</form>
</template>
How It Works
- You define actions in
server/actions/using the builder chain - The module scans that directory and generates Nitro API routes at
/api/_actions/<name> - A typed virtual module (
#safe-action/actions) provides client-side references with full type inference useAction()calls the generated route via$fetchand returns reactive state
Action file names become the import names.
server/actions/create-post.ts is imported as createPost from #safe-action/actions. You can add a method suffix (e.g. .get, .put, .delete) to change the HTTP method — see Defining Actions.