Unified Account and Workspace drop-downs; Layout updates, now header lives within the PageBody component; Sidebars now use floating variant
2.9 KiB
2.9 KiB
Next.js Utilities
Quick Reference
| Function | Import | Purpose |
|---|---|---|
authActionClient |
@kit/next/safe-action |
Authenticated server actions |
publicActionClient |
@kit/next/safe-action |
Public server actions (no auth) |
captchaActionClient |
@kit/next/safe-action |
Server actions with CAPTCHA + auth |
enhanceRouteHandler |
@kit/next/routes |
API routes with auth + validation |
Guidelines
- Server Actions for mutations only, not data-fetching
- Keep actions light - move business logic to services
- Authorization via RLS, not application code
- Use
'use server'at top of file - Always validate with Zod schema
- Use
useActionhook fromnext-safe-action/hooksin client components
Skills
For detailed implementation patterns:
/server-action-builder- Complete server action workflow
Server Action Pattern (next-safe-action)
'use server';
import { authActionClient } from '@kit/next/safe-action';
// Authenticated action with schema validation
export const myAction = authActionClient
.schema(MySchema)
.action(async ({ parsedInput: data, ctx: { user } }) => {
// data: validated input, user: authenticated user
return { success: true };
});
// Public action (no auth required)
import { publicActionClient } from '@kit/next/safe-action';
export const publicAction = publicActionClient
.schema(MySchema)
.action(async ({ parsedInput: data }) => {
return { success: true };
});
Admin actions
Admin actions use a dedicated client in @kit/admin:
import { adminActionClient } from '../utils/admin-action-client';
export const adminAction = adminActionClient
.schema(MySchema)
.action(async ({ parsedInput: data, ctx: { user } }) => {
// Only accessible to super admins
return { success: true };
});
Client Component Pattern (useAction)
'use client';
import { useAction } from 'next-safe-action/hooks';
import { myAction } from '../server/server-actions';
function MyComponent() {
const { execute, isPending, hasErrored, result } = useAction(myAction, {
onSuccess: ({ data }) => {
// Handle success
},
onError: ({ error }) => {
// Handle error
},
});
return (
<form onSubmit={(e) => { e.preventDefault(); execute(formData); }}>
{/* form fields */}
<button disabled={isPending}>Submit</button>
</form>
);
}
Route Handler Pattern
import { enhanceRouteHandler } from '@kit/next/routes';
export const POST = enhanceRouteHandler(
async function ({ body, user, request }) {
return NextResponse.json({ success: true });
},
{ auth: true, schema: MySchema },
);
Revalidation
- Use
revalidatePathafter mutations - Never use
router.refresh()orrouter.push()after Server Actions