Get the FREE Ultimate OpenClaw Setup Guide →

server-actions

npx machina-cli add skill JanSzewczyk/claude-plugins/server-actions --openclaw
Files (1)
SKILL.md
7.0 KB

Server Actions Skill

Create Next.js Server Actions with TypeScript following best practices for validation, error handling, and React integration.

Reference Files:

First Step: Read Project Context

IMPORTANT: Before creating server actions, check project configuration files:

.claude/project-context.md for:

  • Authentication provider (Clerk, NextAuth, JWT)
  • Database patterns (tuple error handling, DbError class)
  • Logging conventions

CLAUDE.md for:

  • Server Actions patterns (ActionResponse type)
  • Database error handling (DbError class)
  • Toast notification system
  • File organization conventions

Context

This skill helps you create:

  • Form actions - Handle form submissions with validation
  • CRUD operations - Create, read, update, delete mutations
  • Redirect flows - Multi-step wizards, onboarding
  • Data mutations - Any server-side data changes

Instructions

When the user requests a server action:

1. Analyze Requirements

Gather information about:

  • What data does the action handle?
  • Does it return data or redirect?
  • What validation is needed?
  • What authentication/authorization is required?
  • What errors need to be handled?
  • What cache paths need revalidation?

2. Choose Response Type

ScenarioTypeDescription
Returns dataActionResponse<T>Action returns data to client
Redirects on successRedirectActionAction navigates to new page
Form with useActionStateModified signatureAccepts previousState as first param

3. Create Server Action

File Location: features/[feature]/server/actions/[action-name].ts

Standard Template:

"use server";

import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { auth } from "@clerk/nextjs/server"; // or your auth provider
import { createLogger } from "~/lib/logger";
import type { ActionResponse, RedirectAction } from "~/lib/action-types";

const logger = createLogger({ module: "[feature]-actions" });

export async function actionName(data: InputType): ActionResponse<OutputType> {
  // 1. Authentication
  const { userId } = await auth();
  if (!userId) {
    return { success: false, error: "Authentication required" };
  }

  // 2. Validation
  const parsed = schema.safeParse(data);
  if (!parsed.success) {
    return {
      success: false,
      error: "Validation failed",
      fieldErrors: parsed.error.flatten().fieldErrors,
    };
  }

  // 3. Database operation
  const [error, result] = await dbOperation(parsed.data);
  if (error) {
    logger.error({ userId, error }, "Operation failed");
    return { success: false, error: "Operation failed" };
  }

  // 4. Revalidate cache
  revalidatePath("/affected-path");

  // 5. Return response
  logger.info({ userId, resultId: result.id }, "Operation succeeded");
  return { success: true, data: result };
}

4. Create Validation Schema

File Location: features/[feature]/schemas/[schema-name].ts

import { z } from "zod";

export const inputSchema = z.object({
  name: z.string().min(2, "Name must be at least 2 characters"),
  email: z.string().email("Invalid email address"),
});

export type InputData = z.infer<typeof inputSchema>;

5. Integrate with React Component

Choose integration pattern based on form complexity:

ComplexityPatternUse When
SimpleuseActionStateNative form, simple state
ComplexReact Hook Form + useTransitionDynamic fields, complex validation
RedirectBound action propMulti-step flows

See hooks.md and react-hook-form.md for implementation details.

Core Patterns

Error Handling

Use tuple pattern for database operations:

const [error, data] = await dbOperation();
if (error) {
  if (error.isNotFound) return { success: false, error: "Not found" };
  if (error.isRetryable) return { success: false, error: "Please try again" };
  return { success: false, error: "Operation failed" };
}

Cache Revalidation

Always revalidate after mutations:

revalidatePath("/posts"); // Specific path
revalidateTag("posts"); // By cache tag

Toast Notifications

For user feedback with redirects:

import { setToastCookie } from "~/lib/toast/server/toast.cookie";

await setToastCookie("Saved successfully!", "success");
redirect("/dashboard");

Security Checklist

  1. ✅ Verify authentication (await auth())
  2. ✅ Check authorization (ownership, permissions)
  3. ✅ Validate all inputs (Zod schema)
  4. ✅ Log important operations
  5. ✅ Never expose internal errors to client

File Organization

features/
  users/
    server/
      actions/
        create-user.ts
        update-user.ts
        delete-user.ts
        index.ts         # Re-exports
      db/
        users.ts
    schemas/
      user.ts
    types/
      user.ts
    components/
      user-form.tsx

Running and Testing

# Type check
npm run type-check

# Run related tests
npm run test -- features/[feature]

# Test in Storybook (if form component)
npm run storybook:dev

Questions to Ask

When creating server actions:

  • What data does this action create/update/delete?
  • Does it return data or redirect to another page?
  • What validation rules apply to the input?
  • What authentication/authorization is needed?
  • What error cases should be handled?
  • What paths/tags need cache revalidation?
  • Should there be toast notification feedback?
  • Is this part of a multi-step flow?

Source

git clone https://github.com/JanSzewczyk/claude-plugins/blob/main/plugins/nextjs-react/skills/server-actions/SKILL.mdView on GitHub

Overview

Learn to build Next.js Server Actions with TypeScript, covering forms, mutations, and data flows. It emphasizes type-safe responses, robust validation, and error handling aligned with project patterns. Use cases include server-side form handling, CRUD mutations, and multi-step redirects.

How This Skill Works

Actions live in features/[feature]/server/actions/[action-name].ts and run with the 'use server' directive. They perform authentication checks, validate inputs with Zod (safeParse), and execute database mutations, returning ActionResponse or RedirectAction. Errors and field-level feedback are standardized to support the client via hooks like useActionState.

When to Use It

  • Implement server-side form submissions with validation
  • Perform CRUD mutations (create, update, delete) on server
  • Create redirect flows for multi-step onboarding
  • Handle data mutations requiring authentication/authorization
  • Implement client-facing error handling and cache revalidation when data changes

Quick Start

  1. Step 1: Read project context (.claude/project-context.md) and auth/db patterns
  2. Step 2: Create a server action file at features/[feature]/server/actions/[action-name].ts with 'use server' and skeleton logic
  3. Step 3: Validate input with a Zod schema, perform DB operation, and return ActionResponse or RedirectAction; test with React hooks like useActionState

Best Practices

  • Return ActionResponse<T> for data results and RedirectAction for navigations
  • Validate inputs with Zod schemas using safeParse and propagate fieldErrors
  • Enforce authentication (e.g., Clerk/NextAuth) before mutations
  • Use next/cache revalidatePath to refresh affected pages after mutations
  • Organize actions under features/[feature]/server/actions with clear logging

Example Use Cases

  • Create a server action for a user registration form
  • Implement CRUD actions for budget management
  • Add form validation with Zod to the contact form
  • Create redirect action for onboarding flow
  • Guard server mutations with auth checks and structured error handling

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers