Server Actions

Server Actions allow client components and forms to invoke asynchronous server-side Rust/Bun functions without manually defining API endpoints.

The "use server" Directive

Define server actions by annotating an async function or an entire module with "use server":

app/actions.ts
"use server";

export async function addComment(formData: FormData) {
  const content = formData.get("content");
  // Mutations execute securely on the server
  await db.comments.create({ content });
  return { success: true };
}

Forms with Progressive Enhancement

Use the <Form> component from swift-rust to bind server actions directly:

app/comments/page.tsx
import { Form } from "swift-rust";
import { addComment } from "../actions";

export default function CommentsPage() {
  return (
    <Form action={addComment} className="flex flex-col gap-4">
      <textarea name="content" required placeholder="Write a comment..." />
      <button type="submit">Post Comment</button>
    </Form>
  );
}

Direct Invocation from Client Components

Server actions can be called directly like standard async JavaScript functions:

app/like-button.tsx
"use client";
import { useState, useTransition } from "react";
import { likePost } from "./actions";

export function LikeButton({ postId }: { postId: string }) {
  const [likes, setLikes] = useState(0);
  const [isPending, startTransition] = useTransition();

  return (
    <button
      disabled={isPending}
      onClick={() => {
        startTransition(async () => {
          const res = await likePost(postId);
          setLikes(res.newCount);
        });
      }}
    >
      {likes} Likes
    </button>
  );
}